Add various methods and flags to Syscall
[mono.git] / mcs / class / Mono.Posix / Mono.Unix.Native / Syscall.cs
index 51491d3801428976b529902c3fb7284de45b7ef7..083fb6c40936b97f6f5c93b46802743d012668c7 100644 (file)
@@ -55,6 +55,7 @@
 
 using System;
 using System.Collections;
+using System.Collections.Generic;
 using System.Runtime.InteropServices;
 using System.Security;
 using System.Text;
@@ -148,7 +149,19 @@ namespace Mono.Unix.Native {
                O_DIRECTORY = 0x00010000,
                O_DIRECT    = 0x00004000,
                O_ASYNC     = 0x00002000,
-               O_LARGEFILE = 0x00008000
+               O_LARGEFILE = 0x00008000,
+               O_CLOEXEC   = 0x00080000,
+               O_PATH      = 0x00200000
+       }
+       
+       [Map][Flags]
+       [CLSCompliant (false)]
+       public enum AtFlags : int {
+               AT_SYMLINK_NOFOLLOW = 0x00000100,
+               AT_REMOVEDIR        = 0x00000200,
+               AT_SYMLINK_FOLLOW   = 0x00000400,
+               AT_NO_AUTOMOUNT     = 0x00000800,
+               AT_EMPTY_PATH       = 0x00001000
        }
        
        // mode_t
@@ -1136,6 +1149,14 @@ namespace Mono.Unix.Native {
                }
        }
 
