diff options
Diffstat (limited to 'drivers/windows/file_access_windows.cpp')
-rw-r--r-- | drivers/windows/file_access_windows.cpp | 47 |
1 files changed, 33 insertions, 14 deletions
diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp index dbffac8ebd..072790876f 100644 --- a/drivers/windows/file_access_windows.cpp +++ b/drivers/windows/file_access_windows.cpp @@ -31,6 +31,7 @@ #ifdef WINDOWS_ENABLED #include "file_access_windows.h" +#include "os/os.h" #include "shlwapi.h" #include <windows.h> @@ -115,28 +116,41 @@ void FileAccessWindows::close() { //_wunlink(save_path.c_str()); //unlink if exists //int rename_error = _wrename((save_path+".tmp").c_str(),save_path.c_str()); - bool rename_error; + bool rename_error = true; + int attempts = 4; + while (rename_error && attempts) { + // This workaround of trying multiple times is added to deal with paranoid Windows + // antiviruses that love reading just written files even if they are not executable, thus + // locking the file and preventing renaming from happening. #ifdef UWP_ENABLED - // UWP has no PathFileExists, so we check attributes instead - DWORD fileAttr; + // UWP has no PathFileExists, so we check attributes instead + DWORD fileAttr; - fileAttr = GetFileAttributesW(save_path.c_str()); - if (INVALID_FILE_ATTRIBUTES == fileAttr) { + fileAttr = GetFileAttributesW(save_path.c_str()); + if (INVALID_FILE_ATTRIBUTES == fileAttr) { #else - if (!PathFileExistsW(save_path.c_str())) { + if (!PathFileExistsW(save_path.c_str())) { #endif - //creating new file - rename_error = _wrename((save_path + ".tmp").c_str(), save_path.c_str()) != 0; - } else { - //atomic replace for existing file - rename_error = !ReplaceFileW(save_path.c_str(), (save_path + ".tmp").c_str(), NULL, 2 | 4, NULL, NULL); - } - if (rename_error && close_fail_notify) { - close_fail_notify(save_path); + //creating new file + rename_error = _wrename((save_path + ".tmp").c_str(), save_path.c_str()) != 0; + } else { + //atomic replace for existing file + rename_error = !ReplaceFileW(save_path.c_str(), (save_path + ".tmp").c_str(), NULL, 2 | 4, NULL, NULL); + } + if (rename_error && close_fail_notify) { + close_fail_notify(save_path); + } + if (rename_error) { + attempts--; + OS::get_singleton()->delay_usec(1000000); //wait 100msec and try again + } } save_path = ""; + if (rename_error) { + ERR_EXPLAIN("Safe save failed. This may be a permissions problem, but also may happen because you are running a paranoid antivirus. If this is the case, please switch to Windows Defender or disable the 'safe save' option in editor settings. This makes it work, but increases the risk of file corruption in a crash."); + } ERR_FAIL_COND(rename_error); } } @@ -221,6 +235,11 @@ void FileAccessWindows::store_8(uint8_t p_dest) { fwrite(&p_dest, 1, 1, f); } +void FileAccessWindows::store_buffer(const uint8_t *p_src, int p_length) { + ERR_FAIL_COND(!f); + ERR_FAIL_COND(fwrite(p_src, 1, p_length, f) != p_length); +} + bool FileAccessWindows::file_exists(const String &p_name) { FILE *g; |