[w32file] Move MonoIO.Find{First,Next,Close} to managed
[mono.git] / mcs / class / corlib / System.IO / DirectoryInfo.cs
index ce558743516117060aec9c27bc44a691bcf3f713..1cf54bf5b2bbf408cea543afcdd4ae1994f922bf 100644 (file)
@@ -6,10 +6,12 @@
 //   Jim Richardson, develop@wtfo-guru.com
 //   Dan Lewis, dihlewis@yahoo.co.uk
 //   Sebastien Pouliot  <sebastien@ximian.com>
+//   Marek Safar  <marek.safar@gmail.com>
 //
 // Copyright (C) 2002 Ximian, Inc.
 // Copyright (C) 2001 Moonlight Enterprises, All Rights Reserved
 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2014 Xamarin, Inc (http://www.xamarin.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -39,6 +41,8 @@ using System.Security;
 using System.Text;
 using System.Security.AccessControl;
 
+using Microsoft.Win32.SafeHandles;
+
 namespace System.IO {
        
        [Serializable]
@@ -60,7 +64,7 @@ namespace System.IO {
 
                        FullPath = Path.GetFullPath (path);
                        if (simpleOriginalPath)
-                               OriginalPath = Path.GetFileName (path);
+                               OriginalPath = Path.GetFileName (FullPath);
                        else
                                OriginalPath = path;
 
@@ -100,12 +104,13 @@ namespace System.IO {
 
                public override bool Exists {
                        get {
-                               Refresh (false);
+                               if (_dataInitialised == -1)
+                                       Refresh ();
 
-                               if (stat.Attributes == MonoIO.InvalidFileAttributes)
+                               if (_data.fileAttributes == MonoIO.InvalidFileAttributes)
                                        return false;
 
-                               if ((stat.Attributes & FileAttributes.Directory) == 0)
+                               if ((_data.fileAttributes & FileAttributes.Directory) == 0)
                                        return false;
 
                                return true;
@@ -202,9 +207,7 @@ namespace System.IO {
                        return GetFileSystemInfos (searchPattern, SearchOption.TopDirectoryOnly);
                }
 
-#if NET_4_0
                public
-#endif
                FileSystemInfo [] GetFileSystemInfos (string searchPattern, SearchOption searchOption)
                {
                        if (searchPattern == null)
@@ -354,7 +357,6 @@ namespace System.IO {
                        Directory.SetAccessControl (FullPath, directorySecurity);
                }
 
-#if NET_4_0
 
                public IEnumerable<DirectoryInfo> EnumerateDirectories ()
                {
@@ -424,48 +426,73 @@ namespace System.IO {
                        return EnumerateFileSystemInfos (FullPath, searchPattern, searchOption);
                }
 
-               static internal IEnumerable<FileSystemInfo> EnumerateFileSystemInfos (string full, string searchPattern, SearchOption searchOption)
+               static internal IEnumerable<FileSystemInfo> EnumerateFileSystemInfos (string basePath, string searchPattern, SearchOption searchOption)
                {
-                       string path_with_pattern = Path.Combine (full, searchPattern);
-                       IntPtr handle;
-                       MonoIOError error;
-                       FileAttributes rattr;
-                       bool subdirs = searchOption == SearchOption.AllDirectories;
+                       Path.Validate (basePath);
 
-                       Path.Validate (full);
-                       
-                       string s = MonoIO.FindFirst (full, path_with_pattern, out rattr, out error, out handle);
-                       if (s == null)
-                               yield break;
-                       if (error != 0)
-                               throw MonoIO.GetException (Path.GetDirectoryName (path_with_pattern), (MonoIOError) error);
+                       SafeFindHandle findHandle = null;
 
                        try {
-                               if (((rattr & FileAttributes.ReparsePoint) == 0)){
-                                       if ((rattr & FileAttributes.Directory) != 0)
-                                               yield return new DirectoryInfo (s);
-                                       else
-                                               yield return new FileInfo (s);
+                               string filePath;
+                               int nativeAttrs;
+
+                               string basePathWithPattern = Path.Combine (basePath, searchPattern);
+
+                               int nativeError;
+                               try {} finally {
+                                       findHandle = new SafeFindHandle (MonoIO.FindFirstFile (basePathWithPattern, out filePath, out nativeAttrs, out nativeError));
                                }
-                               
-                               while ((s = MonoIO.FindNext (handle, out rattr, out error)) != null){
-                                       if ((rattr & FileAttributes.ReparsePoint) != 0)
+
+                               if (findHandle.IsInvalid) {
+                                       MonoIOError error = (MonoIOError) nativeError;
+                                       if (error != MonoIOError.ERROR_FILE_NOT_FOUND)
+                                               throw MonoIO.GetException (Path.GetDirectoryName (basePathWithPattern), error);
+
+                                       yield break;
+                               }
+
+                               do {
+                                       if (filePath == null)
+                                               yield break;
+
+                                       if (filePath == "." || filePath == "..")
                                                continue;
-                                       if ((rattr & FileAttributes.Directory) != 0)
-                                               yield return new DirectoryInfo (s);
-                                       else
-                                               yield return new FileInfo (s);
-                                       
-                                       if (((rattr & FileAttributes.Directory) != 0) && subdirs)
-                                               foreach (FileSystemInfo child in EnumerateFileSystemInfos (s, searchPattern, searchOption))
+
+                                       FileAttributes attrs = (FileAttributes) nativeAttrs;
+
+                                       string fullPath = Path.Combine (basePath, filePath);
+
+                                       if ((attrs & FileAttributes.ReparsePoint) == 0) {
+                                               if ((attrs & FileAttributes.Directory) != 0)
+                                                       yield return new DirectoryInfo (fullPath);
+                                               else
+                                                       yield return new FileInfo (fullPath);
+                                       }
+
+                                       if ((attrs & FileAttributes.Directory) != 0 && searchOption == SearchOption.AllDirectories) {
+                                               foreach (FileSystemInfo child in EnumerateFileSystemInfos (fullPath, searchPattern, searchOption))
                                                        yield return child;
-                               }
+                                       }
+                               } while (MonoIO.FindNextFile (findHandle.DangerousGetHandle (), out filePath, out nativeAttrs, out int _));
                        } finally {
-                               MonoIO.FindClose (handle);
+                               if (findHandle != null)
+                                       findHandle.Dispose ();
                        }
                }
                
-               
-#endif
+               internal void CheckPath (string path)
+               {
+                       if (path == null)
+                               throw new ArgumentNullException ("path");
+                       if (path.Length == 0)
+                               throw new ArgumentException ("An empty file name is not valid.");
+                       if (path.IndexOfAny (Path.InvalidPathChars) != -1)
+                               throw new ArgumentException ("Illegal characters in path.");
+                       if (Environment.IsRunningOnWindows) {
+                               int idx = path.IndexOf (':');
+                               if (idx >= 0 && idx != 1)
+                                       throw new ArgumentException ("path");
+                       }
+               }
        }
 }