+       [Map ("struct iovec")]
+       public struct Iovec
+       {
+               public IntPtr   iov_base; // Starting address
+               [CLSCompliant (false)]
+               public ulong    iov_len;  // Number of bytes to transfer
+       }
+
        [Flags][Map]
        public enum EpollFlags {
                EPOLL_CLOEXEC = 02000000,
@@ -2004,6 +2025,9 @@ namespace Mono.Unix.Native {
 
                [DllImport (LIBC, SetLastError=true)]
                public static extern int dirfd (IntPtr dir);
+
+               [DllImport (LIBC, SetLastError=true)]
+               public static extern IntPtr fdopendir (int fd);
                #endregion
 
                #region <fcntl.h> Declarations
@@ -2067,6 +2091,40 @@ namespace Mono.Unix.Native {
                [DllImport (MPH, SetLastError=true, 
                                EntryPoint="Mono_Posix_Syscall_posix_fallocate")]
                public static extern int posix_fallocate (int fd, long offset, ulong len);
+
+               [DllImport (LIBC, SetLastError=true, 
+                               EntryPoint="openat")]
+               private static extern int sys_openat (int dirfd,
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string pathname, int flags);
+
+               // openat(2)
+               //    int openat(int dirfd, const char *pathname, int flags, mode_t mode);
+               [DllImport (LIBC, SetLastError=true, 
+                               EntryPoint="openat")]
+               private static extern int sys_openat (int dirfd,
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string pathname, int flags, uint mode);
+
+               public static int openat (int dirfd, string pathname, OpenFlags flags)
+               {
+                       int _flags = NativeConvert.FromOpenFlags (flags);
+                       return sys_openat (dirfd, pathname, _flags);
+               }
+
+               public static int openat (int dirfd, string pathname, OpenFlags flags, FilePermissions mode)
+               {
+                       int _flags = NativeConvert.FromOpenFlags (flags);
+                       uint _mode = NativeConvert.FromFilePermissions (mode);
+                       return sys_openat (dirfd, pathname, _flags, _mode);
+               }
+
+               [DllImport (MPH, SetLastError=true, 
+                               EntryPoint="Mono_Posix_Syscall_get_at_fdcwd")]
+               private static extern int get_at_fdcwd ();
+
+               public static readonly int AT_FDCWD = get_at_fdcwd ();
+
                #endregion
 
                #region <fstab.h> Declarations
@@ -2192,40 +2250,50 @@ namespace Mono.Unix.Native {
                //
                // TODO: putgrent(3), fgetgrent_r(), initgroups(3)
 
-               // getgrouplist(2) 
+               // getgrouplist(2)
                [DllImport (LIBC, SetLastError=true, EntryPoint="getgrouplist")]
-               private static extern int sys_getgrouplist(string user, uint grp, uint [] groups,ref int ngroups);
-        
+               private static extern int sys_getgrouplist (string user, uint grp, uint [] groups,ref int ngroups);
+
                public static Group [] getgrouplist (string username)
                {
-                       if (String.IsNullOrEmpty(username))
-                               return new Group[0];
+                       if (username == null)
+                               throw new ArgumentNullException ("username");
+                       if (username.Trim () == "")
+                               throw new ArgumentException ("Username cannot be empty", "username");
                        // Syscall to getpwnam to retrieve user uid
                        Passwd pw = Syscall.getpwnam (username);
-                       if (pw == null) 
-                               return new Group [0];
-                       // initializing ngroups by 1 to get the group count
-                       int ngroups = 1;
+                       if (pw == null)
+                               throw new ArgumentException (string.Format ("User {0} does not exists",username), "username");
+                       return getgrouplist (pw);
+               }
+
+               public static Group [] getgrouplist (Passwd user)
+               {
+                       if (user == null)
+                               throw new ArgumentNullException ("user");
+                       // initializing ngroups by 16 to get the group count
+                       int ngroups = 8;
                        int res = -1;
                        // allocating buffer to store group uid's
-                       uint [] groups = new uint [ngroups];
+                       uint [] groups=null;
                        do {
-                               res = sys_getgrouplist (username, pw.pw_gid, groups, ref ngroups);
-                               if (res == -1) {
-                                       ngroups *=2;
-                                       Array.Resize(ref groups, ngroups);
-                               }
+                               Array.Resize (ref groups, ngroups*=2);
+                               res = sys_getgrouplist (user.pw_name, user.pw_gid, groups, ref ngroups);
                        }
                        while (res == -1);
-                       Group [] result = new Group [res];
-                       for (int i = 0; i < res; i++) 
-                               result [i] = Syscall.getgrgid (groups [i]);
-                       return result;
+                       List<Group> result = new List<Group> ();
+                       Group gr = null;
+                       for (int i = 0; i < res; i++) {
+                               gr = Syscall.getgrgid (groups [i]);
+                               if (gr != null)
+                                       result.Add (gr);
+                       }
+                       return result.ToArray ();
                }
 
                // setgroups(2)
                //    int setgroups (size_t size, const gid_t *list);
-               [DllImport (MPH, SetLastError=true, 
+               [DllImport (MPH, SetLastError=true,
                                EntryPoint="Mono_Posix_Syscall_setgroups")]
                public static extern int setgroups (ulong size, uint[] list);
 
@@ -2653,6 +2721,12 @@ namespace Mono.Unix.Native {
                        }
                }
 
+               [DllImport (LIBC, SetLastError=true)]
+               public static extern int renameat (int olddirfd,
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string oldpath, int newdirfd,
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string newpath);
                #endregion
 
                #region <stdlib.h> Declarations
@@ -2662,6 +2736,16 @@ namespace Mono.Unix.Native {
                [DllImport (LIBC, SetLastError=true)]
                public static extern int mkstemp (StringBuilder template);
 
+               [DllImport (LIBC, SetLastError=true, EntryPoint="mkdtemp")]
+               private static extern IntPtr sys_mkdtemp (StringBuilder template);
+
+               public static StringBuilder mkdtemp (StringBuilder template)
+               {
+                       if (sys_mkdtemp (template) == IntPtr.Zero)
+                               return null;
+                       return template;
+               }
+
                [DllImport (LIBC, SetLastError=true)]
                public static extern int ttyslot ();
 
@@ -2969,6 +3053,100 @@ namespace Mono.Unix.Native {
                        return sys_mkfifo (pathname, _mode);
                }
 
+               // fchmodat(2)
+               //    int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags);
+               [DllImport (LIBC, SetLastError=true, EntryPoint="fchmodat")]
+               private static extern int sys_fchmodat (int dirfd,
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string pathname, uint mode, int flags);
+
+               public static int fchmodat (int dirfd, string pathname, FilePermissions mode, AtFlags flags)
+               {
+                       uint _mode = NativeConvert.FromFilePermissions (mode);
+                       int _flags = NativeConvert.FromAtFlags (flags);
+                       return sys_fchmodat (dirfd, pathname, _mode, _flags);
+               }
+
+               [DllImport (MPH, SetLastError=true, 
+                               EntryPoint="Mono_Posix_Syscall_fstatat")]
+               public static extern int fstatat (int dirfd,
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string file_name, out Stat buf, AtFlags flags);
+
+               [DllImport (MPH, SetLastError=true, 
+                               EntryPoint="Mono_Posix_Syscall_get_utime_now")]
+               private static extern long get_utime_now ();
+
+               [DllImport (MPH, SetLastError=true, 
+                               EntryPoint="Mono_Posix_Syscall_get_utime_omit")]
+               private static extern long get_utime_omit ();
+
+               public static readonly long UTIME_NOW = get_utime_now ();
+
+               public static readonly long UTIME_OMIT = get_utime_omit ();
+
+               [DllImport (MPH, SetLastError=true, 
+                               EntryPoint="Mono_Posix_Syscall_futimens")]
+               private static extern int sys_futimens (int fd, Timespec[] times);
+
+               public static int futimens (int fd, Timespec[] times)
+               {
+                       if (times != null && times.Length != 2) {
+                               SetLastError (Errno.EINVAL);
+                               return -1;
+                       }
+                       return sys_futimens (fd, times);
+               }
+
+               [DllImport (MPH, SetLastError=true, 
+                               EntryPoint="Mono_Posix_Syscall_utimensat")]
+               private static extern int sys_utimensat (int dirfd,
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string pathname, Timespec[] times, int flags);
+
+               public static int utimensat (int dirfd, string pathname, Timespec[] times, AtFlags flags)
+               {
+                       if (times != null && times.Length != 2) {
+                               SetLastError (Errno.EINVAL);
+                               return -1;
+                       }
+                       int _flags = NativeConvert.FromAtFlags (flags);
+                       return sys_utimensat (dirfd, pathname, times, _flags);
+               }
+
+               // mkdirat(2)
+               //    int mkdirat(int dirfd, const char *pathname, mode_t mode);
+               [DllImport (LIBC, SetLastError=true, EntryPoint="mkdirat")]
+               private static extern int sys_mkdirat (int dirfd,
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string oldpath, uint mode);
+
+               public static int mkdirat (int dirfd, string oldpath, FilePermissions mode)
+               {
+                       uint _mode = NativeConvert.FromFilePermissions (mode);
+                       return sys_mkdirat (dirfd, oldpath, _mode);
+               }
+
+               // mknodat(2)
+               //    int mknodat (int dirfd, const char *pathname, mode_t mode, dev_t dev);
+               [DllImport (MPH, SetLastError=true,
+                               EntryPoint="Mono_Posix_Syscall_mknodat")]
+               public static extern int mknodat (int dirfd,
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string pathname, FilePermissions mode, ulong dev);
+
+               // mkfifoat(3)
+               //    int mkfifoat(int dirfd, const char *pathname, mode_t mode);
+               [DllImport (LIBC, SetLastError=true, EntryPoint="mkfifoat")]
+               private static extern int sys_mkfifoat (int dirfd,
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string pathname, uint mode);
+
+               public static int mkfifoat (int dirfd, string pathname, FilePermissions mode)
+               {
+                       uint _mode = NativeConvert.FromFilePermissions (mode);
+                       return sys_mkfifoat (dirfd, pathname, _mode);
+               }
                #endregion
 
                #region <sys/stat.h> Declarations
@@ -3967,6 +4145,74 @@ namespace Mono.Unix.Native {
                        swab ((IntPtr) from, (IntPtr) to, n);
                }
 
+               [DllImport (LIBC, SetLastError=true, EntryPoint="faccessat")]
+               private static extern int sys_faccessat (int dirfd,
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string pathname, int mode, int flags);
+
+               public static int faccessat (int dirfd, string pathname, AccessModes mode, AtFlags flags)
+               {
+                       int _mode = NativeConvert.FromAccessModes (mode);
+                       int _flags = NativeConvert.FromAtFlags (flags);
+                       return sys_faccessat (dirfd, pathname, _mode, _flags);
+               }
+
+               // fchownat(2)
+               //    int fchownat(int dirfd, const char *path, uid_t owner, gid_t group, int flags);
+               [DllImport (LIBC, SetLastError=true, EntryPoint="fchownat")]
+               private static extern int sys_fchownat (int dirfd,
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string pathname, uint owner, uint group, int flags);
+
+               public static int fchownat (int dirfd, string pathname, uint owner, uint group, AtFlags flags)
+               {
+                       int _flags = NativeConvert.FromAtFlags (flags);
+                       return sys_fchownat (dirfd, pathname, owner, group, _flags);
+               }
+
+               [DllImport (LIBC, SetLastError=true, EntryPoint="linkat")]
+               private static extern int sys_linkat (int olddirfd,
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string oldpath, int newdirfd,
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string newpath, int flags);
+
+               public static int linkat (int olddirfd, string oldpath, int newdirfd, string newpath, AtFlags flags)
+               {
+                       int _flags = NativeConvert.FromAtFlags (flags);
+                       return sys_linkat (olddirfd, oldpath, newdirfd, newpath, _flags);
+               }
+
+               // readlinkat(2)
+               //    int readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsize);
+               [DllImport (MPH, SetLastError=true,
+                               EntryPoint="Mono_Posix_Syscall_readlinkat")]
+               public static extern int readlinkat (int dirfd,
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string pathname, [Out] StringBuilder buf, ulong bufsiz);
+
+               public static int readlinkat (int dirfd, string pathname, [Out] StringBuilder buf)
+               {
+                       return readlinkat (dirfd, pathname, buf, (ulong) buf.Capacity);
+               }
+
+               [DllImport (LIBC, SetLastError=true)]
+               public static extern int symlinkat (
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string oldpath, int dirfd,
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string newpath);
+
+               [DllImport (LIBC, SetLastError=true, EntryPoint="unlinkat")]
+               private static extern int sys_unlinkat (int dirfd,
+                               [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+                               string pathname, int flags);
+
+               public static int unlinkat (int dirfd, string pathname, AtFlags flags)
+               {
+                       int _flags = NativeConvert.FromAtFlags (flags);
+                       return sys_unlinkat (dirfd, pathname, _flags);
+               }
                #endregion
 
                #region <utime.h> Declarations
@@ -3991,6 +4237,56 @@ namespace Mono.Unix.Native {
                        return sys_utime (filename, ref buf, 0);
                }
                #endregion
+
+               #region <sys/uio.h> Declarations
+               //
+               // <sys/uio.h> -- COMPLETE
+               //
+
+               // readv(2)
+               //    ssize_t readv(int fd, const struct iovec *iov, int iovcnt);
+               [DllImport (MPH, SetLastError=true,
+                               EntryPoint="Mono_Posix_Syscall_readv")]
+               private static extern long sys_readv (int fd, Iovec[] iov, int iovcnt);
+
+               public static long readv (int fd, Iovec[] iov)
+               {
+                       return sys_readv (fd, iov, iov.Length);
+               }
+
+               // writev(2)
+               //    ssize_t writev(int fd, const struct iovec *iov, int iovcnt);
+               [DllImport (MPH, SetLastError=true,
+                               EntryPoint="Mono_Posix_Syscall_writev")]
+               private static extern long sys_writev (int fd, Iovec[] iov, int iovcnt);
+
+               public static long writev (int fd, Iovec[] iov)
+               {
+                       return sys_writev (fd, iov, iov.Length);
+               }
+
+               // preadv(2)
+               //    ssize_t preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset);
+               [DllImport (MPH, SetLastError=true,
+                               EntryPoint="Mono_Posix_Syscall_preadv")]
+               private static extern long sys_preadv (int fd, Iovec[] iov, int iovcnt, long offset);
+
+               public static long preadv (int fd, Iovec[] iov, long offset)
+               {
+                       return sys_preadv (fd, iov, iov.Length, offset);
+               }
+
+               // pwritev(2)
+               //    ssize_t pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset);
+               [DllImport (MPH, SetLastError=true,
+                               EntryPoint="Mono_Posix_Syscall_pwritev")]
+               private static extern long sys_pwritev (int fd, Iovec[] iov, int iovcnt, long offset);
+
+               public static long pwritev (int fd, Iovec[] iov, long offset)
+               {
+                       return sys_pwritev (fd, iov, iov.Length, offset);
+               }
+               #endregion
        }
 
        #endregion