From f1380f5cda2e29179b538ca74971f2f9b6ebdc65 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Wed, 29 Dec 2004 17:20:25 +0000 Subject: * Syscall.cs: Fix Object.Equals implementations. * UnixPath.cs: New & improved, with Testing! GetRealPath() is changed so that it doesn't walk the entire path looking for symlinks, it just reads the leaf. GetCompletRealPath() walks the entire path resolving symlinks. GetCanonicalPath() added, which "cleans up" a path (removing extraneous "." and ".." entries). * UnixSymbolicLinkInfo.cs: Rename ContentsLength -> MaxContentsSize. svn path=/trunk/mcs/; revision=38158 --- mcs/class/Mono.Posix/Mono.Unix/ChangeLog | 10 ++++++ mcs/class/Mono.Posix/Mono.Unix/Syscall.cs | 16 ++++++--- mcs/class/Mono.Posix/Mono.Unix/UnixPath.cs | 42 +++++++++++++++------- .../Mono.Posix/Mono.Unix/UnixSymbolicLinkInfo.cs | 8 ++--- 4 files changed, 54 insertions(+), 22 deletions(-) (limited to 'mcs/class/Mono.Posix') diff --git a/mcs/class/Mono.Posix/Mono.Unix/ChangeLog b/mcs/class/Mono.Posix/Mono.Unix/ChangeLog index 30d83b0ca3a..35148170042 100644 --- a/mcs/class/Mono.Posix/Mono.Unix/ChangeLog +++ b/mcs/class/Mono.Posix/Mono.Unix/ChangeLog @@ -1,3 +1,13 @@ +2004-12-29 Jonathan Pryor + + * Syscall.cs: Fix Object.Equals implementations. + * UnixPath.cs: New & improved, with Testing! GetRealPath() is changed so + that it doesn't walk the entire path looking for symlinks, it just reads + the leaf. GetCompletRealPath() walks the entire path resolving symlinks. + GetCanonicalPath() added, which "cleans up" a path (removing extraneous + "." and ".." entries). + * UnixSymbolicLinkInfo.cs: Rename ContentsLength -> MaxContentsSize. + 2004-12-28 Jonathan Pryor * UnixFileSystemInfo.cs: Add a link(2) wrapper, CreateLink(). Strictly diff --git a/mcs/class/Mono.Posix/Mono.Unix/Syscall.cs b/mcs/class/Mono.Posix/Mono.Unix/Syscall.cs index 0a16ec25b70..43d9f33b4af 100644 --- a/mcs/class/Mono.Posix/Mono.Unix/Syscall.cs +++ b/mcs/class/Mono.Posix/Mono.Unix/Syscall.cs @@ -838,7 +838,7 @@ namespace Mono.Unix { 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.d_name; + d.d_name == d_name; } public override string ToString () @@ -925,8 +925,14 @@ namespace Mono.Unix { Group g = (Group) obj; if (g.gr_gid != gr_gid) return false; - if (g.gr_gid == gr_gid && g.gr_name == g.gr_name && - g.gr_passwd == g.gr_passwd && g.gr_mem.Length == gr_mem.Length) { + if (g.gr_gid == gr_gid && g.gr_name == gr_name && + g.gr_passwd == gr_passwd) { + if (g.gr_mem == gr_mem) + return true; + if (g.gr_mem == null || gr_mem == null) + return false; + if (g.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]) return false; @@ -989,8 +995,8 @@ namespace Mono.Unix { 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 == p.pw_gecos && - p.pw_dir == p.pw_dir && p.pw_shell == p.pw_shell; + p.pw_passwd == pw_passwd && p.pw_gecos == pw_gecos && + p.pw_dir == pw_dir && p.pw_shell == pw_shell; } // Generate string in /etc/passwd format diff --git a/mcs/class/Mono.Posix/Mono.Unix/UnixPath.cs b/mcs/class/Mono.Posix/Mono.Unix/UnixPath.cs index 679c2c1405a..6503c7a7429 100644 --- a/mcs/class/Mono.Posix/Mono.Unix/UnixPath.cs +++ b/mcs/class/Mono.Posix/Mono.Unix/UnixPath.cs @@ -103,10 +103,7 @@ namespace Mono.Unix { public static string GetFullPath (string path) { path = _GetFullPath (path); - string [] dirs; - int lastIndex; - GetPathComponents (path, out dirs, out lastIndex); - return string.Join ("/", dirs, 0, lastIndex); + return GetCanonicalPath (path); } private static string _GetFullPath (string path) @@ -119,15 +116,25 @@ namespace Mono.Unix { return path; } + public static string GetCanonicalPath (string path) + { + string [] dirs; + int lastIndex; + GetPathComponents (path, out dirs, out lastIndex); + string end = string.Join ("/", dirs, 0, lastIndex); + return IsPathRooted (path) ? "/" + end : end; + } + private static void GetPathComponents (string path, out string[] components, out int lastIndex) { string [] dirs = path.Split (DirectorySeparatorChar); int target = 0; for (int i = 0; i < dirs.Length; ++i) { - if (dirs [i] == "." || (i != 0 && dirs [i] == string.Empty)) continue; + if (dirs [i] == "." || dirs [i] == string.Empty) continue; else if (dirs [i] == "..") { if (target != 0) --target; + else ++target; } else dirs [target++] = dirs [i]; @@ -145,25 +152,32 @@ namespace Mono.Unix { return "/"; } - public static string GetRealPath (string path) + public static string GetCompleteRealPath (string path) { - path = _GetFullPath (path); + if (path == null) + throw new ArgumentNullException ("path"); string [] dirs; int lastIndex; GetPathComponents (path, out dirs, out lastIndex); StringBuilder realPath = new StringBuilder (); - for (int i = 0; i < dirs.Length; ++i) { + if (dirs.Length > 0) { + string dir = IsPathRooted (path) ? "/" : ""; + dir += dirs [0]; + realPath.Append (GetRealPath (dir)); + } + for (int i = 1; i < lastIndex; ++i) { realPath.Append ("/").Append (dirs [i]); - string p = _GetRealPath (realPath.ToString()); + string p = GetRealPath (realPath.ToString()); realPath.Remove (0, realPath.Length); realPath.Append (p); } return realPath.ToString (); } - private static string _GetRealPath (string path) + public static string GetRealPath (string path) { - StringBuilder buf = new StringBuilder (1024); + StringBuilder buf = + new StringBuilder (UnixSymbolicLinkInfo.MaxContentsSize); int r; do { r = Syscall.readlink (path, buf); @@ -178,8 +192,10 @@ namespace Mono.Unix { break; } } - path = buf.ToString (); - } while (r == 0); + string name = buf.ToString (0, r); + path = GetDirectoryName (path) + DirectorySeparatorChar + name; + path = GetCanonicalPath (path); + } while (r >= 0); return path; } diff --git a/mcs/class/Mono.Posix/Mono.Unix/UnixSymbolicLinkInfo.cs b/mcs/class/Mono.Posix/Mono.Unix/UnixSymbolicLinkInfo.cs index ea0336da154..1411410a1a0 100644 --- a/mcs/class/Mono.Posix/Mono.Unix/UnixSymbolicLinkInfo.cs +++ b/mcs/class/Mono.Posix/Mono.Unix/UnixSymbolicLinkInfo.cs @@ -50,7 +50,7 @@ namespace Mono.Unix { } // maximum number of bytes read from the symbolic link - public static readonly int ContentsLength = 1024; + public static readonly int MaxContentsSize = 1024; public UnixFileSystemInfo Contents { get { @@ -108,11 +108,11 @@ namespace Mono.Unix { { // Who came up with readlink(2)? There doesn't seem to be a way to // properly handle it. - StringBuilder sb = new StringBuilder (ContentsLength+1); - int r = Syscall.readlink (FullPath, sb, (ulong) ContentsLength); + StringBuilder sb = new StringBuilder (MaxContentsSize+1); + int r = Syscall.readlink (FullPath, sb, (ulong) MaxContentsSize); if (r == -1) return null; - return sb.ToString().Substring (0, r); + return sb.ToString(0, r); } } } -- cgit v1.2.3