diff --git a/core/os/os.h b/core/os/os.h index c42a39e0a42b..c3c0dba10800 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -109,6 +109,7 @@ class OS { void add_logger(Logger *p_logger); virtual void initialize() = 0; + virtual void initialize_filesystem() = 0; virtual void initialize_joypads() = 0; void set_display_driver_id(int p_display_driver_id) { _display_driver_id = p_display_driver_id; } diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp index f7632842ed6c..bf21944c1c45 100644 --- a/drivers/windows/dir_access_windows.cpp +++ b/drivers/windows/dir_access_windows.cpp @@ -32,6 +32,7 @@ #include "dir_access_windows.h" #include "file_access_windows.h" +#include "file_system_protocol_os_windows.h" #include "core/config/project_settings.h" #include "core/os/memory.h" @@ -188,7 +189,7 @@ Error DirAccessWindows::change_dir(String p_dir) { Error DirAccessWindows::make_dir(String p_dir) { GLOBAL_LOCK_FUNCTION - if (FileAccessWindows::is_path_invalid(p_dir)) { + if (FileSystemProtocolOSWindows::is_path_invalid(p_dir)) { #ifdef DEBUG_ENABLED WARN_PRINT("The path :" + p_dir + " is a reserved Windows system pipe, so it can't be used for creating directories."); #endif diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp index a8a2ea6b5e0d..b1c133239591 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 "file_system_protocol_os_windows.h" #include "core/config/project_settings.h" #include "core/os/os.h" @@ -60,37 +61,14 @@ void FileAccessWindows::check_errors() const { } } -bool FileAccessWindows::is_path_invalid(const String &p_path) { - // Check for invalid operating system file. - String fname = p_path.get_file().to_lower(); - - int dot = fname.find("."); - if (dot != -1) { - fname = fname.substr(0, dot); - } - return invalid_files.has(fname); -} - String FileAccessWindows::fix_path(const String &p_path) const { String r_path = FileAccess::fix_path(p_path); - if (r_path.is_relative_path()) { - Char16String current_dir_name; - size_t str_len = GetCurrentDirectoryW(0, nullptr); - current_dir_name.resize(str_len + 1); - GetCurrentDirectoryW(current_dir_name.size(), (LPWSTR)current_dir_name.ptrw()); - r_path = String::utf16((const char16_t *)current_dir_name.get_data()).trim_prefix(R"(\\?\)").replace("\\", "/").path_join(r_path); - } - r_path = r_path.simplify_path(); - r_path = r_path.replace("/", "\\"); - if (!r_path.is_network_share_path() && !r_path.begins_with(R"(\\?\)")) { - r_path = R"(\\?\)" + r_path; - } - return r_path; + return FileSystemProtocolOSWindows::fix_path(r_path); } Error FileAccessWindows::open_internal(const String &p_path, int p_mode_flags) { - if (is_path_invalid(p_path)) { + if (FileSystemProtocolOSWindows::is_path_invalid(p_path)) { #ifdef DEBUG_ENABLED if (p_mode_flags != READ) { WARN_PRINT("The path :" + p_path + " is a reserved Windows system pipe, so it can't be used for creating files."); @@ -388,23 +366,13 @@ void FileAccessWindows::store_buffer(const uint8_t *p_src, uint64_t p_length) { ERR_FAIL_COND(fwrite(p_src, 1, p_length, f) != (size_t)p_length); } +// TODO: Remove bool FileAccessWindows::file_exists(const String &p_name) { - if (is_path_invalid(p_name)) { - return false; - } - - String filename = fix_path(p_name); - FILE *g = _wfsopen((LPCWSTR)(filename.utf16().get_data()), L"rb", _SH_DENYNO); - if (g == nullptr) { - return false; - } else { - fclose(g); - return true; - } + return FileSystemProtocolOSWindows::file_exists_static(p_name); } uint64_t FileAccessWindows::_get_modified_time(const String &p_file) { - if (is_path_invalid(p_file)) { + if (FileSystemProtocolOSWindows::is_path_invalid(p_file)) { return 0; } @@ -514,21 +482,4 @@ FileAccessWindows::~FileAccessWindows() { _close(); } -HashSet FileAccessWindows::invalid_files; - -void FileAccessWindows::initialize() { - static const char *reserved_files[]{ - "con", "prn", "aux", "nul", "com0", "com1", "com2", "com3", "com4", "com5", "com6", "com7", "com8", "com9", "lpt0", "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9", nullptr - }; - int reserved_file_index = 0; - while (reserved_files[reserved_file_index] != nullptr) { - invalid_files.insert(reserved_files[reserved_file_index]); - reserved_file_index++; - } -} - -void FileAccessWindows::finalize() { - invalid_files.clear(); -} - #endif // WINDOWS_ENABLED diff --git a/drivers/windows/file_access_windows.h b/drivers/windows/file_access_windows.h index f458ff9c6c60..1be05f4d7bc6 100644 --- a/drivers/windows/file_access_windows.h +++ b/drivers/windows/file_access_windows.h @@ -50,10 +50,7 @@ class FileAccessWindows : public FileAccess { void _close(); - static HashSet invalid_files; - public: - static bool is_path_invalid(const String &p_path); virtual String fix_path(const String &p_path) const override; virtual Error open_internal(const String &p_path, int p_mode_flags) override; ///< open a file @@ -90,9 +87,6 @@ class FileAccessWindows : public FileAccess { virtual void close() override; - static void initialize(); - static void finalize(); - FileAccessWindows() {} virtual ~FileAccessWindows(); }; diff --git a/drivers/windows/file_system_protocol_os_windows.cpp b/drivers/windows/file_system_protocol_os_windows.cpp new file mode 100644 index 000000000000..77dd5b28b0d3 --- /dev/null +++ b/drivers/windows/file_system_protocol_os_windows.cpp @@ -0,0 +1,106 @@ +/**************************************************************************/ +/* file_system_protocol_os_windows.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifdef WINDOWS_ENABLED + +#include "file_system_protocol_os_windows.h" + +#include // _SH_DENYNO +#include +#define WIN32_LEAN_AND_MEAN +#include + +HashSet FileSystemProtocolOSWindows::invalid_files; +void FileSystemProtocolOSWindows::initialize() { + static const char *reserved_files[]{ + "con", "prn", "aux", "nul", "com0", "com1", "com2", "com3", "com4", "com5", "com6", "com7", "com8", "com9", "lpt0", "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9", nullptr + }; + int reserved_file_index = 0; + while (reserved_files[reserved_file_index] != nullptr) { + invalid_files.insert(reserved_files[reserved_file_index]); + reserved_file_index++; + } +} +void FileSystemProtocolOSWindows::finalize() { + invalid_files.clear(); +} + +bool FileSystemProtocolOSWindows::is_path_invalid(const String &p_path) { + // Check for invalid operating system file. + String fname = p_path.get_file().to_lower(); + + int dot = fname.find("."); + if (dot != -1) { + fname = fname.substr(0, dot); + } + return invalid_files.has(fname); +} + +String FileSystemProtocolOSWindows::fix_path(const String &p_path) { + String r_path = p_path; + + if (r_path.is_relative_path()) { + Char16String current_dir_name; + size_t str_len = GetCurrentDirectoryW(0, nullptr); + current_dir_name.resize(str_len + 1); + GetCurrentDirectoryW(current_dir_name.size(), (LPWSTR)current_dir_name.ptrw()); + r_path = String::utf16((const char16_t *)current_dir_name.get_data()).trim_prefix(R"(\\?\)").replace("\\", "/").path_join(r_path); + } + r_path = r_path.simplify_path(); + r_path = r_path.replace("/", "\\"); + if (!r_path.is_network_share_path() && !r_path.begins_with(R"(\\?\)")) { + r_path = R"(\\?\)" + r_path; + } + return r_path; +} + +bool FileSystemProtocolOSWindows::file_exists_static(const String &p_path) { + if (is_path_invalid(p_path)) { + return false; + } + + String filename = fix_path(p_path); + FILE *g = _wfsopen((LPCWSTR)(filename.utf16().get_data()), L"rb", _SH_DENYNO); + if (g == nullptr) { + return false; + } else { + fclose(g); + return true; + } +} + +Ref FileSystemProtocolOSWindows::open_file(const String &p_path, int p_mode_flags, Error *r_error) const { + *r_error = ERR_UNAVAILABLE; + return Ref(); +} +bool FileSystemProtocolOSWindows::file_exists(const String &p_path) const { + return file_exists_static(p_path); +} +#endif // WINDOWS_ENABLED diff --git a/drivers/windows/file_system_protocol_os_windows.h b/drivers/windows/file_system_protocol_os_windows.h new file mode 100644 index 000000000000..009d69c69c72 --- /dev/null +++ b/drivers/windows/file_system_protocol_os_windows.h @@ -0,0 +1,55 @@ +/**************************************************************************/ +/* file_system_protocol_os_windows.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef FILE_SYSTEM_PROTOCOL_OS_WINDOWS_H +#define FILE_SYSTEM_PROTOCOL_OS_WINDOWS_H + +#ifdef WINDOWS_ENABLED + +#include "core/io/file_system_protocol.h" + +class FileSystemProtocolOSWindows : public FileSystemProtocol { +private: + static HashSet invalid_files; + +public: + static void initialize(); + static void finalize(); + + static String fix_path(const String &p_path); + static bool is_path_invalid(const String &p_path); + static bool file_exists_static(const String &p_path); + + virtual Ref open_file(const String &p_path, int p_mode_flags, Error *r_error) const override; + virtual bool file_exists(const String &p_path) const override; +}; +#endif // WINDOWS_ENABLED + +#endif // FILE_SYSTEM_PROTOCOL_OS_WINDOWS_H diff --git a/main/main.cpp b/main/main.cpp index 1e0b021d9ce7..7aae4a8c52c8 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -958,6 +958,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph input_map = memnew(InputMap); globals = memnew(ProjectSettings); filesystem = memnew(FileSystem); + OS::get_singleton()->initialize_filesystem(); register_core_settings(); //here globals are present diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index adc72a79e9cf..daf23d4fb2c0 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -38,12 +38,14 @@ #include "core/debugger/engine_debugger.h" #include "core/debugger/script_debugger.h" +#include "core/io/file_system.h" #include "core/io/marshalls.h" #include "core/version_generated.gen.h" #include "drivers/unix/net_socket_posix.h" #include "drivers/windows/dir_access_windows.h" #include "drivers/windows/file_access_windows.h" #include "drivers/windows/file_access_windows_pipe.h" +#include "drivers/windows/file_system_protocol_os_windows.h" #include "main/main.h" #include "servers/audio_server.h" #include "servers/rendering/rendering_server_default.h" @@ -201,14 +203,6 @@ void OS_Windows::initialize() { add_error_handler(&error_handlers); #endif - FileAccess::make_default(FileAccess::ACCESS_RESOURCES); - FileAccess::make_default(FileAccess::ACCESS_USERDATA); - FileAccess::make_default(FileAccess::ACCESS_FILESYSTEM); - FileAccess::make_default(FileAccess::ACCESS_PIPE); - DirAccess::make_default(DirAccess::ACCESS_RESOURCES); - DirAccess::make_default(DirAccess::ACCESS_USERDATA); - DirAccess::make_default(DirAccess::ACCESS_FILESYSTEM); - NetSocketPosix::make_default(); // We need to know how often the clock is updated @@ -250,8 +244,22 @@ void OS_Windows::initialize() { } else if (!dwrite2_init) { print_verbose("Unable to load IDWriteFactory2, automatic system font fallback is disabled."); } +} +void OS_Windows::initialize_filesystem() { + FileSystem *fs = FileSystem::get_singleton(); + FileSystemProtocolOSWindows::initialize(); + + Ref protocol_os = Ref(); + protocol_os.instantiate(); + fs->add_protocol(FileSystem::protocol_name_os, protocol_os); - FileAccessWindows::initialize(); + FileAccess::make_default(FileAccess::ACCESS_RESOURCES); + FileAccess::make_default(FileAccess::ACCESS_USERDATA); + FileAccess::make_default(FileAccess::ACCESS_FILESYSTEM); + FileAccess::make_default(FileAccess::ACCESS_PIPE); + DirAccess::make_default(DirAccess::ACCESS_RESOURCES); + DirAccess::make_default(DirAccess::ACCESS_USERDATA); + DirAccess::make_default(DirAccess::ACCESS_FILESYSTEM); } void OS_Windows::delete_main_loop() { @@ -298,7 +306,7 @@ void OS_Windows::finalize_core() { _remove_temp_library(temp_libraries.last()->key); } - FileAccessWindows::finalize(); + FileSystemProtocolOSWindows::finalize(); timeEndPeriod(1); diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 4f9bc049ee5b..2dc57b33e5e5 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -137,6 +137,7 @@ class OS_Windows : public OS { // functions used by main to initialize/deinitialize the OS protected: virtual void initialize() override; + virtual void initialize_filesystem() override; virtual void set_main_loop(MainLoop *p_main_loop) override; virtual void delete_main_loop() override;