From ab0b591ca59d99a2370bf9f579b091c5edf09ae5 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Wed, 27 Sep 2017 11:28:16 -0400 Subject: [PATCH] [w32file] Move MonoIO.Find{First,Next,Close} to managed --- mcs/class/corlib/System.IO/DirectoryInfo.cs | 64 ++++++---- mcs/class/corlib/System.IO/MonoIO.cs | 8 -- mono/metadata/icall-def.h | 3 - mono/metadata/w32file.c | 130 -------------------- mono/metadata/w32file.h | 12 -- 5 files changed, 42 insertions(+), 175 deletions(-) diff --git a/mcs/class/corlib/System.IO/DirectoryInfo.cs b/mcs/class/corlib/System.IO/DirectoryInfo.cs index 205fadc0026..1cf54bf5b2b 100644 --- a/mcs/class/corlib/System.IO/DirectoryInfo.cs +++ b/mcs/class/corlib/System.IO/DirectoryInfo.cs @@ -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 EnumerateFileSystemInfos (string full, string searchPattern, SearchOption searchOption) + static internal IEnumerable 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 (); } } diff --git a/mcs/class/corlib/System.IO/MonoIO.cs b/mcs/class/corlib/System.IO/MonoIO.cs index 7542dabe9cb..38c8cf3de73 100644 --- a/mcs/class/corlib/System.IO/MonoIO.cs +++ b/mcs/class/corlib/System.IO/MonoIO.cs @@ -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); diff --git a/mono/metadata/icall-def.h b/mono/metadata/icall-def.h index 68913ad8ec5..aa9404b3f53 100644 --- a/mono/metadata/icall-def.h +++ b/mono/metadata/icall-def.h @@ -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) diff --git a/mono/metadata/w32file.c b/mono/metadata/w32file.c index 630278f1b26..f10ae499645 100644 --- a/mono/metadata/w32file.c +++ b/mono/metadata/w32file.c @@ -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) { diff --git a/mono/metadata/w32file.h b/mono/metadata/w32file.h index 3604e684917..54f79a39927 100644 --- a/mono/metadata/w32file.h +++ b/mono/metadata/w32file.h @@ -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); -- 2.25.1