From fa08b0f3776f4c30ec642d5b40ea3fee9048f63c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20J=2E=20Est=C3=A9banez?= Date: Mon, 27 Jul 2020 11:18:14 +0200 Subject: [PATCH] Improve/fix packed data API - Enhance directory API - Fix `FileAccess::exists()` not checking for PackedData being disabled - Fix moving to the parent directory (`..`) - Allow absolute paths in existence checks --- core/io/file_access_pack.cpp | 31 +++++++++++++++++++++++++------ core/io/file_access_pack.h | 26 ++++++++++++++++++++++++++ core/os/file_access.cpp | 9 ++++++--- 3 files changed, 57 insertions(+), 9 deletions(-) diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp index 83ce03418af..87c6853dd71 100644 --- a/core/io/file_access_pack.cpp +++ b/core/io/file_access_pack.cpp @@ -403,9 +403,15 @@ String DirAccessPack::get_drive(int p_drive) { return ""; } -Error DirAccessPack::change_dir(String p_dir) { +PackedData::PackedDir *DirAccessPack::_find_dir(String p_dir) { String nd = p_dir.replace("\\", "/"); + + // Special handling since simplify_path() will forbid it + if (p_dir == "..") { + return current->parent; + } + bool absolute = false; if (nd.begins_with("res://")) { nd = nd.replace_first("res://", ""); @@ -445,13 +451,22 @@ Error DirAccessPack::change_dir(String p_dir) { } else { - return ERR_INVALID_PARAMETER; + return NULL; } } - current = pd; + return pd; +} - return OK; +Error DirAccessPack::change_dir(String p_dir) { + + PackedData::PackedDir *pd = _find_dir(p_dir); + if (pd) { + current = pd; + return OK; + } else { + return ERR_INVALID_PARAMETER; + } } String DirAccessPack::get_current_dir() { @@ -471,14 +486,18 @@ bool DirAccessPack::file_exists(String p_file) { p_file = fix_path(p_file); - return current->files.has(p_file); + PackedData::PackedDir *pd = _find_dir(p_file.get_base_dir()); + if (!pd) { + return false; + } + return pd->files.has(p_file.get_file()); } bool DirAccessPack::dir_exists(String p_dir) { p_dir = fix_path(p_dir); - return current->subdirs.has(p_dir); + return _find_dir(p_dir) != NULL; } Error DirAccessPack::make_dir(String p_dir) { diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h index b6ea9c158fd..20c71459cc4 100644 --- a/core/io/file_access_pack.h +++ b/core/io/file_access_pack.h @@ -118,6 +118,9 @@ public: _FORCE_INLINE_ FileAccess *try_open_path(const String &p_path); _FORCE_INLINE_ bool has_path(const String &p_path); + _FORCE_INLINE_ DirAccess *try_open_directory(const String &p_path); + _FORCE_INLINE_ bool has_directory(const String &p_path); + PackedData(); ~PackedData(); }; @@ -197,6 +200,17 @@ bool PackedData::has_path(const String &p_path) { return files.has(PathMD5(p_path.md5_buffer())); } +bool PackedData::has_directory(const String &p_path) { + + DirAccess *da = try_open_directory(p_path); + if (da) { + memdelete(da); + return true; + } else { + return false; + } +} + class DirAccessPack : public DirAccess { PackedData::PackedDir *current; @@ -205,6 +219,8 @@ class DirAccessPack : public DirAccess { List list_files; bool cdir; + PackedData::PackedDir *_find_dir(String p_dir); + public: virtual Error list_dir_begin(); virtual String get_next(); @@ -234,4 +250,14 @@ public: ~DirAccessPack(); }; +DirAccess *PackedData::try_open_directory(const String &p_path) { + + DirAccess *da = memnew(DirAccessPack()); + if (da->change_dir(p_path) != OK) { + memdelete(da); + da = NULL; + } + return da; +} + #endif // FILE_ACCESS_PACK_H diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp index 2917351a2f9..bacdfd3c8ad 100644 --- a/core/os/file_access.cpp +++ b/core/os/file_access.cpp @@ -53,7 +53,7 @@ FileAccess *FileAccess::create(AccessType p_access) { bool FileAccess::exists(const String &p_name) { - if (PackedData::get_singleton() && PackedData::get_singleton()->has_path(p_name)) + if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && PackedData::get_singleton()->has_path(p_name)) return true; FileAccess *f = open(p_name, READ); @@ -494,7 +494,7 @@ void FileAccess::store_double(double p_dest) { uint64_t FileAccess::get_modified_time(const String &p_file) { - if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && PackedData::get_singleton()->has_path(p_file)) + if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) return 0; FileAccess *fa = create_for_path(p_file); @@ -507,7 +507,7 @@ uint64_t FileAccess::get_modified_time(const String &p_file) { uint32_t FileAccess::get_unix_permissions(const String &p_file) { - if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && PackedData::get_singleton()->has_path(p_file)) + if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) return 0; FileAccess *fa = create_for_path(p_file); @@ -520,6 +520,9 @@ uint32_t FileAccess::get_unix_permissions(const String &p_file) { Error FileAccess::set_unix_permissions(const String &p_file, uint32_t p_permissions) { + if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) + return ERR_UNAVAILABLE; + FileAccess *fa = create_for_path(p_file); ERR_FAIL_COND_V_MSG(!fa, ERR_CANT_CREATE, "Cannot create FileAccess for path '" + p_file + "'.");