Add ability for PCK patches to remove files

Co-authored-by: Mikael Hermansson <mikael@hermansson.io>
This commit is contained in:
Juan 2024-09-23 12:39:54 +02:00 committed by Mikael Hermansson
parent 0f5f3bc954
commit 2ac562cdf8
9 changed files with 210 additions and 56 deletions

View file

@ -48,7 +48,8 @@ static int _get_pad(int p_alignment, int p_n) {
void PCKPacker::_bind_methods() {
ClassDB::bind_method(D_METHOD("pck_start", "pck_path", "alignment", "key", "encrypt_directory"), &PCKPacker::pck_start, DEFVAL(32), DEFVAL("0000000000000000000000000000000000000000000000000000000000000000"), DEFVAL(false));
ClassDB::bind_method(D_METHOD("add_file", "pck_path", "source_path", "encrypt"), &PCKPacker::add_file, DEFVAL(false));
ClassDB::bind_method(D_METHOD("add_file", "target_path", "source_path", "encrypt"), &PCKPacker::add_file, DEFVAL(false));
ClassDB::bind_method(D_METHOD("add_file_removal", "target_path"), &PCKPacker::add_file_removal);
ClassDB::bind_method(D_METHOD("flush", "verbose"), &PCKPacker::flush, DEFVAL(false));
}
@ -106,23 +107,42 @@ Error PCKPacker::pck_start(const String &p_pck_path, int p_alignment, const Stri
return OK;
}
Error PCKPacker::add_file(const String &p_pck_path, const String &p_src, bool p_encrypt) {
Error PCKPacker::add_file_removal(const String &p_target_path) {
ERR_FAIL_COND_V_MSG(file.is_null(), ERR_INVALID_PARAMETER, "File must be opened before use.");
Ref<FileAccess> f = FileAccess::open(p_src, FileAccess::READ);
File pf;
// Simplify path here and on every 'files' access so that paths that have extra '/'
// symbols or 'res://' in them still match the MD5 hash for the saved path.
pf.path = p_target_path.simplify_path().trim_prefix("res://");
pf.ofs = ofs;
pf.size = 0;
pf.removal = true;
pf.md5.resize(16);
pf.md5.fill(0);
files.push_back(pf);
return OK;
}
Error PCKPacker::add_file(const String &p_target_path, const String &p_source_path, bool p_encrypt) {
ERR_FAIL_COND_V_MSG(file.is_null(), ERR_INVALID_PARAMETER, "File must be opened before use.");
Ref<FileAccess> f = FileAccess::open(p_source_path, FileAccess::READ);
if (f.is_null()) {
return ERR_FILE_CANT_OPEN;
}
File pf;
// Simplify path here and on every 'files' access so that paths that have extra '/'
// symbols in them still match to the MD5 hash for the saved path.
pf.path = p_pck_path.simplify_path();
pf.src_path = p_src;
// symbols or 'res://' in them still match the MD5 hash for the saved path.
pf.path = p_target_path.simplify_path().trim_prefix("res://");
pf.src_path = p_source_path;
pf.ofs = ofs;
pf.size = f->get_length();
Vector<uint8_t> data = FileAccess::get_file_as_bytes(p_src);
Vector<uint8_t> data = FileAccess::get_file_as_bytes(p_source_path);
{
unsigned char hash[16];
CryptoCore::md5(data.ptr(), data.size(), hash);
@ -195,6 +215,9 @@ Error PCKPacker::flush(bool p_verbose) {
if (files[i].encrypted) {
flags |= PACK_FILE_ENCRYPTED;
}
if (files[i].removal) {
flags |= PACK_FILE_REMOVAL;
}
fhead->store_32(flags);
}
@ -218,6 +241,10 @@ Error PCKPacker::flush(bool p_verbose) {
int count = 0;
for (int i = 0; i < files.size(); i++) {
if (files[i].removal) {
continue;
}
Ref<FileAccess> src = FileAccess::open(files[i].src_path, FileAccess::READ);
uint64_t to_write = files[i].size;