// Copyright (C) 2001 Moonlight Enterprises, All Rights Reserved
// Copyright (C) 2002 Ximian, Inc. (http://www.ximian.com)
// Copyright (C) 2003 Ben Maurer
+// Copyright 2011 Xamarin Inc (http://www.xamarin.com).
//
// Author: Jim Richardson, develop@wtfo-guru.com
// Dan Lewis (dihlewis@yahoo.co.uk)
namespace System.IO {
-#if NET_2_0
[ComVisible (true)]
public static class Path {
[Obsolete ("see GetInvalidPathChars and GetInvalidFileNameChars methods.")]
public static readonly char[] InvalidPathChars;
-#else
- public sealed class Path {
-
- private Path ()
- {
- }
-
- public static readonly char[] InvalidPathChars;
-#endif
public static readonly char AltDirectorySeparatorChar;
public static readonly char DirectorySeparatorChar;
public static readonly char PathSeparator;
string ret = path.Substring (0, nLast);
int l = ret.Length;
- if (l >= 2 && ret [l - 1] == VolumeSeparatorChar)
+ if (l >= 2 && DirectorySeparatorChar == '\\' && ret [l - 1] == VolumeSeparatorChar)
return ret + DirectorySeparatorChar;
+ else if (l == 1 && DirectorySeparatorChar == '\\' && path.Length >= 2 && path [nLast] == VolumeSeparatorChar)
+ return ret + VolumeSeparatorChar;
else {
//
// Important: do not use CanonicalizePath here, use
public static string GetFullPath (string path)
{
string fullpath = InsecureGetFullPath (path);
+
+ SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
+
+#if !NET_2_1
if (SecurityManager.SecurityEnabled) {
new FileIOPermission (FileIOPermissionAccess.PathDiscovery, fullpath).Demand ();
}
+#endif
return fullpath;
}
if ((path [1] != ':') || !Char.IsLetter (path [0]))
return path;
- string current = Directory.GetCurrentDirectory ();
+ string current = Directory.InsecureGetCurrentDirectory ();
// first, only the drive is specified
if (path.Length == 2) {
// then if the current directory is on the same drive
// if the supplied path ends with a separator...
char end = path [path.Length - 1];
+ var canonicalize = true;
if (path.Length >= 2 &&
IsDsc (path [0]) &&
IsDsc (path [1])) {
if (path.Length == 2 || path.IndexOf (path [0], 2) < 0)
- throw new ArgumentException ("UNC pass should be of the form \\\\server\\share.");
+ throw new ArgumentException ("UNC paths should be of the form \\\\server\\share.");
if (path [0] != DirectorySeparatorChar)
path = path.Replace (AltDirectorySeparatorChar, DirectorySeparatorChar);
- path = CanonicalizePath (path);
} else {
- if (!IsPathRooted (path))
- path = Directory.GetCurrentDirectory () + DirectorySeparatorStr + path;
- else if (DirectorySeparatorChar == '\\' &&
+ if (!IsPathRooted (path)) {
+
+ // avoid calling expensive CanonicalizePath when possible
+ if (!Environment.IsRunningOnWindows) {
+ var start = 0;
+ while ((start = path.IndexOf ('.', start)) != -1) {
+ if (++start == path.Length || path [start] == DirectorySeparatorChar || path [start] == AltDirectorySeparatorChar)
+ break;
+ }
+ canonicalize = start > 0;
+ }
+
+ path = Directory.InsecureGetCurrentDirectory() + DirectorySeparatorStr + path;
+ } else if (DirectorySeparatorChar == '\\' &&
path.Length >= 2 &&
IsDsc (path [0]) &&
!IsDsc (path [1])) { // like `\abc\def'
- string current = Directory.GetCurrentDirectory ();
+ string current = Directory.InsecureGetCurrentDirectory();
if (current [1] == VolumeSeparatorChar)
path = current.Substring (0, 2) + path;
else
- path = current.Substring (0, current.IndexOf ('\\', current.IndexOf ("\\\\") + 1));
+ path = current.Substring (0, current.IndexOf ('\\', current.IndexOfOrdinalUnchecked ("\\\\") + 1));
}
- path = CanonicalizePath (path);
}
+
+ if (canonicalize)
+ path = CanonicalizePath (path);
// if the original ended with a [Alt]DirectorySeparatorChar then ensure the full path also ends with one
if (IsDsc (end) && (path [path.Length - 1] != DirectorySeparatorChar))
string path;
Random rnd;
int num = 0;
+ int count = 0;
+
+ SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
rnd = new Random ();
do {
f = new FileStream (path, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.Read,
8192, false, (FileOptions) 1);
}
- catch (SecurityException) {
- // avoid an endless loop
- throw;
+ catch (IOException ex){
+ if (ex.hresult != MonoIO.FileAlreadyExistsHResult || count ++ > 65536)
+ throw;
}
- catch {
+ catch (UnauthorizedAccessException ex) {
+ if (count ++ > 65536)
+ throw new IOException (ex.Message, ex);
}
} while (f == null);
[EnvironmentPermission (SecurityAction.Demand, Unrestricted = true)]
public static string GetTempPath ()
{
+ SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
+
string p = get_temp_path ();
if (p.Length > 0 && p [p.Length - 1] != DirectorySeparatorChar)
return p + DirectorySeparatorChar;
(!dirEqualsVolume && path.Length > 1 && path [1] == VolumeSeparatorChar));
}
-#if NET_2_0
public static char[] GetInvalidFileNameChars ()
{
// return a new array as we do not want anyone to be able to change the values
return sb.ToString ();
}
-#endif
+
// private class methods
private static int findExtension (string path)
AltDirectorySeparatorChar = MonoIO.AltDirectorySeparatorChar;
PathSeparator = MonoIO.PathSeparator;
-#if NET_2_0
// this copy will be modifiable ("by design")
InvalidPathChars = GetInvalidPathChars ();
-#else
- if (Environment.IsRunningOnWindows) {
- InvalidPathChars = new char [15] { '\x00', '\x08', '\x10', '\x11', '\x12', '\x14', '\x15', '\x16',
- '\x17', '\x18', '\x19', '\x22', '\x3C', '\x3E', '\x7C' };
- } else {
- InvalidPathChars = new char [1] { '\x00' };
- }
-#endif
// internal fields
DirectorySeparatorStr = DirectorySeparatorChar.ToString ();
for (int i = 0; i < dirs.Length; i++) {
// WIN32 path components must be trimmed
if (Environment.IsRunningOnWindows)
- dirs[i] = dirs[i].Trim ();
+ dirs[i] = dirs[i].TrimEnd ();
if (dirs[i] == "." || (i != 0 && dirs[i].Length == 0))
continue;
return String.Compare (subset, slast, path, slast, subset.Length - slast) == 0;
}
+
+#if NET_4_0
+ public
+#else
+ internal
+#endif
+ static string Combine (params string [] paths)
+ {
+ if (paths == null)
+ throw new ArgumentNullException ("paths");
+
+ bool need_sep;
+ var ret = new StringBuilder ();
+ int pathsLen = paths.Length;
+ int slen;
+ foreach (var s in paths) {
+ need_sep = false;
+ if (s == null)
+ throw new ArgumentNullException ("One of the paths contains a null value", "paths");
+ if (s.IndexOfAny (InvalidPathChars) != -1)
+ throw new ArgumentException ("Illegal characters in path.");
+
+ pathsLen--;
+ if (IsPathRooted (s))
+ ret.Length = 0;
+
+ ret.Append (s);
+ slen = s.Length;
+ if (slen > 0 && pathsLen > 0) {
+ char p1end = s [slen - 1];
+ if (p1end != DirectorySeparatorChar && p1end != AltDirectorySeparatorChar && p1end != VolumeSeparatorChar)
+ need_sep = true;
+ }
+
+ if (need_sep)
+ ret.Append (DirectorySeparatorStr);
+ }
+
+ return ret.ToString ();
+ }
+
+#if NET_4_0
+ public
+#else
+ internal
+#endif
+ static string Combine (string path1, string path2, string path3)
+ {
+ if (path1 == null)
+ throw new ArgumentNullException ("path1");
+
+ if (path2 == null)
+ throw new ArgumentNullException ("path2");
+
+ if (path3 == null)
+ throw new ArgumentNullException ("path3");
+
+ return Combine (new string [] { path1, path2, path3 });
+ }
+
+#if NET_4_0
+ public
+#else
+ internal
+#endif
+ static string Combine (string path1, string path2, string path3, string path4)
+ {
+ if (path1 == null)
+ throw new ArgumentNullException ("path1");
+
+ if (path2 == null)
+ throw new ArgumentNullException ("path2");
+
+ if (path3 == null)
+ throw new ArgumentNullException ("path3");
+
+ if (path4 == null)
+ throw new ArgumentNullException ("path4");
+
+ return Combine (new string [] { path1, path2, path3, path4 });
+ }
+
+ internal static void Validate (string path)
+ {
+ Validate (path, "path");
+ }
+
+ internal static void Validate (string path, string parameterName)
+ {
+ if (path == null)
+ throw new ArgumentNullException (parameterName);
+ if (String.IsNullOrWhiteSpace (path))
+ throw new ArgumentException (Locale.GetText ("Path is empty"));
+ if (path.IndexOfAny (Path.InvalidPathChars) != -1)
+ throw new ArgumentException (Locale.GetText ("Path contains invalid chars"));
+ if (Environment.IsRunningOnWindows) {
+ int idx = path.IndexOf (':');
+ if (idx >= 0 && idx != 1)
+ throw new ArgumentException (parameterName);
+ }
+ }
}
}