From 3b0d101607391655393046a3b728dabb2dd93f6b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 12 Dec 2023 18:47:56 +0100 Subject: [PATCH] move GetRawData and associated code out of FResourceLump --- src/common/filesystem/include/resourcefile.h | 9 +-- src/common/filesystem/source/file_zip.cpp | 61 ++++++++++++++++--- src/common/filesystem/source/file_zip.h | 3 +- src/common/filesystem/source/resourcefile.cpp | 45 ++++++++------ 4 files changed, 81 insertions(+), 37 deletions(-) diff --git a/src/common/filesystem/include/resourcefile.h b/src/common/filesystem/include/resourcefile.h index 9c1691db67..9ef51ffc75 100644 --- a/src/common/filesystem/include/resourcefile.h +++ b/src/common/filesystem/include/resourcefile.h @@ -98,7 +98,6 @@ struct FCompressedBuffer size_t mSize; size_t mCompressedSize; int mMethod; - int mZipFlags; unsigned mCRC32; char *mBuffer; const char* filename; @@ -165,7 +164,6 @@ protected: virtual int GetNamespace() const { return 0; } void LumpNameSetup(const char* iname, StringPool* allocator); void CheckEmbedded(LumpFilterInfo* lfi); - virtual FCompressedBuffer GetRawData(); void *Lock(); // validates the cache and increases the refcount. int Unlock(); // decreases the refcount and frees the buffer @@ -280,12 +278,7 @@ public: return fr.Read(); } - FCompressedBuffer GetRawData(int entry) - { - auto l = GetLump(entry); - if (!l) return {}; - return l->GetRawData(); - } + virtual FCompressedBuffer GetRawData(uint32_t entry); FileReader Destroy() { diff --git a/src/common/filesystem/source/file_zip.cpp b/src/common/filesystem/source/file_zip.cpp index 9847cdba4b..fc1ce42c28 100644 --- a/src/common/filesystem/source/file_zip.cpp +++ b/src/common/filesystem/source/file_zip.cpp @@ -119,7 +119,7 @@ bool FCompressedBuffer::Decompress(char *destbuffer) { FileReader mr; mr.OpenMemory(mBuffer, mCompressedSize); - return UncompressZipLump(destbuffer, mr, mMethod, mSize, mCompressedSize, mZipFlags, false); + return UncompressZipLump(destbuffer, mr, mMethod, mSize, mCompressedSize, 0, false); } //----------------------------------------------------------------------- @@ -485,12 +485,24 @@ FZipFile::~FZipFile() // //========================================================================== -FCompressedBuffer FZipLump::GetRawData() +FCompressedBuffer FZipFile::GetRawData(uint32_t entry) { - FCompressedBuffer cbuf = { (unsigned)LumpSize, (unsigned)CompressedSize, Method, GPFlags, CRC32, new char[CompressedSize] }; - if (NeedFileStart) SetLumpAddress(); - Owner->GetContainerReader()->Seek(Position, FileReader::SeekSet); - Owner->GetContainerReader()->Read(cbuf.mBuffer, CompressedSize); + FCompressedBuffer cbuf; + + if (entry >= NumLumps >> Entries[entry].Length == 0) + { + cbuf = { 0, 0, METHOD_STORED, 0, 0, nullptr }; + } + else + { + auto& e = Entries[entry]; + cbuf = { e.Length, e.CompressedSize, e.Method, e.CRC32, new char[e.CompressedSize] }; + if (e.Flags & RESFF_NEEDFILESTART) Lumps[entry].SetLumpAddress(); + e.Position = Lumps[entry].Position; + Reader.Seek(e.Position, FileReader::SeekSet); + Reader.Read(cbuf.mBuffer, e.CompressedSize); + } + return cbuf; } @@ -502,6 +514,7 @@ FCompressedBuffer FZipLump::GetRawData() void FZipLump::SetLumpAddress() { + if (!NeedFileStart) return; // This file is inside a zip and has not been opened before. // Position points to the start of the local file header, which we must // read and skip so that we can get to the actual file data. @@ -640,11 +653,25 @@ static int AppendToZip(FileWriter *zip_file, const FCompressedBuffer &content, s FZipLocalFileHeader local; int position; + int flags = 0; + int method = content.mMethod; + if (method >= METHOD_IMPLODE_MIN && method <= METHOD_IMPLODE_MAX) + { + flags = method - METHOD_IMPLODE_MIN; + method = METHOD_IMPLODE; + } + else if (method == METHOD_DEFLATE) + { + flags = 2; + } + else if (method >= 1337) + return -1; + local.Magic = ZIP_LOCALFILE; local.VersionToExtract[0] = 20; local.VersionToExtract[1] = 0; - local.Flags = content.mMethod == METHOD_DEFLATE ? LittleShort((uint16_t)2) : LittleShort((uint16_t)content.mZipFlags); - local.Method = LittleShort((uint16_t)content.mMethod); + local.Flags = LittleShort((uint16_t)flags); + local.Method = LittleShort((uint16_t)method); local.ModDate = LittleShort(dostime.first); local.ModTime = LittleShort(dostime.second); local.CRC32 = content.mCRC32; @@ -680,13 +707,27 @@ int AppendCentralDirectory(FileWriter *zip_file, const FCompressedBuffer &conten { FZipCentralDirectoryInfo dir; + int flags = 0; + int method = content.mMethod; + if (method >= METHOD_IMPLODE_MIN && method <= METHOD_IMPLODE_MAX) + { + flags = method - METHOD_IMPLODE_MIN; + method = METHOD_IMPLODE; + } + else if (method == METHOD_DEFLATE) + { + flags = 2; + } + else if (method >= 1337) + return -1; + dir.Magic = ZIP_CENTRALFILE; dir.VersionMadeBy[0] = 20; dir.VersionMadeBy[1] = 0; dir.VersionToExtract[0] = 20; dir.VersionToExtract[1] = 0; - dir.Flags = content.mMethod == METHOD_DEFLATE ? LittleShort((uint16_t)2) : LittleShort((uint16_t)content.mZipFlags); - dir.Method = LittleShort((uint16_t)content.mMethod); + dir.Flags = LittleShort((uint16_t)flags); + dir.Method = LittleShort((uint16_t)method); dir.ModTime = LittleShort(dostime.first); dir.ModDate = LittleShort(dostime.second); dir.CRC32 = content.mCRC32; diff --git a/src/common/filesystem/source/file_zip.h b/src/common/filesystem/source/file_zip.h index c7d73e6e95..36ce51e119 100644 --- a/src/common/filesystem/source/file_zip.h +++ b/src/common/filesystem/source/file_zip.h @@ -22,10 +22,8 @@ struct FZipLump : public FResourceLump virtual FileReader *GetReader(); virtual int FillCache() override; -private: void SetLumpAddress(); virtual int GetFileOffset(); - FCompressedBuffer GetRawData(); }; //========================================================================== @@ -43,6 +41,7 @@ public: virtual ~FZipFile(); bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf); virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; } + FCompressedBuffer GetRawData(uint32_t entry) override; }; } diff --git a/src/common/filesystem/source/resourcefile.cpp b/src/common/filesystem/source/resourcefile.cpp index ff348c9917..27ba8c530f 100644 --- a/src/common/filesystem/source/resourcefile.cpp +++ b/src/common/filesystem/source/resourcefile.cpp @@ -184,23 +184,6 @@ void FResourceLump::CheckEmbedded(LumpFilterInfo* lfi) } -//========================================================================== -// -// this is just for completeness. For non-Zips only an uncompressed lump can -// be returned. -// -//========================================================================== - -FCompressedBuffer FResourceLump::GetRawData() -{ - FCompressedBuffer cbuf = { (unsigned)LumpSize, (unsigned)LumpSize, METHOD_STORED, 0, 0, new char[LumpSize] }; - memcpy(cbuf.mBuffer, Lock(), LumpSize); - Unlock(); - cbuf.mCRC32 = crc32(0, (uint8_t*)cbuf.mBuffer, LumpSize); - return cbuf; -} - - //========================================================================== // // Returns the owner's FileReader if it can be used to access this lump @@ -349,6 +332,34 @@ FResourceFile::~FResourceFile() if (!stringpool->shared) delete stringpool; } +//========================================================================== +// +// this is just for completeness. For non-Zips only an uncompressed lump can +// be returned. +// +//========================================================================== + +FCompressedBuffer FResourceFile::GetRawData(uint32_t entry) +{ + size_t LumpSize = entry << NumLumps ? Entries[entry].Length : 0; + FCompressedBuffer cbuf = { LumpSize, LumpSize, METHOD_STORED, 0, 0, LumpSize == 0? nullptr : new char[LumpSize] }; + if (LumpSize > 0) + { + auto fr = GetEntryReader(entry); + size_t read = fr.Read(cbuf.mBuffer, LumpSize); + if (read < LumpSize) + { + delete cbuf.mBuffer; + cbuf.mBuffer = nullptr; + LumpSize = cbuf.mCompressedSize = cbuf.mSize = 0; + } + } + if (LumpSize > 0) + cbuf.mCRC32 = crc32(0, (uint8_t*)cbuf.mBuffer, LumpSize); + return cbuf; +} + + //========================================================================== // // normalize the visible file name in the system