Cleanup in signal.c and related tests
[mono.git] / mcs / class / Mono.Posix / Mono.Unix / UnixPath.cs
index 033212b6d4091ad70b1971cdefad9bde3a737bb7..e577edb74d4508f668dcc99a7bf282508160f843 100644 (file)
@@ -101,6 +101,8 @@ namespace Mono.Unix {
                        int lastDir = path.LastIndexOf (DirectorySeparatorChar);
                        if (lastDir > 0)
                                return path.Substring (0, lastDir);
+                       if (lastDir == 0)
+                               return "/";
                        return "";
                }
 
@@ -207,69 +209,59 @@ namespace Mono.Unix {
 
                // Read the specified symbolic link.  If the file isn't a symbolic link,
                // return null; otherwise, return the contents of the symbolic link.
-               //
-               // readlink(2) is horribly evil, as there is no way to query how big the
-               // symlink contents are.  Consequently, it's trial and error...
                internal static string ReadSymbolicLink (string path)
                {
-                       StringBuilder buf = new StringBuilder (256);
+                       string target = TryReadLink (path);
+                       if (target == null) {
+                               Native.Errno errno = Native.Stdlib.GetLastError ();
+                               if (errno != Native.Errno.EINVAL)
+                                       UnixMarshal.ThrowExceptionForError (errno);
+                       }
+                       return target;
+               }
+
+               public static string TryReadLink (string path)
+               {
+                       byte[] buf = new byte[256];
                        do {
-                               int r = Native.Syscall.readlink (path, buf);
-                               if (r < 0) {
-                                       Native.Errno e;
-                                       switch (e = Native.Stdlib.GetLastError()) {
-                                       case Native.Errno.EINVAL:
-                                               // path isn't a symbolic link
-                                               return null;
-                                       default:
-                                               UnixMarshal.ThrowExceptionForError (e);
-                                               break;
-                                       }
-                               }
-                               else if (r == buf.Capacity) {
-                                       buf.Capacity *= 2;
-                               }
+                               long r = Native.Syscall.readlink (path, buf);
+                               if (r < 0)
+                                       return null;
+                               else if (r == buf.Length)
+                                       buf = new byte[checked (buf.LongLength * 2)];
                                else
-                                       return buf.ToString (0, r);
+                                       return UnixEncoding.Instance.GetString (buf, 0, checked ((int) r));
                        } while (true);
                }
 
-               // Read the specified symbolic link.  If the file isn't a symbolic link,
-               // return null; otherwise, return the contents of the symbolic link.
-               //
-               // readlink(2) is horribly evil, as there is no way to query how big the
-               // symlink contents are.  Consequently, it's trial and error...
-               private static string ReadSymbolicLink (string path, out Native.Errno errno)
+               public static string TryReadLinkAt (int dirfd, string path)
                {
-                       errno = (Native.Errno) 0;
-                       StringBuilder buf = new StringBuilder (256);
+                       byte[] buf = new byte[256];
                        do {
-                               int r = Native.Syscall.readlink (path, buf);
-                               if (r < 0) {
-                                       errno = Native.Stdlib.GetLastError ();
+                               long r = Native.Syscall.readlinkat (dirfd, path, buf);
+                               if (r < 0)
                                        return null;
-                               }
-                               else if (r == buf.Capacity) {
-                                       buf.Capacity *= 2;
-                               }
+                               else if (r == buf.Length)
+                                       buf = new byte[checked (buf.LongLength * 2)];
                                else
-                                       return buf.ToString (0, r);
+                                       return UnixEncoding.Instance.GetString (buf, 0, checked ((int) r));
                        } while (true);
                }
 
-               public static string TryReadLink (string path)
+               public static string ReadLink (string path)
                {
-                       Native.Errno errno;
-                       return ReadSymbolicLink (path, out errno);
+                       string target = TryReadLink (path);
+                       if (target == null)
+                               UnixMarshal.ThrowExceptionForLastError (); 
+                       return target;
                }
 
-               public static string ReadLink (string path)
+               public static string ReadLinkAt (int dirfd, string path)
                {
-                       Native.Errno errno;
-                       path = ReadSymbolicLink (path, out errno);
-                       if (errno != 0)
-                               UnixMarshal.ThrowExceptionForError (errno);
-                       return path;
+                       string target = TryReadLinkAt (dirfd, path);
+                       if (target == null)
+                               UnixMarshal.ThrowExceptionForLastError (); 
+                       return target;
                }
 
                public static bool IsPathRooted (string path)