* Syscall.cs: Update comment with correct exception type.
authorJonathan Pryor <jpryor@novell.com>
Wed, 8 Jun 2005 14:09:49 +0000 (14:09 -0000)
committerJonathan Pryor <jpryor@novell.com>
Wed, 8 Jun 2005 14:09:49 +0000 (14:09 -0000)
  * UnixConvert.cs: Rename ToFilePermissions(string) to
    FromOctalPermissionString; Add ToOctalPermissionString,
    FromUnixPermissionString, ToUnixPermissionString.
  * UnixMarshal.cs: Remove ErrorMarshal.HaveStrerror_r and
    UnixMarshal.IsErrorDescriptionThreadSafe.  strerror(3) is now thread-safe
    (from managed code, at least).  Update comment.

svn path=/trunk/mcs/; revision=45637

mcs/class/Mono.Posix/Mono.Unix/ChangeLog
mcs/class/Mono.Posix/Mono.Unix/Syscall.cs
mcs/class/Mono.Posix/Mono.Unix/UnixConvert.cs
mcs/class/Mono.Posix/Mono.Unix/UnixMarshal.cs

index d79af366dd165d701041ab1f4a6bec7b38da6032..fdcd8639633a3f94926fdf77b54bef66731b7bef 100644 (file)
@@ -1,3 +1,13 @@
+2005-06-08  Jonathan Pryor <jonpryor@vt.edu>
+
+       * Syscall.cs: Update comment with correct exception type.
+       * UnixConvert.cs: Rename ToFilePermissions(string) to
+         FromOctalPermissionString; Add ToOctalPermissionString,
+         FromUnixPermissionString, ToUnixPermissionString.
+       * UnixMarshal.cs: Remove ErrorMarshal.HaveStrerror_r and
+         UnixMarshal.IsErrorDescriptionThreadSafe.  strerror(3) is now thread-safe
+         (from managed code, at least).  Update comment.
+
 2005-06-07  Jonathan Pryor <jonpryor@vt.edu>
 
        * UnixFileSystemInfo.cs: Don't use lstat(2), use stat(2).  This fits with
