2009-11-22 Miguel de Icaza <miguel@novell.com>
authorMiguel de Icaza <miguel@gnome.org>
Mon, 23 Nov 2009 03:43:27 +0000 (03:43 -0000)
committerMiguel de Icaza <miguel@gnome.org>
Mon, 23 Nov 2009 03:43:27 +0000 (03:43 -0000)
* file-io.c: Surface a smart FindFirst/FindNext/FindClose API to
the managed world.

* icall-def.h: New entry points.

svn path=/trunk/mono/; revision=146695

mono/metadata/ChangeLog
mono/metadata/file-io.c
mono/metadata/file-io.h
mono/metadata/icall-def.h

index a56830b13efd735e934b92bba2348d7c88d9707c..55d1b619c8708b954c3d935e6d59d55e9c963589 100644 (file)
@@ -1,3 +1,10 @@
+2009-11-22  Miguel de Icaza  <miguel@novell.com>
+
+       * file-io.c: Surface a smart FindFirst/FindNext/FindClose API to
+       the managed world.
+
+       * icall-def.h: New entry points.
+       
 2009-11-19  Mark Probst  <mark.probst@gmail.com>
 
        * process.c: Don't put references to managed objects into a
index b59021787f00ae78eee747a625689282a5052323..e6ea9e55aa2f541ff812ac273f8b61c9c72e56a3 100644 (file)
@@ -385,6 +385,121 @@ ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString *path,
        return result;
 }
 
+typedef struct {
+       MonoDomain *domain;
+       gint attrs, mask;
+       gchar *utf8_path;
+       HANDLE find_handle;
+} IncrementalFind;
+       
+static gboolean
+incremental_find_check_match (IncrementalFind *handle, WIN32_FIND_DATA *data, MonoString **result)
+{
+       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;
+
+       if ((data->dwFileAttributes & handle->mask) != handle->attrs)
+               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 (mono_domain_get (), full_name);
+       g_free (full_name);
+       
+       return TRUE;
+}
+
+MonoString *
+ves_icall_System_IO_MonoIO_FindFirst (MonoString *path,
+                                     MonoString *path_with_pattern,
+                                     gint attrs, gint mask,
+                                     gint32 *error,
+                                     gpointer *handle)
+{
+       WIN32_FIND_DATA data;
+       HANDLE find_handle;
+       IncrementalFind *ifh;
+       MonoString *result;
+       
+       *error = ERROR_SUCCESS;
+       mask = convert_attrs (mask);
+       
+       find_handle = FindFirstFile (mono_string_chars (path_with_pattern), &data);
+       
+       if (find_handle == INVALID_HANDLE_VALUE) {
+               gint32 find_error = GetLastError ();
+               *handle = NULL;
+               
+               if (find_error == ERROR_FILE_NOT_FOUND) 
+                       return NULL;
+               
+               *error = find_error;
+               return NULL;
+       }
+
+       ifh = g_new (IncrementalFind, 1);
+       ifh->find_handle = find_handle;
+       ifh->mask = mask;
+       ifh->attrs = attrs;
+       ifh->utf8_path = mono_string_to_utf8 (path);
+       ifh->domain = mono_domain_get ();
+       *handle = ifh;
+
+       while (incremental_find_check_match (ifh, &data, &result) == 0){
+               if (FindNextFile (find_handle, &data) == FALSE){
+                       int e = GetLastError ();
+                       if (e != ERROR_NO_MORE_FILES)
+                               *error = e;
+                       return NULL;
+               }
+       }
+
+       return result;
+}
+
+MonoString *
+ves_icall_System_IO_MonoIO_FindNext (gpointer handle, gint32 *error)
+{
+       IncrementalFind *ifh = handle;
+       WIN32_FIND_DATA data;
+       MonoString *result;
+
+       error = ERROR_SUCCESS;
+       do {
+               if (FindNextFile (ifh->find_handle, &data) == FALSE){
+                       int e = GetLastError ();
+                       if (e != ERROR_NO_MORE_FILES)
+                               *error = e;
+                       return NULL;
+               }
+       } while (incremental_find_check_match (ifh, &data, &result) == 0);
+
+       return result;
+}
+
+int
+ves_icall_System_IO_MonoIO_FindClose (gpointer handle)
+{
+       IncrementalFind *ifh = handle;
+       gint32 error;
+       
+       if (FindClose (ifh->find_handle) == FALSE){
+               error = GetLastError ();
+       } else
+               error = ERROR_SUCCESS;
+       g_free (ifh->utf8_path);
+       g_free (ifh);
+
+       return error;
+}
+
 MonoString *
 ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32 *error)
 {
index 22c6707be0f0a30cb3b08e62f9d61f0689e497fd..e483e69b17fa441450dcaa90f5daed3f0f573786 100644 (file)
@@ -125,6 +125,18 @@ ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString *path,
                                                 gint mask, gint attrs,
                                                 gint32 *error) MONO_INTERNAL;
 
+extern MonoString *
+ves_icall_System_IO_MonoIO_FindFirst (MonoString *path,
+                                     MonoString *path_with_pattern,
+                                     gint attrs, gint mask,
+                                     gint32 *error,
+                                     gpointer *handle) MONO_INTERNAL;
+extern MonoString *
+ves_icall_System_IO_MonoIO_FindNext (gpointer handle, gint32 *error) MONO_INTERNAL;
+
+extern int
+ves_icall_System_IO_MonoIO_FindClose (gpointer handle) MONO_INTERNAL;
+
 extern MonoString *
 ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32 *error) MONO_INTERNAL;
 
index 2950a138eba58420b0367adf69f33c4b5fa2b3a2..90ceba4bb96c91dd5355079e9b4c8db8aee565d0 100644 (file)
@@ -316,6 +316,9 @@ ICALL(MONOIO_4, "CreatePipe(intptr&,intptr&)", ves_icall_System_IO_MonoIO_Create
 ICALL(MONOIO_5, "DeleteFile(string,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_DeleteFile)
 #endif /* !PLATFORM_RO_FS */
 ICALL(MONOIO_34, "DuplicateHandle", ves_icall_System_IO_MonoIO_DuplicateHandle)
+ICALL(MONOIO_37, "FindClose", ves_icall_System_IO_MonoIO_FindClose)
+ICALL(MONOIO_35, "FindFirst", ves_icall_System_IO_MonoIO_FindFirst)
+ICALL(MONOIO_36, "FindNext", ves_icall_System_IO_MonoIO_FindNext)
 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)
 ICALL(MONOIO_8, "GetFileAttributes(string,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_GetFileAttributes)