2 // System.IO.Directory.cs
5 // Jim Richardson (develop@wtfo-guru.com)
6 // Miguel de Icaza (miguel@ximian.com)
7 // Dan Lewis (dihlewis@yahoo.co.uk)
8 // Eduardo Garcia (kiwnix@yahoo.es)
9 // Ville Palo (vi64pa@kolumbus.fi)
11 // Copyright (C) 2001 Moonlight Enterprises, All Rights Reserved
12 // Copyright (C) 2002 Ximian, Inc.
14 // Created: Monday, August 13, 2001
16 //------------------------------------------------------------------------------
19 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
21 // Permission is hereby granted, free of charge, to any person obtaining
22 // a copy of this software and associated documentation files (the
23 // "Software"), to deal in the Software without restriction, including
24 // without limitation the rights to use, copy, modify, merge, publish,
25 // distribute, sublicense, and/or sell copies of the Software, and to
26 // permit persons to whom the Software is furnished to do so, subject to
27 // the following conditions:
29 // The above copyright notice and this permission notice shall be
30 // included in all copies or substantial portions of the Software.
32 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
33 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
34 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
35 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
36 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
37 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
38 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
42 using System.Collections;
43 using System.Security;
44 using System.Security.Permissions;
59 private Directory () {}
62 public static DirectoryInfo CreateDirectory (string path)
65 throw new ArgumentNullException ("path");
68 throw new ArgumentException ("Path is empty");
70 if (path.IndexOfAny (Path.InvalidPathChars) != -1)
71 throw new ArgumentException ("Path contains invalid chars");
73 if (path.Trim ().Length == 0)
74 throw new ArgumentException ("Only blank characters in path");
76 // LAMESPEC: with .net 1.0 version this throw NotSupportedException and msdn says so too
77 // but v1.1 throws ArgumentException.
79 throw new ArgumentException ("Only ':' In path");
81 return CreateDirectoriesInternal (path);
84 static DirectoryInfo CreateDirectoriesInternal (string path)
86 DirectoryInfo info = new DirectoryInfo (path);
87 if (info.Parent != null && !info.Parent.Exists)
88 info.Parent.Create ();
91 if (!MonoIO.CreateDirectory (path, out error)) {
92 // LAMESPEC: 1.1 and 1.2alpha allow CreateDirectory on a file path.
93 // So CreateDirectory ("/tmp/somefile") will succeed if 'somefile' is
94 // not a directory. However, 1.0 will throw an exception.
95 // We behave like 1.0 here (emulating 1.1-like behavior is just a matter
96 // of comparing error to ERROR_FILE_EXISTS, but it's lame to do:
97 // DirectoryInfo di = Directory.CreateDirectory (something);
98 // and having di.Exists return false afterwards.
99 // I hope we don't break anyone's code, as they should be catching
100 // the exception anyway.
101 if (error != MonoIOError.ERROR_ALREADY_EXISTS)
102 throw MonoIO.GetException (path, error);
108 public static void Delete (string path)
111 throw new ArgumentNullException ("path");
114 throw new ArgumentException ("Path is empty");
116 if (path.IndexOfAny (Path.InvalidPathChars) != -1)
117 throw new ArgumentException ("Path contains invalid chars");
119 if (path.Trim().Length == 0)
120 throw new ArgumentException ("Only blank characters in path");
123 throw new NotSupportedException ("Only ':' In path");
127 if (!MonoIO.RemoveDirectory (path, out error)) {
130 * In io-layer/io.c rmdir returns error_file_not_found if directory does not exists.
131 * So maybe this could be handled somewhere else?
133 if (error == MonoIOError.ERROR_FILE_NOT_FOUND)
134 throw new DirectoryNotFoundException ("Directory '" + path + "' doesnt exists.");
136 throw MonoIO.GetException (path, error);
140 static void RecursiveDelete (string path)
142 foreach (string dir in GetDirectories (path))
143 RecursiveDelete (dir);
145 foreach (string file in GetFiles (path))
148 Directory.Delete (path);
151 public static void Delete (string path, bool recurse)
153 CheckPathExceptions (path);
155 if (recurse == false){
160 RecursiveDelete (path);
163 public static bool Exists (string path)
171 exists = MonoIO.ExistsDirectory (path, out error);
172 if (error != MonoIOError.ERROR_SUCCESS &&
173 error != MonoIOError.ERROR_PATH_NOT_FOUND) {
174 throw MonoIO.GetException (path, error);
180 public static DateTime GetLastAccessTime (string path)
182 return File.GetLastAccessTime (path);
185 public static DateTime GetLastAccessTimeUtc (string path)
187 return GetLastAccessTime (path).ToUniversalTime ();
190 public static DateTime GetLastWriteTime (string path)
192 return File.GetLastWriteTime (path);
195 public static DateTime GetLastWriteTimeUtc (string path)
197 return GetLastWriteTime (path).ToUniversalTime ();
200 public static DateTime GetCreationTime (string path)
202 return File.GetCreationTime (path);
205 public static DateTime GetCreationTimeUtc (string path)
207 return GetCreationTime (path).ToUniversalTime ();
210 public static string GetCurrentDirectory ()
214 string result = MonoIO.GetCurrentDirectory (out error);
215 if (error != MonoIOError.ERROR_SUCCESS)
216 throw MonoIO.GetException (error);
218 if ((result != null) && (result.Length > 0) && SecurityManager.SecurityEnabled) {
219 new FileIOPermission (FileIOPermissionAccess.PathDiscovery, result).Demand ();
224 public static string [] GetDirectories (string path)
226 return GetDirectories (path, "*");
229 public static string [] GetDirectories (string path, string pattern)
231 return GetFileSystemEntries (path, pattern, FileAttributes.Directory, FileAttributes.Directory);
234 public static string GetDirectoryRoot (string path)
236 return new String(Path.DirectorySeparatorChar,1);
239 public static string [] GetFiles (string path)
241 return GetFiles (path, "*");
244 public static string [] GetFiles (string path, string pattern)
246 return GetFileSystemEntries (path, pattern, FileAttributes.Directory, 0);
249 public static string [] GetFileSystemEntries (string path)
251 return GetFileSystemEntries (path, "*");
254 public static string [] GetFileSystemEntries (string path, string pattern)
256 return GetFileSystemEntries (path, pattern, 0, 0);
259 public static string[] GetLogicalDrives ()
261 return Environment.GetLogicalDrives ();
264 static bool IsRootDirectory (string path)
267 if (Path.DirectorySeparatorChar == '/' && path == "/")
271 if (Path.DirectorySeparatorChar == '\\')
272 if (path.Length == 3 && path.EndsWith (":\\"))
278 public static DirectoryInfo GetParent (string path)
281 throw new ArgumentNullException ();
282 if (path.IndexOfAny (Path.InvalidPathChars) != -1)
283 throw new ArgumentException ("Path contains invalid characters");
285 throw new ArgumentException ("The Path do not have a valid format");
287 // return null if the path is the root directory
288 if (IsRootDirectory (path))
291 return new DirectoryInfo (Path.GetDirectoryName (path));
294 public static void Move (string src, string dest)
297 throw new ArgumentNullException ("src");
300 throw new ArgumentNullException ("dest");
302 if (src.Trim () == "" || src.IndexOfAny (Path.InvalidPathChars) != -1)
303 throw new ArgumentException ("Invalid source directory name: " + src, "src");
305 if (dest.Trim () == "" || dest.IndexOfAny (Path.InvalidPathChars) != -1)
306 throw new ArgumentException ("Invalid target directory name: " + dest, "dest");
309 throw new IOException ("Source directory cannot be same as a target directory.");
312 throw new IOException (dest + " already exists.");
315 throw new DirectoryNotFoundException (src + " does not exist");
318 if (!MonoIO.MoveFile (src, dest, out error))
319 throw MonoIO.GetException (error);
322 public static void SetCreationTime (string path, DateTime creation_time)
324 File.SetCreationTime (path, creation_time);
327 public static void SetCreationTimeUtc (string path, DateTime creation_time)
329 SetCreationTime (path, creation_time.ToLocalTime ());
332 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
333 public static void SetCurrentDirectory (string path)
336 throw new ArgumentNullException ("path");
337 if (path.Trim () == String.Empty)
338 throw new ArgumentException ("path string must not be an empty string or whitespace string");
343 throw new DirectoryNotFoundException ("Directory \"" +
344 path + "\" not found.");
346 MonoIO.SetCurrentDirectory (path, out error);
347 if (error != MonoIOError.ERROR_SUCCESS)
348 throw MonoIO.GetException (path, error);
351 public static void SetLastAccessTime (string path, DateTime last_access_time)
353 File.SetLastAccessTime (path, last_access_time);
356 public static void SetLastAccessTimeUtc (string path, DateTime last_access_time)
358 SetLastAccessTime (path, last_access_time.ToLocalTime ());
361 public static void SetLastWriteTime (string path, DateTime last_write_time)
363 File.SetLastWriteTime (path, last_write_time);
366 public static void SetLastWriteTimeUtc (string path, DateTime last_write_time)
368 SetLastWriteTime (path, last_write_time.ToLocalTime ());
373 private static void CheckPathExceptions (string path)
376 throw new System.ArgumentNullException("Path is Null");
378 throw new System.ArgumentException("Path is Empty");
379 if (path.Trim().Length == 0)
380 throw new ArgumentException ("Only blank characters in path");
381 if (path.IndexOfAny (Path.InvalidPathChars) != -1)
382 throw new ArgumentException ("Path contains invalid chars");
385 private static string [] GetFileSystemEntries (string path, string pattern, FileAttributes mask, FileAttributes attrs)
390 if (path == null || pattern == null)
391 throw new ArgumentNullException ();
393 if (pattern == String.Empty)
394 return new string [] {};
396 if (path.Trim () == "")
397 throw new ArgumentException ("The Path does not have a valid format");
399 string wild = Path.Combine (path, pattern);
400 string wildpath = Path.GetDirectoryName (wild);
401 if (wildpath.IndexOfAny (Path.InvalidPathChars) != -1)
402 throw new ArgumentException ("Path contains invalid characters");
404 if (wildpath.IndexOfAny (Path.InvalidPathChars) != -1) {
405 if (path.IndexOfAny (SearchPattern.InvalidChars) == -1)
406 throw new ArgumentException ("Path contains invalid characters", "path");
408 throw new ArgumentException ("Pattern contains invalid characters", "pattern");
412 if (!MonoIO.ExistsDirectory (wildpath, out error)) {
413 if (error != MonoIOError.ERROR_PATH_NOT_FOUND)
414 throw MonoIO.GetException (wildpath, error);
416 if (wildpath.IndexOfAny (SearchPattern.WildcardChars) == -1)
417 throw new DirectoryNotFoundException ("Directory '" + wildpath + "' not found.");
419 if (path.IndexOfAny (SearchPattern.WildcardChars) == -1)
420 throw new ArgumentException ("Pattern is invalid", "pattern");
422 throw new ArgumentException ("Path is invalid", "path");
425 find = MonoIO.FindFirstFile (wild, out stat, out error);
426 if (find == MonoIO.InvalidHandle) {
428 case MonoIOError.ERROR_PATH_NOT_FOUND:
429 string message = String.Format ("Could not find a part of the path \"{0}\"",
431 throw new DirectoryNotFoundException (message);
432 case MonoIOError.ERROR_FILE_NOT_FOUND:
433 case MonoIOError.ERROR_NO_MORE_FILES:
434 return new string [0];
437 throw MonoIO.GetException (wildpath, error);
441 ArrayList entries = new ArrayList ();
444 if ((stat.Attributes & mask) == attrs)
445 entries.Add (Path.Combine (wildpath, stat.Name));
446 } while (MonoIO.FindNextFile (find, out stat, out error));
448 MonoIO.FindClose (find, out error);
450 return (string []) entries.ToArray (typeof (string));