[w32file] Move MonoIO.Find{First,Next,Close} to managed
authorLudovic Henry <ludovic@xamarin.com>
Wed, 27 Sep 2017 15:28:16 +0000 (11:28 -0400)
committerMarek Safar <marek.safar@gmail.com>
Fri, 29 Sep 2017 09:24:22 +0000 (11:24 +0200)
mcs/class/corlib/System.IO/DirectoryInfo.cs
mcs/class/corlib/System.IO/MonoIO.cs
mono/metadata/icall-def.h
mono/metadata/w32file.c
mono/metadata/w32file.h

index 205fadc0026b852b25a17c83bdd4cf76aaff0239..1cf54bf5b2bbf408cea543afcdd4ae1994f922bf 100644 (file)
@@ -41,6 +41,8 @@ using System.Security;
 using System.Text;
 using System.Security.AccessControl;
 
+using Microsoft.Win32.SafeHandles;
+
 namespace System.IO {
        
        [Serializable]
@@ -424,39 +426,57 @@ 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 = IntPtr.Zero;
-                       MonoIOError error;
-                       FileAttributes rattr;
-                       bool subdirs = searchOption == SearchOption.AllDirectories;
+                       Path.Validate (basePath);
+
+                       SafeFindHandle findHandle = null;
 
-                       Path.Validate (full);
-                       
                        try {
-                               string s = MonoIO.FindFirst (full, path_with_pattern, out rattr, out error, out handle);
-                               if (s == null)
+                               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));
+                               }
+
+                               if (findHandle.IsInvalid) {
+                                       MonoIOError error = (MonoIOError) nativeError;
+                                       if (error != MonoIOError.ERROR_FILE_NOT_FOUND)
+                                               throw MonoIO.GetException (Path.GetDirectoryName (basePathWithPattern), error);
+
                                        yield break;
-                               if (error != 0)
-                                       throw MonoIO.GetException (Path.GetDirectoryName (path_with_pattern), (MonoIOError) error);
+                               }
 
                                do {
-                                       if (((rattr & FileAttributes.ReparsePoint) == 0)){
-                                               if ((rattr & FileAttributes.Directory) != 0)
-                                                       yield return new DirectoryInfo (s);
+                                       if (filePath == null)
+                                               yield break;
+
+                                       if (filePath == "." || filePath == "..")
+                                               continue;
+
+                                       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 (s);
+                                                       yield return new FileInfo (fullPath);
                                        }
 
-                                       if (((rattr & FileAttributes.Directory) != 0) && subdirs)
-                                               foreach (FileSystemInfo child in EnumerateFileSystemInfos (s, searchPattern, searchOption))
+                                       if ((attrs & FileAttributes.Directory) != 0 && searchOption == SearchOption.AllDirectories) {
+                                               foreach (FileSystemInfo child in EnumerateFileSystemInfos (fullPath, searchPattern, searchOption))
                                                        yield return child;
-
-                               } while ((s = MonoIO.FindNext (handle, out rattr, out error)) != null);
+                                       }
+                               } while (MonoIO.FindNextFile (findHandle.DangerousGetHandle (), out filePath, out nativeAttrs, out int _));
                        } finally {
-                               if (handle != IntPtr.Zero)
-                                       MonoIO.FindClose (handle);
+                               if (findHandle != null)
+                                       findHandle.Dispose ();
                        }
                }
                
index 7542dabe9cb20830a63f83c24d4edaad93bd73b8..38c8cf3de735623fa52e6cd144ae626ceaed1fe7 100644 (file)
@@ -226,14 +226,6 @@ namespace System.IO
                //
                // Find file methods
                //
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static string FindFirst (string path, string pattern, out FileAttributes result_attr, out MonoIOError error, out IntPtr handle);
-               
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static string FindNext (IntPtr handle, out FileAttributes result_attr, out MonoIOError error);
-               
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static int FindClose (IntPtr handle);
 
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
                public extern static IntPtr FindFirstFile (string path_with_pattern, out string fileName, out int fileAttr, out int error);
