Skip to content

Commit f38949a

Browse files
committed
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
1 parent 4fdc3e6 commit f38949a

File tree

3 files changed

+55
-9
lines changed

3 files changed

+55
-9
lines changed

core/io/file_access_pack.cpp

+24-6
Original file line numberDiff line numberDiff line change
@@ -376,8 +376,14 @@ String DirAccessPack::get_drive(int p_drive) {
376376
return "";
377377
}
378378

379-
Error DirAccessPack::change_dir(String p_dir) {
379+
PackedData::PackedDir *DirAccessPack::_find_dir(String p_dir) {
380380
String nd = p_dir.replace("\\", "/");
381+
382+
// Special handling since simplify_path() will forbid it
383+
if (p_dir == "..") {
384+
return current->parent;
385+
}
386+
381387
bool absolute = false;
382388
if (nd.begins_with("res://")) {
383389
nd = nd.replace_first("res://", "");
@@ -417,13 +423,21 @@ Error DirAccessPack::change_dir(String p_dir) {
417423
pd = pd->subdirs[p];
418424

419425
} else {
420-
return ERR_INVALID_PARAMETER;
426+
return nullptr;
421427
}
422428
}
423429

424-
current = pd;
430+
return pd;
431+
}
425432

426-
return OK;
433+
Error DirAccessPack::change_dir(String p_dir) {
434+
PackedData::PackedDir *pd = _find_dir(p_dir);
435+
if (pd) {
436+
current = pd;
437+
return OK;
438+
} else {
439+
return ERR_INVALID_PARAMETER;
440+
}
427441
}
428442

429443
String DirAccessPack::get_current_dir(bool p_include_drive) {
@@ -441,13 +455,17 @@ String DirAccessPack::get_current_dir(bool p_include_drive) {
441455
bool DirAccessPack::file_exists(String p_file) {
442456
p_file = fix_path(p_file);
443457

444-
return current->files.has(p_file);
458+
PackedData::PackedDir *pd = _find_dir(p_file.get_base_dir());
459+
if (!pd) {
460+
return false;
461+
}
462+
return pd->files.has(p_file.get_file());
445463
}
446464

447465
bool DirAccessPack::dir_exists(String p_dir) {
448466
p_dir = fix_path(p_dir);
449467

450-
return current->subdirs.has(p_dir);
468+
return _find_dir(p_dir) != nullptr;
451469
}
452470

453471
Error DirAccessPack::make_dir(String p_dir) {

core/io/file_access_pack.h

+24
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ class PackedData {
113113
_FORCE_INLINE_ FileAccess *try_open_path(const String &p_path);
114114
_FORCE_INLINE_ bool has_path(const String &p_path);
115115

116+
_FORCE_INLINE_ DirAccess *try_open_directory(const String &p_path);
117+
_FORCE_INLINE_ bool has_directory(const String &p_path);
118+
116119
PackedData();
117120
~PackedData();
118121
};
@@ -189,13 +192,25 @@ bool PackedData::has_path(const String &p_path) {
189192
return files.has(PathMD5(p_path.md5_buffer()));
190193
}
191194

195+
bool PackedData::has_directory(const String &p_path) {
196+
DirAccess *da = try_open_directory(p_path);
197+
if (da) {
198+
memdelete(da);
199+
return true;
200+
} else {
201+
return false;
202+
}
203+
}
204+
192205
class DirAccessPack : public DirAccess {
193206
PackedData::PackedDir *current;
194207

195208
List<String> list_dirs;
196209
List<String> list_files;
197210
bool cdir = false;
198211

212+
PackedData::PackedDir *_find_dir(String p_dir);
213+
199214
public:
200215
virtual Error list_dir_begin();
201216
virtual String get_next();
@@ -225,4 +240,13 @@ class DirAccessPack : public DirAccess {
225240
~DirAccessPack() {}
226241
};
227242

243+
DirAccess *PackedData::try_open_directory(const String &p_path) {
244+
DirAccess *da = memnew(DirAccessPack());
245+
if (da->change_dir(p_path) != OK) {
246+
memdelete(da);
247+
da = nullptr;
248+
}
249+
return da;
250+
}
251+
228252
#endif // FILE_ACCESS_PACK_H

core/os/file_access.cpp

+7-3
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ FileAccess *FileAccess::create(AccessType p_access) {
5151
}
5252

5353
bool FileAccess::exists(const String &p_name) {
54-
if (PackedData::get_singleton() && PackedData::get_singleton()->has_path(p_name)) {
54+
if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && PackedData::get_singleton()->has_path(p_name)) {
5555
return true;
5656
}
5757

@@ -456,7 +456,7 @@ void FileAccess::store_double(double p_dest) {
456456
}
457457

458458
uint64_t FileAccess::get_modified_time(const String &p_file) {
459-
if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && PackedData::get_singleton()->has_path(p_file)) {
459+
if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) {
460460
return 0;
461461
}
462462

@@ -469,7 +469,7 @@ uint64_t FileAccess::get_modified_time(const String &p_file) {
469469
}
470470

471471
uint32_t FileAccess::get_unix_permissions(const String &p_file) {
472-
if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && PackedData::get_singleton()->has_path(p_file)) {
472+
if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) {
473473
return 0;
474474
}
475475

@@ -482,6 +482,10 @@ uint32_t FileAccess::get_unix_permissions(const String &p_file) {
482482
}
483483

484484
Error FileAccess::set_unix_permissions(const String &p_file, uint32_t p_permissions) {
485+
if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) {
486+
return ERR_UNAVAILABLE;
487+
}
488+
485489
FileAccess *fa = create_for_path(p_file);
486490
ERR_FAIL_COND_V_MSG(!fa, ERR_CANT_CREATE, "Cannot create FileAccess for path '" + p_file + "'.");
487491

0 commit comments

Comments
 (0)