From 59f04e16b87ed5ce013c4ed184fdac796d814dc8 Mon Sep 17 00:00:00 2001 From: Samuele Panzeri Date: Fri, 5 May 2023 02:12:55 +0200 Subject: [PATCH] Support long path in file access on windows Changed windows file access file to check for path length and use the \\?\ long format when needed --- core/io/dir_access.h | 2 +- core/io/file_access.h | 2 +- drivers/windows/dir_access_windows.cpp | 15 +++++++++------ drivers/windows/dir_access_windows.h | 3 +++ drivers/windows/file_access_windows.cpp | 8 ++++++++ drivers/windows/file_access_windows.h | 1 + 6 files changed, 23 insertions(+), 8 deletions(-) diff --git a/core/io/dir_access.h b/core/io/dir_access.h index 51eb68eaea0c..52ed688debf3 100644 --- a/core/io/dir_access.h +++ b/core/io/dir_access.h @@ -68,7 +68,7 @@ class DirAccess : public RefCounted { virtual String _get_root_string() const; AccessType get_access_type() const; - String fix_path(String p_path) const; + virtual String fix_path(String p_path) const; template static Ref _create_builtin() { diff --git a/core/io/file_access.h b/core/io/file_access.h index 34c80b3dd9b4..ad1ac665f313 100644 --- a/core/io/file_access.h +++ b/core/io/file_access.h @@ -81,7 +81,7 @@ class FileAccess : public RefCounted { static void _bind_methods(); AccessType get_access_type() const; - String fix_path(const String &p_path) const; + virtual String fix_path(const String &p_path) const; virtual Error open_internal(const String &p_path, int p_mode_flags) = 0; ///< open a file virtual uint64_t _get_modified_time(const String &p_file) = 0; virtual void _set_access_type(AccessType p_access); diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp index 7b88bd8a9577..88eb89656ab9 100644 --- a/drivers/windows/dir_access_windows.cpp +++ b/drivers/windows/dir_access_windows.cpp @@ -59,6 +59,14 @@ struct DirAccessWindowsPrivate { WIN32_FIND_DATAW fu; //unicode version }; +String DirAccessWindows::fix_path(String p_path) const { + String r_path = DirAccess::fix_path(p_path); + if (r_path.is_absolute_path() && !r_path.is_network_share_path() && r_path.length() > MAX_PATH) { + r_path = "\\\\?\\" + r_path.replace("/", "\\"); + } + return r_path; +} + // CreateFolderAsync Error DirAccessWindows::list_dir_begin() { @@ -158,6 +166,7 @@ Error DirAccessWindows::make_dir(String p_dir) { p_dir = fix_path(p_dir); if (p_dir.is_relative_path()) { p_dir = current_dir.path_join(p_dir); + p_dir = fix_path(p_dir); } p_dir = p_dir.simplify_path().replace("/", "\\"); @@ -165,12 +174,6 @@ Error DirAccessWindows::make_dir(String p_dir) { bool success; int err; - if (!p_dir.is_network_share_path()) { - p_dir = "\\\\?\\" + p_dir; - // Add "\\?\" to the path to extend max. path length past 248, if it's not a network share UNC path. - // See https://msdn.microsoft.com/en-us/library/windows/desktop/aa363855(v=vs.85).aspx - } - success = CreateDirectoryW((LPCWSTR)(p_dir.utf16().get_data()), nullptr); err = GetLastError(); diff --git a/drivers/windows/dir_access_windows.h b/drivers/windows/dir_access_windows.h index 9d91c22f7ecb..1e55917756ad 100644 --- a/drivers/windows/dir_access_windows.h +++ b/drivers/windows/dir_access_windows.h @@ -53,6 +53,9 @@ class DirAccessWindows : public DirAccess { bool _cisdir = false; bool _cishidden = false; +protected: + virtual String fix_path(String p_path) const override; + public: virtual Error list_dir_begin() override; ///< This starts dir listing virtual String get_next() override; diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp index f36bbcc350f6..6e69743d4ef1 100644 --- a/drivers/windows/file_access_windows.cpp +++ b/drivers/windows/file_access_windows.cpp @@ -68,6 +68,14 @@ bool FileAccessWindows::is_path_invalid(const String &p_path) { 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_absolute_path() && !r_path.is_network_share_path() && r_path.length() > MAX_PATH) { + r_path = "\\\\?\\" + r_path.replace("/", "\\"); + } + return r_path; +} + Error FileAccessWindows::open_internal(const String &p_path, int p_mode_flags) { if (is_path_invalid(p_path)) { #ifdef DEBUG_ENABLED diff --git a/drivers/windows/file_access_windows.h b/drivers/windows/file_access_windows.h index 453f8d3b5f87..13c881e562a0 100644 --- a/drivers/windows/file_access_windows.h +++ b/drivers/windows/file_access_windows.h @@ -54,6 +54,7 @@ class FileAccessWindows : public FileAccess { static HashSet invalid_files; public: + 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 virtual bool is_open() const override; ///< true when file is open