X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fw32file-win32.c;h=6ecb7ff9d5f40c58d05e8c72cff844bb9b1ee634;hb=1bcf21e0480acf5dc4d68bf4e8b700217e35eb92;hp=8b1c3a9f5b87938d165d4c66af723fe2d5cd789e;hpb=648916b0281598bcd863ba02c25eaab932972030;p=mono.git diff --git a/mono/metadata/w32file-win32.c b/mono/metadata/w32file-win32.c index 8b1c3a9f5b8..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 @@ -299,20 +356,20 @@ gboolean mono_w32file_get_disk_free_space (const gunichar2 *path_name, guint64 *free_bytes_avail, guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes) { gboolean result; - ULARGE_INTEGER *wapi_free_bytes_avail; - ULARGE_INTEGER *wapi_total_number_of_bytes; - ULARGE_INTEGER *wapi_total_number_of_free_bytes; + ULARGE_INTEGER wapi_free_bytes_avail; + ULARGE_INTEGER wapi_total_number_of_bytes; + ULARGE_INTEGER wapi_total_number_of_free_bytes; MONO_ENTER_GC_SAFE; - result = GetDiskFreeSpaceEx (path_name, wapi_free_bytes_avail, wapi_total_number_of_bytes, wapi_total_number_of_free_bytes); + result = GetDiskFreeSpaceEx (path_name, &wapi_free_bytes_avail, &wapi_total_number_of_bytes, &wapi_total_number_of_free_bytes); MONO_EXIT_GC_SAFE; if (result) { if (free_bytes_avail) - *free_bytes_avail = wapi_free_bytes_avail->QuadPart; + *free_bytes_avail = wapi_free_bytes_avail.QuadPart; if (total_number_of_bytes) - *total_number_of_bytes = wapi_total_number_of_bytes->QuadPart; + *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart; if (total_number_of_free_bytes) - *total_number_of_free_bytes = wapi_total_number_of_free_bytes->QuadPart; + *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart; } return result;