From 1bcf21e0480acf5dc4d68bf4e8b700217e35eb92 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Tue, 3 Oct 2017 10:38:09 -0400 Subject: [PATCH] [w32file] Push win32 specific error to win32 specific implementation (#5665) ERROR_SHARING_VIOLATION can only happen on win32, so pushing the code to deal with this error to w32file-win32.c file. --- mono/metadata/w32file-win32.c | 79 ++++++++++++++++++++++++++++++----- mono/metadata/w32file.c | 75 ++------------------------------- 2 files changed, 71 insertions(+), 83 deletions(-) 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 diff --git a/mono/metadata/w32file.c b/mono/metadata/w32file.c index f10ae499645..03cac78ac1c 100644 --- a/mono/metadata/w32file.c +++ b/mono/metadata/w32file.c @@ -172,11 +172,6 @@ static guint32 convert_seekorigin(MonoSeekOrigin origin) return(w32origin); } -static gint64 convert_filetime (const FILETIME *filetime) -{ - return (gint64) ((((guint64) filetime->dwHighDateTime) << 32) + filetime->dwLowDateTime); -} - /* Managed file attributes have nearly but not quite the same values * as the w32 equivalents. */ @@ -189,70 +184,6 @@ static guint32 convert_attrs(MonoFileAttributes attrs) return(attrs); } -/* - * On Win32, mono_w32file_get_attributes|_ex () seems to try opening the file, - * which might lead to sharing violation errors, whereas mono_w32file_find_first - * always succeeds. These 2 wrappers resort to mono_w32file_find_first if - * mono_w32file_get_attributes|_ex () has failed. - */ -static guint32 -get_file_attributes (const gunichar2 *path) -{ - guint32 res; - WIN32_FIND_DATA find_data; - HANDLE find_handle; - gint32 error; - - res = mono_w32file_get_attributes (path); - if (res != -1) - return res; - - error = mono_w32error_get_last (); - - if (error != ERROR_SHARING_VIOLATION) - return res; - - find_handle = mono_w32file_find_first (path, &find_data); - - if (find_handle == INVALID_HANDLE_VALUE) - return res; - - mono_w32file_find_close (find_handle); - - return find_data.dwFileAttributes; -} - -static gboolean -get_file_attributes_ex (const gunichar2 *path, MonoIOStat *stat) -{ - gboolean res; - WIN32_FIND_DATA find_data; - HANDLE find_handle; - gint32 error; - - res = mono_w32file_get_attributes_ex (path, stat); - if (res) - return TRUE; - - error = mono_w32error_get_last (); - if (error != ERROR_SHARING_VIOLATION) - return FALSE; - - find_handle = mono_w32file_find_first (path, &find_data); - - if (find_handle == INVALID_HANDLE_VALUE) - return FALSE; - - mono_w32file_find_close (find_handle); - - 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; -} - /* System.IO.MonoIO internal calls */ MonoBoolean @@ -455,7 +386,7 @@ ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path, gint32 *error) gint32 ret; *error=ERROR_SUCCESS; - ret=get_file_attributes (mono_string_chars (path)); + ret = mono_w32file_get_attributes (mono_string_chars (path)); /* * The definition of INVALID_FILE_ATTRIBUTES in the cygwin win32 @@ -510,7 +441,7 @@ ves_icall_System_IO_MonoIO_GetFileStat (MonoString *path, MonoIOStat *stat, gint *error=ERROR_SUCCESS; - result = get_file_attributes_ex (mono_string_chars (path), stat); + result = mono_w32file_get_attributes_ex (mono_string_chars (path), stat); if (!result) { *error=mono_w32error_get_last (); @@ -554,7 +485,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 = get_file_attributes (chars); + attrs = mono_w32file_get_attributes (chars); if (attrs != INVALID_FILE_ATTRIBUTES) { if (attrs & FILE_ATTRIBUTE_DIRECTORY) { attributes |= FILE_FLAG_BACKUP_SEMANTICS; -- 2.25.1