Merge pull request #2721 from ludovic-henry/fix-mono_ms_ticks
[mono.git] / mcs / class / corlib / System.IO / Directory.cs
1 // 
2 // System.IO.Directory.cs 
3 //
4 // Authors:
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)
10 //
11 // Copyright (C) 2001 Moonlight Enterprises, All Rights Reserved
12 // Copyright (C) 2002 Ximian, Inc.
13 // 
14 // Created:        Monday, August 13, 2001 
15 //
16 //------------------------------------------------------------------------------
17
18 //
19 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
20 //
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:
28 // 
29 // The above copyright notice and this permission notice shall be
30 // included in all copies or substantial portions of the Software.
31 // 
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.
39 //
40
41 using System.Collections;
42 using System.Collections.Generic;
43 using System.Security;
44 using System.Security.Permissions;
45 using System.Text;
46 using System.Runtime.InteropServices;
47 using System.Security.AccessControl;
48
49 namespace System.IO
50 {
51         [ComVisible (true)]
52         public static class Directory
53         {
54
55                 public static DirectoryInfo CreateDirectory (string path)
56                 {
57                         if (path == null)
58                                 throw new ArgumentNullException ("path");
59                         
60                         if (path.Length == 0)
61                                 throw new ArgumentException ("Path is empty");
62                         
63                         if (path.IndexOfAny (Path.InvalidPathChars) != -1)
64                                 throw new ArgumentException ("Path contains invalid chars");
65
66                         if (path.Trim ().Length == 0)
67                                 throw new ArgumentException ("Only blank characters in path");
68
69                         // after validations but before File.Exists to avoid an oracle
70                         SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
71
72                         if (File.Exists(path))
73                                 throw new IOException ("Cannot create " + path + " because a file with the same name already exists.");
74                         
75                         if (Environment.IsRunningOnWindows && path == ":")
76                                 throw new ArgumentException ("Only ':' In path");
77                         
78                         return CreateDirectoriesInternal (path);
79                 }
80
81                 [MonoLimitation ("DirectorySecurity not implemented")]
82                 public static DirectoryInfo CreateDirectory (string path, DirectorySecurity directorySecurity)
83                 {
84                         return(CreateDirectory (path));
85                 }
86
87                 static DirectoryInfo CreateDirectoriesInternal (string path)
88                 {
89 #if !NET_2_1
90                         if (SecurityManager.SecurityEnabled) {
91                                 new FileIOPermission (FileIOPermissionAccess.Read | FileIOPermissionAccess.Write, path).Demand ();
92                         }
93 #endif
94                         DirectoryInfo info = new DirectoryInfo (path, true);
95                         if (info.Parent != null && !info.Parent.Exists)
96                                  info.Parent.Create ();
97
98                         MonoIOError error;
99                         if (!MonoIO.CreateDirectory (info.FullName, out error)) {
100                                 // LAMESPEC: 1.1 and 1.2alpha allow CreateDirectory on a file path.
101                                 // So CreateDirectory ("/tmp/somefile") will succeed if 'somefile' is
102                                 // not a directory. However, 1.0 will throw an exception.
103                                 // We behave like 1.0 here (emulating 1.1-like behavior is just a matter
104                                 // of comparing error to ERROR_FILE_EXISTS, but it's lame to do:
105                                 //    DirectoryInfo di = Directory.CreateDirectory (something);
106                                 // and having di.Exists return false afterwards.
107                                 // I hope we don't break anyone's code, as they should be catching
108                                 // the exception anyway.
109                                 if (error != MonoIOError.ERROR_ALREADY_EXISTS &&
110                                     error != MonoIOError.ERROR_FILE_EXISTS)
111                                         throw MonoIO.GetException (path, error);
112                         }
113
114                         return info;
115                 }
116                 
117                 public static void Delete (string path)
118                 {
119                         Path.Validate (path);
120
121                         if (Environment.IsRunningOnWindows && path == ":")
122                                 throw new NotSupportedException ("Only ':' In path");
123
124                         SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
125
126                         MonoIOError error;
127                         bool success;
128                         
129                         if (MonoIO.ExistsSymlink (path, out error)) {
130                                 /* RemoveDirectory maps to rmdir()
131                                  * which fails on symlinks (ENOTDIR)
132                                  */
133                                 success = MonoIO.DeleteFile (path, out error);
134                         } else {
135                                 success = MonoIO.RemoveDirectory (path, out error);
136                         }
137                         
138                         if (!success) {
139                                 /*
140                                  * FIXME:
141                                  * In io-layer/io.c rmdir returns error_file_not_found if directory does not exist.
142                                  * So maybe this could be handled somewhere else?
143                                  */
144                                 if (error == MonoIOError.ERROR_FILE_NOT_FOUND) {
145                                         if (File.Exists (path))
146                                                 throw new IOException ("Directory does not exist, but a file of the same name exists.");
147                                         else
148                                                 throw new DirectoryNotFoundException ("Directory does not exist.");
149                                 } else
150                                         throw MonoIO.GetException (path, error);
151                         }
152                 }
153
154                 static void RecursiveDelete (string path)
155                 {
156                         MonoIOError error;
157                         
158                         foreach (string dir in GetDirectories (path)) {
159                                 if (MonoIO.ExistsSymlink (dir, out error)) {
160                                         MonoIO.DeleteFile (dir, out error);
161                                 } else {
162                                         RecursiveDelete (dir);
163                                 }
164                         }
165
166                         foreach (string file in GetFiles (path))
167                                 File.Delete (file);
168
169                         Directory.Delete (path);
170                 }
171                 
172                 public static void Delete (string path, bool recursive)
173                 {
174                         Path.Validate (path);                   
175                         SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
176
177                         if (recursive)
178                                 RecursiveDelete (path);
179                         else
180                                 Delete (path);
181                 }
182
183                 public static bool Exists (string path)
184                 {
185                         if (path == null)
186                                 return false;
187
188                         // on Moonlight this does not throw but returns false
189                         if (!SecurityManager.CheckElevatedPermissions ())
190                                 return false;
191                                 
192                         MonoIOError error;
193                         bool exists;
194                         
195                         exists = MonoIO.ExistsDirectory (path, out error);
196                         /* This should not throw exceptions */
197                         return exists;
198                 }
199
200                 public static DateTime GetLastAccessTime (string path)
201                 {
202                         return File.GetLastAccessTime (path);
203                 }
204
205                 public static DateTime GetLastAccessTimeUtc (string path)
206                 {
207                         return GetLastAccessTime (path).ToUniversalTime ();
208                 }
209
210                 public static DateTime GetLastWriteTime (string path)
211                 {
212                         return File.GetLastWriteTime (path);
213                 }
214                 
215                 public static DateTime GetLastWriteTimeUtc (string path)
216                 {
217                         return GetLastWriteTime (path).ToUniversalTime ();
218                 }
219
220                 public static DateTime GetCreationTime (string path)
221                 {
222                         return File.GetCreationTime (path);
223                 }
224
225                 public static DateTime GetCreationTimeUtc (string path)
226                 {
227                         return GetCreationTime (path).ToUniversalTime ();
228                 }
229
230                 public static string GetCurrentDirectory ()
231                 {
232                         SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
233
234                         string result = InsecureGetCurrentDirectory();
235 #if !NET_2_1
236                         if ((result != null) && (result.Length > 0) && SecurityManager.SecurityEnabled) {
237                                 new FileIOPermission (FileIOPermissionAccess.PathDiscovery, result).Demand ();
238                         }
239 #endif
240                         return result;
241                 }
242
243                 internal static string InsecureGetCurrentDirectory()
244                 {
245                         MonoIOError error;
246                         string result = MonoIO.GetCurrentDirectory(out error);
247
248                         if (error != MonoIOError.ERROR_SUCCESS)
249                                 throw MonoIO.GetException(error);
250
251                         return result;
252                 }
253                 
254                 public static string [] GetDirectories (string path)
255                 {
256                         return GetDirectories (path, "*");
257                 }
258                 
259                 public static string [] GetDirectories (string path, string searchPattern)
260                 {
261                         return GetFileSystemEntries (path, searchPattern, FileAttributes.Directory, FileAttributes.Directory);
262                 }
263                 
264                 public static string [] GetDirectories (string path, string searchPattern, SearchOption searchOption)
265                 {
266                         if (searchOption == SearchOption.TopDirectoryOnly)
267                                 return GetDirectories (path, searchPattern);
268                         var all = new List<string> ();
269                         GetDirectoriesRecurse (path, searchPattern, all);
270                         return all.ToArray ();
271                 }
272                 
273                 static void GetDirectoriesRecurse (string path, string searchPattern, List<string> all)
274                 {
275                         all.AddRange (GetDirectories (path, searchPattern));
276                         foreach (string dir in GetDirectories (path))
277                                 GetDirectoriesRecurse (dir, searchPattern, all);
278                 }
279
280                 public static string GetDirectoryRoot (string path)
281                 {
282                         Path.Validate (path);                   
283                         SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
284
285                         // FIXME nice hack but that does not work under windows
286                         return new String(Path.DirectorySeparatorChar,1);
287                 }
288                 
289                 public static string [] GetFiles (string path)
290                 {
291                         return GetFiles (path, "*");
292                 }
293                 
294                 public static string [] GetFiles (string path, string searchPattern)
295                 {
296                         return GetFileSystemEntries (path, searchPattern, FileAttributes.Directory, 0);
297                 }
298
299                 public static string[] GetFiles (string path, string searchPattern, SearchOption searchOption)
300                 {
301                         if (searchOption == SearchOption.TopDirectoryOnly)
302                                 return GetFiles (path, searchPattern);
303                         var all = new List<string> ();
304                         GetFilesRecurse (path, searchPattern, all);
305                         return all.ToArray ();
306                 }
307                 
308                 static void GetFilesRecurse (string path, string searchPattern, List<string> all)
309                 {
310                         all.AddRange (GetFiles (path, searchPattern));
311                         foreach (string dir in GetDirectories (path))
312                                 GetFilesRecurse (dir, searchPattern, all);
313                 }
314
315                 public static string [] GetFileSystemEntries (string path)
316                 {
317                         return GetFileSystemEntries (path, "*");
318                 }
319
320                 public static string [] GetFileSystemEntries (string path, string searchPattern)
321                 {
322                         return GetFileSystemEntries (path, searchPattern, 0, 0);
323                 }
324                 
325                 public static string[] GetLogicalDrives ()
326                 { 
327                         return Environment.GetLogicalDrives ();
328                 }
329
330                 static bool IsRootDirectory (string path)
331                 {
332                         // Unix
333                         if (Path.DirectorySeparatorChar == '/' && path == "/")
334                                 return true;
335
336                         // Windows
337                         if (Path.DirectorySeparatorChar == '\\')
338                                 if (path.Length == 3 && path.EndsWith (":\\"))
339                                         return true;
340
341                         return false;
342                 }
343
344                 public static DirectoryInfo GetParent (string path)
345                 {
346                         Path.Validate (path);                   
347
348                         // return null if the path is the root directory
349                         if (IsRootDirectory (path))
350                                 return null;
351
352                         string parent_name = Path.GetDirectoryName (path);
353                         if (parent_name.Length == 0)
354                                 parent_name = GetCurrentDirectory();
355
356                         return new DirectoryInfo (parent_name);
357                 }
358
359                 public static void Move (string sourceDirName, string destDirName)
360                 {
361                         if (sourceDirName == null)
362                                 throw new ArgumentNullException ("sourceDirName");
363
364                         if (destDirName == null)
365                                 throw new ArgumentNullException ("destDirName");
366
367                         if (sourceDirName.Trim ().Length == 0 || sourceDirName.IndexOfAny (Path.InvalidPathChars) != -1)
368                                 throw new ArgumentException ("Invalid source directory name: " + sourceDirName, "sourceDirName");
369
370                         if (destDirName.Trim ().Length == 0 || destDirName.IndexOfAny (Path.InvalidPathChars) != -1)
371                                 throw new ArgumentException ("Invalid target directory name: " + destDirName, "destDirName");
372
373                         if (sourceDirName == destDirName)
374                                 throw new IOException ("Source and destination path must be different.");
375
376                         SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
377
378                         if (Exists (destDirName))
379                                 throw new IOException (destDirName + " already exists.");
380
381                         if (!Exists (sourceDirName) && !File.Exists (sourceDirName))
382                                 throw new DirectoryNotFoundException (sourceDirName + " does not exist");
383
384                         MonoIOError error;
385                         if (!MonoIO.MoveFile (sourceDirName, destDirName, out error))
386                                 throw MonoIO.GetException (error);
387                 }
388
389                 public static void SetAccessControl (string path, DirectorySecurity directorySecurity)
390                 {
391                         if (null == directorySecurity)
392                                 throw new ArgumentNullException ("directorySecurity");
393                                 
394                         directorySecurity.PersistModifications (path);
395                 }
396
397                 public static void SetCreationTime (string path, DateTime creationTime)
398                 {
399                         File.SetCreationTime (path, creationTime);
400                 }
401
402                 public static void SetCreationTimeUtc (string path, DateTime creationTimeUtc)
403                 {
404                         SetCreationTime (path, creationTimeUtc.ToLocalTime ());
405                 }
406
407                 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
408                 public static void SetCurrentDirectory (string path)
409                 {
410                         if (path == null)
411                                 throw new ArgumentNullException ("path");
412                         if (path.Trim ().Length == 0)
413                                 throw new ArgumentException ("path string must not be an empty string or whitespace string");
414
415                         MonoIOError error;
416                                 
417                         if (!Exists (path))
418                                 throw new DirectoryNotFoundException ("Directory \"" +
419                                                                         path + "\" not found.");
420
421                         MonoIO.SetCurrentDirectory (path, out error);
422                         if (error != MonoIOError.ERROR_SUCCESS)
423                                 throw MonoIO.GetException (path, error);
424                 }
425
426                 public static void SetLastAccessTime (string path, DateTime lastAccessTime)
427                 {
428                         File.SetLastAccessTime (path, lastAccessTime);
429                 }
430
431                 public static void SetLastAccessTimeUtc (string path, DateTime lastAccessTimeUtc)
432                 {
433                         SetLastAccessTime (path, lastAccessTimeUtc.ToLocalTime ());
434                 }
435
436                 public static void SetLastWriteTime (string path, DateTime lastWriteTime)
437                 {
438                         File.SetLastWriteTime (path, lastWriteTime);
439                 }
440
441                 public static void SetLastWriteTimeUtc (string path, DateTime lastWriteTimeUtc)
442                 {
443                         SetLastWriteTime (path, lastWriteTimeUtc.ToLocalTime ());
444                 }
445
446                 // private
447                 
448                 // Does the common validation, searchPattern has already been checked for not-null
449                 static string ValidateDirectoryListing (string path, string searchPattern, out bool stop)
450                 {
451                         Path.Validate (path);
452
453                         string wild = Path.Combine (path, searchPattern);
454                         string wildpath = Path.GetDirectoryName (wild);
455                         if (wildpath.IndexOfAny (Path.InvalidPathChars) != -1)
456                                 throw new ArgumentException ("Pattern contains invalid characters", "pattern");
457
458                         MonoIOError error;
459                         if (!MonoIO.ExistsDirectory (wildpath, out error)) {
460                                 if (error == MonoIOError.ERROR_SUCCESS) {
461                                         MonoIOError file_error;
462                                         if (MonoIO.ExistsFile (wildpath, out file_error))
463                                                 throw new IOException ("The directory name is invalid.");
464                                 }
465
466                                 if (error != MonoIOError.ERROR_PATH_NOT_FOUND)
467                                         throw MonoIO.GetException (wildpath, error);
468
469                                 if (wildpath.IndexOfAny (SearchPattern.WildcardChars) == -1)
470                                         throw new DirectoryNotFoundException ("Directory '" + wildpath + "' not found.");
471
472                                 if (path.IndexOfAny (SearchPattern.WildcardChars) == -1)
473                                         throw new ArgumentException ("Pattern is invalid", "searchPattern");
474
475                                 throw new ArgumentException ("Path is invalid", "path");
476                         }
477
478                         stop = false;
479                         return wild;
480                 }
481                 
482                 private static string [] GetFileSystemEntries (string path, string searchPattern, FileAttributes mask, FileAttributes attrs)
483                 {
484                         if (searchPattern == null)
485                                 throw new ArgumentNullException ("searchPattern");
486                         if (searchPattern.Length == 0)
487                                 return new string [] {};
488                         bool stop;
489                         string path_with_pattern = ValidateDirectoryListing (path, searchPattern, out stop);
490                         if (stop)
491                                 return new string [] { path_with_pattern };
492
493                         MonoIOError error;
494                         string [] result = MonoIO.GetFileSystemEntries (path, path_with_pattern, (int) attrs, (int) mask, out error);
495                         if (error != 0)
496                                 throw MonoIO.GetException (Path.GetDirectoryName (Path.Combine (path, searchPattern)), error);
497                         
498                         return result;
499                 }
500
501                 public static string[] GetFileSystemEntries (string path, string searchPattern, SearchOption searchOption)
502                 {
503                         // Take the simple way home:
504                         return new List<string> (EnumerateFileSystemEntries (path, searchPattern, searchOption)).ToArray ();
505                 }
506
507                 static void EnumerateCheck (string path, string searchPattern, SearchOption searchOption)
508                 {
509                         if (searchPattern == null)
510                                 throw new ArgumentNullException ("searchPattern");
511
512                         if (searchPattern.Length == 0)
513                                 return;
514
515                         if (searchOption != SearchOption.TopDirectoryOnly && searchOption != SearchOption.AllDirectories)
516                                 throw new ArgumentOutOfRangeException ("searchoption");
517
518                         Path.Validate (path);
519                         SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
520                 }
521
522                 internal static IEnumerable<string> EnumerateKind (string path, string searchPattern, SearchOption searchOption, FileAttributes kind)
523                 {
524                         if (searchPattern.Length == 0)
525                                 yield break;
526
527                         bool stop;
528                         string path_with_pattern = ValidateDirectoryListing (path, searchPattern, out stop);
529                         if (stop){
530                                 yield return path_with_pattern;
531                                 yield break;
532                         }
533
534                         IntPtr handle;
535                         MonoIOError error;
536                         FileAttributes rattr;
537                         string s = MonoIO.FindFirst (path, path_with_pattern, out rattr, out error, out handle);
538                         try {
539                                 while (s != null) {
540                                         // Convert any file specific flag to FileAttributes.Normal which is used as include files flag
541                                         if (((rattr & FileAttributes.Directory) == 0) && rattr != 0)
542                                                 rattr |= FileAttributes.Normal;
543
544                                         if ((rattr & kind) != 0)
545                                                 yield return s;
546
547                                         s = MonoIO.FindNext (handle, out rattr, out error);
548                                 }
549
550                                 if (error != 0)
551                                         throw MonoIO.GetException (Path.GetDirectoryName (Path.Combine (path, searchPattern)), (MonoIOError) error);
552                         } finally {
553                                 if (handle != IntPtr.Zero)
554                                         MonoIO.FindClose (handle);
555                         }
556
557                         if (searchOption == SearchOption.AllDirectories) {
558                                 s = MonoIO.FindFirst (path, Path.Combine (path, "*"), out rattr, out error, out handle);
559
560                                 try {
561                                         while (s != null) {
562                                                 if ((rattr & FileAttributes.Directory) != 0 && (rattr & FileAttributes.ReparsePoint) == 0)
563                                                         foreach (string child in EnumerateKind (s, searchPattern, searchOption, kind))
564                                                                 yield return child;
565                                                 s = MonoIO.FindNext (handle, out rattr, out error);
566                                         }
567
568                                         if (error != 0)
569                                                 throw MonoIO.GetException (path, (MonoIOError) error);
570                                 } finally {
571                                         if (handle != IntPtr.Zero)
572                                                 MonoIO.FindClose (handle);
573                                 }
574                         }
575                 }
576
577                 public static IEnumerable<string> EnumerateDirectories (string path, string searchPattern, SearchOption searchOption)
578                 {
579                         EnumerateCheck (path, searchPattern, searchOption);
580                         return EnumerateKind (path, searchPattern, searchOption, FileAttributes.Directory);
581                 }
582                 
583                 public static IEnumerable<string> EnumerateDirectories (string path, string searchPattern)
584                 {
585                         EnumerateCheck (path, searchPattern, SearchOption.TopDirectoryOnly);
586                         return EnumerateKind (path, searchPattern, SearchOption.TopDirectoryOnly, FileAttributes.Directory);
587                 }
588
589                 public static IEnumerable<string> EnumerateDirectories (string path)
590                 {
591                         Path.Validate (path); // no need for EnumerateCheck since we supply valid arguments
592                         SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
593                         return EnumerateKind (path, "*", SearchOption.TopDirectoryOnly, FileAttributes.Directory);
594                 }
595
596                 public static IEnumerable<string> EnumerateFiles (string path, string searchPattern, SearchOption searchOption)
597                 {
598                         EnumerateCheck (path, searchPattern, searchOption);
599                         return EnumerateKind (path, searchPattern, searchOption, FileAttributes.Normal);
600                 }
601
602                 public static IEnumerable<string> EnumerateFiles (string path, string searchPattern)
603                 {
604                         EnumerateCheck (path, searchPattern, SearchOption.TopDirectoryOnly);
605                         return EnumerateKind (path, searchPattern, SearchOption.TopDirectoryOnly, FileAttributes.Normal);
606                 }
607
608                 public static IEnumerable<string> EnumerateFiles (string path)
609                 {
610                         Path.Validate (path); // no need for EnumerateCheck since we supply valid arguments
611                         SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
612                         return EnumerateKind (path, "*", SearchOption.TopDirectoryOnly, FileAttributes.Normal);
613                 }
614
615                 public static IEnumerable<string> EnumerateFileSystemEntries (string path, string searchPattern, SearchOption searchOption)
616                 {
617                         EnumerateCheck (path, searchPattern, searchOption);
618                         return EnumerateKind (path, searchPattern, searchOption, FileAttributes.Normal | FileAttributes.Directory);
619                 }
620
621                 public static IEnumerable<string> EnumerateFileSystemEntries (string path, string searchPattern)
622                 {
623                         EnumerateCheck (path, searchPattern, SearchOption.TopDirectoryOnly);
624                         return EnumerateKind (path, searchPattern, SearchOption.TopDirectoryOnly, FileAttributes.Normal | FileAttributes.Directory);
625                 }
626
627                 public static IEnumerable<string> EnumerateFileSystemEntries (string path)
628                 {
629                         Path.Validate (path); // no need for EnumerateCheck since we supply valid arguments
630                         SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
631                         return EnumerateKind (path, "*", SearchOption.TopDirectoryOnly, FileAttributes.Normal | FileAttributes.Directory);
632                 }
633                 
634
635                 public static DirectorySecurity GetAccessControl (string path, AccessControlSections includeSections)
636                 {
637                         return new DirectorySecurity (path, includeSections);
638                 }
639
640                 public static DirectorySecurity GetAccessControl (string path)
641                 {
642                         // AccessControlSections.Audit requires special permissions.
643                         return GetAccessControl (path,
644                                                  AccessControlSections.Owner |
645                                                  AccessControlSections.Group |
646                                                  AccessControlSections.Access);
647                 }
648
649 #region Copied from reference source
650         internal static String GetDemandDir(string fullPath, bool thisDirOnly)
651         {
652             String demandPath;
653
654             if (thisDirOnly) {
655                 if (fullPath.EndsWith( Path.DirectorySeparatorChar ) 
656                     || fullPath.EndsWith( Path.AltDirectorySeparatorChar ) )
657                     demandPath = fullPath + ".";
658                 else
659                     demandPath = fullPath + Path.DirectorySeparatorCharAsString + ".";
660             }
661             else {
662                 if (!(fullPath.EndsWith( Path.DirectorySeparatorChar ) 
663                     || fullPath.EndsWith( Path.AltDirectorySeparatorChar )) )
664                     demandPath = fullPath + Path.DirectorySeparatorCharAsString;
665                 else
666                     demandPath = fullPath;
667             }
668             return demandPath;
669         }
670 #endregion
671         }
672 }