summaryrefslogtreecommitdiff
path: root/drivers/windows
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/windows')
-rw-r--r--drivers/windows/dir_access_windows.cpp27
-rw-r--r--drivers/windows/file_access_windows.cpp66
-rw-r--r--drivers/windows/file_access_windows.h6
-rw-r--r--drivers/windows/stream_peer_tcp_winsock.cpp6
-rw-r--r--drivers/windows/stream_peer_tcp_winsock.h2
-rw-r--r--drivers/windows/tcp_server_winsock.cpp1
6 files changed, 89 insertions, 19 deletions
diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp
index 2e64b55430..cf4d82fb07 100644
--- a/drivers/windows/dir_access_windows.cpp
+++ b/drivers/windows/dir_access_windows.cpp
@@ -261,13 +261,30 @@ Error DirAccessWindows::rename(String p_path, String p_new_path) {
p_new_path = fix_path(p_new_path);
- if (file_exists(p_new_path)) {
- if (remove(p_new_path) != OK) {
+ // If we're only changing file name case we need to do a little juggling
+ if (p_path.to_lower() == p_new_path.to_lower()) {
+ WCHAR tmpfile[MAX_PATH];
+
+ if (!GetTempFileNameW(fix_path(get_current_dir()).c_str(), NULL, 0, tmpfile)) {
return FAILED;
- };
- };
+ }
+
+ if (!::ReplaceFileW(tmpfile, p_path.c_str(), NULL, 0, NULL, NULL)) {
+ DeleteFileW(tmpfile);
+ return FAILED;
+ }
- return ::_wrename(p_path.c_str(), p_new_path.c_str()) == 0 ? OK : FAILED;
+ return ::_wrename(tmpfile, p_new_path.c_str()) == 0 ? OK : FAILED;
+
+ } else {
+ if (file_exists(p_new_path)) {
+ if (remove(p_new_path) != OK) {
+ return FAILED;
+ }
+ }
+
+ return ::_wrename(p_path.c_str(), p_new_path.c_str()) == 0 ? OK : FAILED;
+ }
}
Error DirAccessWindows::remove(String p_path) {
diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp
index 832d75b17d..aa0fd34e0a 100644
--- a/drivers/windows/file_access_windows.cpp
+++ b/drivers/windows/file_access_windows.cpp
@@ -57,7 +57,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 +79,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;
@@ -112,7 +134,7 @@ void FileAccessWindows::close() {
if (save_path != "") {
//unlink(save_path.utf8().get_data());
- //print_line("renaming..");
+ //print_line("renaming...");
//_wunlink(save_path.c_str()); //unlink if exists
//int rename_error = _wrename((save_path+".tmp").c_str(),save_path.c_str());
@@ -138,19 +160,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
+ }
+ }
+
+ 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);
@@ -232,6 +271,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;
diff --git a/drivers/windows/file_access_windows.h b/drivers/windows/file_access_windows.h
index bbdf830c96..0462c1e942 100644
--- a/drivers/windows/file_access_windows.h
+++ b/drivers/windows/file_access_windows.h
@@ -46,6 +46,8 @@ class FileAccessWindows : public FileAccess {
int flags;
void check_errors() const;
mutable Error last_error;
+ String path;
+ String path_src;
String save_path;
public:
@@ -53,6 +55,9 @@ public:
virtual void close(); ///< close a file
virtual bool is_open() const; ///< true when file is open
+ virtual String get_path() const; /// returns the path for the current open file
+ virtual String get_path_absolute() const; /// returns the absolute path for the current open file
+
virtual void seek(size_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
virtual size_t get_position() const; ///< get position in the file
@@ -67,6 +72,7 @@ public:
virtual void flush();
virtual void store_8(uint8_t p_dest); ///< store a byte
+ virtual void store_buffer(const uint8_t *p_src, int p_length); ///< store an array of bytes
virtual bool file_exists(const String &p_name); ///< return true if a file exists
diff --git a/drivers/windows/stream_peer_tcp_winsock.cpp b/drivers/windows/stream_peer_tcp_winsock.cpp
index d6a320fb5e..cb501ce35d 100644
--- a/drivers/windows/stream_peer_tcp_winsock.cpp
+++ b/drivers/windows/stream_peer_tcp_winsock.cpp
@@ -332,10 +332,12 @@ Error StreamPeerTCPWinsock::connect_to_host(const IP_Address &p_host, uint16_t p
return OK;
};
-void StreamPeerTCPWinsock::set_nodelay(bool p_enabled) {
+void StreamPeerTCPWinsock::set_no_delay(bool p_enabled) {
ERR_FAIL_COND(!is_connected_to_host());
int flag = p_enabled ? 1 : 0;
- setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
+ if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int)) != 0) {
+ ERR_PRINT("Unable to set TCP no delay option");
+ }
}
int StreamPeerTCPWinsock::get_available_bytes() const {
diff --git a/drivers/windows/stream_peer_tcp_winsock.h b/drivers/windows/stream_peer_tcp_winsock.h
index 9be8414878..a0177d374e 100644
--- a/drivers/windows/stream_peer_tcp_winsock.h
+++ b/drivers/windows/stream_peer_tcp_winsock.h
@@ -81,7 +81,7 @@ public:
static void make_default();
static void cleanup();
- virtual void set_nodelay(bool p_enabled);
+ virtual void set_no_delay(bool p_enabled);
StreamPeerTCPWinsock();
~StreamPeerTCPWinsock();
diff --git a/drivers/windows/tcp_server_winsock.cpp b/drivers/windows/tcp_server_winsock.cpp
index 413a0d19b5..ddb955549f 100644
--- a/drivers/windows/tcp_server_winsock.cpp
+++ b/drivers/windows/tcp_server_winsock.cpp
@@ -105,6 +105,7 @@ Error TCPServerWinsock::listen(uint16_t p_port, const IP_Address &p_bind_address
ERR_FAIL_V(FAILED);
};
} else {
+ closesocket(sockfd);
return ERR_ALREADY_IN_USE;
};