// 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
// 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
}
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
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]
#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;
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 ()
}
public sealed class Fstab
+#if NET_2_0
+ : IEquatable <Fstab>
+#endif
{
public string fs_spec;
public string fs_file;
{
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 ()
}
public sealed class Group
+#if NET_2_0
+ : IEquatable <Group>
+#endif
{
public string gr_name;
public string gr_passwd;
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;
}
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 ();
}
}
public sealed class Passwd
+#if NET_2_0
+ : IEquatable <Passwd>
+#endif
{
public string pw_name;
public string pw_passwd;
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
}
}
+ 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.
public sealed class Syscall : Stdlib
{
new internal const string LIBC = "libc";
- private const string CRYPT = "crypt";
private Syscall () {}
// 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)
{
// 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)
{
// 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)
{
// 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)
{
// 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)
{
// 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)
{
// 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)
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)
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,
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
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;
}
}
+ 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);
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 ();
//
// <fstab.h> -- COMPLETE
//
+ [Map]
private struct _Fstab {
public IntPtr fs_spec;
public IntPtr fs_file;
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_;
//
// 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;
[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
#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>
//
// <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")]
[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
// <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
//
// <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,
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)