using System.Text;
using System.Security.AccessControl;
+using Microsoft.Win32.SafeHandles;
+
namespace System.IO {
[Serializable]
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 ();
}
}
//
// 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);
#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)
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)
{
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)
{
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);