summaryrefslogtreecommitdiffstats
path: root/core/io/file_access_pack.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/io/file_access_pack.cpp')
-rw-r--r--core/io/file_access_pack.cpp145
1 files changed, 76 insertions, 69 deletions
diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp
index 7dbea96c3d..ba120de68b 100644
--- a/core/io/file_access_pack.cpp
+++ b/core/io/file_access_pack.cpp
@@ -32,6 +32,7 @@
#include "core/io/file_access_encrypted.h"
#include "core/object/script_language.h"
+#include "core/os/os.h"
#include "core/version.h"
#include <stdio.h>
@@ -126,60 +127,81 @@ PackedData::~PackedData() {
//////////////////////////////////////////////////////////////////
bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset) {
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ if (f.is_null()) {
return false;
}
- f->seek(p_offset);
+ bool pck_header_found = false;
+ // Search for the header at the start offset - standalone PCK file.
+ f->seek(p_offset);
uint32_t magic = f->get_32();
+ if (magic == PACK_HEADER_MAGIC) {
+ pck_header_found = true;
+ }
- if (magic != PACK_HEADER_MAGIC) {
- // loading with offset feature not supported for self contained exe files
+ // Search for the header in the executable "pck" section - self contained executable.
+ if (!pck_header_found) {
+ // Loading with offset feature not supported for self contained exe files.
if (p_offset != 0) {
- f->close();
- memdelete(f);
ERR_FAIL_V_MSG(false, "Loading self-contained executable with offset not supported.");
}
- //maybe at the end.... self contained exe
- f->seek_end();
- f->seek(f->get_position() - 4);
- magic = f->get_32();
- if (magic != PACK_HEADER_MAGIC) {
- f->close();
- memdelete(f);
- return false;
+ int64_t pck_off = OS::get_singleton()->get_embedded_pck_offset();
+ if (pck_off != 0) {
+ // Search for the header, in case PCK start and section have different alignment.
+ for (int i = 0; i < 8; i++) {
+ f->seek(pck_off);
+ magic = f->get_32();
+ if (magic == PACK_HEADER_MAGIC) {
+#ifdef DEBUG_ENABLED
+ print_verbose("PCK header found in executable pck section, loading from offset 0x" + String::num_int64(pck_off - 4, 16));
+#endif
+ pck_header_found = true;
+ break;
+ }
+ pck_off++;
+ }
}
- f->seek(f->get_position() - 12);
+ }
- uint64_t ds = f->get_64();
- f->seek(f->get_position() - ds - 8);
+ // Search for the header at the end of file - self contained executable.
+ if (!pck_header_found) {
+ // Loading with offset feature not supported for self contained exe files.
+ if (p_offset != 0) {
+ ERR_FAIL_V_MSG(false, "Loading self-contained executable with offset not supported.");
+ }
+ f->seek_end();
+ f->seek(f->get_position() - 4);
magic = f->get_32();
- if (magic != PACK_HEADER_MAGIC) {
- f->close();
- memdelete(f);
- return false;
+
+ if (magic == PACK_HEADER_MAGIC) {
+ f->seek(f->get_position() - 12);
+ uint64_t ds = f->get_64();
+ f->seek(f->get_position() - ds - 8);
+ magic = f->get_32();
+ if (magic == PACK_HEADER_MAGIC) {
+#ifdef DEBUG_ENABLED
+ print_verbose("PCK header found at the end of executable, loading from offset 0x" + String::num_int64(f->get_position() - 4, 16));
+#endif
+ pck_header_found = true;
+ }
}
}
+ if (!pck_header_found) {
+ return false;
+ }
+
uint32_t version = f->get_32();
uint32_t ver_major = f->get_32();
uint32_t ver_minor = f->get_32();
f->get_32(); // patch number, not used for validation.
- if (version != PACK_FORMAT_VERSION) {
- f->close();
- memdelete(f);
- ERR_FAIL_V_MSG(false, "Pack version unsupported: " + itos(version) + ".");
- }
- if (ver_major > VERSION_MAJOR || (ver_major == VERSION_MAJOR && ver_minor > VERSION_MINOR)) {
- f->close();
- memdelete(f);
- ERR_FAIL_V_MSG(false, "Pack created with a newer version of the engine: " + itos(ver_major) + "." + itos(ver_minor) + ".");
- }
+ ERR_FAIL_COND_V_MSG(version != PACK_FORMAT_VERSION, false, "Pack version unsupported: " + itos(version) + ".");
+ ERR_FAIL_COND_V_MSG(ver_major > VERSION_MAJOR || (ver_major == VERSION_MAJOR && ver_minor > VERSION_MINOR), false, "Pack created with a newer version of the engine: " + itos(ver_major) + "." + itos(ver_minor) + ".");
uint32_t pack_flags = f->get_32();
uint64_t file_base = f->get_64();
@@ -194,12 +216,9 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files,
int file_count = f->get_32();
if (enc_directory) {
- FileAccessEncrypted *fae = memnew(FileAccessEncrypted);
- if (!fae) {
- f->close();
- memdelete(f);
- ERR_FAIL_V_MSG(false, "Can't open encrypted pack directory.");
- }
+ Ref<FileAccessEncrypted> fae;
+ fae.instantiate();
+ ERR_FAIL_COND_V_MSG(fae.is_null(), false, "Can't open encrypted pack directory.");
Vector<uint8_t> key;
key.resize(32);
@@ -208,12 +227,7 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files,
}
Error err = fae->open_and_parse(f, key, FileAccessEncrypted::MODE_READ, false);
- if (err) {
- f->close();
- memdelete(f);
- memdelete(fae);
- ERR_FAIL_V_MSG(false, "Can't open encrypted pack directory.");
- }
+ ERR_FAIL_COND_V_MSG(err, false, "Can't open encrypted pack directory.");
f = fae;
}
@@ -236,12 +250,10 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files,
PackedData::get_singleton()->add_path(p_path, path, ofs + p_offset, size, md5, this, p_replace_files, (flags & PACK_FILE_ENCRYPTED));
}
- f->close();
- memdelete(f);
return true;
}
-FileAccess *PackedSourcePCK::get_file(const String &p_path, PackedData::PackedFile *p_file) {
+Ref<FileAccess> PackedSourcePCK::get_file(const String &p_path, PackedData::PackedFile *p_file) {
return memnew(FileAccessPack(p_path, *p_file));
}
@@ -252,15 +264,17 @@ Error FileAccessPack::_open(const String &p_path, int p_mode_flags) {
return ERR_UNAVAILABLE;
}
-void FileAccessPack::close() {
- f->close();
-}
-
bool FileAccessPack::is_open() const {
- return f->is_open();
+ if (f.is_valid()) {
+ return f->is_open();
+ } else {
+ return false;
+ }
}
void FileAccessPack::seek(uint64_t p_position) {
+ ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use.");
+
if (p_position > pf.size) {
eof = true;
} else {
@@ -288,6 +302,7 @@ bool FileAccessPack::eof_reached() const {
}
uint8_t FileAccessPack::get_8() const {
+ ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use.");
if (pos >= pf.size) {
eof = true;
return 0;
@@ -298,6 +313,7 @@ uint8_t FileAccessPack::get_8() const {
}
uint64_t FileAccessPack::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
+ ERR_FAIL_COND_V_MSG(f.is_null(), -1, "File must be opened before use.");
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
if (eof) {
@@ -321,6 +337,8 @@ uint64_t FileAccessPack::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
}
void FileAccessPack::set_big_endian(bool p_big_endian) {
+ ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use.");
+
FileAccess::set_big_endian(p_big_endian);
f->set_big_endian(p_big_endian);
}
@@ -351,16 +369,15 @@ bool FileAccessPack::file_exists(const String &p_name) {
FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file) :
pf(p_file),
f(FileAccess::open(pf.pack, FileAccess::READ)) {
- ERR_FAIL_COND_MSG(!f, "Can't open pack-referenced file '" + String(pf.pack) + "'.");
+ ERR_FAIL_COND_MSG(f.is_null(), "Can't open pack-referenced file '" + String(pf.pack) + "'.");
f->seek(pf.offset);
off = pf.offset;
if (pf.encrypted) {
- FileAccessEncrypted *fae = memnew(FileAccessEncrypted);
- if (!fae) {
- ERR_FAIL_MSG("Can't open encrypted pack-referenced file '" + String(pf.pack) + "'.");
- }
+ Ref<FileAccessEncrypted> fae;
+ fae.instantiate();
+ ERR_FAIL_COND_MSG(fae.is_null(), "Can't open encrypted pack-referenced file '" + String(pf.pack) + "'.");
Vector<uint8_t> key;
key.resize(32);
@@ -369,10 +386,7 @@ FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFil
}
Error err = fae->open_and_parse(f, key, FileAccessEncrypted::MODE_READ, false);
- if (err) {
- memdelete(fae);
- ERR_FAIL_MSG("Can't open encrypted pack-referenced file '" + String(pf.pack) + "'.");
- }
+ ERR_FAIL_COND_MSG(err, "Can't open encrypted pack-referenced file '" + String(pf.pack) + "'.");
f = fae;
off = 0;
}
@@ -380,13 +394,6 @@ FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFil
eof = false;
}
-FileAccessPack::~FileAccessPack() {
- if (f) {
- f->close();
- memdelete(f);
- }
-}
-
//////////////////////////////////////////////////////////////////////////////////
// DIR ACCESS
//////////////////////////////////////////////////////////////////////////////////
@@ -507,7 +514,7 @@ Error DirAccessPack::change_dir(String p_dir) {
}
}
-String DirAccessPack::get_current_dir(bool p_include_drive) {
+String DirAccessPack::get_current_dir(bool p_include_drive) const {
PackedData::PackedDir *pd = current;
String p = current->name;