From cf0bd389cc7294c7e8bc6dbc57a88880cfd8372e 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 (cherry picked from commit 59f04e16b87ed5ce013c4ed184fdac796d814dc8) --- 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 51eb68eaea0..52ed688debf 100644 --- a/core/io/dir_access.h +++ b/core/io/dir_access.h @@ -68,7 +68,7 @@ protected: 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 47770cad870..3374dca7a12 100644 --- a/core/io/file_access.h +++ b/core/io/file_access.h @@ -80,7 +80,7 @@ protected: 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 7b88bd8a957..88eb89656ab 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 9d91c22f7ec..1e55917756a 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 0e51586b5a4..03930626a52 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 453f8d3b5f8..13c881e562a 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