X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FMono.Posix%2FMono.Unix.Native%2FSyscall.cs;h=a95c5ee670991e0508aefb0f7fda765e694d9e2f;hb=1afdb2bead4045a55774d96c7b10d35cc6fc7f83;hp=0036b63bcc8349e00e14a9e8509fbce6841e1895;hpb=de5c4842372e787f8245305adbb721960656cc61;p=mono.git diff --git a/mcs/class/Mono.Posix/Mono.Unix.Native/Syscall.cs b/mcs/class/Mono.Posix/Mono.Unix.Native/Syscall.cs index 0036b63bcc8..a95c5ee6709 100644 --- a/mcs/class/Mono.Posix/Mono.Unix.Native/Syscall.cs +++ b/mcs/class/Mono.Posix/Mono.Unix.Native/Syscall.cs @@ -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. @@ -56,29 +56,10 @@ 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 +#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 +#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 +#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 +#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 +#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 +#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 +#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 +#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 +#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 +#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 +#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 +#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 +#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 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 { // // -- 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 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 Declarations // // @@ -2375,7 +2961,7 @@ namespace Mono.Unix.Native { // // // - // 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 { // // - // 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 Declarations // @@ -2600,6 +3265,12 @@ namespace Mono.Unix.Native { // // + // 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)