index ac6f73e509ab253ea60cd26faec59eb1b54c3ccf..65ea10c00ca7483f7a0892038439bdd78b1b61f4 100644 (file)
@@ -1062,7 +1062,7 @@ namespace Mono.Unix {
        //      Examples: mount(2), umount(2), etc.
        //    - Note: if a platform doesn't support a function AT ALL, the
        //      MonoPosixHelper wrapper won't be compiled, resulting in a
-       //      MissingMethodException.  This is also consistent with a missing 
+       //      EntryPointNotFoundException.  This is also consistent with a missing 
        //      P/Invoke into libc.so.
        //
        public sealed class Syscall : Stdlib
index 95d550ab2f219ad4ef8c3b2ea1adafc7e9d3974c..0b169c2dd6b0f0142b66567e346436cc2e359887 100644 (file)
@@ -892,12 +892,152 @@ namespace Mono.Unix {
                //
 
                // convert from octal representation.
-               public static FilePermissions ToFilePermissions (string value)
+               public static FilePermissions FromOctalPermissionString (string value)
                {
                        uint n = Convert.ToUInt32 (value, 8);
                        return ToFilePermissions (n);
                }
 
+               public static string ToOctalPermissionString (FilePermissions value)
+               {
+                       string s = Convert.ToString ((int) (value & ~FilePermissions.S_IFMT), 8);
+                       return new string ('0', 4-s.Length) + s;
+               }
+
+               public static FilePermissions FromUnixPermissionString (string value)
+               {
+                       if (value == null)
+                               throw new ArgumentNullException ("value");
+                       if (value.Length != 9 && value.Length != 10)
+                               throw new ArgumentException ("value", "must contain 9 or 10 characters");
+
+                       int i = 0;
+                       FilePermissions perms = new FilePermissions ();
+
+                       if (value.Length == 10) {
+                               perms |= GetUnixPermissionDevice (value [i]);
+                               ++i;
+                       }
+
+                       perms |= GetUnixPermissionGroup (
+                               value [i++], FilePermissions.S_IRUSR,
+                               value [i++], FilePermissions.S_IWUSR,
+                               value [i++], FilePermissions.S_IXUSR,
+                               's', 'S', FilePermissions.S_ISUID);
+
+                       perms |= GetUnixPermissionGroup (
+                               value [i++], FilePermissions.S_IRGRP,
+                               value [i++], FilePermissions.S_IWGRP,
+                               value [i++], FilePermissions.S_IXGRP,
+                               's', 'S', FilePermissions.S_ISGID);
+
+                       perms |= GetUnixPermissionGroup (
+                               value [i++], FilePermissions.S_IROTH,
+                               value [i++], FilePermissions.S_IWOTH,
+                               value [i++], FilePermissions.S_IXOTH,
+                               't', 'T', FilePermissions.S_ISVTX);
+
+                       return perms;
+               }
+
+               private static FilePermissions GetUnixPermissionDevice (char value)
+               {
+                       switch (value) {
+                       case 'd': return FilePermissions.S_IFDIR;
+                       case 'c': return FilePermissions.S_IFCHR;
+                       case 'b': return FilePermissions.S_IFBLK;
+                       case '-': return FilePermissions.S_IFREG;
+                       case 'p': return FilePermissions.S_IFIFO;
+                       case 'l': return FilePermissions.S_IFLNK;
+                       case 's': return FilePermissions.S_IFSOCK;
+                       }
+                       throw new ArgumentException ("value", "invalid device specification: " + 
+                               value);
+               }
+
+               private static FilePermissions GetUnixPermissionGroup (
+                       char read, FilePermissions readb, 
+                       char write, FilePermissions writeb, 
+                       char exec, FilePermissions execb,
+                       char xboth, char xbitonly, FilePermissions xbit)
+               {
+                       FilePermissions perms = new FilePermissions ();
+                       if (read == 'r')
+                               perms |= readb;
+                       if (write == 'w')
+                               perms |= writeb;
+                       if (exec == 'x')
+                               perms |= execb;
+                       else if (exec == xbitonly)
+                               perms |= xbit;
+                       else if (exec == xboth)
+                               perms |= (execb | xbit);
+                       return perms;
+               }
+
+               // Create ls(1) drwxrwxrwx permissions display
+               public static string ToUnixPermissionString (FilePermissions value)
+               {
+                       char [] access = new char[] {
+                               '-',            // device
+                               '-', '-', '-',  // owner
+                               '-', '-', '-',  // group
+                               '-', '-', '-',  // other
+                       };
+                       bool have_device = true;
+                       switch (value & FilePermissions.S_IFMT) {
+                               case FilePermissions.S_IFDIR:   access [0] = 'd'; break;
+                               case FilePermissions.S_IFCHR:   access [0] = 'c'; break;
+                               case FilePermissions.S_IFBLK:   access [0] = 'b'; break;
+                               case FilePermissions.S_IFREG:   access [0] = '-'; break;
+                               case FilePermissions.S_IFIFO:   access [0] = 'p'; break;
+                               case FilePermissions.S_IFLNK:   access [0] = 'l'; break;
+                               case FilePermissions.S_IFSOCK:  access [0] = 's'; break;
+                               default:                        have_device = false; break;
+                       }
+                       SetUnixPermissionGroup (value, access, 1, 
+                               FilePermissions.S_IRUSR, FilePermissions.S_IWUSR, FilePermissions.S_IXUSR,
+                               's', 'S', FilePermissions.S_ISUID);
+                       SetUnixPermissionGroup (value, access, 4, 
+                               FilePermissions.S_IRGRP, FilePermissions.S_IWGRP, FilePermissions.S_IXGRP,
+                               's', 'S', FilePermissions.S_ISGID);
+                       SetUnixPermissionGroup (value, access, 7, 
+                               FilePermissions.S_IROTH, FilePermissions.S_IWOTH, FilePermissions.S_IXOTH,
+                               't', 'T', FilePermissions.S_ISVTX);
+                       return have_device 
+                               ? new string (access)
+                               : new string (access, 1, 9);
+               }
+
+               private static void SetUnixPermissionGroup (FilePermissions value,
+                       char[] access, int index,
+                       FilePermissions read, FilePermissions write, FilePermissions exec,
+                       char both, char setonly, FilePermissions setxbit)
+               {
+                       if (UnixFileSystemInfo.IsType (value, read))
+                               access [index] = 'r';
+                       if (UnixFileSystemInfo.IsType (value, write))
+                               access [index+1] = 'w';
+                       access [index+2] = GetSymbolicMode (value, exec, both, setonly, setxbit);
+               }
+
+               // Implement the GNU ls(1) permissions spec; see `info coreutils ls`,
+               // section 10.1.2, the `-l' argument information.
+               private static char GetSymbolicMode (FilePermissions value, 
+                       FilePermissions xbit, char both, char setonly, FilePermissions setxbit)
+               {
+                       bool is_x  = UnixFileSystemInfo.IsType (value, xbit);
+                       bool is_sx = UnixFileSystemInfo.IsType (value, setxbit);
+                       
+                       if (is_x && is_sx)
+                               return both;
+                       if (is_sx)
+                               return setonly;
+                       if (is_x)
+                               return 'x';
+                       return '-';
+               }
+
                public static readonly DateTime LocalUnixEpoch = 
                        new DateTime (1970, 1, 1).ToLocalTime();
 
index 10ba4b21fcc62a339e7018b71b49d25c6a33cdab..c9ba832f18dd4212e31e0d3a785605e8120be2e2 100644 (file)
@@ -51,27 +51,22 @@ namespace Mono.Unix {
        //            using strerror(3).
        //            This should be thread safe, since the check is done within the
        //            class constructor lock.
-       //  Problem:  But if strerror_r() isn't present, we're not thread safe!
-       // Solution:  Tough.  It's still better than nothing.  I think.  
-       //            Check UnixMarshal.IsErrorDescriptionThreadSafe if you need to
-       //            know which error translator is being used.
+       //            Strerror(3) will be thread-safe from managed code, but won't
+       //            be thread-safe between managed & unmanaged code.
        internal class ErrorMarshal
        {
                internal delegate string ErrorTranslator (Error errno);
 
                internal static readonly ErrorTranslator Translate;
-               internal static readonly bool HaveStrerror_r;
 
                static ErrorMarshal ()
                {
                        try {
                                Translate = new ErrorTranslator (strerror_r);
                                Translate (Error.ERANGE);
-                               HaveStrerror_r = true;
                        }
                        catch (EntryPointNotFoundException e) {
                                Translate = new ErrorTranslator (strerror);
-                               HaveStrerror_r = false;
                        }
                }
 
@@ -104,10 +99,6 @@ namespace Mono.Unix {
                        return ErrorMarshal.Translate (errno);
                }
 
-               public static bool IsErrorDescriptionThreadSafe {
-                       get {return ErrorMarshal.HaveStrerror_r;}
-               }
-
                public static IntPtr Alloc (long size)
                {
                        if (size < 0)