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
This commit is contained in:
Samuele Panzeri 2023-05-05 02:12:55 +02:00
parent d023e51363
commit 59f04e16b8
6 changed files with 23 additions and 8 deletions

View File

@ -68,7 +68,7 @@ protected:
virtual String _get_root_string() const; virtual String _get_root_string() const;
AccessType get_access_type() const; AccessType get_access_type() const;
String fix_path(String p_path) const; virtual String fix_path(String p_path) const;
template <class T> template <class T>
static Ref<DirAccess> _create_builtin() { static Ref<DirAccess> _create_builtin() {

View File

@ -81,7 +81,7 @@ protected:
static void _bind_methods(); static void _bind_methods();
AccessType get_access_type() const; 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 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 uint64_t _get_modified_time(const String &p_file) = 0;
virtual void _set_access_type(AccessType p_access); virtual void _set_access_type(AccessType p_access);

View File

@ -59,6 +59,14 @@ struct DirAccessWindowsPrivate {
WIN32_FIND_DATAW fu; //unicode version 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 // CreateFolderAsync
Error DirAccessWindows::list_dir_begin() { Error DirAccessWindows::list_dir_begin() {
@ -158,6 +166,7 @@ Error DirAccessWindows::make_dir(String p_dir) {
p_dir = fix_path(p_dir); p_dir = fix_path(p_dir);
if (p_dir.is_relative_path()) { if (p_dir.is_relative_path()) {
p_dir = current_dir.path_join(p_dir); p_dir = current_dir.path_join(p_dir);
p_dir = fix_path(p_dir);
} }
p_dir = p_dir.simplify_path().replace("/", "\\"); p_dir = p_dir.simplify_path().replace("/", "\\");
@ -165,12 +174,6 @@ Error DirAccessWindows::make_dir(String p_dir) {
bool success; bool success;
int err; 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); success = CreateDirectoryW((LPCWSTR)(p_dir.utf16().get_data()), nullptr);
err = GetLastError(); err = GetLastError();

View File

@ -53,6 +53,9 @@ class DirAccessWindows : public DirAccess {
bool _cisdir = false; bool _cisdir = false;
bool _cishidden = false; bool _cishidden = false;
protected:
virtual String fix_path(String p_path) const override;
public: public:
virtual Error list_dir_begin() override; ///< This starts dir listing virtual Error list_dir_begin() override; ///< This starts dir listing
virtual String get_next() override; virtual String get_next() override;

View File

@ -68,6 +68,14 @@ bool FileAccessWindows::is_path_invalid(const String &p_path) {
return invalid_files.has(fname); 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) { Error FileAccessWindows::open_internal(const String &p_path, int p_mode_flags) {
if (is_path_invalid(p_path)) { if (is_path_invalid(p_path)) {
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED

View File

@ -54,6 +54,7 @@ class FileAccessWindows : public FileAccess {
static HashSet<String> invalid_files; static HashSet<String> invalid_files;
public: 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 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 virtual bool is_open() const override; ///< true when file is open