Style
[mono.git] / mcs / class / Mono.Posix / Mono.Unix.Native / Syscall.cs
index 0036b63bcc8349e00e14a9e8509fbce6841e1895..a95c5ee670991e0508aefb0f7fda765e694d9e2f 100644 (file)
@@ -6,7 +6,7 @@
 //   Jonathan Pryor (jonpryor@vt.edu)
 //
 // (C) 2003 Novell, Inc.
-// (C) 2004-2005 Jonathan Pryor
+// (C) 2004-2006 Jonathan Pryor
 //
 // This file implements the low-level syscall interface to the POSIX
 // subsystem.
 using System;
 using System.Collections;
 using System.Runtime.InteropServices;
+using System.Security;
 using System.Text;
 using Mono.Unix.Native;
 
-[assembly:Mono.Unix.Native.HeaderAttribute (
-       Includes=
-               "sys/types.h," + 
-               "sys/stat.h," + 
-               "ah:sys/poll.h," + 
-               "ah:sys/wait.h," +
-               "ah:sys/statvfs.h," +
-               "ah:sys/xattr.h," +
-               "unistd.h," + 
-               "fcntl.h," + 
-               "signal.h," + 
-               "ah:poll.h," + 
-               "ah:grp.h," + 
-               "errno.h," + 
-               "ah:syslog.h",
-       Defines=
-               "_GNU_SOURCE," +
-               "_XOPEN_SOURCE"
-)]
-
 namespace Mono.Unix.Native {
 
        #region Enumerations
@@ -197,12 +178,19 @@ namespace Mono.Unix.Native {
                // Device types
                // Why these are held in "mode_t" is beyond me...
                S_IFMT      = 0xF000, // Bits which determine file type
+               [Map(SuppressFlags="S_IFMT")]
                S_IFDIR     = 0x4000, // Directory
+               [Map(SuppressFlags="S_IFMT")]
                S_IFCHR     = 0x2000, // Character device
+               [Map(SuppressFlags="S_IFMT")]
                S_IFBLK     = 0x6000, // Block device
+               [Map(SuppressFlags="S_IFMT")]
                S_IFREG     = 0x8000, // Regular file
+               [Map(SuppressFlags="S_IFMT")]
                S_IFIFO     = 0x1000, // FIFO
+               [Map(SuppressFlags="S_IFMT")]
                S_IFLNK     = 0xA000, // Symbolic link
+               [Map(SuppressFlags="S_IFMT")]
                S_IFSOCK    = 0xC000, // Socket
        }
 
@@ -638,7 +626,7 @@ namespace Mono.Unix.Native {
                POLLHUP     = 0x0010, // Hung up
                POLLNVAL    = 0x0020, // Invalid request; fd not open
                // XPG4.2 definitions (via _XOPEN_SOURCE)
-               POLLRDNORM  = 0x0040, // Normal data bay be read
+               POLLRDNORM  = 0x0040, // Normal data may be read
                POLLRDBAND  = 0x0080, // Priority data may be read
                POLLWRNORM  = 0x0100, // Writing now will not block
                POLLWRBAND  = 0x0200, // Priority data may be written
@@ -658,13 +646,16 @@ namespace Mono.Unix.Native {
                ST_RDONLY      =    1,  // Mount read-only
                ST_NOSUID      =    2,  // Ignore suid and sgid bits
                ST_NODEV       =    4,  // Disallow access to device special files
+               ST_NOEXEC      =    8,  // Disallow program execution
                ST_SYNCHRONOUS =   16,  // Writes are synced at once
+               ST_REMOUNT     =   32,  // Alter flags of a mounted FS
                ST_MANDLOCK    =   64,  // Allow mandatory locks on an FS
                ST_WRITE       =  128,  // Write on file/directory/symlink
                ST_APPEND      =  256,  // Append-only file
                ST_IMMUTABLE   =  512,  // Immutable file
                ST_NOATIME     = 1024,  // Do not update access times
                ST_NODIRATIME  = 2048,  // Do not update directory access times
+               ST_BIND        = 4096,  // Bind directory at different place
        }
 
        [Map][Flags]
@@ -726,85 +717,477 @@ namespace Mono.Unix.Native {
 
        #region Structures
 
-       public struct Flock {
+       [Map ("struct flock")]
+       public struct Flock
+#if NET_2_0
+               : IEquatable <Flock>
+#endif
+       {
                [CLSCompliant (false)]
                public LockType         l_type;    // Type of lock: F_RDLCK, F_WRLCK, F_UNLCK
                [CLSCompliant (false)]
                public SeekFlags        l_whence;  // How to interpret l_start
-               public /* off_t */ long l_start;   // Starting offset for lock
-               public /* off_t */ long l_len;     // Number of bytes to lock
-               public /* pid_t */ int  l_pid;     // PID of process blocking our lock (F_GETLK only)
+               [off_t] public long     l_start;   // Starting offset for lock
+               [off_t] public long     l_len;     // Number of bytes to lock
+               [pid_t] public int      l_pid;     // PID of process blocking our lock (F_GETLK only)
+
+               public override int GetHashCode ()
+               {
+                       return l_type.GetHashCode () ^ l_whence.GetHashCode () ^ 
+                               l_start.GetHashCode () ^ l_len.GetHashCode () ^
+                               l_pid.GetHashCode ();
+               }
+
+               public override bool Equals (object obj)
+               {
+                       if ((obj == null) || (obj.GetType () != GetType ()))
+                               return false;
+                       Flock value = (Flock) obj;
+                       return l_type == value.l_type && l_whence == value.l_whence && 
+                               l_start == value.l_start && l_len == value.l_len && 
+                               l_pid == value.l_pid;
+               }
+
+               public bool Equals (Flock value)
+               {
+                       return l_type == value.l_type && l_whence == value.l_whence && 
+                               l_start == value.l_start && l_len == value.l_len && 
+                               l_pid == value.l_pid;
+               }
+
+               public static bool operator== (Flock lhs, Flock rhs)
+               {
+                       return lhs.Equals (rhs);
+               }
+
+               public static bool operator!= (Flock lhs, Flock rhs)
+               {
+                       return !lhs.Equals (rhs);
+               }
        }
 
-       [StructLayout(LayoutKind.Sequential)]
-       public struct Pollfd {
+       [Map ("struct pollfd")]
+       public struct Pollfd
+#if NET_2_0
+               : IEquatable <Pollfd>
+#endif
+       {
                public int fd;
                [CLSCompliant (false)]
                public PollEvents events;
                [CLSCompliant (false)]
                public PollEvents revents;
+
+               public override int GetHashCode ()
+               {
+                       return events.GetHashCode () ^ revents.GetHashCode ();
+               }
+
+               public override bool Equals (object obj)
+               {
+                       if (obj == null || obj.GetType () != GetType ())
+                               return false;
+                       Pollfd value = (Pollfd) obj;
+                       return value.events == events && value.revents == revents;
+               }
+
+               public bool Equals (Pollfd value)
+               {
+                       return value.events == events && value.revents == revents;
+               }
+
+               public static bool operator== (Pollfd lhs, Pollfd rhs)
+               {
+                       return lhs.Equals (rhs);
+               }
+
+               public static bool operator!= (Pollfd lhs, Pollfd rhs)
+               {
+                       return !lhs.Equals (rhs);
+               }
        }
 
-       public struct Stat {
-               [CLSCompliant (false)]
-               public  /* dev_t */     ulong   st_dev;     // device
+       [Map ("struct stat")]
+       public struct Stat
+#if NET_2_0
+               : IEquatable <Stat>
+#endif
+       {
                [CLSCompliant (false)]
-               public  /* ino_t */     ulong   st_ino;     // inode
+               [dev_t]     public ulong    st_dev;     // device
                [CLSCompliant (false)]
-               public  FilePermissions         st_mode;    // protection
+               [ino_t]     public  ulong   st_ino;     // inode
                [CLSCompliant (false)]
-               private uint                    _padding_;  // padding for structure alignment
+               public  FilePermissions     st_mode;    // protection
+               [NonSerialized]
+#pragma warning disable 169            
+               private uint                _padding_;  // padding for structure alignment
+#pragma warning restore 169            
                [CLSCompliant (false)]
-               public  /* nlink_t */   ulong   st_nlink;   // number of hard links
+               [nlink_t]   public  ulong   st_nlink;   // number of hard links
                [CLSCompliant (false)]
-               public  /* uid_t */     uint    st_uid;     // user ID of owner
+               [uid_t]     public  uint    st_uid;     // user ID of owner
                [CLSCompliant (false)]
-               public  /* gid_t */     uint    st_gid;     // group ID of owner
+               [gid_t]     public  uint    st_gid;     // group ID of owner
                [CLSCompliant (false)]
-               public  /* dev_t */     ulong   st_rdev;    // device type (if inode device)
-               public  /* off_t */     long    st_size;    // total size, in bytes
-               public  /* blksize_t */ long    st_blksize; // blocksize for filesystem I/O
-               public  /* blkcnt_t */  long    st_blocks;  // number of blocks allocated
-               public  /* time_t */    long    st_atime;   // time of last access
-               public  /* time_t */    long    st_mtime;   // time of last modification
-               public  /* time_t */    long    st_ctime;   // time of last status change
+               [dev_t]     public  ulong   st_rdev;    // device type (if inode device)
+               [off_t]     public  long    st_size;    // total size, in bytes
+               [blksize_t] public  long    st_blksize; // blocksize for filesystem I/O
+               [blkcnt_t]  public  long    st_blocks;  // number of blocks allocated
+               [time_t]    public  long    st_atime;   // time of last access
+               [time_t]    public  long    st_mtime;   // time of last modification
+               [time_t]    public  long    st_ctime;   // time of last status change
+
+               public override int GetHashCode ()
+               {
+                       return st_dev.GetHashCode () ^
+                               st_ino.GetHashCode () ^
+                               st_mode.GetHashCode () ^
+                               st_nlink.GetHashCode () ^
+                               st_uid.GetHashCode () ^
+                               st_gid.GetHashCode () ^
+                               st_rdev.GetHashCode () ^
+                               st_size.GetHashCode () ^
+                               st_blksize.GetHashCode () ^
+                               st_blocks.GetHashCode () ^
+                               st_atime.GetHashCode () ^
+                               st_mtime.GetHashCode () ^
+                               st_ctime.GetHashCode ();
+               }
+
+               public override bool Equals (object obj)
+               {
+                       if (obj == null || obj.GetType() != GetType ())
+                               return false;
+                       Stat value = (Stat) obj;
+                       return value.st_dev == st_dev &&
+                               value.st_ino == st_ino &&
+                               value.st_mode == st_mode &&
+                               value.st_nlink == st_nlink &&
+                               value.st_uid == st_uid &&
+                               value.st_gid == st_gid &&
+                               value.st_rdev == st_rdev &&
+                               value.st_size == st_size &&
+                               value.st_blksize == st_blksize &&
+                               value.st_blocks == st_blocks &&
+                               value.st_atime == st_atime &&
+                               value.st_mtime == st_mtime &&
+                               value.st_ctime == st_ctime;
+               }
+
+               public bool Equals (Stat value)
+               {
+                       return value.st_dev == st_dev &&
+                               value.st_ino == st_ino &&
+                               value.st_mode == st_mode &&
+                               value.st_nlink == st_nlink &&
+                               value.st_uid == st_uid &&
+                               value.st_gid == st_gid &&
+                               value.st_rdev == st_rdev &&
+                               value.st_size == st_size &&
+                               value.st_blksize == st_blksize &&
+                               value.st_blocks == st_blocks &&
+                               value.st_atime == st_atime &&
+                               value.st_mtime == st_mtime &&
+                               value.st_ctime == st_ctime;
+               }
+
+               public static bool operator== (Stat lhs, Stat rhs)
+               {
+                       return lhs.Equals (rhs);
+               }
+
+               public static bool operator!= (Stat lhs, Stat rhs)
+               {
+                       return !lhs.Equals (rhs);
+               }
        }
 
+       // `struct statvfs' isn't portable, so don't generate To/From methods.
+       [Map]
        [CLSCompliant (false)]
-       public struct Statvfs {
+       public struct Statvfs
+#if NET_2_0
+               : IEquatable <Statvfs>
+#endif
+       {
                public                  ulong f_bsize;    // file system block size
                public                  ulong f_frsize;   // fragment size
-               public /* fsblkcnt_t */ ulong f_blocks;   // size of fs in f_frsize units
-               public /* fsblkcnt_t */ ulong f_bfree;    // # free blocks
-               public /* fsblkcnt_t */ ulong f_bavail;   // # free blocks for non-root
-               public /* fsfilcnt_t */ ulong f_files;    // # inodes
-               public /* fsfilcnt_t */ ulong f_ffree;    // # free inodes
-               public /* fsfilcnt_t */ ulong f_favail;   // # free inodes for non-root
+               [fsblkcnt_t] public     ulong f_blocks;   // size of fs in f_frsize units
+               [fsblkcnt_t] public     ulong f_bfree;    // # free blocks
+               [fsblkcnt_t] public     ulong f_bavail;   // # free blocks for non-root
+               [fsfilcnt_t] public     ulong f_files;    // # inodes
+               [fsfilcnt_t] public     ulong f_ffree;    // # free inodes
+               [fsfilcnt_t] public     ulong f_favail;   // # free inodes for non-root
                public                  ulong f_fsid;     // file system id
                public MountFlags             f_flag;     // mount flags
                public                  ulong f_namemax;  // maximum filename length
+
+               public override int GetHashCode ()
+               {
+                       return f_bsize.GetHashCode () ^
+                               f_frsize.GetHashCode () ^
+                               f_blocks.GetHashCode () ^
+                               f_bfree.GetHashCode () ^
+                               f_bavail.GetHashCode () ^
+                               f_files.GetHashCode () ^
+                               f_ffree.GetHashCode () ^
+                               f_favail.GetHashCode () ^
+                               f_fsid.GetHashCode () ^
+                               f_flag.GetHashCode () ^
+                               f_namemax.GetHashCode ();
+               }
+
+               public override bool Equals (object obj)
+               {
+                       if (obj == null || obj.GetType() != GetType ())
+                               return false;
+                       Statvfs value = (Statvfs) obj;
+                       return value.f_bsize == f_bsize &&
+                               value.f_frsize == f_frsize &&
+                               value.f_blocks == f_blocks &&
+                               value.f_bfree == f_bfree &&
+                               value.f_bavail == f_bavail &&
+                               value.f_files == f_files &&
+                               value.f_ffree == f_ffree &&
+                               value.f_favail == f_favail &&
+                               value.f_fsid == f_fsid &&
+                               value.f_flag == f_flag &&
+                               value.f_namemax == f_namemax;
+               }
+
+               public bool Equals (Statvfs value)
+               {
+                       return value.f_bsize == f_bsize &&
+                               value.f_frsize == f_frsize &&
+                               value.f_blocks == f_blocks &&
+                               value.f_bfree == f_bfree &&
+                               value.f_bavail == f_bavail &&
+                               value.f_files == f_files &&
+                               value.f_ffree == f_ffree &&
+                               value.f_favail == f_favail &&
+                               value.f_fsid == f_fsid &&
+                               value.f_flag == f_flag &&
+                               value.f_namemax == f_namemax;
+               }
+
+               public static bool operator== (Statvfs lhs, Statvfs rhs)
+               {
+                       return lhs.Equals (rhs);
+               }
+
+               public static bool operator!= (Statvfs lhs, Statvfs rhs)
+               {
+                       return !lhs.Equals (rhs);
+               }
        }
 
-       public struct Timeval {
-               public  /* time_t */      long    tv_sec;   // seconds
-               public  /* suseconds_t */ long    tv_usec;  // microseconds
+       [Map ("struct timeval")]
+       public struct Timeval
+#if NET_2_0
+               : IEquatable <Timeval>
+#endif
+       {
+               [time_t]      public long tv_sec;   // seconds
+               [suseconds_t] public long tv_usec;  // microseconds
+
+               public override int GetHashCode ()
+               {
+                       return tv_sec.GetHashCode () ^ tv_usec.GetHashCode ();
+               }
+
+               public override bool Equals (object obj)
+               {
+                       if (obj == null || obj.GetType () != GetType ())
+                               return false;
+                       Timeval value = (Timeval) obj;
+                       return value.tv_sec == tv_sec && value.tv_usec == tv_usec;
+               }
+
+               public bool Equals (Timeval value)
+               {
+                       return value.tv_sec == tv_sec && value.tv_usec == tv_usec;
+               }
+
+               public static bool operator== (Timeval lhs, Timeval rhs)
+               {
+                       return lhs.Equals (rhs);
+               }
+
+               public static bool operator!= (Timeval lhs, Timeval rhs)
+               {
+                       return !lhs.Equals (rhs);
+               }
        }
 
-       public struct Timezone {
+       [Map ("struct timezone")]
+       public struct Timezone
+#if NET_2_0
+               : IEquatable <Timezone>
+#endif
+       {
                public  int tz_minuteswest; // minutes W of Greenwich
+#pragma warning disable 169            
                private int tz_dsttime;     // type of dst correction (OBSOLETE)
+#pragma warning restore 169            
+
+               public override int GetHashCode ()
+               {
+                       return tz_minuteswest.GetHashCode ();
+               }
+
+               public override bool Equals (object obj)
+               {
+                       if (obj == null || obj.GetType () != GetType ())
+                               return false;
+                       Timezone value = (Timezone) obj;
+                       return value.tz_minuteswest == tz_minuteswest;
+               }
+
+               public bool Equals (Timezone value)
+               {
+                       return value.tz_minuteswest == tz_minuteswest;
+               }
+
+               public static bool operator== (Timezone lhs, Timezone rhs)
+               {
+                       return lhs.Equals (rhs);
+               }
+
+               public static bool operator!= (Timezone lhs, Timezone rhs)
+               {
+                       return !lhs.Equals (rhs);
+               }
+       }
+
+       [Map ("struct utimbuf")]
+       public struct Utimbuf
+#if NET_2_0
+               : IEquatable <Utimbuf>
+#endif
+       {
+               [time_t] public long    actime;   // access time
+               [time_t] public long    modtime;  // modification time
+
+               public override int GetHashCode ()
+               {
+                       return actime.GetHashCode () ^ modtime.GetHashCode ();
+               }
+
+               public override bool Equals (object obj)
+               {
+                       if (obj == null || obj.GetType () != GetType ())
+                               return false;
+                       Utimbuf value = (Utimbuf) obj;
+                       return value.actime == actime && value.modtime == modtime;
+               }
+
+               public bool Equals (Utimbuf value)
+               {
+                       return value.actime == actime && value.modtime == modtime;
+               }
+
+               public static bool operator== (Utimbuf lhs, Utimbuf rhs)
+               {
+                       return lhs.Equals (rhs);
+               }
+
+               public static bool operator!= (Utimbuf lhs, Utimbuf rhs)
+               {
+                       return !lhs.Equals (rhs);
+               }
+       }
+
+       [Map ("struct timespec")]
+       public struct Timespec
+#if NET_2_0
+               : IEquatable <Timespec>
+#endif
+       {
+               [time_t] public long    tv_sec;   // Seconds.
+               public          long    tv_nsec;  // Nanoseconds.
+
+               public override int GetHashCode ()
+               {
+                       return tv_sec.GetHashCode () ^ tv_nsec.GetHashCode ();
+               }
+
+               public override bool Equals (object obj)
+               {
+                       if (obj == null || obj.GetType () != GetType ())
+                               return false;
+                       Timespec value = (Timespec) obj;
+                       return value.tv_sec == tv_sec && value.tv_nsec == tv_nsec;
+               }
+
+               public bool Equals (Timespec value)
+               {
+                       return value.tv_sec == tv_sec && value.tv_nsec == tv_nsec;
+               }
+
+               public static bool operator== (Timespec lhs, Timespec rhs)
+               {
+                       return lhs.Equals (rhs);
+               }
+
+               public static bool operator!= (Timespec lhs, Timespec rhs)
+               {
+                       return !lhs.Equals (rhs);
+               }
+       }
+
+       [Flags][Map]
+       public enum EpollFlags {
+               EPOLL_CLOEXEC = 02000000,
+               EPOLL_NONBLOCK = 04000,
+       }
+
+       [Flags][Map]
+       [CLSCompliant (false)]
+       public enum EpollEvents : uint {
+               EPOLLIN = 0x001,
+               EPOLLPRI = 0x002,
+               EPOLLOUT = 0x004,
+               EPOLLRDNORM = 0x040,
+               EPOLLRDBAND = 0x080,
+               EPOLLWRNORM = 0x100,
+               EPOLLWRBAND = 0x200,
+               EPOLLMSG = 0x400,
+               EPOLLERR = 0x008,
+               EPOLLHUP = 0x010,
+               EPOLLRDHUP = 0x2000,
+               EPOLLONESHOT = 1 << 30,
+               EPOLLET = unchecked ((uint) (1 << 31))
        }
 
-       public struct Utimbuf {
-               public  /* time_t */      long    actime;   // access time
-               public  /* time_t */      long    modtime;  // modification time
+       public enum EpollOp {
+               EPOLL_CTL_ADD = 1,
+               EPOLL_CTL_DEL = 2,
+               EPOLL_CTL_MOD = 3,
        }
 
+       [StructLayout (LayoutKind.Explicit, Size=12, Pack=1)]
+       [CLSCompliant (false)]
+       public struct EpollEvent {
+               [FieldOffset (0)]
+               public EpollEvents events;
+               [FieldOffset (4)]
+               public int fd;
+               [FieldOffset (4)]
+               public IntPtr ptr;
+               [FieldOffset (4)]
+               public uint u32;
+               [FieldOffset (4)]
+               public ulong u64;
+       }
        #endregion
 
        #region Classes
 
        public sealed class Dirent
+#if NET_2_0
+               : IEquatable <Dirent>
+#endif
        {
                [CLSCompliant (false)]
                public /* ino_t */ ulong  d_ino;
@@ -826,9 +1209,16 @@ namespace Mono.Unix.Native {
                        if (obj == null || GetType() != obj.GetType())
                                return false;
                        Dirent d = (Dirent) obj;
-                       return d.d_ino == d_ino && d.d_off == d_off &&
-                               d.d_reclen == d_reclen && d.d_type == d_type &&
-                               d.d_name == d_name;
+                       return Equals (d);
+               }
+
+               public bool Equals (Dirent value)
+               {
+                       if (value == null)
+                               return false;
+                       return value.d_ino == d_ino && value.d_off == d_off &&
+                               value.d_reclen == d_reclen && value.d_type == d_type &&
+                               value.d_name == d_name;
                }
 
                public override string ToString ()
@@ -848,6 +1238,9 @@ namespace Mono.Unix.Native {
        }
 
        public sealed class Fstab
+#if NET_2_0
+               : IEquatable <Fstab>
+#endif
        {
                public string fs_spec;
                public string fs_file;
@@ -868,11 +1261,18 @@ namespace Mono.Unix.Native {
                {
                        if (obj == null || GetType() != obj.GetType())
                                return false;
-                       Fstab  f = (Fstab) obj;
-                       return f.fs_spec == fs_spec && f.fs_file == fs_file &&
-                               f.fs_vfstype == fs_vfstype && f.fs_mntops == fs_mntops &&
-                               f.fs_type == fs_type && f.fs_freq == fs_freq && 
-                               f.fs_passno == fs_passno;
+                       Fstab f = (Fstab) obj;
+                       return Equals (f);
+               }
+
+               public bool Equals (Fstab value)
+               {
+                       if (value == null)
+                               return false;
+                       return value.fs_spec == fs_spec && value.fs_file == fs_file &&
+                               value.fs_vfstype == fs_vfstype && value.fs_mntops == fs_mntops &&
+                               value.fs_type == fs_type && value.fs_freq == fs_freq && 
+                               value.fs_passno == fs_passno;
                }
 
                public override string ToString ()
@@ -892,6 +1292,9 @@ namespace Mono.Unix.Native {
        }
 
        public sealed class Group
+#if NET_2_0
+               : IEquatable <Group>
+#endif
        {
                public string           gr_name;
                public string           gr_passwd;
@@ -914,18 +1317,25 @@ namespace Mono.Unix.Native {
                        if (obj == null || GetType() != obj.GetType())
                                return false;
                        Group g = (Group) obj;
-                       if (g.gr_gid != gr_gid)
+                       return Equals (g);
+               }
+
+               public bool Equals (Group value)
+               {
+                       if (value == null)
+                               return false;
+                       if (value.gr_gid != gr_gid)
                                return false;
-                       if (g.gr_gid == gr_gid && g.gr_name == gr_name &&
-                               g.gr_passwd == gr_passwd) {
-                               if (g.gr_mem == gr_mem)
+                       if (value.gr_gid == gr_gid && value.gr_name == gr_name &&
+                               value.gr_passwd == gr_passwd) {
+                               if (value.gr_mem == gr_mem)
                                        return true;
-                               if (g.gr_mem == null || gr_mem == null)
+                               if (value.gr_mem == null || gr_mem == null)
                                        return false;
-                               if (g.gr_mem.Length != gr_mem.Length)
+                               if (value.gr_mem.Length != gr_mem.Length)
                                        return false;
                                for (int i = 0; i < gr_mem.Length; ++i)
-                                       if (gr_mem[i] != g.gr_mem[i])
+                                       if (gr_mem[i] != value.gr_mem[i])
                                                return false;
                                return true;
                        }
@@ -936,7 +1346,8 @@ namespace Mono.Unix.Native {
                public override string ToString ()
                {
                        StringBuilder sb = new StringBuilder ();
-                       sb.AppendFormat ("{0}:{1}:{2}:", gr_name, gr_passwd, gr_gid);
+                       sb.Append (gr_name).Append (":").Append (gr_passwd).Append (":");
+                       sb.Append (gr_gid).Append (":");
                        GetMembers (sb, gr_mem);
                        return sb.ToString ();
                }
@@ -963,6 +1374,9 @@ namespace Mono.Unix.Native {
        }
 
        public sealed class Passwd
+#if NET_2_0
+               : IEquatable <Passwd>
+#endif
        {
                public string           pw_name;
                public string           pw_passwd;
@@ -987,9 +1401,17 @@ namespace Mono.Unix.Native {
                        if (obj == null || GetType() != obj.GetType())
                                return false;
                        Passwd p = (Passwd) obj;
-                       return p.pw_uid == pw_uid && p.pw_gid == pw_gid && p.pw_name == pw_name && 
-                               p.pw_passwd == pw_passwd && p.pw_gecos == pw_gecos && 
-                               p.pw_dir == pw_dir && p.pw_shell == pw_shell;
+                       return Equals (p);
+               }
+
+               public bool Equals (Passwd value)
+               {
+                       if (value == null)
+                               return false;
+                       return value.pw_uid == pw_uid && value.pw_gid == pw_gid && 
+                               value.pw_name == pw_name && value.pw_passwd == pw_passwd && 
+                               value.pw_gecos == pw_gecos && value.pw_dir == pw_dir && 
+                               value.pw_shell == pw_shell;
                }
 
                // Generate string in /etc/passwd format
@@ -1010,6 +1432,58 @@ namespace Mono.Unix.Native {
                }
        }
 
+       public sealed class Utsname
+#if NET_2_0
+               : IEquatable <Utsname>
+#endif
+       {
+               public string sysname;
+               public string nodename;
+               public string release;
+               public string version;
+               public string machine;
+               public string domainname;
+
+               public override int GetHashCode ()
+               {
+                       return sysname.GetHashCode () ^ nodename.GetHashCode () ^ 
+                               release.GetHashCode () ^ version.GetHashCode () ^
+                               machine.GetHashCode () ^ domainname.GetHashCode ();
+               }
+
+               public override bool Equals (object obj)
+               {
+                       if (obj == null || GetType() != obj.GetType())
+                               return false;
+                       Utsname u = (Utsname) obj;
+                       return Equals (u);
+               }
+
+               public bool Equals (Utsname value)
+               {
+                       return value.sysname == sysname && value.nodename == nodename && 
+                               value.release == release && value.version == version && 
+                               value.machine == machine && value.domainname == domainname;
+               }
+
+               // Generate string in /etc/passwd format
+               public override string ToString ()
+               {
+                       return string.Format ("{0} {1} {2} {3} {4}",
+                               sysname, nodename, release, version, machine);
+               }
+
+               public static bool operator== (Utsname lhs, Utsname rhs)
+               {
+                       return Object.Equals (lhs, rhs);
+               }
+
+               public static bool operator!= (Utsname lhs, Utsname rhs)
+               {
+                       return !Object.Equals (lhs, rhs);
+               }
+       }
+
        //
        // Convention: Functions *not* part of the standard C library AND part of
        // a POSIX and/or Unix standard (X/Open, SUS, XPG, etc.) go here.
@@ -1125,7 +1599,6 @@ namespace Mono.Unix.Native {
        public sealed class Syscall : Stdlib
        {
                new internal const string LIBC  = "libc";
-                   private  const string CRYPT = "crypt";
 
                private Syscall () {}
 
@@ -1149,7 +1622,11 @@ namespace Mono.Unix.Native {
                //        const void *value, size_t size, int flags);
                [DllImport (MPH, SetLastError=true,
                                EntryPoint="Mono_Posix_Syscall_setxattr")]
-               public static extern int setxattr (string path, string name, byte[] value, ulong size, XattrFlags flags);
+               public static extern int setxattr (
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string path, 
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string name, byte[] value, ulong size, XattrFlags flags);
 
                public static int setxattr (string path, string name, byte [] value, ulong size)
                {
@@ -1171,7 +1648,11 @@ namespace Mono.Unix.Native {
                //                   const void *value, size_t size, int flags);
                [DllImport (MPH, SetLastError=true,
                                EntryPoint="Mono_Posix_Syscall_lsetxattr")]
-               public static extern int lsetxattr (string path, string name, byte[] value, ulong size, XattrFlags flags);
+               public static extern int lsetxattr (
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string path, 
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string name, byte[] value, ulong size, XattrFlags flags);
 
                public static int lsetxattr (string path, string name, byte [] value, ulong size)
                {
@@ -1193,7 +1674,9 @@ namespace Mono.Unix.Native {
                //                   const void *value, size_t size, int flags);
                [DllImport (MPH, SetLastError=true,
                                EntryPoint="Mono_Posix_Syscall_fsetxattr")]
-               public static extern int fsetxattr (int fd, string name, byte[] value, ulong size, XattrFlags flags);
+               public static extern int fsetxattr (int fd, 
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string name, byte[] value, ulong size, XattrFlags flags);
 
                public static int fsetxattr (int fd, string name, byte [] value, ulong size)
                {
@@ -1215,7 +1698,11 @@ namespace Mono.Unix.Native {
                //                      void *value, size_t size);
                [DllImport (MPH, SetLastError=true,
                                EntryPoint="Mono_Posix_Syscall_getxattr")]
-               public static extern long getxattr (string path, string name, byte[] value, ulong size);
+               public static extern long getxattr (
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string path, 
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string name, byte[] value, ulong size);
 
                public static long getxattr (string path, string name, byte [] value)
                {
@@ -1238,7 +1725,11 @@ namespace Mono.Unix.Native {
                //                       void *value, size_t size);
                [DllImport (MPH, SetLastError=true,
                                EntryPoint="Mono_Posix_Syscall_lgetxattr")]
-               public static extern long lgetxattr (string path, string name, byte[] value, ulong size);
+               public static extern long lgetxattr (
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string path, 
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string name, byte[] value, ulong size);
 
                public static long lgetxattr (string path, string name, byte [] value)
                {
@@ -1260,7 +1751,9 @@ namespace Mono.Unix.Native {
                //        ssize_t fgetxattr (int fd, const char *name, void *value, size_t size);
                [DllImport (MPH, SetLastError=true,
                                EntryPoint="Mono_Posix_Syscall_fgetxattr")]
-               public static extern long fgetxattr (int fd, string name, byte[] value, ulong size);
+               public static extern long fgetxattr (int fd, 
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string name, byte[] value, ulong size);
 
                public static long fgetxattr (int fd, string name, byte [] value)
                {
@@ -1282,7 +1775,9 @@ namespace Mono.Unix.Native {
                //        ssize_t listxattr (const char *path, char *list, size_t size);
                [DllImport (MPH, SetLastError=true,
                                EntryPoint="Mono_Posix_Syscall_listxattr")]
-               public static extern long listxattr (string path, byte[] list, ulong size);
+               public static extern long listxattr (
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string path, byte[] list, ulong size);
 
                // Slight modification: returns 0 on success, negative on error
                public static long listxattr (string path, Encoding encoding, out string [] values)
@@ -1299,17 +1794,40 @@ namespace Mono.Unix.Native {
                        if (ret < 0)
                                return (int) ret;
 
-                       string [] output = encoding.GetString (list).Split((char) 0);
-                       values = new string [output.Length - 1];
-                       Array.Copy (output, 0, values, 0, output.Length - 1);
+                       GetValues (list, encoding, out values);
                        return 0;
                }
 
+               public static long listxattr (string path, out string[] values)
+               {
+                       return listxattr (path, UnixEncoding.Instance, out values);
+               }
+
+               private static void GetValues (byte[] list, Encoding encoding, out string[] values)
+               {
+                       int num_values = 0;
+                       for (int i = 0; i < list.Length; ++i)
+                               if (list [i] == 0)
+                                       ++num_values;
+
+                       values = new string [num_values];
+                       num_values = 0;
+                       int str_start = 0;
+                       for (int i = 0; i < list.Length; ++i) {
+                               if (list [i] == 0) {
+                                       values [num_values++] = encoding.GetString (list, str_start, i - str_start);
+                                       str_start = i+1;
+                               }
+                       }
+               }
+
                // llistxattr(2)
                //        ssize_t llistxattr (const char *path, char *list, size_t size);
                [DllImport (MPH, SetLastError=true,
                                EntryPoint="Mono_Posix_Syscall_llistxattr")]
-               public static extern long llistxattr (string path, byte[] list, ulong size);
+               public static extern long llistxattr (
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string path, byte[] list, ulong size);
 
                // Slight modification: returns 0 on success, negative on error
                public static long llistxattr (string path, Encoding encoding, out string [] values)
@@ -1326,12 +1844,15 @@ namespace Mono.Unix.Native {
                        if (ret < 0)
                                return (int) ret;
 
-                       string [] output = encoding.GetString (list).Split((char) 0);
-                       values = new string [output.Length - 1];
-                       Array.Copy (output, 0, values, 0, output.Length - 1);
+                       GetValues (list, encoding, out values);
                        return 0;
                }
 
+               public static long llistxattr (string path, out string[] values)
+               {
+                       return llistxattr (path, UnixEncoding.Instance, out values);
+               }
+
                // flistxattr(2)
                //        ssize_t flistxattr (int fd, char *list, size_t size);
                [DllImport (MPH, SetLastError=true,
@@ -1353,23 +1874,36 @@ namespace Mono.Unix.Native {
                        if (ret < 0)
                                return (int) ret;
 
-                       string [] output = encoding.GetString (list).Split((char) 0);
-                       values = new string [output.Length - 1];
-                       Array.Copy (output, 0, values, 0, output.Length - 1);
+                       GetValues (list, encoding, out values);
                        return 0;
                }
 
+               public static long flistxattr (int fd, out string[] values)
+               {
+                       return flistxattr (fd, UnixEncoding.Instance, out values);
+               }
+
                [DllImport (MPH, SetLastError=true,
                                EntryPoint="Mono_Posix_Syscall_removexattr")]
-               public static extern int removexattr (string path, string name);
+               public static extern int removexattr (
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string path, 
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string name);
 
                [DllImport (MPH, SetLastError=true,
                                EntryPoint="Mono_Posix_Syscall_lremovexattr")]
-               public static extern int lremovexattr (string path, string name);
+               public static extern int lremovexattr (
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string path, 
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string name);
 
                [DllImport (MPH, SetLastError=true,
                                EntryPoint="Mono_Posix_Syscall_fremovexattr")]
-               public static extern int fremovexattr (int fd, string name);
+               public static extern int fremovexattr (int fd, 
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string name);
                #endregion
 
                #region <dirent.h> Declarations
@@ -1404,8 +1938,8 @@ namespace Mono.Unix.Native {
                public static extern int rewinddir (IntPtr dir);
 
                private struct _Dirent {
-                       public /* ino_t */ ulong  d_ino;
-                       public /* off_t */ long   d_off;
+                       [ino_t] public ulong      d_ino;
+                       [off_t] public long       d_off;
                        public ushort             d_reclen;
                        public byte               d_type;
                        public IntPtr             d_name;
@@ -1426,6 +1960,8 @@ namespace Mono.Unix.Native {
                        }
                }
 
+               internal static object readdir_lock = new object ();
+
                [DllImport (MPH, SetLastError=true,
                                EntryPoint="Mono_Posix_Syscall_readdir")]
                private static extern int sys_readdir (IntPtr dir, out _Dirent dentry);
@@ -1433,7 +1969,10 @@ namespace Mono.Unix.Native {
                public static Dirent readdir (IntPtr dir)
                {
                        _Dirent dentry;
-                       int r = sys_readdir (dir, out dentry);
+                       int r;
+                       lock (readdir_lock) {
+                               r = sys_readdir (dir, out dentry);
+                       }
                        if (r != 0)
                                return null;
                        Dirent d = new Dirent ();
@@ -1534,6 +2073,7 @@ namespace Mono.Unix.Native {
                //
                // <fstab.h>  -- COMPLETE
                //
+               [Map]
                private struct _Fstab {
                        public IntPtr fs_spec;
                        public IntPtr fs_file;
@@ -1663,11 +2203,12 @@ namespace Mono.Unix.Native {
                        return setgroups ((ulong) list.Length, list);
                }
 
+               [Map]
                private struct _Group
                {
                        public IntPtr           gr_name;
                        public IntPtr           gr_passwd;
-                       public /* gid_t */ uint gr_gid;
+                       [gid_t] public uint     gr_gid;
                        public int              _gr_nmem_;
                        public IntPtr           gr_mem;
                        public IntPtr           _gr_buf_;
@@ -1835,12 +2376,13 @@ namespace Mono.Unix.Native {
                //
                // SKIPPING: getpw(3): it's dangerous.  Use getpwuid(3) instead.
 
+               [Map]
                private struct _Passwd
                {
                        public IntPtr           pw_name;
                        public IntPtr           pw_passwd;
-                       public /* uid_t */ uint pw_uid;
-                       public /* gid_t */ uint pw_gid;
+                       [uid_t] public uint     pw_uid;
+                       [gid_t] public uint     pw_gid;
                        public IntPtr           pw_gecos;
                        public IntPtr           pw_dir;
                        public IntPtr           pw_shell;
@@ -2092,9 +2634,11 @@ namespace Mono.Unix.Native {
                [DllImport (LIBC, SetLastError=true)]
                public static extern int ttyslot ();
 
-               [DllImport (MPH, SetLastError=true,
-                               EntryPoint="Mono_Posix_Syscall_setkey")]
-               public static extern int setkey (string key);
+               [Obsolete ("This is insecure and should not be used", true)]
+               public static int setkey (string key)
+               {
+                       throw new SecurityException ("crypt(3) has been broken.  Use something more secure.");
+               }
 
                #endregion
 
@@ -2123,6 +2667,48 @@ namespace Mono.Unix.Native {
 
                #endregion
 
+               #region <sys/epoll.h> Declarations
+
+               public static int epoll_create (int size)
+               {
+                       return sys_epoll_create (size);
+               }
+
+               public static int epoll_create (EpollFlags flags)
+               {
+                       return sys_epoll_create1 (flags);
+               }
+
+               public static int epoll_ctl (int epfd, EpollOp op, int fd, EpollEvents events)
+               {
+                       EpollEvent ee = new EpollEvent ();
+                       ee.events = events;
+                       ee.fd = fd;
+
+                       return sys_epoll_ctl (epfd, op, fd, ref ee);
+               }
+
+               public static int epoll_wait (int epfd, EpollEvent [] events, int max_events, int timeout)
+               {
+                       if (events.Length < max_events)
+                               throw new ArgumentOutOfRangeException ("events", "Must refer to at least 'max_events' elements.");
+
+                       return sys_epoll_wait (epfd, events, max_events, timeout);
+               }
+
+               [DllImport (LIBC, SetLastError=true, EntryPoint="epoll_create")]
+               private static extern int sys_epoll_create (int size);
+
+               [DllImport (LIBC, SetLastError=true, EntryPoint="epoll_create1")]
+               private static extern int sys_epoll_create1 (EpollFlags flags);
+
+               [DllImport (LIBC, SetLastError=true, EntryPoint="epoll_ctl")]
+               private static extern int sys_epoll_ctl (int epfd, EpollOp op, int fd, ref EpollEvent ee);
+
+               [DllImport (LIBC, SetLastError=true, EntryPoint="epoll_wait")]
+               private static extern int sys_epoll_wait (int epfd, EpollEvent [] ee, int maxevents, int timeout);
+               #endregion
+               
                #region <sys/mman.h> Declarations
                //
                // <sys/mman.h>
@@ -2375,7 +2961,7 @@ namespace Mono.Unix.Native {
                //
                // <sys/time.h>
                //
-               // TODO: adjtime(), getitimer(2), setitimer(2), lutimes(), futimes()
+               // TODO: adjtime(), getitimer(2), setitimer(2)
 
                [DllImport (MPH, SetLastError=true, 
                                EntryPoint="Mono_Posix_Syscall_gettimeofday")]
@@ -2414,9 +3000,46 @@ namespace Mono.Unix.Native {
 
                [DllImport (MPH, SetLastError=true, 
                                EntryPoint="Mono_Posix_Syscall_utimes")]
-               public static extern int utimes (
+               private static extern int sys_utimes (
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string filename, Timeval[] tvp);
+
+               public static int utimes (string filename, Timeval[] tvp)
+               {
+                       if (tvp != null && tvp.Length != 2) {
+                               SetLastError (Errno.EINVAL);
+                               return -1;
+                       }
+                       return sys_utimes (filename, tvp);
+               }
+
+               [DllImport (MPH, SetLastError=true, 
+                               EntryPoint="Mono_Posix_Syscall_lutimes")]
+               private static extern int sys_lutimes (
                                [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
-                               string filename, ref Timeval tvp);
+                               string filename, Timeval[] tvp);
+
+               public static int lutimes (string filename, Timeval[] tvp)
+               {
+                       if (tvp != null && tvp.Length != 2) {
+                               SetLastError (Errno.EINVAL);
+                               return -1;
+                       }
+                       return sys_lutimes (filename, tvp);
+               }
+
+               [DllImport (MPH, SetLastError=true, 
+                               EntryPoint="Mono_Posix_Syscall_futimes")]
+               private static extern int sys_futimes (int fd, Timeval[] tvp);
+
+               public static int futimes (int fd, Timeval[] tvp)
+               {
+                       if (tvp != null && tvp.Length != 2) {
+                               SetLastError (Errno.EINVAL);
+                               return -1;
+                       }
+                       return sys_futimes (fd, tvp);
+               }
 
                #endregion
 
@@ -2436,7 +3059,49 @@ namespace Mono.Unix.Native {
                // <sys/utsname.h>
                //
 
-               // TODO: uname(2)
+               [Map]
+               private struct _Utsname
+               {
+                       public IntPtr sysname;
+                       public IntPtr nodename;
+                       public IntPtr release;
+                       public IntPtr version;
+                       public IntPtr machine;
+                       public IntPtr domainname;
+                       public IntPtr _buf_;
+               }
+
+               private static void CopyUtsname (ref Utsname to, ref _Utsname from)
+               {
+                       try {
+                               to = new Utsname ();
+                               to.sysname     = UnixMarshal.PtrToString (from.sysname);
+                               to.nodename    = UnixMarshal.PtrToString (from.nodename);
+                               to.release     = UnixMarshal.PtrToString (from.release);
+                               to.version     = UnixMarshal.PtrToString (from.version);
+                               to.machine     = UnixMarshal.PtrToString (from.machine);
+                               to.domainname  = UnixMarshal.PtrToString (from.domainname);
+                       }
+                       finally {
+                               Stdlib.free (from._buf_);
+                               from._buf_ = IntPtr.Zero;
+                       }
+               }
+
+               [DllImport (MPH, SetLastError=true, 
+                               EntryPoint="Mono_Posix_Syscall_uname")]
+               private static extern int sys_uname (out _Utsname buf);
+
+               public static int uname (out Utsname buf)
+               {
+                       _Utsname _buf;
+                       int r = sys_uname (out _buf);
+                       buf = new Utsname ();
+                       if (r == 0) {
+                               CopyUtsname (ref buf, ref _buf);
+                       }
+                       return r;
+               }
 
                #region <sys/wait.h> Declarations
                //
@@ -2600,6 +3265,12 @@ namespace Mono.Unix.Native {
                // <time.h>
                //
 
+               // nanosleep(2)
+               //    int nanosleep(const struct timespec *req, struct timespec *rem);
+               [DllImport (MPH, SetLastError=true,
+                               EntryPoint="Mono_Posix_Syscall_nanosleep")]
+               public static extern int nanosleep (ref Timespec req, ref Timespec rem);
+
                // stime(2)
                //    int stime(time_t *t);
                [DllImport (MPH, SetLastError=true,
@@ -3242,32 +3913,16 @@ namespace Mono.Unix.Native {
                                EntryPoint="Mono_Posix_Syscall_lockf")]
                public static extern int lockf (int fd, LockfCommand cmd, long len);
 
-               internal static object crypt_lock = new object ();
-
-               [DllImport (CRYPT, SetLastError=true, EntryPoint="crypt")]
-               private static extern IntPtr sys_crypt (string key, string salt);
-
+               [Obsolete ("This is insecure and should not be used", true)]
                public static string crypt (string key, string salt)
                {
-                       lock (crypt_lock) {
-                               IntPtr r = sys_crypt (key, salt);
-                               return UnixMarshal.PtrToString (r);
-                       }
+                       throw new SecurityException ("crypt(3) has been broken.  Use something more secure.");
                }
 
-               internal static object encrypt_lock = new object ();
-
-               [DllImport (MPH, SetLastError=true, 
-                               EntryPoint="Mono_Posix_Syscall_encrypt")]
-               private static extern int sys_encrypt ([In, Out] byte[] block, int edflag);
-
+               [Obsolete ("This is insecure and should not be used", true)]
                public static int encrypt (byte[] block, bool decode)
                {
-                       if (block.Length < 64)
-                               throw new ArgumentOutOfRangeException ("block", "Must refer to at least 64 bytes");
-                       lock (encrypt_lock) {
-                               return sys_encrypt (block, decode ? 1 : 0);
-                       }
+                       throw new SecurityException ("crypt(3) has been broken.  Use something more secure.");
                }
 
                // swab(3)