2008-04-04 Rodrigo Kumpera <rkumpera@novell.com>
[mono.git] / mono / metadata / file-io.c
index f8b01be0f7697cb7fe6d3cc5f18945efb4903340..8e250b72624d95a259e95ad5da3e17f8921be9e5 100644 (file)
 
 #include <config.h>
 
-#ifdef PLATFORM_WIN32
-#define _WIN32_WINNT 0x0500
-#endif
-
 #include <glib.h>
 #include <string.h>
 #include <errno.h>
@@ -207,6 +203,73 @@ static guint32 convert_attrs(MonoFileAttributes attrs)
        return(attrs);
 }
 
+/*
+ * On Win32, GetFileAttributes|Ex () seems to try opening the file,
+ * which might lead to sharing violation errors, whereas FindFirstFile
+ * always succeeds. These 2 wrappers resort to FindFirstFile if
+ * GetFileAttributes|Ex () has failed.
+ */
+static guint32
+get_file_attributes (const gunichar2 *path)
+{
+       guint32 res;
+       WIN32_FIND_DATA find_data;
+       HANDLE find_handle;
+       gint32 error;
+
+       res = GetFileAttributes (path);
+       if (res != -1)
+               return res;
+
+       error = GetLastError ();
+
+       if (error != ERROR_SHARING_VIOLATION)
+               return res;
+
+       find_handle = FindFirstFile (path, &find_data);
+
+       if (find_handle == INVALID_HANDLE_VALUE)
+               return res;
+
+       FindClose (find_handle);
+
+       return find_data.dwFileAttributes;
+}
+
+static gboolean
+get_file_attributes_ex (const gunichar2 *path, WIN32_FILE_ATTRIBUTE_DATA *data)
+{
+       gboolean res;
+       WIN32_FIND_DATA find_data;
+       HANDLE find_handle;
+       gint32 error;
+
+       res = GetFileAttributesEx (path, GetFileExInfoStandard, data);
+       if (res)
+               return TRUE;
+
+       error = GetLastError ();
+
+       if (error != ERROR_SHARING_VIOLATION)
+               return FALSE;
+
+       find_handle = FindFirstFile (path, &find_data);
+
+       if (find_handle == INVALID_HANDLE_VALUE)
+               return FALSE;
+
+       FindClose (find_handle);
+
+       data->dwFileAttributes = find_data.dwFileAttributes;
+       data->ftCreationTime = find_data.ftCreationTime;
+       data->ftLastAccessTime = find_data.ftLastAccessTime;
+       data->ftLastWriteTime = find_data.ftLastWriteTime;
+       data->nFileSizeHigh = find_data.nFileSizeHigh;
+       data->nFileSizeLow = find_data.nFileSizeLow;
+       
+       return TRUE;
+}
+
 /* System.IO.MonoIO internal calls */
 
 MonoBoolean
@@ -462,7 +525,7 @@ ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path, gint32 *error)
 
        *error=ERROR_SUCCESS;
        
-       ret=GetFileAttributes (mono_string_chars (path));
+       ret=get_file_attributes (mono_string_chars (path));
 
        /* 
         * The definition of INVALID_FILE_ATTRIBUTES in the cygwin win32
@@ -528,7 +591,7 @@ ves_icall_System_IO_MonoIO_GetFileStat (MonoString *path, MonoIOStat *stat,
 
        *error=ERROR_SUCCESS;
        
-       result = GetFileAttributesEx (mono_string_chars (path), GetFileExInfoStandard, &data);
+       result = get_file_attributes_ex (mono_string_chars (path), &data);
 
        if (result) {
                convert_win32_file_attribute_data (&data,
@@ -580,7 +643,7 @@ ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode,
 
        /* If we're opening a directory we need to set the extra flag
         */
-       attrs = GetFileAttributes (chars);
+       attrs = get_file_attributes (chars);
        if (attrs != INVALID_FILE_ATTRIBUTES) {
                if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
                        attributes |= FILE_FLAG_BACKUP_SEMANTICS;