Changeset View
Changeset View
Standalone View
Standalone View
source/lib/file/archive/archive_zip.cpp
/* Copyright (c) 2017 Wildfire Games | /* Copyright (c) 2017 Wildfire Games | ||||
Stan: 2020 | |||||
* | * | ||||
* Permission is hereby granted, free of charge, to any person obtaining | * Permission is hereby granted, free of charge, to any person obtaining | ||||
* a copy of this software and associated documentation files (the | * a copy of this software and associated documentation files (the | ||||
* "Software"), to deal in the Software without restriction, including | * "Software"), to deal in the Software without restriction, including | ||||
* without limitation the rights to use, copy, modify, merge, publish, | * without limitation the rights to use, copy, modify, merge, publish, | ||||
* distribute, sublicense, and/or sell copies of the Software, and to | * distribute, sublicense, and/or sell copies of the Software, and to | ||||
* permit persons to whom the Software is furnished to do so, subject to | * permit persons to whom the Software is furnished to do so, subject to | ||||
* the following conditions: | * the following conditions: | ||||
▲ Show 20 Lines • Show All 433 Lines • ▼ Show 20 Lines | public: | ||||
virtual Status ReadEntries(ArchiveEntryCallback cb, uintptr_t cbData) | virtual Status ReadEntries(ArchiveEntryCallback cb, uintptr_t cbData) | ||||
{ | { | ||||
// locate and read Central Directory | // locate and read Central Directory | ||||
off_t cd_ofs = 0; | off_t cd_ofs = 0; | ||||
size_t cd_numEntries = 0; | size_t cd_numEntries = 0; | ||||
size_t cd_size = 0; | size_t cd_size = 0; | ||||
RETURN_STATUS_IF_ERR(LocateCentralDirectory(m_file, m_fileSize, cd_ofs, cd_numEntries, cd_size)); | RETURN_STATUS_IF_ERR(LocateCentralDirectory(m_file, m_fileSize, cd_ofs, cd_numEntries, cd_size)); | ||||
UniqueRange buf(io::Allocate(cd_size)); | unique_ptr_aligned buf(io::Allocate(cd_size)); | ||||
io::Operation op(*m_file.get(), buf.get(), cd_size, cd_ofs); | io::Operation op(*m_file.get(), buf.get(), cd_size, cd_ofs); | ||||
RETURN_STATUS_IF_ERR(io::Run(op)); | RETURN_STATUS_IF_ERR(io::Run(op)); | ||||
// iterate over Central Directory | // iterate over Central Directory | ||||
const u8* pos = (const u8*)buf.get(); | const u8* pos = (const u8*)buf.get(); | ||||
for(size_t i = 0; i < cd_numEntries; i++) | for(size_t i = 0; i < cd_numEntries; i++) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | static Status ScanForEcdr(const PFile& file, off_t fileSize, u8* buf, size_t maxScanSize, size_t& cd_numEntries, off_t& cd_ofs, size_t& cd_size) | ||||
ecdr->Decompose(cd_numEntries, cd_ofs, cd_size); | ecdr->Decompose(cd_numEntries, cd_ofs, cd_size); | ||||
return INFO::OK; | return INFO::OK; | ||||
} | } | ||||
static Status LocateCentralDirectory(const PFile& file, off_t fileSize, off_t& cd_ofs, size_t& cd_numEntries, size_t& cd_size) | static Status LocateCentralDirectory(const PFile& file, off_t fileSize, off_t& cd_ofs, size_t& cd_numEntries, size_t& cd_size) | ||||
{ | { | ||||
const size_t maxScanSize = 66000u; // see below | const size_t maxScanSize = 66000u; // see below | ||||
UniqueRange buf(io::Allocate(maxScanSize)); | unique_ptr_aligned buf(io::Allocate(maxScanSize)); | ||||
// expected case: ECDR at EOF; no file comment | // expected case: ECDR at EOF; no file comment | ||||
Status ret = ScanForEcdr(file, fileSize, (u8*)buf.get(), sizeof(ECDR), cd_numEntries, cd_ofs, cd_size); | Status ret = ScanForEcdr(file, fileSize, (u8*)buf.get(), sizeof(ECDR), cd_numEntries, cd_ofs, cd_size); | ||||
if(ret == INFO::OK) | if(ret == INFO::OK) | ||||
return INFO::OK; | return INFO::OK; | ||||
// worst case: ECDR precedes 64 KiB of file comment | // worst case: ECDR precedes 64 KiB of file comment | ||||
ret = ScanForEcdr(file, fileSize, (u8*)buf.get(), maxScanSize, cd_numEntries, cd_ofs, cd_size); | ret = ScanForEcdr(file, fileSize, (u8*)buf.get(), maxScanSize, cd_numEntries, cd_ofs, cd_size); | ||||
if(ret == INFO::OK) | if(ret == INFO::OK) | ||||
▲ Show 20 Lines • Show All 112 Lines • ▼ Show 20 Lines | Status AddFileOrMemory(const CFileInfo& fileInfo, const OsPath& pathnameInArchive, const PFile& file, const u8* data) | ||||
else | else | ||||
{ | { | ||||
method = ZIP_METHOD_DEFLATE; | method = ZIP_METHOD_DEFLATE; | ||||
codec = CreateCompressor_ZLibDeflate(); | codec = CreateCompressor_ZLibDeflate(); | ||||
} | } | ||||
// allocate memory | // allocate memory | ||||
const size_t csizeMax = codec->MaxOutputSize(size_t(usize)); | const size_t csizeMax = codec->MaxOutputSize(size_t(usize)); | ||||
UniqueRange buf(io::Allocate(sizeof(LFH) + pathnameLength + csizeMax)); | unique_ptr_aligned buf(io::Allocate(sizeof(LFH) + pathnameLength + csizeMax)); | ||||
// read and compress file contents | // read and compress file contents | ||||
size_t csize; u32 checksum; | size_t csize; u32 checksum; | ||||
{ | { | ||||
u8* cdata = (u8*)buf.get() + sizeof(LFH) + pathnameLength; | u8* cdata = (u8*)buf.get() + sizeof(LFH) + pathnameLength; | ||||
Stream stream(codec); | Stream stream(codec); | ||||
stream.SetOutputBuffer(cdata, csizeMax); | stream.SetOutputBuffer(cdata, csizeMax); | ||||
StreamFeeder streamFeeder(stream); | StreamFeeder streamFeeder(stream); | ||||
▲ Show 20 Lines • Show All 82 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator
2020