New tests.
[mono.git] / mcs / class / corlib / System.IO / Directory.cs
index 9e0748e9707c4e817a7e7e69bbc34d4ba5f78641..69709f060d61821495ba05cbe512c6b6e0cd4e5f 100644 (file)
 //
 
 using System.Collections;
+using System.Collections.Generic;
 using System.Security;
 using System.Security.Permissions;
 using System.Text;
+using System.Runtime.InteropServices;
+
+#if !MOONLIGHT
+using System.Security.AccessControl;
+#endif
 
 namespace System.IO
 {
-       public
-#if NET_2_0
-       static
-#else
-       sealed
-#endif
-       class Directory
+       [ComVisible (true)]
+       public static class Directory
        {
 
-#if !NET_2_0
-               private Directory () {}
-#endif
-               
                public static DirectoryInfo CreateDirectory (string path)
                {
                        if (path == null)
                                throw new ArgumentNullException ("path");
                        
-                       if (path == "")
+                       if (path.Length == 0)
                                throw new ArgumentException ("Path is empty");
                        
                        if (path.IndexOfAny (Path.InvalidPathChars) != -1)
@@ -71,22 +68,37 @@ namespace System.IO
 
                        if (path.Trim ().Length == 0)
                                throw new ArgumentException ("Only blank characters in path");
+
+                       // after validations but before File.Exists to avoid an oracle
+                       SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
+
+                       if (File.Exists(path))
+                               throw new IOException ("Cannot create " + path + " because a file with the same name already exists.");
                        
                        // LAMESPEC: with .net 1.0 version this throw NotSupportedException and msdn says so too
                        // but v1.1 throws ArgumentException.
-                       if (path == ":")
+                       if (Environment.IsRunningOnWindows && path == ":")
                                throw new ArgumentException ("Only ':' In path");
                        
                        return CreateDirectoriesInternal (path);
                }
 
+#if !MOONLIGHT
+               [MonoLimitation ("DirectorySecurity not implemented")]
+               public static DirectoryInfo CreateDirectory (string path, DirectorySecurity directorySecurity)
+               {
+                       return(CreateDirectory (path));
+               }
+#endif
+
                static DirectoryInfo CreateDirectoriesInternal (string path)
                {
+#if !MOONLIGHT
                        if (SecurityManager.SecurityEnabled) {
                                new FileIOPermission (FileIOPermissionAccess.Read | FileIOPermissionAccess.Write, path).Demand ();
                        }
-
-                       DirectoryInfo info = new DirectoryInfo (path);
+#endif
+                       DirectoryInfo info = new DirectoryInfo (path, true);
                        if (info.Parent != null && !info.Parent.Exists)
                                 info.Parent.Create ();
 
@@ -111,40 +123,52 @@ namespace System.IO
                
                public static void Delete (string path)
                {
-                       if (path == null)
-                               throw new ArgumentNullException ("path");
-                       
-                       if (path == "")
-                               throw new ArgumentException ("Path is empty");
-                       
-                       if (path.IndexOfAny (Path.InvalidPathChars) != -1)
-                               throw new ArgumentException ("Path contains invalid chars");
+                       Path.Validate (path);
 
-                       if (path.Trim().Length == 0)
-                               throw new ArgumentException ("Only blank characters in path");
-
-                       if (path == ":")
+                       if (Environment.IsRunningOnWindows && path == ":")
                                throw new NotSupportedException ("Only ':' In path");
 
+                       SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
+
                        MonoIOError error;
+                       bool success;
                        
-                       if (!MonoIO.RemoveDirectory (path, out error)) {
+                       if (MonoIO.ExistsSymlink (path, out error)) {
+                               /* RemoveDirectory maps to rmdir()
+                                * which fails on symlinks (ENOTDIR)
+                                */
+                               success = MonoIO.DeleteFile (path, out error);
+                       } else {
+                               success = MonoIO.RemoveDirectory (path, out error);
+                       }
+                       
+                       if (!success) {
                                /*
                                 * FIXME:
                                 * In io-layer/io.c rmdir returns error_file_not_found if directory does not exists.
                                 * So maybe this could be handled somewhere else?
                                 */
-                               if (error == MonoIOError.ERROR_FILE_NOT_FOUND) 
-                                       throw new DirectoryNotFoundException ("Directory '" + path + "' doesnt exists.");
-                               else
+                               if (error == MonoIOError.ERROR_FILE_NOT_FOUND) {
+                                       if (File.Exists (path))
+                                               throw new IOException ("Directory does not exist, but a file of the same name exists.");
+                                       else
+                                               throw new DirectoryNotFoundException ("Directory does not exist.");
+                               } else
                                        throw MonoIO.GetException (path, error);
                        }
                }
 
                static void RecursiveDelete (string path)
                {
-                       foreach (string dir in GetDirectories (path))
-                               RecursiveDelete (dir);
+                       MonoIOError error;
+                       
+                       foreach (string dir in GetDirectories (path)) {
+                               if (MonoIO.ExistsSymlink (dir, out error)) {
+                                       MonoIO.DeleteFile (dir, out error);
+                               } else {
+                                       RecursiveDelete (dir);
+                               }
+                       }
 
                        foreach (string file in GetFiles (path))
                                File.Delete (file);
@@ -152,52 +176,44 @@ namespace System.IO
                        Directory.Delete (path);
                }
                
-               public static void Delete (string path, bool recurse)
+               public static void Delete (string path, bool recursive)
                {
-                       CheckPathExceptions (path);
-                       
-                       if (recurse == false){
-                               Delete (path);
-                               return;
-                       }
+                       Path.Validate (path);                   
+                       SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
 
-                       RecursiveDelete (path);
+                       if (recursive)
+                               RecursiveDelete (path);
+                       else
+                               Delete (path);
                }
 
                public static bool Exists (string path)
                {
                        if (path == null)
                                return false;
+
+                       // on Moonlight this does not throw but returns false
+                       if (!SecurityManager.CheckElevatedPermissions ())
+                               return false;
                                
                        MonoIOError error;
                        bool exists;
                        
                        exists = MonoIO.ExistsDirectory (path, out error);
-                       if (error != MonoIOError.ERROR_SUCCESS &&
-                           error != MonoIOError.ERROR_PATH_NOT_FOUND &&
-                           error != MonoIOError.ERROR_INVALID_HANDLE &&
-                           error != MonoIOError.ERROR_ACCESS_DENIED) {
-
-                               // INVALID_HANDLE might happen if the file is moved
-                               // while testing for the existence, a kernel issue
-                               // according to Larry Ewing.
-                               
-                               throw MonoIO.GetException (path, error);
-                       }
-
-                       return(exists);
+                       /* This should not throw exceptions */
+                       return exists;
                }
 
                public static DateTime GetLastAccessTime (string path)
                {
                        return File.GetLastAccessTime (path);
                }
-               
+
                public static DateTime GetLastAccessTimeUtc (string path)
                {
                        return GetLastAccessTime (path).ToUniversalTime ();
                }
-                     
+
                public static DateTime GetLastWriteTime (string path)
                {
                        return File.GetLastWriteTime (path);
@@ -221,14 +237,17 @@ namespace System.IO
                public static string GetCurrentDirectory ()
                {
                        MonoIOError error;
+
+                       SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
                                
                        string result = MonoIO.GetCurrentDirectory (out error);
                        if (error != MonoIOError.ERROR_SUCCESS)
                                throw MonoIO.GetException (error);
-
+#if !MOONLIGHT
                        if ((result != null) && (result.Length > 0) && SecurityManager.SecurityEnabled) {
                                new FileIOPermission (FileIOPermissionAccess.PathDiscovery, result).Demand ();
                        }
+#endif
                        return result;
                }
                
@@ -237,31 +256,35 @@ namespace System.IO
                        return GetDirectories (path, "*");
                }
                
-               public static string [] GetDirectories (string path, string pattern)
+               public static string [] GetDirectories (string path, string searchPattern)
                {
-                       return GetFileSystemEntries (path, pattern, FileAttributes.Directory, FileAttributes.Directory);
+                       return GetFileSystemEntries (path, searchPattern, FileAttributes.Directory, FileAttributes.Directory);
                }
                
-#if NET_2_0
-               public static string [] GetDirectories (string path, string pattern, SearchOption option)
+#if !MOONLIGHT
+               public static string [] GetDirectories (string path, string searchPattern, SearchOption searchOption)
                {
-                       if (option == SearchOption.TopDirectoryOnly)
-                               return GetDirectories (path, pattern);
+                       if (searchOption == SearchOption.TopDirectoryOnly)
+                               return GetDirectories (path, searchPattern);
                        ArrayList all = new ArrayList ();
-                       GetDirectoriesRecurse (path, pattern, all);
+                       GetDirectoriesRecurse (path, searchPattern, all);
                        return (string []) all.ToArray (typeof (string));
                }
                
-               static void GetDirectoriesRecurse (string path, string pattern, ArrayList all)
+               static void GetDirectoriesRecurse (string path, string searchPattern, ArrayList all)
                {
-                       all.AddRange (GetDirectories (path, pattern));
+                       all.AddRange (GetDirectories (path, searchPattern));
                        foreach (string dir in GetDirectories (path))
-                               GetDirectoriesRecurse (dir, pattern, all);
+                               GetDirectoriesRecurse (dir, searchPattern, all);
                }
 #endif
 
                public static string GetDirectoryRoot (string path)
                {
+                       Path.Validate (path);                   
+                       SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
+
+                       // FIXME nice hack but that does not work under windows
                        return new String(Path.DirectorySeparatorChar,1);
                }
                
@@ -270,12 +293,12 @@ namespace System.IO
                        return GetFiles (path, "*");
                }
                
-               public static string [] GetFiles (string path, string pattern)
+               public static string [] GetFiles (string path, string searchPattern)
                {
-                       return GetFileSystemEntries (path, pattern, FileAttributes.Directory, 0);
+                       return GetFileSystemEntries (path, searchPattern, FileAttributes.Directory, 0);
                }
 
-#if NET_2_0
+#if !MOONLIGHT
                public static string[] GetFiles (string path, string searchPattern, SearchOption searchOption)
                {
                        if (searchOption == SearchOption.TopDirectoryOnly)
@@ -285,11 +308,11 @@ namespace System.IO
                        return (string []) all.ToArray (typeof (string));
                }
                
-               static void GetFilesRecurse (string path, string pattern, ArrayList all)
+               static void GetFilesRecurse (string path, string searchPattern, ArrayList all)
                {
-                       all.AddRange (GetFiles (path, pattern));
+                       all.AddRange (GetFiles (path, searchPattern));
                        foreach (string dir in GetDirectories (path))
-                               GetFilesRecurse (dir, pattern, all);
+                               GetFilesRecurse (dir, searchPattern, all);
                }
 #endif
 
@@ -298,9 +321,9 @@ namespace System.IO
                        return GetFileSystemEntries (path, "*");
                }
 
-               public static string [] GetFileSystemEntries (string path, string pattern)
+               public static string [] GetFileSystemEntries (string path, string searchPattern)
                {
-                       return GetFileSystemEntries (path, pattern, 0, 0);
+                       return GetFileSystemEntries (path, searchPattern, 0, 0);
                }
                
                public static string[] GetLogicalDrives ()
@@ -311,73 +334,77 @@ namespace System.IO
                static bool IsRootDirectory (string path)
                {
                        // Unix
-                      if (Path.DirectorySeparatorChar == '/' && path == "/")
-                              return true;
+                       if (Path.DirectorySeparatorChar == '/' && path == "/")
+                               return true;
 
-                      // Windows
-                      if (Path.DirectorySeparatorChar == '\\')
-                              if (path.Length == 3 && path.EndsWith (":\\"))
-                                      return true;
+                       // Windows
+                       if (Path.DirectorySeparatorChar == '\\')
+                               if (path.Length == 3 && path.EndsWith (":\\"))
+                                       return true;
 
-                      return false;
+                       return false;
                }
 
                public static DirectoryInfo GetParent (string path)
                {
-                       if (path == null)
-                               throw new ArgumentNullException ();
-                       if (path.IndexOfAny (Path.InvalidPathChars) != -1)
-                               throw new ArgumentException ("Path contains invalid characters");
-                       if (path == "")
-                               throw new ArgumentException ("The Path do not have a valid format");
+                       Path.Validate (path);                   
 
                        // return null if the path is the root directory
                        if (IsRootDirectory (path))
                                return null;
 
                        string parent_name = Path.GetDirectoryName (path);
-                       if (parent_name == "")
+                       if (parent_name.Length == 0)
                                parent_name = GetCurrentDirectory();
 
                        return new DirectoryInfo (parent_name);
                }
 
-               public static void Move (string src, string dest)
+               public static void Move (string sourceDirName, string destDirName)
                {
-                       if (src == null)
-                               throw new ArgumentNullException ("src");
+                       if (sourceDirName == null)
+                               throw new ArgumentNullException ("sourceDirName");
+
+                       if (destDirName == null)
+                               throw new ArgumentNullException ("destDirName");
 
-                       if (dest == null)
-                               throw new ArgumentNullException ("dest");
+                       if (sourceDirName.Trim ().Length == 0 || sourceDirName.IndexOfAny (Path.InvalidPathChars) != -1)
+                               throw new ArgumentException ("Invalid source directory name: " + sourceDirName, "sourceDirName");
 
-                       if (src.Trim () == "" || src.IndexOfAny (Path.InvalidPathChars) != -1)
-                               throw new ArgumentException ("Invalid source directory name: " + src, "src");
+                       if (destDirName.Trim ().Length == 0 || destDirName.IndexOfAny (Path.InvalidPathChars) != -1)
+                               throw new ArgumentException ("Invalid target directory name: " + destDirName, "destDirName");
 
-                       if (dest.Trim () == "" || dest.IndexOfAny (Path.InvalidPathChars) != -1)
-                               throw new ArgumentException ("Invalid target directory name: " + dest, "dest");
+                       if (sourceDirName == destDirName)
+                               throw new IOException ("Source and destination path must be different.");
 
-                       if (src == dest)
-                               throw new IOException ("Source directory cannot be same as a target directory.");
+                       SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
 
-                       if (Exists (dest))
-                               throw new IOException (dest + " already exists.");
+                       if (Exists (destDirName))
+                               throw new IOException (destDirName + " already exists.");
 
-                       if (!Exists (src))
-                               throw new DirectoryNotFoundException (src + " does not exist");
+                       if (!Exists (sourceDirName) && !File.Exists (sourceDirName))
+                               throw new DirectoryNotFoundException (sourceDirName + " does not exist");
 
                        MonoIOError error;
-                       if (!MonoIO.MoveFile (src, dest, out error))
+                       if (!MonoIO.MoveFile (sourceDirName, destDirName, out error))
                                throw MonoIO.GetException (error);
                }
 
-               public static void SetCreationTime (string path, DateTime creation_time)
+#if !MOONLIGHT
+               public static void SetAccessControl (string path, DirectorySecurity directorySecurity)
                {
-                       File.SetCreationTime (path, creation_time);
+                       throw new NotImplementedException ();
                }
+#endif
 
-               public static void SetCreationTimeUtc (string path, DateTime creation_time)
+               public static void SetCreationTime (string path, DateTime creationTime)
                {
-                       SetCreationTime (path, creation_time.ToLocalTime ());
+                       File.SetCreationTime (path, creationTime);
+               }
+
+               public static void SetCreationTimeUtc (string path, DateTime creationTimeUtc)
+               {
+                       SetCreationTime (path, creationTimeUtc.ToLocalTime ());
                }
 
                [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
@@ -385,7 +412,7 @@ namespace System.IO
                {
                        if (path == null)
                                throw new ArgumentNullException ("path");
-                       if (path.Trim () == String.Empty)
+                       if (path.Trim ().Length == 0)
                                throw new ArgumentException ("path string must not be an empty string or whitespace string");
 
                        MonoIOError error;
@@ -399,69 +426,45 @@ namespace System.IO
                                throw MonoIO.GetException (path, error);
                }
 
-               public static void SetLastAccessTime (string path, DateTime last_access_time)
+               public static void SetLastAccessTime (string path, DateTime lastAccessTime)
                {
-                       File.SetLastAccessTime (path, last_access_time);
+                       File.SetLastAccessTime (path, lastAccessTime);
                }
 
-               public static void SetLastAccessTimeUtc (string path, DateTime last_access_time)
+               public static void SetLastAccessTimeUtc (string path, DateTime lastAccessTimeUtc)
                {
-                       SetLastAccessTime (path, last_access_time.ToLocalTime ());
+                       SetLastAccessTime (path, lastAccessTimeUtc.ToLocalTime ());
                }
 
-               public static void SetLastWriteTime (string path, DateTime last_write_time)
+               public static void SetLastWriteTime (string path, DateTime lastWriteTime)
                {
-                       File.SetLastWriteTime (path, last_write_time);
+                       File.SetLastWriteTime (path, lastWriteTime);
                }
 
-               public static void SetLastWriteTimeUtc (string path, DateTime last_write_time)
+               public static void SetLastWriteTimeUtc (string path, DateTime lastWriteTimeUtc)
                {
-                       SetLastWriteTime (path, last_write_time.ToLocalTime ());
+                       SetLastWriteTime (path, lastWriteTimeUtc.ToLocalTime ());
                }
 
                // private
                
-               private static void CheckPathExceptions (string path)
+               // Does the common validation, searchPattern has already been checked for not-null
+               static string ValidateDirectoryListing (string path, string searchPattern, out bool stop)
                {
-                       if (path == null)
-                               throw new System.ArgumentNullException("Path is Null");
-                       if (path == "")
-                               throw new System.ArgumentException("Path is Empty");
-                       if (path.Trim().Length == 0)
-                               throw new ArgumentException ("Only blank characters in path");
-                       if (path.IndexOfAny (Path.InvalidPathChars) != -1)
-                               throw new ArgumentException ("Path contains invalid chars");
-               }
-
-               private static string [] GetFileSystemEntries (string path, string pattern, FileAttributes mask, FileAttributes attrs)
-               {
-                       if (path == null || pattern == null)
-                               throw new ArgumentNullException ();
-
-                       if (pattern == String.Empty)
-                               return new string [] {};
-                       
-                       if (path.Trim () == "")
-                               throw new ArgumentException ("The Path does not have a valid format");
+                       Path.Validate (path);
 
-                       string wild = Path.Combine (path, pattern);
+                       string wild = Path.Combine (path, searchPattern);
                        string wildpath = Path.GetDirectoryName (wild);
                        if (wildpath.IndexOfAny (Path.InvalidPathChars) != -1)
-                               throw new ArgumentException ("Path contains invalid characters");
-
-                       if (wildpath.IndexOfAny (Path.InvalidPathChars) != -1) {
-                               if (path.IndexOfAny (SearchPattern.InvalidChars) == -1)
-                                       throw new ArgumentException ("Path contains invalid characters", "path");
-
                                throw new ArgumentException ("Pattern contains invalid characters", "pattern");
-                       }
 
                        MonoIOError error;
                        if (!MonoIO.ExistsDirectory (wildpath, out error)) {
                                if (error == MonoIOError.ERROR_SUCCESS) {
                                        MonoIOError file_error;
                                        if (MonoIO.ExistsFile (wildpath, out file_error)) {
-                                               return new string [] { wildpath };
+                                               stop = true;
+                                               return wildpath;
                                        }
                                }
 
@@ -472,17 +475,169 @@ namespace System.IO
                                        throw new DirectoryNotFoundException ("Directory '" + wildpath + "' not found.");
 
                                if (path.IndexOfAny (SearchPattern.WildcardChars) == -1)
-                                       throw new ArgumentException ("Pattern is invalid", "pattern");
+                                       throw new ArgumentException ("Pattern is invalid", "searchPattern");
 
                                throw new ArgumentException ("Path is invalid", "path");
                        }
 
-                       string [] result = MonoIO.GetFileSystemEntries (wildpath, pattern, (int) attrs, (int) mask, out error);
-                       if (error != 0)
-                               throw MonoIO.GetException (wildpath, error);
+                       stop = false;
+                       return Path.Combine (wildpath, searchPattern);
+               }
+               
+               private static string [] GetFileSystemEntries (string path, string searchPattern, FileAttributes mask, FileAttributes attrs)
+               {
+                       if (searchPattern == null)
+                               throw new ArgumentNullException ("searchPattern");
+                       if (searchPattern.Length == 0)
+                               return new string [] {};
+                       bool stop;
+                       string path_with_pattern = ValidateDirectoryListing (path, searchPattern, out stop);
+                       if (stop)
+                               return new string [] { path_with_pattern };
 
+                       MonoIOError error;
+                       string [] result = MonoIO.GetFileSystemEntries (path, path_with_pattern, (int) attrs, (int) mask, out error);
+                       if (error != 0)
+                               throw MonoIO.GetException (Path.GetDirectoryName (Path.Combine (path, searchPattern)), error);
+                       
                        return result;
                }
+
+#if NET_4_0 || MOONLIGHT
+               public static string[] GetFileSystemEntries (string path, string searchPattern, SearchOption searchOption)
+               {
+                       // Take the simple way home:
+                       return new List<string> (EnumerateFileSystemEntries (path, searchPattern, searchOption)).ToArray ();
+               }
+
+               static void EnumerateCheck (string path, string searchPattern, SearchOption searchOption)
+               {
+                       if (searchPattern == null)
+                               throw new ArgumentNullException ("searchPattern");
+
+                       if (searchPattern.Length == 0)
+                               return;
+
+                       if (searchOption != SearchOption.TopDirectoryOnly && searchOption != SearchOption.AllDirectories)
+                               throw new ArgumentOutOfRangeException ("searchoption");
+
+                       Path.Validate (path);
+                       SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
+               }
+
+               internal static IEnumerable<string> EnumerateKind (string path, string searchPattern, SearchOption searchOption, FileAttributes kind)
+               {
+                       if (searchPattern.Length == 0)
+                               yield break;
+
+                       bool stop;
+                       string path_with_pattern = ValidateDirectoryListing (path, searchPattern, out stop);
+                       if (stop){
+                               yield return path_with_pattern;
+                               yield break;
+                       }
+                       
+                       IntPtr handle;
+                       MonoIOError error;
+                       FileAttributes rattr;
+                       bool subdirs = searchOption == SearchOption.AllDirectories;
+                       
+                       string s = MonoIO.FindFirst (path, path_with_pattern, out rattr, out error, out handle);
+                       if (s == null)
+                               yield break;
+                       if (error != 0)
+                               throw MonoIO.GetException (Path.GetDirectoryName (Path.Combine (path, searchPattern)), (MonoIOError) error);
+
+                       try {
+                               if (((rattr & FileAttributes.ReparsePoint) == 0) && ((rattr & kind) != 0))
+                                       yield return s;
+                               
+                               while ((s = MonoIO.FindNext (handle, out rattr, out error)) != null){
+                                       if ((rattr & FileAttributes.ReparsePoint) != 0)
+                                               continue;
+                                       if ((rattr & kind) != 0)
+                                               yield return s;
+                                       
+                                       if (((rattr & FileAttributes.Directory) != 0) && subdirs)
+                                               foreach (string child in EnumerateKind (s, searchPattern, searchOption, kind))
+                                                       yield return child;
+                               }
+                       } finally {
+                               MonoIO.FindClose (handle);
+                       }
+               }
+
+               public static IEnumerable<string> EnumerateDirectories (string path, string searchPattern, SearchOption searchOption)
+               {
+                       EnumerateCheck (path, searchPattern, searchOption);
+                       return EnumerateKind (path, searchPattern, searchOption, FileAttributes.Directory);
+               }
+               
+               public static IEnumerable<string> EnumerateDirectories (string path, string searchPattern)
+               {
+                       EnumerateCheck (path, searchPattern, SearchOption.TopDirectoryOnly);
+                       return EnumerateKind (path, searchPattern, SearchOption.TopDirectoryOnly, FileAttributes.Directory);
+               }
+
+               public static IEnumerable<string> EnumerateDirectories (string path)
+               {
+                       Path.Validate (path); // no need for EnumerateCheck since we supply valid arguments
+                       SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
+                       return EnumerateKind (path, "*", SearchOption.TopDirectoryOnly, FileAttributes.Directory);
+               }
+
+               public static IEnumerable<string> EnumerateFiles (string path, string searchPattern, SearchOption searchOption)
+               {
+                       EnumerateCheck (path, searchPattern, searchOption);
+                       return EnumerateKind (path, searchPattern, searchOption, FileAttributes.Normal);
+               }
+
+               public static IEnumerable<string> EnumerateFiles (string path, string searchPattern)
+               {
+                       EnumerateCheck (path, searchPattern, SearchOption.TopDirectoryOnly);
+                       return EnumerateKind (path, searchPattern, SearchOption.TopDirectoryOnly, FileAttributes.Normal);
+               }
+
+               public static IEnumerable<string> EnumerateFiles (string path)
+               {
+                       Path.Validate (path); // no need for EnumerateCheck since we supply valid arguments
+                       SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
+                       return EnumerateKind (path, "*", SearchOption.TopDirectoryOnly, FileAttributes.Normal);
+               }
+
+               public static IEnumerable<string> EnumerateFileSystemEntries (string path, string searchPattern, SearchOption searchOption)
+               {
+                       EnumerateCheck (path, searchPattern, searchOption);
+                       return EnumerateKind (path, searchPattern, searchOption, FileAttributes.Normal | FileAttributes.Directory);
+               }
+
+               public static IEnumerable<string> EnumerateFileSystemEntries (string path, string searchPattern)
+               {
+                       EnumerateCheck (path, searchPattern, SearchOption.TopDirectoryOnly);
+                       return EnumerateKind (path, searchPattern, SearchOption.TopDirectoryOnly, FileAttributes.Normal | FileAttributes.Directory);
+               }
+
+               public static IEnumerable<string> EnumerateFileSystemEntries (string path)
+               {
+                       Path.Validate (path); // no need for EnumerateCheck since we supply valid arguments
+                       SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
+                       return EnumerateKind (path, "*", SearchOption.TopDirectoryOnly, FileAttributes.Normal | FileAttributes.Directory);
+               }
+               
+#endif
+
+#if !MOONLIGHT
+               [MonoNotSupported ("DirectorySecurity isn't implemented")]
+               public static DirectorySecurity GetAccessControl (string path, AccessControlSections includeSections)
+               {
+                       throw new PlatformNotSupportedException ();
+               }
+
+               [MonoNotSupported ("DirectorySecurity isn't implemented")]
+               public static DirectorySecurity GetAccessControl (string path)
+               {
+                       throw new PlatformNotSupportedException ();
+               }
+#endif
        }
 }
-