2005-07-21 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mono / metadata / file-io.c
index 3847409fcd8bb741d46223265387345bf1f0cd20..8fdc927669fa7eb305a4d8ac3007002691b67f7e 100644 (file)
@@ -9,12 +9,17 @@
 
 #include <config.h>
 #include <glib.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <unistd.h>
 
 #include <mono/metadata/object.h>
 #include <mono/io-layer/io-layer.h>
 #include <mono/metadata/file-io.h>
 #include <mono/metadata/exception.h>
 #include <mono/metadata/appdomain.h>
+#include <mono/metadata/marshal.h>
 
 #undef DEBUG
 
@@ -231,21 +236,36 @@ ves_icall_System_IO_MonoIO_FindFirstFile (MonoString *path, MonoIOStat *stat,
 {
        WIN32_FIND_DATA data;
        HANDLE result;
+       gboolean r = TRUE;
 
        MONO_ARCH_SAVE_REGS;
 
        *error=ERROR_SUCCESS;
-       
+
        result = FindFirstFile (mono_string_chars (path), &data);
 
        /* note: WIN32_FIND_DATA is an extension of WIN32_FILE_ATTRIBUTE_DATA */
-
-       if (result != INVALID_HANDLE_VALUE) {
-               convert_win32_file_attribute_data ((const WIN32_FILE_ATTRIBUTE_DATA *)&data,
-                                                  &data.cFileName [0], stat);
-       } else {
+       while (result != INVALID_HANDLE_VALUE && r) {
+               if ((data.cFileName [0] == '.' && data.cFileName [1] == 0) ||
+                   (data.cFileName [0] == '.' && data.cFileName [1] == '.' && data.cFileName [2] == 0)) {
+                       r = FindNextFile (result, &data);
+               } else {
+                       convert_win32_file_attribute_data ((const WIN32_FILE_ATTRIBUTE_DATA *)&data,
+                                                          &data.cFileName [0], stat);
+                       break;
+               } 
+       }
+       
+       if (result == INVALID_HANDLE_VALUE) {
                *error=GetLastError ();
        }
+       
+       if (r == FALSE) {
+               /* No more files were found, after we discarded . and .. */
+               FindClose(result);
+               result = INVALID_HANDLE_VALUE;
+               *error = ERROR_NO_MORE_FILES;
+       }
 
        return result;
 }
@@ -262,10 +282,18 @@ ves_icall_System_IO_MonoIO_FindNextFile (HANDLE find, MonoIOStat *stat,
        *error=ERROR_SUCCESS;
        
        result = FindNextFile (find, &data);
-       if (result) {
-               convert_win32_file_attribute_data ((const WIN32_FILE_ATTRIBUTE_DATA *)&data,
-                                                  &data.cFileName [0], stat);
-       } else {
+       while (result != FALSE) {
+               if ((data.cFileName [0] == '.' && data.cFileName [1] == 0) ||
+                   (data.cFileName [0] == '.' && data.cFileName [1] == '.' && data.cFileName [2] == 0)) {
+                       result = FindNextFile (find, &data);
+               } else {
+                       convert_win32_file_attribute_data ((const WIN32_FILE_ATTRIBUTE_DATA *)&data,
+                                                          &data.cFileName [0], stat);
+                       break;
+               } 
+       }
+       
+       if (result == FALSE) {
                *error=GetLastError ();
        }
 
@@ -407,7 +435,7 @@ ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path, gint32 *error)
         * http://cygwin.com/ml/cygwin/2003-09/msg01771.html
         */
        if (ret==-1) {
-//     if(ret==INVALID_FILE_ATTRIBUTES) {
+         /* if(ret==INVALID_FILE_ATTRIBUTES) { */
                *error=GetLastError ();
        }
        
@@ -480,7 +508,7 @@ ves_icall_System_IO_MonoIO_GetFileStat (MonoString *path, MonoIOStat *stat,
 HANDLE 
 ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode,
                                 gint32 access_mode, gint32 share,
-                                gint32 *error)
+                                MonoBoolean async, gint32 *error)
 {
        HANDLE ret;
        
@@ -490,7 +518,8 @@ ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode,
        
        ret=CreateFile (mono_string_chars (filename),
                        convert_access (access_mode), convert_share (share),
-                       NULL, convert_mode (mode), FILE_ATTRIBUTE_NORMAL,
+                       NULL, convert_mode (mode),
+                       FILE_ATTRIBUTE_NORMAL | ((async) ? FILE_FLAG_OVERLAPPED : 0),
                        NULL);
        if(ret==INVALID_HANDLE_VALUE) {
                *error=GetLastError ();
@@ -762,52 +791,45 @@ ves_icall_System_IO_MonoIO_CreatePipe (HANDLE *read_handle,
 gunichar2 
 ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar ()
 {
-       MONO_ARCH_SAVE_REGS;
-
 #if defined (PLATFORM_WIN32)
-       return (gunichar2) 0x003a;      /* colon */
+       return (gunichar2) ':'; /* colon */
 #else
-       return (gunichar2) 0x002f;      /* forward slash */
+       return (gunichar2) '/'; /* forward slash */
 #endif
 }
 
 gunichar2 
 ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar ()
 {
-       MONO_ARCH_SAVE_REGS;
-
 #if defined (PLATFORM_WIN32)
-       return (gunichar2) 0x005c;      /* backslash */
+       return (gunichar2) '\\';        /* backslash */
 #else
-       return (gunichar2) 0x002f;      /* forward slash */
+       return (gunichar2) '/'; /* forward slash */
 #endif
 }
 
 gunichar2 
 ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar ()
 {
-       MONO_ARCH_SAVE_REGS;
-
 #if defined (PLATFORM_WIN32)
-       return (gunichar2) 0x002f;      /* forward slash */
+       return (gunichar2) '/'; /* forward slash */
 #else
-       return (gunichar2) 0x005c;      /* backslash */
+       return (gunichar2) '/'; /* slash, same as DirectorySeparatorChar */
 #endif
 }
 
 gunichar2 
 ves_icall_System_IO_MonoIO_get_PathSeparator ()
 {
-       MONO_ARCH_SAVE_REGS;
-
 #if defined (PLATFORM_WIN32)
-       return (gunichar2) 0x003b;      /* semicolon */
+       return (gunichar2) ';'; /* semicolon */
 #else
-       return (gunichar2) 0x003a;      /* colon */
+       return (gunichar2) ':'; /* colon */
 #endif
 }
 
-static gunichar2 invalid_path_chars [] = {
+static const gunichar2
+invalid_path_chars [] = {
 #if defined (PLATFORM_WIN32)
        0x0022,                         /* double quote, which seems allowed in MS.NET but should be rejected */
        0x003c,                         /* less than */
@@ -837,9 +859,8 @@ ves_icall_System_IO_MonoIO_get_InvalidPathChars ()
        MONO_ARCH_SAVE_REGS;
 
        domain = mono_domain_get ();
-       chars = mono_array_new (domain, mono_defaults.char_class, 15);
-
        n = sizeof (invalid_path_chars) / sizeof (gunichar2);
+       chars = mono_array_new (domain, mono_defaults.char_class, n);
 
        for (i = 0; i < n; ++ i)
                mono_array_set (chars, gunichar2, i, invalid_path_chars [i]);
@@ -877,3 +898,32 @@ ves_icall_System_IO_MonoIO_GetTempPath (MonoString **mono_name)
        
        return(ret);
 }
+
+void ves_icall_System_IO_MonoIO_Lock (HANDLE handle, gint64 position,
+                                     gint64 length, gint32 *error)
+{
+       gboolean ret;
+       
+       *error=ERROR_SUCCESS;
+       
+       ret=LockFile (handle, position & 0xFFFFFFFF, position >> 32,
+                     length & 0xFFFFFFFF, length >> 32);
+       if (ret == FALSE) {
+               *error = GetLastError ();
+       }
+}
+
+void ves_icall_System_IO_MonoIO_Unlock (HANDLE handle, gint64 position,
+                                       gint64 length, gint32 *error)
+{
+       gboolean ret;
+       
+       *error=ERROR_SUCCESS;
+       
+       ret=UnlockFile (handle, position & 0xFFFFFFFF, position >> 32,
+                       length & 0xFFFFFFFF, length >> 32);
+       if (ret == FALSE) {
+               *error = GetLastError ();
+       }
+}
+