123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321 |
- #ifdef WINDOWS_ENABLED
- #include "file_access_windows.h"
- #include "core/os/os.h"
- #include "core/print_string.h"
- #include <shlwapi.h>
- #include <windows.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <tchar.h>
- #include <wchar.h>
- #ifdef _MSC_VER
- #define S_ISREG(m) ((m)&_S_IFREG)
- #endif
- void FileAccessWindows::check_errors() const {
- ERR_FAIL_COND(!f);
- if (feof(f)) {
- last_error = ERR_FILE_EOF;
- }
- }
- Error FileAccessWindows::_open(const String &p_path, int p_mode_flags) {
- path_src = p_path;
- path = fix_path(p_path);
- if (f)
- close();
- const wchar_t *mode_string;
- if (p_mode_flags == READ)
- mode_string = L"rb";
- else if (p_mode_flags == WRITE)
- mode_string = L"wb";
- else if (p_mode_flags == READ_WRITE)
- mode_string = L"rb+";
- else if (p_mode_flags == WRITE_READ)
- mode_string = L"wb+";
- else
- return ERR_INVALID_PARAMETER;
-
- struct _stat st;
- if (_wstat(path.c_str(), &st) == 0) {
- if (!S_ISREG(st.st_mode))
- return ERR_FILE_CANT_OPEN;
- };
- #ifdef TOOLS_ENABLED
-
-
-
-
- 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 = path;
- path = path + ".tmp";
- }
- _wfopen_s(&f, path.c_str(), mode_string);
- if (f == NULL) {
- last_error = ERR_FILE_CANT_OPEN;
- return ERR_FILE_CANT_OPEN;
- } else {
- last_error = OK;
- flags = p_mode_flags;
- return OK;
- }
- }
- void FileAccessWindows::close() {
- if (!f)
- return;
- fclose(f);
- f = NULL;
- if (save_path != "") {
- bool rename_error = true;
- int attempts = 4;
- while (rename_error && attempts) {
-
-
-
- #ifdef UWP_ENABLED
-
- DWORD fileAttr;
- fileAttr = GetFileAttributesW(save_path.c_str());
- if (INVALID_FILE_ATTRIBUTES == fileAttr) {
- #else
- if (!PathFileExistsW(save_path.c_str())) {
- #endif
-
- rename_error = _wrename((save_path + ".tmp").c_str(), save_path.c_str()) != 0;
- } else {
-
- rename_error = !ReplaceFileW(save_path.c_str(), (save_path + ".tmp").c_str(), NULL, 2 | 4, NULL, NULL);
- }
- if (rename_error) {
- attempts--;
- OS::get_singleton()->delay_usec(100000);
- }
- }
- 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);
- }
- void FileAccessWindows::seek(size_t p_position) {
- ERR_FAIL_COND(!f);
- last_error = OK;
- if (fseek(f, p_position, SEEK_SET))
- check_errors();
- }
- void FileAccessWindows::seek_end(int64_t p_position) {
- ERR_FAIL_COND(!f);
- if (fseek(f, p_position, SEEK_END))
- check_errors();
- }
- size_t FileAccessWindows::get_position() const {
- size_t aux_position = 0;
- aux_position = ftell(f);
- if (!aux_position) {
- check_errors();
- };
- return aux_position;
- }
- size_t FileAccessWindows::get_len() const {
- ERR_FAIL_COND_V(!f, 0);
- size_t pos = get_position();
- fseek(f, 0, SEEK_END);
- int size = get_position();
- fseek(f, pos, SEEK_SET);
- return size;
- }
- bool FileAccessWindows::eof_reached() const {
- check_errors();
- return last_error == ERR_FILE_EOF;
- }
- uint8_t FileAccessWindows::get_8() const {
- ERR_FAIL_COND_V(!f, 0);
- uint8_t b;
- if (fread(&b, 1, 1, f) == 0) {
- check_errors();
- b = '\0';
- };
- return b;
- }
- int FileAccessWindows::get_buffer(uint8_t *p_dst, int p_length) const {
- ERR_FAIL_COND_V(!f, -1);
- int read = fread(p_dst, 1, p_length, f);
- check_errors();
- return read;
- };
- Error FileAccessWindows::get_error() const {
- return last_error;
- }
- void FileAccessWindows::flush() {
- ERR_FAIL_COND(!f);
- fflush(f);
- }
- void FileAccessWindows::store_8(uint8_t p_dest) {
- ERR_FAIL_COND(!f);
- 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;
-
- String filename = fix_path(p_name);
- _wfopen_s(&g, filename.c_str(), L"rb");
- if (g == NULL) {
- return false;
- } else {
- fclose(g);
- return true;
- }
- }
- uint64_t FileAccessWindows::_get_modified_time(const String &p_file) {
- String file = fix_path(p_file);
- if (file.ends_with("/") && file != "/")
- file = file.substr(0, file.length() - 1);
- struct _stat st;
- int rv = _wstat(file.c_str(), &st);
- if (rv == 0) {
- return st.st_mtime;
- } else {
- ERR_EXPLAIN("Failed to get modified time for: " + file);
- ERR_FAIL_V(0);
- }
- }
- FileAccessWindows::FileAccessWindows() :
- f(NULL),
- flags(0),
- last_error(OK) {
- }
- FileAccessWindows::~FileAccessWindows() {
- close();
- }
- #endif
|