diff options
Diffstat (limited to 'drivers/windows/file_access_windows.cpp')
-rw-r--r-- | drivers/windows/file_access_windows.cpp | 84 |
1 files changed, 58 insertions, 26 deletions
diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp index 072790876f..b4492a2022 100644 --- a/drivers/windows/file_access_windows.cpp +++ b/drivers/windows/file_access_windows.cpp @@ -31,11 +31,13 @@ #ifdef WINDOWS_ENABLED #include "file_access_windows.h" -#include "os/os.h" -#include "shlwapi.h" + +#include "core/os/os.h" +#include "core/print_string.h" + +#include <shlwapi.h> #include <windows.h> -#include "print_string.h" #include <sys/stat.h> #include <sys/types.h> #include <tchar.h> @@ -57,7 +59,8 @@ void FileAccessWindows::check_errors() const { Error FileAccessWindows::_open(const String &p_path, int p_mode_flags) { - String filename = fix_path(p_path); + path_src = p_path; + path = fix_path(p_path); if (f) close(); @@ -78,19 +81,40 @@ Error FileAccessWindows::_open(const String &p_path, int p_mode_flags) { backend supports utf8 encoding */ struct _stat st; - if (_wstat(filename.c_str(), &st) == 0) { + if (_wstat(path.c_str(), &st) == 0) { if (!S_ISREG(st.st_mode)) return ERR_FILE_CANT_OPEN; }; +#ifdef TOOLS_ENABLED + // Windows is case insensitive, but all other platforms are sensitive to it + // To ease cross-platform development, we issue a warning if users try to access + // a file using the wrong case (which *works* on Windows, but won't on other + // platforms). + if (p_mode_flags == READ) { + WIN32_FIND_DATAW d = { 0 }; + HANDLE f = FindFirstFileW(path.c_str(), &d); + if (f) { + String fname = d.cFileName; + if (fname != String()) { + + String base_file = path.get_file(); + if (base_file != fname && base_file.findn(fname) == 0) { + WARN_PRINTS("Case mismatch opening requested file '" + base_file + "', stored as '" + fname + "' in the filesystem. This file will not open when exported to other case-sensitive platforms."); + } + } + FindClose(f); + } + } +#endif + if (is_backup_save_enabled() && p_mode_flags & WRITE && !(p_mode_flags & READ)) { - save_path = filename; - filename = filename + ".tmp"; - //print_line("saving instead to "+path); + save_path = path; + path = path + ".tmp"; } - f = _wfopen(filename.c_str(), mode_string); + f = _wfopen(path.c_str(), mode_string); if (f == NULL) { last_error = ERR_FILE_CANT_OPEN; @@ -111,17 +135,12 @@ void FileAccessWindows::close() { if (save_path != "") { - //unlink(save_path.utf8().get_data()); - //print_line("renaming.."); - //_wunlink(save_path.c_str()); //unlink if exists - //int rename_error = _wrename((save_path+".tmp").c_str(),save_path.c_str()); - 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. + // 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 @@ -138,22 +157,36 @@ void FileAccessWindows::close() { //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 + OS::get_singleton()->delay_usec(100000); // wait 100msec and try again } } - save_path = ""; if (rename_error) { + if (close_fail_notify) { + close_fail_notify(save_path); + } + 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."); } + + save_path = ""; + ERR_FAIL_COND(rename_error); } } + +String FileAccessWindows::get_path() const { + + return path_src; +} + +String FileAccessWindows::get_path_absolute() const { + + return path; +} + bool FileAccessWindows::is_open() const { return (f != NULL); @@ -269,11 +302,10 @@ uint64_t FileAccessWindows::_get_modified_time(const String &p_file) { return st.st_mtime; } else { - print_line("no access to " + file); + ERR_EXPLAIN("Failed to get modified time for: " + file); + ERR_FAIL_V(0); } - - ERR_FAIL_V(0); -}; +} FileAccessWindows::FileAccessWindows() { |