X-Git-Url: http://wien.tomnetworks.com/gitweb/?p=mono.git;a=blobdiff_plain;f=mono%2Fmetadata%2Fw32file-win32.c;h=6ecb7ff9d5f40c58d05e8c72cff844bb9b1ee634;hp=a0fbf95003d08d3c0ee12cf5de77a73907982910;hb=1bcf21e0480acf5dc4d68bf4e8b700217e35eb92;hpb=abcca89bd4e256a74f55e46f4c45c25ad9c3cdf2 diff --git a/mono/metadata/w32file-win32.c b/mono/metadata/w32file-win32.c index a0fbf95003d..6ecb7ff9d5f 100644 --- a/mono/metadata/w32file-win32.c +++ b/mono/metadata/w32file-win32.c @@ -221,34 +221,91 @@ mono_w32file_remove_directory (const gunichar2 *name) return res; } +/* + * GetFileAttributes|Ex () seems to try opening the file, which might lead to sharing violation errors, whereas + * FindFirstFile always succeeds. + */ guint32 mono_w32file_get_attributes (const gunichar2 *name) { guint32 res; + guint32 error; + HANDLE find_handle; + WIN32_FIND_DATA find_data; + MONO_ENTER_GC_SAFE; res = GetFileAttributes (name); MONO_EXIT_GC_SAFE; - return res; + + if (res != INVALID_FILE_ATTRIBUTES) + return res; + + error = GetLastError (); + if (error != ERROR_SHARING_VIOLATION) + return INVALID_FILE_ATTRIBUTES; + + MONO_ENTER_GC_SAFE; + find_handle = FindFirstFile (name, &find_data); + MONO_EXIT_GC_SAFE; + + if (find_handle == INVALID_HANDLE_VALUE) + return INVALID_FILE_ATTRIBUTES; + + MONO_ENTER_GC_SAFE; + FindClose (find_handle); + MONO_EXIT_GC_SAFE; + + return find_data.dwFileAttributes; +} + +static gint64 +convert_filetime (const FILETIME *filetime) +{ + return (gint64) ((((guint64) filetime->dwHighDateTime) << 32) + filetime->dwLowDateTime); } gboolean mono_w32file_get_attributes_ex (const gunichar2 *name, MonoIOStat *stat) { - gboolean result; - WIN32_FILE_ATTRIBUTE_DATA data; + gboolean res; + guint32 error; + HANDLE find_handle; + WIN32_FIND_DATA find_data; + WIN32_FILE_ATTRIBUTE_DATA file_attribute_data; MONO_ENTER_GC_SAFE; - result = GetFileAttributesEx (name, GetFileExInfoStandard, &data); + res = GetFileAttributesEx (name, GetFileExInfoStandard, &file_attribute_data); MONO_EXIT_GC_SAFE; - if (result) { - stat->attributes = data.dwFileAttributes; - stat->creation_time = (gint64) ((((guint64) data.ftCreationTime.dwHighDateTime) << 32) + data.ftCreationTime.dwLowDateTime); - stat->last_access_time = (gint64) ((((guint64) data.ftLastAccessTime.dwHighDateTime) << 32) + data.ftLastAccessTime.dwLowDateTime); - stat->last_write_time = (gint64) ((((guint64) data.ftLastWriteTime.dwHighDateTime) << 32) + data.ftLastWriteTime.dwLowDateTime); - stat->length = ((gint64)data.nFileSizeHigh << 32) | data.nFileSizeLow; + if (res) { + stat->attributes = file_attribute_data.dwFileAttributes; + stat->creation_time = convert_filetime (&file_attribute_data.ftCreationTime); + stat->last_access_time = convert_filetime (&file_attribute_data.ftLastAccessTime); + stat->last_write_time = convert_filetime (&file_attribute_data.ftLastWriteTime); + stat->length = ((gint64)file_attribute_data.nFileSizeHigh << 32) | file_attribute_data.nFileSizeLow; + return TRUE; } - return result; + error = GetLastError (); + if (error != ERROR_SHARING_VIOLATION) + return FALSE; + + MONO_ENTER_GC_SAFE; + find_handle = FindFirstFile (name, &find_data); + MONO_EXIT_GC_SAFE; + + if (find_handle == INVALID_HANDLE_VALUE) + return FALSE; + + MONO_ENTER_GC_SAFE; + FindClose (find_handle); + MONO_EXIT_GC_SAFE; + + stat->attributes = find_data.dwFileAttributes; + stat->creation_time = convert_filetime (&find_data.ftCreationTime); + stat->last_access_time = convert_filetime (&find_data.ftLastAccessTime); + stat->last_write_time = convert_filetime (&find_data.ftLastWriteTime); + stat->length = ((gint64)find_data.nFileSizeHigh << 32) | find_data.nFileSizeLow; + return TRUE; } gboolean