New tests.
[mono.git] / mono / metadata / file-io.c
index 9e1de2fb669c477e4a55ca8aa835589f9aee8446..1ee2d20efc1f58808db5f1acbd6b5df3cd81357b 100644 (file)
@@ -385,6 +385,115 @@ ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString *path,
        return result;
 }
 
+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)
+{
+       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 (mono_domain_get (), full_name);
+       g_free (full_name);
+       
+       return TRUE;
+}
+
+MonoString *
+ves_icall_System_IO_MonoIO_FindFirst (MonoString *path,
+                                     MonoString *path_with_pattern,
+                                     gint32 *result_attr, gint32 *error,
+                                     gpointer *handle)
+{
+       WIN32_FIND_DATA data;
+       HANDLE find_handle;
+       IncrementalFind *ifh;
+       MonoString *result;
+       
+       *error = ERROR_SUCCESS;
+       
+       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->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;
+               }
+       }
+       *result_attr = data.dwFileAttributes;
+       
+       return result;
+}
+
+MonoString *
+ves_icall_System_IO_MonoIO_FindNext (gpointer handle, gint32 *result_attr, 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);
+
+       *result_attr = data.dwFileAttributes;
+       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)
 {
@@ -606,6 +715,7 @@ ves_icall_System_IO_MonoIO_GetFileStat (MonoString *path, MonoIOStat *stat,
                                                   stat);
        } else {
                *error=GetLastError ();
+               memset (stat, 0, sizeof (MonoIOStat));
        }
 
        return result;
@@ -749,7 +859,7 @@ ves_icall_System_IO_MonoIO_Seek (HANDLE handle, gint64 offset, gint32 origin,
        *error=ERROR_SUCCESS;
        
        offset_hi = offset >> 32;
-       offset = SetFilePointer (handle, offset & 0xFFFFFFFF, &offset_hi,
+       offset = SetFilePointer (handle, (gint32) (offset & 0xFFFFFFFF), &offset_hi,
                                 convert_seekorigin (origin));
 
        if(offset==INVALID_SET_FILE_POINTER) {
@@ -948,7 +1058,7 @@ MonoBoolean ves_icall_System_IO_MonoIO_DuplicateHandle (HANDLE source_process_ha
 gunichar2 
 ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar ()
 {
-#if defined (PLATFORM_WIN32)
+#if defined (TARGET_WIN32)
        return (gunichar2) ':'; /* colon */
 #else
        return (gunichar2) '/'; /* forward slash */
@@ -958,7 +1068,7 @@ ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar ()
 gunichar2 
 ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar ()
 {
-#if defined (PLATFORM_WIN32)
+#if defined (TARGET_WIN32)
        return (gunichar2) '\\';        /* backslash */
 #else
        return (gunichar2) '/'; /* forward slash */
@@ -968,7 +1078,7 @@ ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar ()
 gunichar2 
 ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar ()
 {
-#if defined (PLATFORM_WIN32)
+#if defined (TARGET_WIN32)
        return (gunichar2) '/'; /* forward slash */
 #else
        return (gunichar2) '/'; /* slash, same as DirectorySeparatorChar */
@@ -978,7 +1088,7 @@ ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar ()
 gunichar2 
 ves_icall_System_IO_MonoIO_get_PathSeparator ()
 {
-#if defined (PLATFORM_WIN32)
+#if defined (TARGET_WIN32)
        return (gunichar2) ';'; /* semicolon */
 #else
        return (gunichar2) ':'; /* colon */
@@ -987,7 +1097,7 @@ ves_icall_System_IO_MonoIO_get_PathSeparator ()
 
 static const gunichar2
 invalid_path_chars [] = {
-#if defined (PLATFORM_WIN32)
+#if defined (TARGET_WIN32)
        0x0022,                         /* double quote, which seems allowed in MS.NET but should be rejected */
        0x003c,                         /* less than */
        0x003e,                         /* greater than */