[Mono.Posix] Support OS X ENOATTR
authorJonathan Pryor <jonpryor@vt.edu>
Fri, 23 May 2014 17:26:52 +0000 (13:26 -0400)
committerJonathan Pryor <jonpryor@vt.edu>
Fri, 23 May 2014 17:45:10 +0000 (13:45 -0400)
commitd2b527948437307f5077b8904ad6e3fb1905c2bd
treefda5ccda222659bb587ca881a6d8b86f0d352df2
parent4bc2c11690f112de4cc0f9696963d1743f4398c6
[Mono.Posix] Support OS X ENOATTR

Fixes: https://bugzilla.xamarin.com/show_bug.cgi?id=19991

The original Mono.Unix.Native.Errno design used the Linux <errno.h>
constants and values...largely because it was easy.

As it turns out, this is also incomplete. The getxattr(2) defines
ENOATTR as a possible error code. On Linux, ENOATTR is an alias for
ENODATA [0]. On OS X, ENOATTR is _not_ an alias. Furthermore, since
ENOATTR is not a Linux errno value (it's an alias!),
Mono_Posix_ToErrno() couldn't check for the native ENOATTR value, so a
Syscall.GetLastError() call after a failing Syscall.getxattr() would
fail with a System.ArgumentOutOfRangeException:

$ csharp -r:Mono.Posix.dll
Mono C# Shell, type "help;" for help

Enter statements below.
csharp> using Mono.Unix.Native;
csharp> byte[] value;
csharp> Syscall.getxattr(".", "test", out value);
-1
csharp> Syscall.GetLastError();
System.ArgumentOutOfRangeException: Current platform doesn't support this value.
Parameter name: value
93
at Mono.Unix.Native.NativeConvert.ThrowArgumentException (System.Object value) [0x00000] in <filename unknown>:0
at Mono.Unix.Native.NativeConvert.ToErrno (Int32 value) [0x00000] in <filename unknown>:0
at Mono.Unix.Native.Stdlib.GetLastError () [0x00000] in <filename unknown>:0

The fix is to add an Errno.ENOATTR field [1].

The complication is one of what enum value to use: at present, the
Errno values are based on the Linux values. In the case of ENOATTR
(and others), there is no Linux value. Meanwhile, there is the
possibility of additional Linux error values; how do we future proof
ourselves?

This isn't a perfect solution, but it should punt the problem down the
road a bit: Errno is an `int` enum, and thus has large range. To
support the OS X values, we add 1000 to the OS X error value.

/* OS X: <errno.h> */
#define ENOATTR 93 /* Attribute not found */

// C# Errno enum:
public enum Errno : int {
// ...
ENOATTR = 1093,
}

This gives us 0..1000 for POSIX+Linux error codes, 1000..2000 for OS X
specific error codes, and as new platforms require additional support
they can all start at multiples of 1000.

Hopefully no single *nix platform will add more than 1000 error codes...

[0]: http://linux.die.net/man/2/getxattr
[1]: Related part of the fix: add all the OTHER <errno.h> values that
     OS X includes but weren't included in the Errno enum.
mcs/class/Mono.Posix/Mono.Unix.Native/Stdlib.cs
support/map.c
support/map.h