index 68913ad8ec5bdea2e460c98a827379637eaec9bf..aa9404b3f5304cd6eed1b4e75a21371bb124fd37 100644 (file)
@@ -365,11 +365,8 @@ ICALL(MONOIO_5, "DeleteFile(string,System.IO.MonoIOError&)", ves_icall_System_IO
 #endif /* !PLATFORM_RO_FS */
 ICALL(MONOIO_38, "DumpHandles", ves_icall_System_IO_MonoIO_DumpHandles)
 ICALL(MONOIO_34, "DuplicateHandle", ves_icall_System_IO_MonoIO_DuplicateHandle)
-ICALL(MONOIO_37, "FindClose", ves_icall_System_IO_MonoIO_FindClose)
 ICALL(MONOIO_37a, "FindCloseFile", ves_icall_System_IO_MonoIO_FindCloseFile)
-ICALL(MONOIO_35, "FindFirst", ves_icall_System_IO_MonoIO_FindFirst)
 ICALL(MONOIO_35a, "FindFirstFile", ves_icall_System_IO_MonoIO_FindFirstFile)
-ICALL(MONOIO_36, "FindNext", ves_icall_System_IO_MonoIO_FindNext)
 ICALL(MONOIO_36a, "FindNextFile", ves_icall_System_IO_MonoIO_FindNextFile)
 ICALL(MONOIO_6, "Flush(intptr,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_Flush)
 ICALL(MONOIO_7, "GetCurrentDirectory(System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_GetCurrentDirectory)
index 630278f1b26841232678a578f038006f8d96ff96..f10ae499645e1afd7093c4ca76c1d731d239a85e 100644 (file)
@@ -285,36 +285,6 @@ ves_icall_System_IO_MonoIO_RemoveDirectory (MonoString *path, gint32 *error)
        return(ret);
 }
 
-typedef struct {
-       MonoDomain *domain;
-       gchar *utf8_path;
-       HANDLE find_handle;
-} IncrementalFind;
-       
-static gboolean
-incremental_find_check_match (IncrementalFind *handle, WIN32_FIND_DATA *data, MonoString **result, MonoError *error)
-{
-       error_init (error);
-       gchar *utf8_result;
-       gchar *full_name;
-       
-       if ((data->cFileName[0] == '.' && data->cFileName[1] == 0) || (data->cFileName[0] == '.' && data->cFileName[1] == '.' && data->cFileName[2] == 0))
-               return FALSE;
-
-       utf8_result = g_utf16_to_utf8 (data->cFileName, -1, NULL, NULL, NULL);
-       if (utf8_result == NULL) 
-               return FALSE;
-       
-       full_name = g_build_filename (handle->utf8_path, utf8_result, NULL);
-       g_free (utf8_result);
-       *result = mono_string_new_checked (mono_domain_get (), full_name, error);
-       g_free (full_name);
-       if (!is_ok (error))
-               return FALSE;
-       
-       return TRUE;
-}
-
 HANDLE
 ves_icall_System_IO_MonoIO_FindFirstFile (MonoString *path_with_pattern, MonoString **file_name, gint32 *file_attr, gint32 *ioerror)
 {
@@ -371,106 +341,6 @@ ves_icall_System_IO_MonoIO_FindCloseFile (HANDLE hnd)
        return mono_w32file_find_close (hnd);
 }
 
-/* FIXME make gc suspendable */
-MonoString *
-ves_icall_System_IO_MonoIO_FindFirst (MonoString *path,
-                                     MonoString *path_with_pattern,
-                                     gint32 *result_attr, gint32 *ioerror,
-                                     gpointer *handle)
-{
-       MonoError error;
-       WIN32_FIND_DATA data;
-       HANDLE find_handle;
-       IncrementalFind *ifh;
-       MonoString *result;
-       
-       *ioerror = ERROR_SUCCESS;
-       
-       find_handle = mono_w32file_find_first (mono_string_chars (path_with_pattern), &data);
-       
-       if (find_handle == INVALID_HANDLE_VALUE) {
-               gint32 find_error = mono_w32error_get_last ();
-               *handle = NULL;
-               
-               if (find_error == ERROR_FILE_NOT_FOUND) 
-                       return NULL;
-               
-               *ioerror = find_error;
-               return NULL;
-       }
-
-       ifh = g_new (IncrementalFind, 1);
-       ifh->find_handle = find_handle;
-       ifh->utf8_path = mono_string_to_utf8_checked (path, &error);
-       if (mono_error_set_pending_exception (&error)) {
-               mono_w32file_find_close (find_handle);
-               g_free (ifh);
-               return NULL;
-       }
-       ifh->domain = mono_domain_get ();
-       *handle = ifh;
-
-       while (incremental_find_check_match (ifh, &data, &result, &error) == 0){
-               if (!is_ok (&error)) {
-                       mono_error_set_pending_exception (&error);
-                       return NULL;
-               }
-               if (mono_w32file_find_next (find_handle, &data) == FALSE){
-                       int e = mono_w32error_get_last ();
-                       if (e != ERROR_NO_MORE_FILES)
-                               *ioerror = e;
-                       return NULL;
-               }
-       }
-       *result_attr = data.dwFileAttributes;
-
-       return result;
-}
-
-/* FIXME make gc suspendable */
-MonoString *
-ves_icall_System_IO_MonoIO_FindNext (gpointer handle, gint32 *result_attr, gint32 *ioerror)
-{
-       MonoError error;
-       IncrementalFind *ifh = (IncrementalFind *)handle;
-       WIN32_FIND_DATA data;
-       MonoString *result;
-
-       error_init (&error);
-       *ioerror = ERROR_SUCCESS;
-       do {
-               if (!is_ok (&error)) {
-                       mono_error_set_pending_exception (&error);
-                       return NULL;
-               }
-               if (mono_w32file_find_next (ifh->find_handle, &data) == FALSE){
-                       int e = mono_w32error_get_last ();
-                       if (e != ERROR_NO_MORE_FILES)
-                               *ioerror = e;
-                       return NULL;
-               }
-       } while (incremental_find_check_match (ifh, &data, &result, &error) == 0);
-
-       *result_attr = data.dwFileAttributes;
-       return result;
-}
-
-int
-ves_icall_System_IO_MonoIO_FindClose (gpointer handle)
-{
-       IncrementalFind *ifh = (IncrementalFind *)handle;
-       gint32 error;
-
-       if (mono_w32file_find_close (ifh->find_handle) == FALSE){
-               error = mono_w32error_get_last ();
-       } else
-               error = ERROR_SUCCESS;
-       g_free (ifh->utf8_path);
-       g_free (ifh);
-
-       return error;
-}
-
 MonoString *
 ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32 *io_error)
 {
index 3604e684917905ebb919f6471ebef298471c4cb2..54f79a39927e093a6d42e13e913513f8b6bd70b6 100644 (file)
@@ -135,18 +135,6 @@ ves_icall_System_IO_MonoIO_FindNextFile (gpointer hnd,
 extern MonoBoolean
 ves_icall_System_IO_MonoIO_FindCloseFile (gpointer hnd);
 
-extern MonoString *
-ves_icall_System_IO_MonoIO_FindFirst (MonoString *path,
-                                     MonoString *path_with_pattern,
-                                     gint32 *result_mask,
-                                     gint32 *error,
-                                     gpointer *handle);
-extern MonoString *
-ves_icall_System_IO_MonoIO_FindNext (gpointer handle, gint32 *result_mask, gint32 *error);
-
-extern int
-ves_icall_System_IO_MonoIO_FindClose (gpointer handle);
-
 extern MonoString *
 ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32 *error);