2 // System.IO.DirectoryInfo.cs
5 // Miguel de Icaza, miguel@ximian.com
6 // Jim Richardson, develop@wtfo-guru.com
7 // Dan Lewis, dihlewis@yahoo.co.uk
8 // Sebastien Pouliot <sebastien@ximian.com>
10 // Copyright (C) 2002 Ximian, Inc.
11 // Copyright (C) 2001 Moonlight Enterprises, All Rights Reserved
12 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System.Collections;
35 using System.Collections.Generic;
36 using System.Runtime.InteropServices;
37 using System.Runtime.Serialization;
39 #if !NET_2_1 || MONOTOUCH
40 using System.Security.AccessControl;
47 public sealed class DirectoryInfo : FileSystemInfo {
49 private string current;
50 private string parent;
52 public DirectoryInfo (string path) : this (path, false)
56 internal DirectoryInfo (string path, bool simpleOriginalPath)
60 FullPath = Path.GetFullPath (path);
61 if (simpleOriginalPath)
62 OriginalPath = Path.GetFileName (path);
69 private DirectoryInfo (SerializationInfo info, StreamingContext context)
70 : base (info, context)
77 int len = FullPath.Length - 1;
78 if ((len > 1) && (FullPath [len] == Path.DirectorySeparatorChar))
80 int last = FullPath.LastIndexOf (Path.DirectorySeparatorChar, len);
81 if ((last == -1) || ((last == 0) && (len == 0))) {
85 current = FullPath.Substring (last + 1, len - last);
86 if (last == 0 && !Environment.IsRunningOnWindows)
87 parent = Path.DirectorySeparatorStr;
89 parent = FullPath.Substring (0, last);
90 // adjust for drives, i.e. a special case for windows
91 if (Environment.IsRunningOnWindows) {
92 if ((parent.Length == 2) && (parent [1] == ':') && Char.IsLetter (parent [0]))
93 parent += Path.DirectorySeparatorChar;
100 public override bool Exists {
104 if (stat.Attributes == MonoIO.InvalidFileAttributes)
107 if ((stat.Attributes & FileAttributes.Directory) == 0)
114 public override string Name {
115 get { return current; }
118 public DirectoryInfo Parent {
120 if ((parent == null) || (parent.Length == 0))
122 return new DirectoryInfo (parent);
126 public DirectoryInfo Root {
128 string root = Path.GetPathRoot (FullPath);
132 return new DirectoryInfo (root);
136 // creational methods
138 public void Create ()
140 Directory.CreateDirectory (FullPath);
143 public DirectoryInfo CreateSubdirectory (string path)
147 path = Path.Combine (FullPath, path);
148 Directory.CreateDirectory (path);
149 return new DirectoryInfo (path);
152 // directory listing methods
154 public FileInfo [] GetFiles ()
156 return GetFiles ("*");
159 public FileInfo [] GetFiles (string searchPattern)
161 if (searchPattern == null)
162 throw new ArgumentNullException ("searchPattern");
164 string [] names = Directory.GetFiles (FullPath, searchPattern);
166 FileInfo[] infos = new FileInfo [names.Length];
168 foreach (string name in names)
169 infos [i++] = new FileInfo (name);
174 public DirectoryInfo [] GetDirectories ()
176 return GetDirectories ("*");
179 public DirectoryInfo [] GetDirectories (string searchPattern)
181 if (searchPattern == null)
182 throw new ArgumentNullException ("searchPattern");
184 string [] names = Directory.GetDirectories (FullPath, searchPattern);
186 DirectoryInfo[] infos = new DirectoryInfo [names.Length];
188 foreach (string name in names)
189 infos [i++] = new DirectoryInfo (name);
194 public FileSystemInfo [] GetFileSystemInfos ()
196 return GetFileSystemInfos ("*");
199 public FileSystemInfo [] GetFileSystemInfos (string searchPattern)
201 if (searchPattern == null)
202 throw new ArgumentNullException ("searchPattern");
204 if (!Directory.Exists (FullPath))
205 throw new IOException ("Invalid directory");
206 string [] dirs = Directory.GetDirectories (FullPath, searchPattern);
207 string [] files = Directory.GetFiles (FullPath, searchPattern);
209 FileSystemInfo[] infos = new FileSystemInfo [dirs.Length + files.Length];
211 foreach (string dir in dirs)
212 infos [i++] = new DirectoryInfo (dir);
213 foreach (string file in files)
214 infos [i++] = new FileInfo (file);
219 // directory management methods
221 public override void Delete ()
226 public void Delete (bool recursive)
228 Directory.Delete (FullPath, recursive);
231 public void MoveTo (string destDirName)
233 if (destDirName == null)
234 throw new ArgumentNullException ("destDirName");
235 if (destDirName.Length == 0)
236 throw new ArgumentException ("An empty file name is not valid.", "destDirName");
238 Directory.Move (FullPath, Path.GetFullPath (destDirName));
241 public override string ToString ()
246 #if !NET_2_1 || MONOTOUCH
247 public DirectoryInfo[] GetDirectories (string searchPattern, SearchOption searchOption)
249 switch (searchOption) {
250 case SearchOption.TopDirectoryOnly:
251 return GetDirectories (searchPattern);
252 case SearchOption.AllDirectories:
253 Queue workq = new Queue(GetDirectories(searchPattern));
254 Queue doneq = new Queue();
255 while (workq.Count > 0)
257 DirectoryInfo cinfo = (DirectoryInfo) workq.Dequeue();
258 DirectoryInfo[] cinfoDirs = cinfo.GetDirectories(searchPattern);
259 foreach (DirectoryInfo i in cinfoDirs) workq.Enqueue(i);
260 doneq.Enqueue(cinfo);
263 DirectoryInfo[] infos = new DirectoryInfo[doneq.Count];
264 doneq.CopyTo(infos, 0);
267 string msg = Locale.GetText ("Invalid enum value '{0}' for '{1}'.", searchOption, "SearchOption");
268 throw new ArgumentOutOfRangeException ("searchOption", msg);
272 internal int GetFilesSubdirs (ArrayList l, string pattern)
275 FileInfo [] thisdir = null;
278 thisdir = GetFiles (pattern);
279 } catch (System.UnauthorizedAccessException){
283 count = thisdir.Length;
286 foreach (DirectoryInfo subdir in GetDirectories ()){
287 count += subdir.GetFilesSubdirs (l, pattern);
292 public FileInfo[] GetFiles (string searchPattern, SearchOption searchOption)
294 switch (searchOption) {
295 case SearchOption.TopDirectoryOnly:
296 return GetFiles (searchPattern);
297 case SearchOption.AllDirectories: {
298 ArrayList groups = new ArrayList ();
299 int count = GetFilesSubdirs (groups, searchPattern);
302 FileInfo [] all = new FileInfo [count];
303 foreach (FileInfo [] p in groups){
304 p.CopyTo (all, current);
310 string msg = Locale.GetText ("Invalid enum value '{0}' for '{1}'.", searchOption, "SearchOption");
311 throw new ArgumentOutOfRangeException ("searchOption", msg);
315 // access control methods
317 [MonoLimitation ("DirectorySecurity isn't implemented")]
318 public void Create (DirectorySecurity directorySecurity)
320 if (directorySecurity != null)
321 throw new UnauthorizedAccessException ();
325 [MonoLimitation ("DirectorySecurity isn't implemented")]
326 public DirectoryInfo CreateSubdirectory (string path, DirectorySecurity directorySecurity)
328 if (directorySecurity != null)
329 throw new UnauthorizedAccessException ();
330 return CreateSubdirectory (path);
333 [MonoNotSupported ("DirectorySecurity isn't implemented")]
334 public DirectorySecurity GetAccessControl ()
336 throw new UnauthorizedAccessException ();
339 [MonoNotSupported ("DirectorySecurity isn't implemented")]
340 public DirectorySecurity GetAccessControl (AccessControlSections includeSections)
342 throw new UnauthorizedAccessException ();
345 [MonoLimitation ("DirectorySecurity isn't implemented")]
346 public void SetAccessControl (DirectorySecurity directorySecurity)
348 if (directorySecurity != null)
349 throw new ArgumentNullException ("directorySecurity");
350 throw new UnauthorizedAccessException ();
356 public IEnumerable<DirectoryInfo> EnumerateDirectories ()
358 return EnumerateDirectories ("*", SearchOption.TopDirectoryOnly);
361 public IEnumerable<DirectoryInfo> EnumerateDirectories (string searchPattern)
363 return EnumerateDirectories (searchPattern, SearchOption.TopDirectoryOnly);
366 public IEnumerable<DirectoryInfo> EnumerateDirectories (string searchPattern, SearchOption searchOption)
368 foreach (string name in Directory.EnumerateDirectories (FullPath, searchPattern, searchOption))
369 yield return new DirectoryInfo (name);
372 public IEnumerable<FileInfo> EnumerateFiles ()
374 return EnumerateFiles ("*", SearchOption.TopDirectoryOnly);
377 public IEnumerable<FileInfo> EnumerateFiles (string searchPattern)
379 return EnumerateFiles (searchPattern, SearchOption.TopDirectoryOnly);
382 public IEnumerable<FileInfo> EnumerateFiles (string searchPattern, SearchOption searchOption)
384 foreach (string name in Directory.EnumerateFiles (FullPath, searchPattern, searchOption))
385 yield return new FileInfo (name);
388 public IEnumerable<FileSystemInfo> EnumerateFileSystemInfos ()
390 return EnumerateFileSystemInfos ("*", SearchOption.TopDirectoryOnly);
393 public IEnumerable<FileSystemInfo> EnumerateFileSystemInfos (string searchPattern)
395 return EnumerateFileSystemInfos (searchPattern, SearchOption.TopDirectoryOnly);
398 public IEnumerable<FileSystemInfo> EnumerateFileSystemInfos (string searchPattern, SearchOption searchOption)
400 if (searchPattern == null)
401 throw new ArgumentNullException ("searchPattern");
402 if (searchOption != SearchOption.TopDirectoryOnly && searchOption != SearchOption.AllDirectories)
403 throw new ArgumentOutOfRangeException ("searchoption");
405 return EnumerateFileSystemInfos (FullPath, searchPattern, searchOption);
408 static internal IEnumerable<FileSystemInfo> EnumerateFileSystemInfos (string full, string searchPattern, SearchOption searchOption)
410 string path_with_pattern = Path.Combine (full, searchPattern);
413 FileAttributes rattr;
414 bool subdirs = searchOption == SearchOption.AllDirectories;
416 string s = MonoIO.FindFirst (full, path_with_pattern, out rattr, out error, out handle);
420 throw MonoIO.GetException (Path.GetDirectoryName (path_with_pattern), (MonoIOError) error);
423 if (((rattr & FileAttributes.ReparsePoint) == 0)){
424 if ((rattr & FileAttributes.Directory) != 0)
425 yield return new DirectoryInfo (s);
427 yield return new FileInfo (s);
430 while ((s = MonoIO.FindNext (handle, out rattr, out error)) != null){
431 if ((rattr & FileAttributes.ReparsePoint) != 0)
433 if ((rattr & FileAttributes.Directory) != 0)
434 yield return new DirectoryInfo (s);
436 yield return new FileInfo (s);
438 if (((rattr & FileAttributes.Directory) != 0) && subdirs)
439 foreach (FileSystemInfo child in EnumerateFileSystemInfos (s, searchPattern, searchOption))
443 MonoIO.FindClose (handle);