mirror of
https://github.com/Relintai/pandemonium_engine_minimal.git
synced 2024-11-17 22:17:19 +01:00
zip support cleanups.
This commit is contained in:
parent
8f12605cd5
commit
decd780d70
@ -33,7 +33,6 @@
|
||||
#include "core/bind/core_bind.h"
|
||||
#include "core/core_string_names.h"
|
||||
#include "core/io/file_access_network.h"
|
||||
#include "core/io/file_access_pack.h"
|
||||
#include "core/io/marshalls.h"
|
||||
#include "core/os/dir_access.h"
|
||||
#include "core/os/file_access.h"
|
||||
@ -41,8 +40,6 @@
|
||||
#include "core/os/os.h"
|
||||
#include "core/variant/variant_parser.h"
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
const String ProjectSettings::PROJECT_DATA_DIR_NAME_SUFFIX = "import";
|
||||
|
||||
ProjectSettings *ProjectSettings::singleton = nullptr;
|
||||
@ -276,24 +273,6 @@ void ProjectSettings::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||
}
|
||||
}
|
||||
|
||||
bool ProjectSettings::_load_resource_pack(const String &p_pack, bool p_replace_files, int p_offset) {
|
||||
if (PackedData::get_singleton()->is_disabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ok = PackedData::get_singleton()->add_pack(p_pack, p_replace_files, p_offset) == OK;
|
||||
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//if data.pck is found, all directory access will be from here
|
||||
DirAccess::make_default<DirAccessPack>(DirAccess::ACCESS_RESOURCES);
|
||||
using_datapack = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ProjectSettings::_convert_to_last_version(int p_from_version) {
|
||||
if (p_from_version <= 3) {
|
||||
// Converts the actions from array to dictionary (array of events to dictionary with deadzone + events)
|
||||
@ -356,84 +335,6 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
|
||||
return err;
|
||||
}
|
||||
|
||||
// Attempt with a user-defined main pack first
|
||||
|
||||
if (p_main_pack != "") {
|
||||
bool ok = _load_resource_pack(p_main_pack);
|
||||
ERR_FAIL_COND_V_MSG(!ok, ERR_CANT_OPEN, "Cannot open resource pack '" + p_main_pack + "'.");
|
||||
|
||||
Error err = _load_settings_text_or_binary("res://project.pandemonium", "res://project.binary");
|
||||
if (err == OK && !p_ignore_override) {
|
||||
// Load override from location of the main pack
|
||||
// Optional, we don't mind if it fails
|
||||
_load_settings_text(p_main_pack.get_base_dir().plus_file("override.cfg"));
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
String exec_path = OS::get_singleton()->get_executable_path();
|
||||
|
||||
if (exec_path != "") {
|
||||
// We do several tests sequentially until one succeeds to find a PCK,
|
||||
// and if so we attempt loading it at the end.
|
||||
|
||||
// Attempt with PCK bundled into executable.
|
||||
bool found = _load_resource_pack(exec_path);
|
||||
|
||||
// Attempt with exec_name.pck.
|
||||
// (This is the usual case when distributing a Pandemonium game.)
|
||||
String exec_dir = exec_path.get_base_dir();
|
||||
String exec_filename = exec_path.get_file();
|
||||
String exec_basename = exec_filename.get_basename();
|
||||
|
||||
// Based on the OS, it can be the exec path + '.pck' (Linux w/o extension, macOS in .app bundle)
|
||||
// or the exec path's basename + '.pck' (Windows).
|
||||
// We need to test both possibilities as extensions for Linux binaries are optional
|
||||
// (so both 'mygame.bin' and 'mygame' should be able to find 'mygame.pck').
|
||||
|
||||
#ifdef OSX_ENABLED
|
||||
if (!found) {
|
||||
// Attempt to load PCK from macOS .app bundle resources.
|
||||
found = _load_resource_pack(OS::get_singleton()->get_bundle_resource_dir().plus_file(exec_basename + ".pck")) || _load_resource_pack(OS::get_singleton()->get_bundle_resource_dir().plus_file(exec_filename + ".pck"));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!found) {
|
||||
// Try to load data pack at the location of the executable.
|
||||
// As mentioned above, we have two potential names to attempt.
|
||||
found = _load_resource_pack(exec_dir.plus_file(exec_basename + ".pck")) || _load_resource_pack(exec_dir.plus_file(exec_filename + ".pck"));
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
// If we couldn't find them next to the executable, we attempt
|
||||
// the current working directory. Same story, two tests.
|
||||
found = _load_resource_pack(exec_basename + ".pck") || _load_resource_pack(exec_filename + ".pck");
|
||||
}
|
||||
|
||||
// If we opened our package, try and load our project.
|
||||
if (found) {
|
||||
Error err = _load_settings_text_or_binary("res://project.pandemonium", "res://project.binary");
|
||||
if (err == OK && !p_ignore_override) {
|
||||
// Load override from location of the executable.
|
||||
// Optional, we don't mind if it fails.
|
||||
_load_settings_text(exec_path.get_base_dir().plus_file("override.cfg"));
|
||||
}
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to use the filesystem for files, according to OS.
|
||||
// (Only Android -when reading from pck- and iOS use this.)
|
||||
|
||||
if (OS::get_singleton()->get_resource_dir() != "") {
|
||||
Error err = _load_settings_text_or_binary("res://project.pandemonium", "res://project.binary");
|
||||
if (err == OK && !p_ignore_override) {
|
||||
// Optional, we don't mind if it fails.
|
||||
_load_settings_text("res://override.cfg");
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
// Nothing was found, try to find a project file in provided path (`p_path`)
|
||||
// or, if requested (`p_upwards`) in parent directories.
|
||||
|
||||
@ -1001,7 +902,6 @@ void ProjectSettings::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("localize_path", "path"), &ProjectSettings::localize_path);
|
||||
ClassDB::bind_method(D_METHOD("globalize_path", "path"), &ProjectSettings::globalize_path);
|
||||
ClassDB::bind_method(D_METHOD("save"), &ProjectSettings::save);
|
||||
ClassDB::bind_method(D_METHOD("load_resource_pack", "pack", "replace_files", "offset"), &ProjectSettings::_load_resource_pack, DEFVAL(true), DEFVAL(0));
|
||||
ClassDB::bind_method(D_METHOD("property_can_revert", "name"), &ProjectSettings::property_can_revert);
|
||||
ClassDB::bind_method(D_METHOD("property_get_revert", "name"), &ProjectSettings::property_get_revert);
|
||||
|
||||
|
@ -135,8 +135,6 @@ protected:
|
||||
|
||||
void _convert_to_last_version(int p_from_version);
|
||||
|
||||
bool _load_resource_pack(const String &p_pack, bool p_replace_files = true, int p_offset = 0);
|
||||
|
||||
void _add_property_info_bind(const Dictionary &p_info);
|
||||
|
||||
Error _setup(const String &p_path, const String &p_main_pack, bool p_upwards = false, bool p_ignore_override = false);
|
||||
|
@ -1,542 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* file_access_pack.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "file_access_pack.h"
|
||||
|
||||
#include "core/os/os.h"
|
||||
#include "core/version.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
Error PackedData::add_pack(const String &p_path, bool p_replace_files, uint64_t p_offset) {
|
||||
for (int i = 0; i < sources.size(); i++) {
|
||||
if (sources[i]->try_open_pack(p_path, p_replace_files, p_offset)) {
|
||||
return OK;
|
||||
};
|
||||
};
|
||||
|
||||
return ERR_FILE_UNRECOGNIZED;
|
||||
};
|
||||
|
||||
void PackedData::add_path(const String &p_pkg_path, const String &p_path, uint64_t p_ofs, uint64_t p_size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files) {
|
||||
PathMD5 pmd5(p_path.md5_buffer());
|
||||
|
||||
bool exists = files.has(pmd5);
|
||||
|
||||
PackedFile pf;
|
||||
pf.pack = p_pkg_path;
|
||||
pf.offset = p_ofs;
|
||||
pf.size = p_size;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
pf.md5[i] = p_md5[i];
|
||||
}
|
||||
pf.src = p_src;
|
||||
|
||||
if (!exists || p_replace_files) {
|
||||
files[pmd5] = pf;
|
||||
}
|
||||
|
||||
if (!exists) {
|
||||
//search for dir
|
||||
String p = p_path.replace_first("res://", "");
|
||||
PackedDir *cd = root;
|
||||
|
||||
if (p.find("/") != -1) { //in a subdir
|
||||
|
||||
Vector<String> ds = p.get_base_dir().split("/");
|
||||
|
||||
for (int j = 0; j < ds.size(); j++) {
|
||||
if (!cd->subdirs.has(ds[j])) {
|
||||
PackedDir *pd = memnew(PackedDir);
|
||||
pd->name = ds[j];
|
||||
pd->parent = cd;
|
||||
cd->subdirs[pd->name] = pd;
|
||||
cd = pd;
|
||||
} else {
|
||||
cd = cd->subdirs[ds[j]];
|
||||
}
|
||||
}
|
||||
}
|
||||
String filename = p_path.get_file();
|
||||
// Don't add as a file if the path points to a directory
|
||||
if (!filename.empty()) {
|
||||
cd->files.insert(filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PackedData::add_pack_source(PackSource *p_source) {
|
||||
if (p_source != nullptr) {
|
||||
sources.push_back(p_source);
|
||||
}
|
||||
};
|
||||
|
||||
PackedData *PackedData::singleton = nullptr;
|
||||
|
||||
PackedData::PackedData() {
|
||||
singleton = this;
|
||||
root = memnew(PackedDir);
|
||||
root->parent = nullptr;
|
||||
disabled = false;
|
||||
|
||||
add_pack_source(memnew(PackedSourcePCK));
|
||||
}
|
||||
|
||||
void PackedData::_free_packed_dirs(PackedDir *p_dir) {
|
||||
for (RBMap<String, PackedDir *>::Element *E = p_dir->subdirs.front(); E; E = E->next()) {
|
||||
_free_packed_dirs(E->get());
|
||||
}
|
||||
memdelete(p_dir);
|
||||
}
|
||||
|
||||
PackedData::~PackedData() {
|
||||
for (int i = 0; i < sources.size(); i++) {
|
||||
memdelete(sources[i]);
|
||||
}
|
||||
_free_packed_dirs(root);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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.");
|
||||
}
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
f->close();
|
||||
memdelete(f);
|
||||
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->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) {
|
||||
f->close();
|
||||
memdelete(f);
|
||||
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) + ".");
|
||||
}
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
//reserved
|
||||
f->get_32();
|
||||
}
|
||||
|
||||
int file_count = f->get_32();
|
||||
|
||||
for (int i = 0; i < file_count; i++) {
|
||||
uint32_t sl = f->get_32();
|
||||
CharString cs;
|
||||
cs.resize(sl + 1);
|
||||
f->get_buffer((uint8_t *)cs.ptr(), sl);
|
||||
cs[sl] = 0;
|
||||
|
||||
String path;
|
||||
path.parse_utf8(cs.ptr());
|
||||
|
||||
uint64_t ofs = f->get_64();
|
||||
uint64_t size = f->get_64();
|
||||
uint8_t md5[16];
|
||||
f->get_buffer(md5, 16);
|
||||
PackedData::get_singleton()->add_path(p_path, path, ofs + p_offset, size, md5, this, p_replace_files);
|
||||
};
|
||||
|
||||
f->close();
|
||||
memdelete(f);
|
||||
return true;
|
||||
};
|
||||
|
||||
FileAccess *PackedSourcePCK::get_file(const String &p_path, PackedData::PackedFile *p_file) {
|
||||
return memnew(FileAccessPack(p_path, *p_file));
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
Error FileAccessPack::_open(const String &p_path, int p_mode_flags) {
|
||||
ERR_FAIL_V(ERR_UNAVAILABLE);
|
||||
return ERR_UNAVAILABLE;
|
||||
}
|
||||
|
||||
void FileAccessPack::close() {
|
||||
f->close();
|
||||
}
|
||||
|
||||
bool FileAccessPack::is_open() const {
|
||||
return f->is_open();
|
||||
}
|
||||
|
||||
void FileAccessPack::seek(uint64_t p_position) {
|
||||
if (p_position > pf.size) {
|
||||
eof = true;
|
||||
} else {
|
||||
eof = false;
|
||||
}
|
||||
|
||||
f->seek(pf.offset + p_position);
|
||||
pos = p_position;
|
||||
}
|
||||
|
||||
void FileAccessPack::seek_end(int64_t p_position) {
|
||||
seek(pf.size + p_position);
|
||||
}
|
||||
|
||||
uint64_t FileAccessPack::get_position() const {
|
||||
return pos;
|
||||
}
|
||||
|
||||
uint64_t FileAccessPack::get_len() const {
|
||||
return pf.size;
|
||||
}
|
||||
|
||||
bool FileAccessPack::eof_reached() const {
|
||||
return eof;
|
||||
}
|
||||
|
||||
uint8_t FileAccessPack::get_8() const {
|
||||
if (pos >= pf.size) {
|
||||
eof = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pos++;
|
||||
return f->get_8();
|
||||
}
|
||||
|
||||
uint64_t FileAccessPack::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
|
||||
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
|
||||
|
||||
if (eof) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t to_read = p_length;
|
||||
if (to_read + pos > pf.size) {
|
||||
eof = true;
|
||||
to_read = (int64_t)pf.size - (int64_t)pos;
|
||||
}
|
||||
|
||||
pos += p_length;
|
||||
|
||||
if (to_read <= 0) {
|
||||
return 0;
|
||||
}
|
||||
f->get_buffer(p_dst, to_read);
|
||||
|
||||
return to_read;
|
||||
}
|
||||
|
||||
void FileAccessPack::set_endian_swap(bool p_swap) {
|
||||
FileAccess::set_endian_swap(p_swap);
|
||||
f->set_endian_swap(p_swap);
|
||||
}
|
||||
|
||||
Error FileAccessPack::get_error() const {
|
||||
if (eof) {
|
||||
return ERR_FILE_EOF;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
void FileAccessPack::flush() {
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
void FileAccessPack::store_8(uint8_t p_dest) {
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
void FileAccessPack::store_buffer(const uint8_t *p_src, uint64_t p_length) {
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
bool FileAccessPack::file_exists(const String &p_name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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) + "'.");
|
||||
|
||||
f->seek(pf.offset);
|
||||
pos = 0;
|
||||
eof = false;
|
||||
}
|
||||
|
||||
FileAccessPack::~FileAccessPack() {
|
||||
if (f) {
|
||||
memdelete(f);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// DIR ACCESS
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Error DirAccessPack::list_dir_begin() {
|
||||
list_dirs.clear();
|
||||
list_files.clear();
|
||||
|
||||
for (RBMap<String, PackedData::PackedDir *>::Element *E = current->subdirs.front(); E; E = E->next()) {
|
||||
list_dirs.push_back(E->key());
|
||||
}
|
||||
|
||||
for (RBSet<String>::Element *E = current->files.front(); E; E = E->next()) {
|
||||
list_files.push_back(E->get());
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
String DirAccessPack::get_next() {
|
||||
if (list_dirs.size()) {
|
||||
cdir = true;
|
||||
String d = list_dirs.front()->get();
|
||||
list_dirs.pop_front();
|
||||
return d;
|
||||
} else if (list_files.size()) {
|
||||
cdir = false;
|
||||
String f = list_files.front()->get();
|
||||
list_files.pop_front();
|
||||
return f;
|
||||
} else {
|
||||
return String();
|
||||
}
|
||||
}
|
||||
bool DirAccessPack::current_is_dir() const {
|
||||
return cdir;
|
||||
}
|
||||
bool DirAccessPack::current_is_hidden() const {
|
||||
return false;
|
||||
}
|
||||
void DirAccessPack::list_dir_end() {
|
||||
list_dirs.clear();
|
||||
list_files.clear();
|
||||
}
|
||||
|
||||
int DirAccessPack::get_drive_count() {
|
||||
return 0;
|
||||
}
|
||||
String DirAccessPack::get_drive(int p_drive) {
|
||||
return "";
|
||||
}
|
||||
|
||||
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://", "");
|
||||
absolute = true;
|
||||
}
|
||||
|
||||
nd = nd.simplify_path();
|
||||
|
||||
if (nd == "") {
|
||||
nd = ".";
|
||||
}
|
||||
|
||||
if (nd.begins_with("/")) {
|
||||
nd = nd.replace_first("/", "");
|
||||
absolute = true;
|
||||
}
|
||||
|
||||
Vector<String> paths = nd.split("/");
|
||||
|
||||
PackedData::PackedDir *pd;
|
||||
|
||||
if (absolute) {
|
||||
pd = PackedData::get_singleton()->root;
|
||||
} else {
|
||||
pd = current;
|
||||
}
|
||||
|
||||
for (int i = 0; i < paths.size(); i++) {
|
||||
String p = paths[i];
|
||||
if (p == ".") {
|
||||
continue;
|
||||
} else if (p == "..") {
|
||||
if (pd->parent) {
|
||||
pd = pd->parent;
|
||||
}
|
||||
} else if (pd->subdirs.has(p)) {
|
||||
pd = pd->subdirs[p];
|
||||
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return pd;
|
||||
}
|
||||
|
||||
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() {
|
||||
PackedData::PackedDir *pd = current;
|
||||
String p = current->name;
|
||||
|
||||
while (pd->parent) {
|
||||
pd = pd->parent;
|
||||
p = pd->name.plus_file(p);
|
||||
}
|
||||
|
||||
return "res://" + p;
|
||||
}
|
||||
|
||||
bool DirAccessPack::file_exists(String p_file) {
|
||||
p_file = fix_path(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 _find_dir(p_dir) != nullptr;
|
||||
}
|
||||
|
||||
Error DirAccessPack::make_dir(String p_dir) {
|
||||
return ERR_UNAVAILABLE;
|
||||
}
|
||||
|
||||
Error DirAccessPack::rename(String p_from, String p_to) {
|
||||
return ERR_UNAVAILABLE;
|
||||
}
|
||||
Error DirAccessPack::remove(String p_name) {
|
||||
return ERR_UNAVAILABLE;
|
||||
}
|
||||
|
||||
uint64_t DirAccessPack::get_space_left() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
String DirAccessPack::get_filesystem_type() const {
|
||||
return "PCK";
|
||||
}
|
||||
|
||||
DirAccessPack::DirAccessPack() {
|
||||
current = PackedData::get_singleton()->root;
|
||||
cdir = false;
|
||||
}
|
||||
|
||||
DirAccessPack::~DirAccessPack() {
|
||||
}
|
@ -1,264 +0,0 @@
|
||||
#ifndef FILE_ACCESS_PACK_H
|
||||
#define FILE_ACCESS_PACK_H
|
||||
/*************************************************************************/
|
||||
/* file_access_pack.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "core/containers/list.h"
|
||||
#include "core/containers/rb_map.h"
|
||||
#include "core/os/dir_access.h"
|
||||
#include "core/os/file_access.h"
|
||||
#include "core/string/print_string.h"
|
||||
#include "core/containers/rb_set.h"
|
||||
#include "core/containers/hashfuncs.h"
|
||||
|
||||
// Pandemonium's packed file magic header ("GDPC" in ASCII).
|
||||
#define PACK_HEADER_MAGIC 0x43504447
|
||||
// The current packed file format version number.
|
||||
#define PACK_FORMAT_VERSION 1
|
||||
|
||||
class PackSource;
|
||||
|
||||
class PackedData {
|
||||
friend class FileAccessPack;
|
||||
friend class DirAccessPack;
|
||||
friend class PackSource;
|
||||
|
||||
public:
|
||||
struct PackedFile {
|
||||
String pack;
|
||||
uint64_t offset; //if offset is ZERO, the file was ERASED
|
||||
uint64_t size;
|
||||
uint8_t md5[16];
|
||||
PackSource *src;
|
||||
};
|
||||
|
||||
private:
|
||||
struct PackedDir {
|
||||
PackedDir *parent;
|
||||
String name;
|
||||
RBMap<String, PackedDir *> subdirs;
|
||||
RBSet<String> files;
|
||||
};
|
||||
|
||||
struct PathMD5 {
|
||||
uint64_t a;
|
||||
uint64_t b;
|
||||
bool operator<(const PathMD5 &p_md5) const {
|
||||
if (p_md5.a == a) {
|
||||
return b < p_md5.b;
|
||||
} else {
|
||||
return a < p_md5.a;
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const PathMD5 &p_md5) const {
|
||||
return a == p_md5.a && b == p_md5.b;
|
||||
};
|
||||
|
||||
static uint32_t hash(const PathMD5 &p_val) {
|
||||
uint32_t h = hash_murmur3_one_32(p_val.a);
|
||||
return hash_fmix32(hash_murmur3_one_32(p_val.b, h));
|
||||
}
|
||||
|
||||
PathMD5() {
|
||||
a = b = 0;
|
||||
};
|
||||
|
||||
PathMD5(const Vector<uint8_t> p_buf) {
|
||||
a = *((uint64_t *)&p_buf[0]);
|
||||
b = *((uint64_t *)&p_buf[8]);
|
||||
};
|
||||
};
|
||||
|
||||
RBMap<PathMD5, PackedFile> files;
|
||||
|
||||
Vector<PackSource *> sources;
|
||||
|
||||
PackedDir *root;
|
||||
|
||||
static PackedData *singleton;
|
||||
bool disabled;
|
||||
|
||||
void _free_packed_dirs(PackedDir *p_dir);
|
||||
|
||||
public:
|
||||
void add_pack_source(PackSource *p_source);
|
||||
void add_path(const String &p_pkg_path, const String &p_path, uint64_t p_ofs, uint64_t p_size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files); // for PackSource
|
||||
|
||||
void set_disabled(bool p_disabled) { disabled = p_disabled; }
|
||||
_FORCE_INLINE_ bool is_disabled() const { return disabled; }
|
||||
|
||||
static PackedData *get_singleton() { return singleton; }
|
||||
Error add_pack(const String &p_path, bool p_replace_files, uint64_t p_offset);
|
||||
|
||||
_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();
|
||||
};
|
||||
|
||||
class PackSource {
|
||||
public:
|
||||
virtual bool try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset) = 0;
|
||||
virtual FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file) = 0;
|
||||
virtual ~PackSource() {}
|
||||
};
|
||||
|
||||
class PackedSourcePCK : public PackSource {
|
||||
public:
|
||||
virtual bool try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset);
|
||||
virtual FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file);
|
||||
};
|
||||
|
||||
class FileAccessPack : public FileAccess {
|
||||
PackedData::PackedFile pf;
|
||||
|
||||
mutable uint64_t pos;
|
||||
mutable bool eof;
|
||||
|
||||
FileAccess *f;
|
||||
virtual Error _open(const String &p_path, int p_mode_flags);
|
||||
virtual uint64_t _get_modified_time(const String &p_file) { return 0; }
|
||||
virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; }
|
||||
virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; }
|
||||
|
||||
public:
|
||||
virtual void close();
|
||||
virtual bool is_open() const;
|
||||
|
||||
virtual void seek(uint64_t p_position);
|
||||
virtual void seek_end(int64_t p_position = 0);
|
||||
virtual uint64_t get_position() const;
|
||||
virtual uint64_t get_len() const;
|
||||
|
||||
virtual bool eof_reached() const;
|
||||
|
||||
virtual uint8_t get_8() const;
|
||||
|
||||
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const;
|
||||
|
||||
virtual void set_endian_swap(bool p_swap);
|
||||
|
||||
virtual Error get_error() const;
|
||||
|
||||
virtual void flush();
|
||||
virtual void store_8(uint8_t p_dest);
|
||||
|
||||
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length);
|
||||
|
||||
virtual bool file_exists(const String &p_name);
|
||||
|
||||
FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file);
|
||||
~FileAccessPack();
|
||||
};
|
||||
|
||||
FileAccess *PackedData::try_open_path(const String &p_path) {
|
||||
PathMD5 pmd5(p_path.md5_buffer());
|
||||
RBMap<PathMD5, PackedFile>::Element *E = files.find(pmd5);
|
||||
if (!E) {
|
||||
return nullptr; //not found
|
||||
}
|
||||
if (E->get().offset == 0) {
|
||||
return nullptr; //was erased
|
||||
}
|
||||
|
||||
return E->get().src->get_file(p_path, &E->get());
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
List<String> list_dirs;
|
||||
List<String> list_files;
|
||||
bool cdir;
|
||||
|
||||
PackedData::PackedDir *_find_dir(String p_dir);
|
||||
|
||||
public:
|
||||
virtual Error list_dir_begin();
|
||||
virtual String get_next();
|
||||
virtual bool current_is_dir() const;
|
||||
virtual bool current_is_hidden() const;
|
||||
virtual void list_dir_end();
|
||||
|
||||
virtual int get_drive_count();
|
||||
virtual String get_drive(int p_drive);
|
||||
|
||||
virtual Error change_dir(String p_dir);
|
||||
virtual String get_current_dir();
|
||||
|
||||
virtual bool file_exists(String p_file);
|
||||
virtual bool dir_exists(String p_dir);
|
||||
|
||||
virtual Error make_dir(String p_dir);
|
||||
|
||||
virtual Error rename(String p_from, String p_to);
|
||||
virtual Error remove(String p_name);
|
||||
|
||||
virtual bool is_link(String p_file) { return false; }
|
||||
virtual String read_link(String p_file) { return p_file; }
|
||||
virtual Error create_link(String p_source, String p_target) { return FAILED; }
|
||||
|
||||
uint64_t get_space_left();
|
||||
|
||||
virtual String get_filesystem_type() const;
|
||||
|
||||
DirAccessPack();
|
||||
~DirAccessPack();
|
||||
};
|
||||
|
||||
DirAccess *PackedData::try_open_directory(const String &p_path) {
|
||||
DirAccess *da = memnew(DirAccessPack());
|
||||
if (da->change_dir(p_path) != OK) {
|
||||
memdelete(da);
|
||||
da = nullptr;
|
||||
}
|
||||
return da;
|
||||
}
|
||||
|
||||
#endif // FILE_ACCESS_PACK_H
|
@ -1,349 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* file_access_zip.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifdef MINIZIP_ENABLED
|
||||
|
||||
#include "file_access_zip.h"
|
||||
|
||||
#include "core/os/file_access.h"
|
||||
|
||||
ZipArchive *ZipArchive::instance = nullptr;
|
||||
|
||||
extern "C" {
|
||||
|
||||
static void *pandemonium_open(void *data, const char *p_fname, int mode) {
|
||||
if (mode & ZLIB_FILEFUNC_MODE_WRITE) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FileAccess *f = FileAccess::open(p_fname, FileAccess::READ);
|
||||
ERR_FAIL_COND_V(!f, nullptr);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
static uLong pandemonium_read(void *data, void *fdata, void *buf, uLong size) {
|
||||
FileAccess *f = (FileAccess *)fdata;
|
||||
f->get_buffer((uint8_t *)buf, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static uLong pandemonium_write(voidpf opaque, voidpf stream, const void *buf, uLong size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long pandemonium_tell(voidpf opaque, voidpf stream) {
|
||||
FileAccess *f = (FileAccess *)stream;
|
||||
return f->get_position();
|
||||
}
|
||||
|
||||
static long pandemonium_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
|
||||
FileAccess *f = (FileAccess *)stream;
|
||||
|
||||
uint64_t pos = offset;
|
||||
switch (origin) {
|
||||
case ZLIB_FILEFUNC_SEEK_CUR:
|
||||
pos = f->get_position() + offset;
|
||||
break;
|
||||
case ZLIB_FILEFUNC_SEEK_END:
|
||||
pos = f->get_len() + offset;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
f->seek(pos);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pandemonium_close(voidpf opaque, voidpf stream) {
|
||||
FileAccess *f = (FileAccess *)stream;
|
||||
if (f) {
|
||||
f->close();
|
||||
memdelete(f);
|
||||
f = nullptr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pandemonium_testerror(voidpf opaque, voidpf stream) {
|
||||
FileAccess *f = (FileAccess *)stream;
|
||||
return f->get_error() != OK ? 1 : 0;
|
||||
}
|
||||
|
||||
static voidpf pandemonium_alloc(voidpf opaque, uInt items, uInt size) {
|
||||
return memalloc(items * size);
|
||||
}
|
||||
|
||||
static void pandemonium_free(voidpf opaque, voidpf address) {
|
||||
memfree(address);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
void ZipArchive::close_handle(unzFile p_file) const {
|
||||
ERR_FAIL_COND_MSG(!p_file, "Cannot close a file if none is open.");
|
||||
unzCloseCurrentFile(p_file);
|
||||
unzClose(p_file);
|
||||
}
|
||||
|
||||
unzFile ZipArchive::get_file_handle(String p_file) const {
|
||||
ERR_FAIL_COND_V_MSG(!file_exists(p_file), nullptr, "File '" + p_file + " doesn't exist.");
|
||||
File file = files[p_file];
|
||||
|
||||
zlib_filefunc_def io;
|
||||
memset(&io, 0, sizeof(io));
|
||||
|
||||
io.opaque = nullptr;
|
||||
io.zopen_file = pandemonium_open;
|
||||
io.zread_file = pandemonium_read;
|
||||
io.zwrite_file = pandemonium_write;
|
||||
|
||||
io.ztell_file = pandemonium_tell;
|
||||
io.zseek_file = pandemonium_seek;
|
||||
io.zclose_file = pandemonium_close;
|
||||
io.zerror_file = pandemonium_testerror;
|
||||
|
||||
io.alloc_mem = pandemonium_alloc;
|
||||
io.free_mem = pandemonium_free;
|
||||
|
||||
unzFile pkg = unzOpen2(packages[file.package].filename.utf8().get_data(), &io);
|
||||
ERR_FAIL_COND_V_MSG(!pkg, nullptr, "Cannot open file '" + packages[file.package].filename + "'.");
|
||||
int unz_err = unzGoToFilePos(pkg, &file.file_pos);
|
||||
if (unz_err != UNZ_OK || unzOpenCurrentFile(pkg) != UNZ_OK) {
|
||||
unzClose(pkg);
|
||||
ERR_FAIL_V(nullptr);
|
||||
}
|
||||
|
||||
return pkg;
|
||||
}
|
||||
|
||||
bool ZipArchive::try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset = 0) {
|
||||
//printf("opening zip pack %s, %i, %i\n", p_name.utf8().get_data(), p_name.extension().nocasecmp_to("zip"), p_name.extension().nocasecmp_to("pcz"));
|
||||
// load with offset feature only supported for PCK files
|
||||
ERR_FAIL_COND_V_MSG(p_offset != 0, false, "Invalid PCK data. Note that loading files with a non-zero offset isn't supported with ZIP archives.");
|
||||
|
||||
if (p_path.get_extension().nocasecmp_to("zip") != 0 && p_path.get_extension().nocasecmp_to("pcz") != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
zlib_filefunc_def io;
|
||||
memset(&io, 0, sizeof(io));
|
||||
|
||||
io.opaque = nullptr;
|
||||
io.zopen_file = pandemonium_open;
|
||||
io.zread_file = pandemonium_read;
|
||||
io.zwrite_file = pandemonium_write;
|
||||
|
||||
io.ztell_file = pandemonium_tell;
|
||||
io.zseek_file = pandemonium_seek;
|
||||
io.zclose_file = pandemonium_close;
|
||||
io.zerror_file = pandemonium_testerror;
|
||||
|
||||
unzFile zfile = unzOpen2(p_path.utf8().get_data(), &io);
|
||||
ERR_FAIL_COND_V(!zfile, false);
|
||||
|
||||
unz_global_info64 gi;
|
||||
int err = unzGetGlobalInfo64(zfile, &gi);
|
||||
ERR_FAIL_COND_V(err != UNZ_OK, false);
|
||||
|
||||
Package pkg;
|
||||
pkg.filename = p_path;
|
||||
pkg.zfile = zfile;
|
||||
packages.push_back(pkg);
|
||||
int pkg_num = packages.size() - 1;
|
||||
|
||||
for (uint64_t i = 0; i < gi.number_entry; i++) {
|
||||
char filename_inzip[256];
|
||||
|
||||
unz_file_info64 file_info;
|
||||
err = unzGetCurrentFileInfo64(zfile, &file_info, filename_inzip, sizeof(filename_inzip), nullptr, 0, nullptr, 0);
|
||||
ERR_CONTINUE(err != UNZ_OK);
|
||||
|
||||
File f;
|
||||
f.package = pkg_num;
|
||||
unzGetFilePos(zfile, &f.file_pos);
|
||||
|
||||
String fname = String("res://") + String::utf8(filename_inzip);
|
||||
files[fname] = f;
|
||||
|
||||
uint8_t md5[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
PackedData::get_singleton()->add_path(p_path, fname, 1, 0, md5, this, p_replace_files);
|
||||
//printf("packed data add path %s, %s\n", p_name.utf8().get_data(), fname.utf8().get_data());
|
||||
|
||||
if ((i + 1) < gi.number_entry) {
|
||||
unzGoToNextFile(zfile);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ZipArchive::file_exists(String p_name) const {
|
||||
return files.has(p_name);
|
||||
}
|
||||
|
||||
FileAccess *ZipArchive::get_file(const String &p_path, PackedData::PackedFile *p_file) {
|
||||
return memnew(FileAccessZip(p_path, *p_file));
|
||||
}
|
||||
|
||||
ZipArchive *ZipArchive::get_singleton() {
|
||||
if (instance == nullptr) {
|
||||
instance = memnew(ZipArchive);
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
ZipArchive::ZipArchive() {
|
||||
instance = this;
|
||||
//fa_create_func = FileAccess::get_create_func();
|
||||
}
|
||||
|
||||
ZipArchive::~ZipArchive() {
|
||||
for (int i = 0; i < packages.size(); i++) {
|
||||
unzClose(packages[i].zfile);
|
||||
}
|
||||
|
||||
packages.clear();
|
||||
}
|
||||
|
||||
Error FileAccessZip::_open(const String &p_path, int p_mode_flags) {
|
||||
close();
|
||||
|
||||
ERR_FAIL_COND_V(p_mode_flags & FileAccess::WRITE, FAILED);
|
||||
ZipArchive *arch = ZipArchive::get_singleton();
|
||||
ERR_FAIL_COND_V(!arch, FAILED);
|
||||
zfile = arch->get_file_handle(p_path);
|
||||
ERR_FAIL_COND_V(!zfile, FAILED);
|
||||
|
||||
int err = unzGetCurrentFileInfo64(zfile, &file_info, nullptr, 0, nullptr, 0, nullptr, 0);
|
||||
ERR_FAIL_COND_V(err != UNZ_OK, FAILED);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
void FileAccessZip::close() {
|
||||
if (!zfile) {
|
||||
return;
|
||||
}
|
||||
|
||||
ZipArchive *arch = ZipArchive::get_singleton();
|
||||
ERR_FAIL_COND(!arch);
|
||||
arch->close_handle(zfile);
|
||||
zfile = nullptr;
|
||||
}
|
||||
|
||||
bool FileAccessZip::is_open() const {
|
||||
return zfile != nullptr;
|
||||
}
|
||||
|
||||
void FileAccessZip::seek(uint64_t p_position) {
|
||||
ERR_FAIL_COND(!zfile);
|
||||
|
||||
unzSeekCurrentFile(zfile, p_position);
|
||||
}
|
||||
|
||||
void FileAccessZip::seek_end(int64_t p_position) {
|
||||
ERR_FAIL_COND(!zfile);
|
||||
unzSeekCurrentFile(zfile, get_len() + p_position);
|
||||
}
|
||||
|
||||
uint64_t FileAccessZip::get_position() const {
|
||||
ERR_FAIL_COND_V(!zfile, 0);
|
||||
return unztell(zfile);
|
||||
}
|
||||
|
||||
uint64_t FileAccessZip::get_len() const {
|
||||
ERR_FAIL_COND_V(!zfile, 0);
|
||||
return file_info.uncompressed_size;
|
||||
}
|
||||
|
||||
bool FileAccessZip::eof_reached() const {
|
||||
ERR_FAIL_COND_V(!zfile, true);
|
||||
|
||||
return at_eof;
|
||||
}
|
||||
|
||||
uint8_t FileAccessZip::get_8() const {
|
||||
uint8_t ret = 0;
|
||||
get_buffer(&ret, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64_t FileAccessZip::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
|
||||
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
|
||||
ERR_FAIL_COND_V(!zfile, -1);
|
||||
|
||||
at_eof = unzeof(zfile);
|
||||
if (at_eof) {
|
||||
return 0;
|
||||
}
|
||||
int64_t read = unzReadCurrentFile(zfile, p_dst, p_length);
|
||||
ERR_FAIL_COND_V(read < 0, read);
|
||||
if ((uint64_t)read < p_length) {
|
||||
at_eof = true;
|
||||
}
|
||||
return read;
|
||||
}
|
||||
|
||||
Error FileAccessZip::get_error() const {
|
||||
if (!zfile) {
|
||||
return ERR_UNCONFIGURED;
|
||||
}
|
||||
if (eof_reached()) {
|
||||
return ERR_FILE_EOF;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
void FileAccessZip::flush() {
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
void FileAccessZip::store_8(uint8_t p_dest) {
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
bool FileAccessZip::file_exists(const String &p_name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FileAccessZip::FileAccessZip(const String &p_path, const PackedData::PackedFile &p_file) :
|
||||
zfile(nullptr) {
|
||||
_open(p_path, FileAccess::READ);
|
||||
}
|
||||
|
||||
FileAccessZip::~FileAccessZip() {
|
||||
close();
|
||||
}
|
||||
|
||||
#endif
|
@ -1,120 +0,0 @@
|
||||
#ifndef FILE_ACCESS_ZIP_H
|
||||
#define FILE_ACCESS_ZIP_H
|
||||
/*************************************************************************/
|
||||
/* file_access_zip.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifdef MINIZIP_ENABLED
|
||||
|
||||
#include "core/io/file_access_pack.h"
|
||||
#include "core/containers/rb_map.h"
|
||||
|
||||
#include "core/thirdparty/minizip/unzip.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
class ZipArchive : public PackSource {
|
||||
public:
|
||||
struct File {
|
||||
int package;
|
||||
unz_file_pos file_pos;
|
||||
File() {
|
||||
package = -1;
|
||||
};
|
||||
};
|
||||
|
||||
private:
|
||||
struct Package {
|
||||
String filename;
|
||||
unzFile zfile;
|
||||
};
|
||||
Vector<Package> packages;
|
||||
|
||||
RBMap<String, File> files;
|
||||
|
||||
static ZipArchive *instance;
|
||||
|
||||
FileAccess::CreateFunc fa_create_func;
|
||||
|
||||
public:
|
||||
void close_handle(unzFile p_file) const;
|
||||
unzFile get_file_handle(String p_file) const;
|
||||
|
||||
Error add_package(String p_name);
|
||||
|
||||
bool file_exists(String p_name) const;
|
||||
|
||||
virtual bool try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset);
|
||||
FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file);
|
||||
|
||||
static ZipArchive *get_singleton();
|
||||
|
||||
ZipArchive();
|
||||
~ZipArchive();
|
||||
};
|
||||
|
||||
class FileAccessZip : public FileAccess {
|
||||
unzFile zfile = nullptr;
|
||||
unz_file_info64 file_info;
|
||||
|
||||
mutable bool at_eof;
|
||||
|
||||
public:
|
||||
virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
|
||||
virtual void close(); ///< close a file
|
||||
virtual bool is_open() const; ///< true when file is open
|
||||
|
||||
virtual void seek(uint64_t p_position); ///< seek to a given position
|
||||
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
|
||||
virtual uint64_t get_position() const; ///< get position in the file
|
||||
virtual uint64_t get_len() const; ///< get size of the file
|
||||
|
||||
virtual bool eof_reached() const; ///< reading passed EOF
|
||||
|
||||
virtual uint8_t get_8() const; ///< get a byte
|
||||
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const;
|
||||
|
||||
virtual Error get_error() const; ///< get last error
|
||||
|
||||
virtual void flush();
|
||||
virtual void store_8(uint8_t p_dest); ///< store a byte
|
||||
|
||||
virtual bool file_exists(const String &p_name); ///< return true if a file exists
|
||||
|
||||
virtual uint64_t _get_modified_time(const String &p_file) { return 0; } // todo
|
||||
virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; }
|
||||
virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; }
|
||||
|
||||
FileAccessZip(const String &p_path, const PackedData::PackedFile &p_file);
|
||||
~FileAccessZip();
|
||||
};
|
||||
|
||||
#endif // MINIZIP_ENABLED
|
||||
|
||||
#endif // FILE_ACCESS_ZIP_H
|
@ -1,187 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* pck_packer.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "pck_packer.h"
|
||||
|
||||
#include "core/io/file_access_pack.h" // PACK_HEADER_MAGIC, PACK_FORMAT_VERSION
|
||||
#include "core/os/file_access.h"
|
||||
#include "core/version.h"
|
||||
|
||||
static uint64_t _align(uint64_t p_n, int p_alignment) {
|
||||
if (p_alignment == 0) {
|
||||
return p_n;
|
||||
}
|
||||
|
||||
uint64_t rest = p_n % p_alignment;
|
||||
if (rest == 0) {
|
||||
return p_n;
|
||||
} else {
|
||||
return p_n + (p_alignment - rest);
|
||||
}
|
||||
};
|
||||
|
||||
static void _pad(FileAccess *p_file, int p_bytes) {
|
||||
for (int i = 0; i < p_bytes; i++) {
|
||||
p_file->store_8(0);
|
||||
};
|
||||
};
|
||||
|
||||
void PCKPacker::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("pck_start", "pck_name", "alignment"), &PCKPacker::pck_start, DEFVAL(0));
|
||||
ClassDB::bind_method(D_METHOD("add_file", "pck_path", "source_path"), &PCKPacker::add_file);
|
||||
ClassDB::bind_method(D_METHOD("flush", "verbose"), &PCKPacker::flush, DEFVAL(false));
|
||||
};
|
||||
|
||||
Error PCKPacker::pck_start(const String &p_file, int p_alignment) {
|
||||
if (file != nullptr) {
|
||||
memdelete(file);
|
||||
}
|
||||
|
||||
file = FileAccess::open(p_file, FileAccess::WRITE);
|
||||
|
||||
ERR_FAIL_COND_V_MSG(!file, ERR_CANT_CREATE, "Can't open file to write: " + String(p_file) + ".");
|
||||
|
||||
alignment = p_alignment;
|
||||
|
||||
file->store_32(PACK_HEADER_MAGIC);
|
||||
file->store_32(PACK_FORMAT_VERSION);
|
||||
file->store_32(VERSION_MAJOR);
|
||||
file->store_32(VERSION_MINOR);
|
||||
file->store_32(VERSION_PATCH);
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
file->store_32(0); // reserved
|
||||
};
|
||||
|
||||
files.clear();
|
||||
|
||||
return OK;
|
||||
};
|
||||
|
||||
Error PCKPacker::add_file(const String &p_file, const String &p_src) {
|
||||
ERR_FAIL_COND_V_MSG(!file, ERR_INVALID_PARAMETER, "File must be opened before use.");
|
||||
|
||||
FileAccess *f = FileAccess::open(p_src, FileAccess::READ);
|
||||
if (!f) {
|
||||
return ERR_FILE_CANT_OPEN;
|
||||
};
|
||||
|
||||
File pf;
|
||||
pf.path = p_file;
|
||||
pf.src_path = p_src;
|
||||
pf.size = f->get_len();
|
||||
pf.offset_offset = 0;
|
||||
|
||||
files.push_back(pf);
|
||||
|
||||
f->close();
|
||||
memdelete(f);
|
||||
|
||||
return OK;
|
||||
};
|
||||
|
||||
Error PCKPacker::flush(bool p_verbose) {
|
||||
ERR_FAIL_COND_V_MSG(!file, ERR_INVALID_PARAMETER, "File must be opened before use.");
|
||||
|
||||
// write the index
|
||||
|
||||
file->store_32(files.size());
|
||||
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
file->store_pascal_string(files[i].path);
|
||||
files.write[i].offset_offset = file->get_position();
|
||||
file->store_64(0); // offset
|
||||
file->store_64(files[i].size); // size
|
||||
|
||||
// # empty md5
|
||||
file->store_32(0);
|
||||
file->store_32(0);
|
||||
file->store_32(0);
|
||||
file->store_32(0);
|
||||
};
|
||||
|
||||
uint64_t ofs = file->get_position();
|
||||
ofs = _align(ofs, alignment);
|
||||
|
||||
_pad(file, ofs - file->get_position());
|
||||
|
||||
const uint32_t buf_max = 65536;
|
||||
uint8_t *buf = memnew_arr(uint8_t, buf_max);
|
||||
|
||||
int count = 0;
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
FileAccess *src = FileAccess::open(files[i].src_path, FileAccess::READ);
|
||||
uint64_t to_write = files[i].size;
|
||||
while (to_write > 0) {
|
||||
uint64_t read = src->get_buffer(buf, MIN(to_write, buf_max));
|
||||
file->store_buffer(buf, read);
|
||||
to_write -= read;
|
||||
};
|
||||
|
||||
uint64_t pos = file->get_position();
|
||||
file->seek(files[i].offset_offset); // go back to store the file's offset
|
||||
file->store_64(ofs);
|
||||
file->seek(pos);
|
||||
|
||||
ofs = _align(ofs + files[i].size, alignment);
|
||||
_pad(file, ofs - pos);
|
||||
|
||||
src->close();
|
||||
memdelete(src);
|
||||
count += 1;
|
||||
const int file_num = files.size();
|
||||
if (p_verbose && (file_num > 0)) {
|
||||
print_line(vformat("[%d/%d - %d%%] PCKPacker flush: %s -> %s", count, file_num, float(count) / file_num * 100, files[i].src_path, files[i].path));
|
||||
}
|
||||
}
|
||||
|
||||
if (p_verbose) {
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
file->close();
|
||||
memdelete(file);
|
||||
file = nullptr;
|
||||
|
||||
memdelete_arr(buf);
|
||||
|
||||
return OK;
|
||||
};
|
||||
|
||||
PCKPacker::PCKPacker() {
|
||||
file = nullptr;
|
||||
};
|
||||
|
||||
PCKPacker::~PCKPacker() {
|
||||
if (file != nullptr) {
|
||||
memdelete(file);
|
||||
};
|
||||
file = nullptr;
|
||||
};
|
@ -1,62 +0,0 @@
|
||||
#ifndef PCK_PACKER_H
|
||||
#define PCK_PACKER_H
|
||||
/*************************************************************************/
|
||||
/* pck_packer.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "core/object/reference.h"
|
||||
|
||||
class FileAccess;
|
||||
|
||||
class PCKPacker : public Reference {
|
||||
GDCLASS(PCKPacker, Reference);
|
||||
|
||||
FileAccess *file;
|
||||
int alignment;
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
struct File {
|
||||
String path;
|
||||
String src_path;
|
||||
uint64_t size;
|
||||
uint64_t offset_offset;
|
||||
};
|
||||
Vector<File> files;
|
||||
|
||||
public:
|
||||
Error pck_start(const String &p_file, int p_alignment = 0);
|
||||
Error add_file(const String &p_file, const String &p_src);
|
||||
Error flush(bool p_verbose = false);
|
||||
|
||||
PCKPacker();
|
||||
~PCKPacker();
|
||||
};
|
||||
|
||||
#endif // PCK_PACKER_H
|
@ -1,125 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* zip_io.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "zip_io.h"
|
||||
|
||||
void *zipio_open(void *data, const char *p_fname, int mode) {
|
||||
FileAccess *&f = *(FileAccess **)data;
|
||||
|
||||
String fname;
|
||||
fname.parse_utf8(p_fname);
|
||||
|
||||
if (mode & ZLIB_FILEFUNC_MODE_WRITE) {
|
||||
f = FileAccess::open(fname, FileAccess::WRITE);
|
||||
} else {
|
||||
f = FileAccess::open(fname, FileAccess::READ);
|
||||
}
|
||||
|
||||
if (!f) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
uLong zipio_read(void *data, void *fdata, void *buf, uLong size) {
|
||||
FileAccess *f = *(FileAccess **)data;
|
||||
return f->get_buffer((uint8_t *)buf, size);
|
||||
}
|
||||
|
||||
uLong zipio_write(voidpf opaque, voidpf stream, const void *buf, uLong size) {
|
||||
FileAccess *f = *(FileAccess **)opaque;
|
||||
f->store_buffer((uint8_t *)buf, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
long zipio_tell(voidpf opaque, voidpf stream) {
|
||||
FileAccess *f = *(FileAccess **)opaque;
|
||||
return f->get_position();
|
||||
}
|
||||
|
||||
long zipio_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
|
||||
FileAccess *f = *(FileAccess **)opaque;
|
||||
|
||||
uint64_t pos = offset;
|
||||
switch (origin) {
|
||||
case ZLIB_FILEFUNC_SEEK_CUR:
|
||||
pos = f->get_position() + offset;
|
||||
break;
|
||||
case ZLIB_FILEFUNC_SEEK_END:
|
||||
pos = f->get_len() + offset;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
f->seek(pos);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zipio_close(voidpf opaque, voidpf stream) {
|
||||
FileAccess *&f = *(FileAccess **)opaque;
|
||||
if (f) {
|
||||
f->close();
|
||||
memdelete(f);
|
||||
f = nullptr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zipio_testerror(voidpf opaque, voidpf stream) {
|
||||
FileAccess *f = *(FileAccess **)opaque;
|
||||
return (f && f->get_error() != OK) ? 1 : 0;
|
||||
}
|
||||
|
||||
voidpf zipio_alloc(voidpf opaque, uInt items, uInt size) {
|
||||
voidpf ptr = memalloc(items * size);
|
||||
memset(ptr, 0, items * size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void zipio_free(voidpf opaque, voidpf address) {
|
||||
memfree(address);
|
||||
}
|
||||
|
||||
zlib_filefunc_def zipio_create_io_from_file(FileAccess **p_file) {
|
||||
zlib_filefunc_def io;
|
||||
io.opaque = p_file;
|
||||
io.zopen_file = zipio_open;
|
||||
io.zread_file = zipio_read;
|
||||
io.zwrite_file = zipio_write;
|
||||
io.ztell_file = zipio_tell;
|
||||
io.zseek_file = zipio_seek;
|
||||
io.zclose_file = zipio_close;
|
||||
io.zerror_file = zipio_testerror;
|
||||
io.alloc_mem = zipio_alloc;
|
||||
io.free_mem = zipio_free;
|
||||
return io;
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
#ifndef ZIP_IO_H
|
||||
#define ZIP_IO_H
|
||||
/*************************************************************************/
|
||||
/* zip_io.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "core/os/file_access.h"
|
||||
|
||||
// Not directly used in this header, but assumed available in downstream users
|
||||
// like platform/*/export/export.cpp. Could be fixed, but probably better to have
|
||||
// thirdparty includes in as little headers as possible.
|
||||
#include "core/thirdparty/minizip/unzip.h"
|
||||
#include "core/thirdparty/minizip/zip.h"
|
||||
|
||||
void *zipio_open(void *data, const char *p_fname, int mode);
|
||||
uLong zipio_read(void *data, void *fdata, void *buf, uLong size);
|
||||
uLong zipio_write(voidpf opaque, voidpf stream, const void *buf, uLong size);
|
||||
|
||||
long zipio_tell(voidpf opaque, voidpf stream);
|
||||
long zipio_seek(voidpf opaque, voidpf stream, uLong offset, int origin);
|
||||
|
||||
int zipio_close(voidpf opaque, voidpf stream);
|
||||
|
||||
int zipio_testerror(voidpf opaque, voidpf stream);
|
||||
|
||||
voidpf zipio_alloc(voidpf opaque, uInt items, uInt size);
|
||||
void zipio_free(voidpf opaque, voidpf address);
|
||||
|
||||
zlib_filefunc_def zipio_create_io_from_file(FileAccess **p_file);
|
||||
|
||||
#endif // ZIP_IO_H
|
@ -31,7 +31,6 @@
|
||||
#include "file_access.h"
|
||||
|
||||
#include "core/crypto/crypto_core.h"
|
||||
#include "core/io/file_access_pack.h"
|
||||
#include "core/io/marshalls.h"
|
||||
#include "core/os/os.h"
|
||||
#include "core/config/project_settings.h"
|
||||
@ -51,10 +50,6 @@ FileAccess *FileAccess::create(AccessType p_access) {
|
||||
}
|
||||
|
||||
bool FileAccess::exists(const String &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);
|
||||
if (!f) {
|
||||
return false;
|
||||
@ -86,20 +81,7 @@ Error FileAccess::reopen(const String &p_path, int p_mode_flags) {
|
||||
};
|
||||
|
||||
FileAccess *FileAccess::open(const String &p_path, int p_mode_flags, Error *r_error) {
|
||||
//try packed data first
|
||||
|
||||
FileAccess *ret = nullptr;
|
||||
if (!(p_mode_flags & WRITE) && PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled()) {
|
||||
ret = PackedData::get_singleton()->try_open_path(p_path);
|
||||
if (ret) {
|
||||
if (r_error) {
|
||||
*r_error = OK;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = create_for_path(p_path);
|
||||
FileAccess *ret = create_for_path(p_path);
|
||||
Error err = ret->_open(p_path, p_mode_flags);
|
||||
|
||||
if (r_error) {
|
||||
@ -460,10 +442,6 @@ 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) || PackedData::get_singleton()->has_directory(p_file))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
FileAccess *fa = create_for_path(p_file);
|
||||
ERR_FAIL_COND_V_MSG(!fa, 0, "Cannot create FileAccess for path '" + p_file + "'.");
|
||||
|
||||
@ -473,10 +451,6 @@ 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) || PackedData::get_singleton()->has_directory(p_file))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
FileAccess *fa = create_for_path(p_file);
|
||||
ERR_FAIL_COND_V_MSG(!fa, 0, "Cannot create FileAccess for path '" + p_file + "'.");
|
||||
|
||||
@ -486,10 +460,6 @@ 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 + "'.");
|
||||
|
||||
|
@ -51,7 +51,6 @@
|
||||
#include "core/io/packet_peer.h"
|
||||
#include "core/io/packet_peer_dtls.h"
|
||||
#include "core/io/packet_peer_udp.h"
|
||||
#include "core/io/pck_packer.h"
|
||||
#include "core/io/resource_format_binary.h"
|
||||
#include "core/io/resource_importer.h"
|
||||
#include "core/io/stream_peer_ssl.h"
|
||||
@ -214,8 +213,6 @@ void register_core_types() {
|
||||
|
||||
ClassDB::register_class<ConfigFile>();
|
||||
|
||||
ClassDB::register_class<PCKPacker>();
|
||||
|
||||
ClassDB::register_class<PackedDataContainer>();
|
||||
ClassDB::register_virtual_class<PackedDataContainerRef>();
|
||||
ClassDB::register_class<AStar>();
|
||||
|
@ -34,8 +34,6 @@
|
||||
#include "core/crypto/crypto.h"
|
||||
#include "core/input/input_map.h"
|
||||
#include "core/io/file_access_network.h"
|
||||
#include "core/io/file_access_pack.h"
|
||||
#include "core/io/file_access_zip.h"
|
||||
#include "core/io/image_loader.h"
|
||||
#include "core/io/ip.h"
|
||||
#include "core/io/resource_loader.h"
|
||||
@ -90,11 +88,7 @@ static ProjectSettings *globals = nullptr;
|
||||
static InputMap *input_map = nullptr;
|
||||
static TranslationServer *translation_server = nullptr;
|
||||
static Performance *performance = nullptr;
|
||||
static PackedData *packed_data = nullptr;
|
||||
static Time *time_singleton = nullptr;
|
||||
#ifdef MINIZIP_ENABLED
|
||||
static ZipArchive *zip_packed_data = nullptr;
|
||||
#endif
|
||||
static FileAccessNetworkClient *file_access_network_client = nullptr;
|
||||
static ScriptDebugger *script_debugger = nullptr;
|
||||
static MessageQueue *message_queue = nullptr;
|
||||
@ -423,23 +417,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
||||
bool found_project = false;
|
||||
#endif
|
||||
|
||||
packed_data = PackedData::get_singleton();
|
||||
if (!packed_data) {
|
||||
packed_data = memnew(PackedData);
|
||||
}
|
||||
|
||||
#ifdef MINIZIP_ENABLED
|
||||
|
||||
//XXX: always get_singleton() == 0x0
|
||||
zip_packed_data = ZipArchive::get_singleton();
|
||||
//TODO: remove this temporary fix
|
||||
if (!zip_packed_data) {
|
||||
zip_packed_data = memnew(ZipArchive);
|
||||
}
|
||||
|
||||
packed_data->add_pack_source(zip_packed_data);
|
||||
#endif
|
||||
|
||||
// Default exit code, can be modified for certain errors.
|
||||
Error exit_code = ERR_INVALID_PARAMETER;
|
||||
|
||||
@ -969,13 +946,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (editor) {
|
||||
packed_data->set_disabled(true);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (editor) {
|
||||
Engine::get_singleton()->set_editor_hint(true);
|
||||
@ -1283,9 +1253,6 @@ error:
|
||||
if (script_debugger) {
|
||||
memdelete(script_debugger);
|
||||
}
|
||||
if (packed_data) {
|
||||
memdelete(packed_data);
|
||||
}
|
||||
if (file_access_network_client) {
|
||||
memdelete(file_access_network_client);
|
||||
}
|
||||
@ -2380,9 +2347,6 @@ void Main::cleanup(bool p_force) {
|
||||
OS::get_singleton()->finalize();
|
||||
finalize_physics();
|
||||
|
||||
if (packed_data) {
|
||||
memdelete(packed_data);
|
||||
}
|
||||
if (file_access_network_client) {
|
||||
memdelete(file_access_network_client);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user