// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
+using System.Globalization;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
[ComVisible (true)]
public static class Path {
- [Obsolete ("see GetInvalidPathChars and GetInvalidfileNameChars methods.")]
+ [Obsolete ("see GetInvalidPathChars and GetInvalidFileNameChars methods.")]
public static readonly char[] InvalidPathChars;
#else
public sealed class Path {
// if the supplied path ends with a separator...
char end = path [path.Length - 1];
- bool end_dsc = ((end == DirectorySeparatorChar) || (end == AltDirectorySeparatorChar));
if (path.Length >= 2 &&
IsDsc (path [0]) &&
}
// if the original ended with a [Alt]DirectorySeparatorChar then ensure the full path also ends with one
- if (end_dsc && (path [path.Length - 1] != DirectorySeparatorChar))
+ if (IsDsc (end) && (path [path.Length - 1] != DirectorySeparatorChar))
path += DirectorySeparatorChar;
return path;
// UNC: \\server or \\server\share
// Get server
while (len < path.Length && !IsDsc (path [len])) len++;
+
// Get share
- while (len < path.Length && !IsDsc (path [len])) len++;
+ if (len < path.Length) {
+ len++;
+ while (len < path.Length && !IsDsc (path [len])) len++;
+ }
+
return DirectorySeparatorStr +
DirectorySeparatorStr +
- path.Substring (2).Replace (AltDirectorySeparatorChar, DirectorySeparatorChar);
+ path.Substring (2, len - 2).Replace (AltDirectorySeparatorChar, DirectorySeparatorChar);
} else if (IsDsc (path [0])) {
// path starts with '\' or '/'
return DirectorySeparatorStr;
do {
num = rnd.Next ();
num++;
- path = Path.Combine (GetTempPath(), "tmp" + num.ToString("x"));
+ path = Path.Combine (GetTempPath(), "tmp" + num.ToString("x") + ".tmp");
try {
- f = new FileStream (path, FileMode.CreateNew);
+ f = new FileStream (path, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.Read,
+ 8192, false, (FileOptions) 1);
}
catch (SecurityException) {
// avoid an endless loop
{
// return a new array as we do not want anyone to be able to change the values
if (Environment.IsRunningOnWindows) {
- return new char [36] { '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
+ return new char [36] { '\x22', '\x3C', '\x3E', '\x7C', '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
'\x08', '\x09', '\x0A', '\x0B', '\x0C', '\x0D', '\x0E', '\x0F', '\x10', '\x11', '\x12',
'\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x1A', '\x1B', '\x1C', '\x1D',
- '\x1E', '\x1F', '\x22', '\x3C', '\x3E', '\x7C' };
+ '\x1E', '\x1F' };
} else {
return new char [1] { '\x00' };
}
int i = 0;
rng.GetNonZeroBytes (buffer);
while ((i < buffer.Length) && (sb.Length < 12)) {
- char c = (char)i;
+ char c = (char) buffer [i];
if (Array.IndexOf (invalid, c) == -1)
sb.Append (c);
i++;
dirEqualsVolume = (DirectorySeparatorChar == VolumeSeparatorChar);
}
-
- static string CanonicalizePath (string path) {
-
+ static bool SameRoot (string root, string path)
+ {
+ // compare root - if enough details are available
+ if ((root.Length < 2) || (path.Length < 2))
+ return false;
+ // same volume/drive
+ if (!root [0].Equals (path [0]))
+ return false;
+ // presence if the separator
+ if (path[1] != Path.VolumeSeparatorChar)
+ return false;
+ if ((root.Length > 2) && (path.Length > 2)) {
+ // but don't directory compare the directory separator
+ return (IsDsc (root[2]) && IsDsc (path[2]));
+ }
+ return true;
+ }
+
+ static string CanonicalizePath (string path)
+ {
// STEP 1: Check for empty string
- if (path == null) return path;
+ if (path == null)
+ return path;
if (Environment.IsRunningOnWindows)
path = path.Trim ();
- if (path == String.Empty) return path;
-
+ if (path.Length == 0)
+ return path;
+
// STEP 2: Check to see if this is only a root
- string root = GetPathRoot (path);
+ string root = Path.GetPathRoot (path);
// it will return '\' for path '\', while it should return 'c:\' or so.
// Note: commenting this out makes the ened for the (target == 1...) check in step 5
//if (root == path) return path;
-
+
// STEP 3: split the directories, this gets rid of consecutative "/"'s
- string [] dirs = path.Split (DirectorySeparatorChar, AltDirectorySeparatorChar);
+ string[] dirs = path.Split (Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
// STEP 4: Get rid of directories containing . and ..
int target = 0;
-
+
for (int i = 0; i < dirs.Length; i++) {
- if (dirs [i] == "." || (i != 0 && dirs [i] == String.Empty)) continue;
- else if (dirs [i] == "..") {
- if (target != 0) target--;
- }
- else
- dirs [target++] = dirs [i];
+ if (dirs[i] == "." || (i != 0 && dirs[i].Length == 0))
+ continue;
+ else if (dirs[i] == "..") {
+ if (target != 0)
+ target--;
+ } else
+ dirs[target++] = dirs[i];
}
// STEP 5: Combine everything.
- if (target == 0 || (target == 1 && dirs [0] == ""))
+ if (target == 0 || (target == 1 && dirs[0] == ""))
return root;
else {
string ret = String.Join (DirectorySeparatorStr, dirs, 0, target);
- switch (DirectorySeparatorChar) {
- case '\\': // Windows
+ if (Environment.IsRunningOnWindows) {
+ if (!SameRoot (root, ret))
+ ret = root + ret;
// In GetFullPath(), it is assured that here never comes UNC. So this must only applied to such path that starts with '\', without drive specification.
- if (path [0] != DirectorySeparatorChar && path.StartsWith (root)) {
+ if (!IsDsc (path[0]) && SameRoot (root, path)) {
if (ret.Length <= 2 && !ret.EndsWith (DirectorySeparatorStr)) // '\' after "c:"
- ret += DirectorySeparatorChar;
+ ret += Path.DirectorySeparatorChar;
return ret;
} else {
string current = Directory.GetCurrentDirectory ();
- if (current.Length > 1 && current [1] == VolumeSeparatorChar) {
+ if (current.Length > 1 && current[1] == Path.VolumeSeparatorChar) {
// DOS local file path
- if (ret.Length == 0 || IsDsc (ret [0]))
+ if (ret.Length == 0 || IsDsc (ret[0]))
ret += '\\';
return current.Substring (0, 2) + ret;
- }
- else if (IsDsc (current [current.Length - 1]) && IsDsc (ret [0]))
+ } else if (IsDsc (current[current.Length - 1]) && IsDsc (ret[0]))
return current + ret.Substring (1);
else
return current + ret;
}
- default: // Unix/Mac
- return ret;
}
+ return ret;
+ }
+ }
+
+ // required for FileIOPermission (and most proibably reusable elsewhere too)
+ // both path MUST be "full paths"
+ static internal bool IsPathSubsetOf (string subset, string path)
+ {
+ if (subset.Length > path.Length)
+ return false;
+
+ // check that everything up to the last separator match
+ int slast = subset.LastIndexOfAny (PathSeparatorChars);
+ if (String.Compare (subset, 0, path, 0, slast) != 0)
+ return false;
+
+ slast++;
+ // then check if the last segment is identical
+ int plast = path.IndexOfAny (PathSeparatorChars, slast);
+ if (plast >= slast) {
+ return String.Compare (subset, slast, path, slast, path.Length - plast) == 0;
}
+ if (subset.Length != path.Length)
+ return false;
+
+ return String.Compare (subset, slast, path, slast, subset.Length - slast) == 0;
}
}
}