2009-09-18 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / class / corlib / System.IO / DirectoryInfo.cs
1 // 
2 // System.IO.DirectoryInfo.cs 
3 //
4 // Authors:
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>
9 //
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)
13 //
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:
21 // 
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 // 
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.
32 //
33
34 using System.Collections;
35 using System.Runtime.InteropServices;
36 using System.Runtime.Serialization;
37 using System.Text;
38 #if NET_2_0 && !NET_2_1
39 using System.Security.AccessControl;
40 #endif
41
42 namespace System.IO {
43         
44         [Serializable]
45 #if NET_2_0
46         [ComVisible (true)]
47 #endif
48         public sealed class DirectoryInfo : FileSystemInfo {
49
50                 private string current;
51                 private string parent;
52         
53                 public DirectoryInfo (string path) : this (path, false)
54                 {
55                 }
56
57                 internal DirectoryInfo (string path, bool simpleOriginalPath)
58                 {
59                         CheckPath (path);
60
61                         FullPath = Path.GetFullPath (path);
62                         if (simpleOriginalPath)
63                                 OriginalPath = Path.GetFileName (path);
64                         else
65                                 OriginalPath = path;
66
67                         Initialize ();
68                 }
69
70                 private DirectoryInfo (SerializationInfo info, StreamingContext context)
71                         : base (info, context)
72                 {
73                         Initialize ();
74                 }
75
76                 void Initialize ()
77                 {
78                         int len = FullPath.Length - 1;
79                         if ((len > 1) && (FullPath [len] == Path.DirectorySeparatorChar))
80                                 len--;
81                         int last = FullPath.LastIndexOf (Path.DirectorySeparatorChar, len);
82                         if ((last == -1) || ((last == 0) && (len == 0))) {
83                                 current = FullPath;
84                                 parent = null;
85                         } else {
86                                 current = FullPath.Substring (last + 1, len - last);
87                                 if (last == 0 && !Environment.IsRunningOnWindows)
88                                         parent = Path.DirectorySeparatorStr;
89                                 else
90                                         parent = FullPath.Substring (0, last);
91                                 // adjust for drives, i.e. a special case for windows
92                                 if (Environment.IsRunningOnWindows) {
93                                         if ((parent.Length == 2) && (parent [1] == ':') && Char.IsLetter (parent [0]))
94                                                 parent += Path.DirectorySeparatorChar;
95                                 }
96                         }
97                 }
98
99                 // properties
100
101                 public override bool Exists {
102                         get {
103                                 Refresh (false);
104
105                                 if (stat.Attributes == MonoIO.InvalidFileAttributes)
106                                         return false;
107
108                                 if ((stat.Attributes & FileAttributes.Directory) == 0)
109                                         return false;
110
111                                 return true;
112                         }
113                 }
114
115                 public override string Name {
116                         get { return current; }
117                 }
118
119                 public DirectoryInfo Parent {
120                         get {
121                                 if ((parent == null) || (parent.Length == 0))
122                                         return null;
123                                 return new DirectoryInfo (parent);
124                         }
125                 }
126
127                 public DirectoryInfo Root {
128                         get {
129                                 string root = Path.GetPathRoot (FullPath);
130                                 if (root == null)
131                                         return null;
132
133                                 return new DirectoryInfo (root);
134                         }
135                 }
136
137                 // creational methods
138
139                 public void Create ()
140                 {
141                         Directory.CreateDirectory (FullPath);
142                 }
143
144                 public DirectoryInfo CreateSubdirectory (string path)
145                 {
146                         CheckPath (path);
147
148                         path = Path.Combine (FullPath, path);
149                         Directory.CreateDirectory (path);
150                         return new DirectoryInfo (path);
151                 }
152
153                 // directory listing methods
154
155                 public FileInfo [] GetFiles ()
156                 {
157                         return GetFiles ("*");
158                 }
159
160                 public FileInfo [] GetFiles (string searchPattern)
161                 {
162                         if (searchPattern == null)
163                                 throw new ArgumentNullException ("searchPattern");
164
165                         string [] names = Directory.GetFiles (FullPath, searchPattern);
166
167                         FileInfo[] infos = new FileInfo [names.Length];
168                         int i = 0;
169                         foreach (string name in names)
170                                 infos [i++] = new FileInfo (name);
171
172                         return infos;
173                 }
174
175                 public DirectoryInfo [] GetDirectories ()
176                 {
177                         return GetDirectories ("*");
178                 }
179
180                 public DirectoryInfo [] GetDirectories (string searchPattern)
181                 {
182                         if (searchPattern == null)
183                                 throw new ArgumentNullException ("searchPattern");
184
185                         string [] names = Directory.GetDirectories (FullPath, searchPattern);
186
187                         DirectoryInfo[] infos = new DirectoryInfo [names.Length];
188                         int i = 0;
189                         foreach (string name in names)
190                                 infos [i++] = new DirectoryInfo (name);
191
192                         return infos;
193                 }
194
195                 public FileSystemInfo [] GetFileSystemInfos ()
196                 {
197                         return GetFileSystemInfos ("*");
198                 }
199
200                 public FileSystemInfo [] GetFileSystemInfos (string searchPattern)
201                 {
202                         if (searchPattern == null)
203                                 throw new ArgumentNullException ("searchPattern");
204
205                         if (!Directory.Exists (FullPath))
206                                 throw new IOException ("Invalid directory");
207                         string [] dirs = Directory.GetDirectories (FullPath, searchPattern);
208                         string [] files = Directory.GetFiles (FullPath, searchPattern);
209
210                         FileSystemInfo[] infos = new FileSystemInfo [dirs.Length + files.Length];
211                         int i = 0;
212                         foreach (string dir in dirs)
213                                 infos [i++] = new DirectoryInfo (dir);
214                         foreach (string file in files)
215                                 infos [i++] = new FileInfo (file);
216
217                         return infos;
218                 }
219
220                 // directory management methods
221
222                 public override void Delete ()
223                 {
224                         Delete (false);
225                 }
226
227                 public void Delete (bool recursive)
228                 {
229                         Directory.Delete (FullPath, recursive);
230                 }
231
232                 public void MoveTo (string destDirName)
233                 {
234                         if (destDirName == null)
235                                 throw new ArgumentNullException ("destDirName");
236                         if (destDirName.Length == 0)
237                                 throw new ArgumentException ("An empty file name is not valid.", "destDirName");
238
239                         Directory.Move (FullPath, Path.GetFullPath (destDirName));
240                 }
241
242                 public override string ToString ()
243                 {
244                         return OriginalPath;
245                 }
246
247 #if NET_2_0
248                 public DirectoryInfo[] GetDirectories (string searchPattern, SearchOption searchOption)
249                 {
250                         switch (searchOption) {
251                         case SearchOption.TopDirectoryOnly:
252                                 return GetDirectories (searchPattern);
253                         case SearchOption.AllDirectories:
254                                 Queue workq = new Queue(GetDirectories(searchPattern));
255                                 Queue doneq = new Queue();
256                                 while (workq.Count > 0)
257                                         {
258                                                 DirectoryInfo cinfo = (DirectoryInfo) workq.Dequeue();
259                                                 DirectoryInfo[] cinfoDirs = cinfo.GetDirectories(searchPattern);
260                                                 foreach (DirectoryInfo i in cinfoDirs) workq.Enqueue(i);
261                                                 doneq.Enqueue(cinfo);
262                                         }
263
264                                 DirectoryInfo[] infos = new DirectoryInfo[doneq.Count];
265                                 doneq.CopyTo(infos, 0);
266                                 return infos;
267                         default:
268                                 string msg = Locale.GetText ("Invalid enum value '{0}' for '{1}'.", searchOption, "SearchOption");
269                                 throw new ArgumentOutOfRangeException ("searchOption", msg);
270                         }
271                 }       
272
273                 internal int GetFilesSubdirs (ArrayList l, string pattern)
274                 {
275                         int count;
276                         FileInfo [] thisdir = null;
277
278                         try {
279                                 thisdir = GetFiles (pattern);
280                         } catch (System.UnauthorizedAccessException){
281                                 return 0;
282                         }
283                         
284                         count = thisdir.Length;
285                         l.Add (thisdir);
286
287                         foreach (DirectoryInfo subdir in GetDirectories ()){
288                                 count += subdir.GetFilesSubdirs (l, pattern);
289                         }
290                         return count;
291                 }
292                 
293                 public FileInfo[] GetFiles (string searchPattern, SearchOption searchOption)
294                 {
295                         switch (searchOption) {
296                         case SearchOption.TopDirectoryOnly:
297                                 return GetFiles (searchPattern);
298                         case SearchOption.AllDirectories: {
299                                 ArrayList groups = new ArrayList ();
300                                 int count = GetFilesSubdirs (groups, searchPattern);
301                                 int current = 0;
302                                 
303                                 FileInfo [] all = new FileInfo [count];
304                                 foreach (FileInfo [] p in groups){
305                                         p.CopyTo (all, current);
306                                         current += p.Length;
307                                 }
308                                 return all;
309                         }
310                         default:
311                                 string msg = Locale.GetText ("Invalid enum value '{0}' for '{1}'.", searchOption, "SearchOption");
312                                 throw new ArgumentOutOfRangeException ("searchOption", msg);
313                         }
314                 }
315 #if !NET_2_1
316                 // access control methods
317
318                 [MonoLimitation ("DirectorySecurity isn't implemented")]
319                 public void Create (DirectorySecurity directorySecurity)
320                 {
321                         if (directorySecurity != null)
322                                 throw new UnauthorizedAccessException ();
323                         Create ();
324                 }
325
326                 [MonoLimitation ("DirectorySecurity isn't implemented")]
327                 public DirectoryInfo CreateSubdirectory (string path, DirectorySecurity directorySecurity)
328                 {
329                         if (directorySecurity != null)
330                                 throw new UnauthorizedAccessException ();
331                         return CreateSubdirectory (path);
332                 }
333
334                 [MonoNotSupported ("DirectorySecurity isn't implemented")]
335                 public DirectorySecurity GetAccessControl ()
336                 {
337                         throw new UnauthorizedAccessException ();
338                 }
339
340                 [MonoNotSupported ("DirectorySecurity isn't implemented")]
341                 public DirectorySecurity GetAccessControl (AccessControlSections includeSections)
342                 {
343                         throw new UnauthorizedAccessException ();
344                 }
345
346                 [MonoLimitation ("DirectorySecurity isn't implemented")]
347                 public void SetAccessControl (DirectorySecurity directorySecurity)
348                 {
349                         if (directorySecurity != null)
350                                 throw new ArgumentNullException ("directorySecurity");
351                         throw new UnauthorizedAccessException ();
352                 }
353 #endif
354 #endif
355         }
356 }