Browse Source

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
Pedro J. Estébanez 5 years ago
parent
commit
fa08b0f377
3 changed files with 57 additions and 9 deletions
  1. 25 6
      core/io/file_access_pack.cpp
  2. 26 0
      core/io/file_access_pack.h
  3. 6 3
      core/os/file_access.cpp

+ 25 - 6
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) {

+ 26 - 0
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<String> 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

+ 6 - 3
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 + "'.");