This commit is contained in:
MihailRis 2025-02-26 00:22:57 +03:00
parent b52cc1aea0
commit 7facc33a7e
2 changed files with 74 additions and 75 deletions

View File

@ -81,19 +81,19 @@ ZipFileDevice::Entry ZipFileDevice::readEntry() {
read_int(file, entry.crc32); read_int(file, entry.crc32);
read_int(file, entry.compressedSize); read_int(file, entry.compressedSize);
read_int(file, entry.uncompressedSize); read_int(file, entry.uncompressedSize);
auto fileNameLength = read_int<uint16_t>(file); auto filename_len = read_int<uint16_t>(file);
auto extraFieldLength = read_int<uint16_t>(file); auto extra_field_len = read_int<uint16_t>(file);
auto fileCommentLength = read_int<uint16_t>(file); auto file_comment_len = read_int<uint16_t>(file);
read_int(file, entry.diskNumberStart); read_int(file, entry.diskNumberStart);
read_int(file, entry.internalAttributes); read_int(file, entry.internalAttributes);
read_int(file, entry.externalAttributes); read_int(file, entry.externalAttributes);
read_int(file, entry.localHeaderOffset); read_int(file, entry.localHeaderOffset);
entry.fileName.resize(fileNameLength, '\0'); entry.fileName.resize(filename_len, '\0');
file->read(entry.fileName.data(), fileNameLength); file->read(entry.fileName.data(), filename_len);
// Skip extra field and file comment // Skip extra field and file comment
file->seekg(extraFieldLength + fileCommentLength, std::ios::cur); file->seekg(extra_field_len + file_comment_len, std::ios::cur);
if (entry.diskNumberStart == 0xFF) { if (entry.diskNumberStart == 0xFF) {
throw std::runtime_error("zip64 is not supported"); throw std::runtime_error("zip64 is not supported");
@ -124,11 +124,11 @@ void ZipFileDevice::findBlob(Entry& entry) {
read_int<uint32_t>(file); // crc32 read_int<uint32_t>(file); // crc32
read_int<uint32_t>(file); // compressed size read_int<uint32_t>(file); // compressed size
read_int<uint32_t>(file); // uncompressed size read_int<uint32_t>(file); // uncompressed size
auto nameLength = read_int<uint16_t>(file); auto name_len = read_int<uint16_t>(file);
auto extraFieldLength = read_int<uint16_t>(file); auto extra_field_len = read_int<uint16_t>(file);
// Skip extra field and file comment // Skip extra field and file comment
file->seekg(nameLength + extraFieldLength, std::ios::cur); file->seekg(name_len + extra_field_len, std::ios::cur);
entry.blobOffset = file->tellg(); entry.blobOffset = file->tellg();
} }
@ -138,10 +138,10 @@ ZipFileDevice::ZipFileDevice(
: file(std::move(filePtr)), separateFunc(std::move(separateFunc)) { : file(std::move(filePtr)), separateFunc(std::move(separateFunc)) {
// Searching for EOCD // Searching for EOCD
file->seekg(0, std::ios::end); file->seekg(0, std::ios::end);
std::streampos fileSize = file->tellg(); std::streampos file_size = file->tellg();
bool foundEOCD = false; bool foundEOCD = false;
for (int pos = static_cast<int>(fileSize)-4; pos >= 0; --pos) { for (int pos = static_cast<int>(file_size)-4; pos >= 0; --pos) {
file->seekg(pos); file->seekg(pos);
if (read_int<uint32_t>(file) == EOCD_SIGNATURE) { if (read_int<uint32_t>(file) == EOCD_SIGNATURE) {
foundEOCD = true; foundEOCD = true;
@ -156,14 +156,14 @@ ZipFileDevice::ZipFileDevice(
read_int<uint16_t>(file); // diskNumber read_int<uint16_t>(file); // diskNumber
read_int<uint16_t>(file); // centralDirDisk read_int<uint16_t>(file); // centralDirDisk
read_int<uint16_t>(file); // numEntriesThisDisk read_int<uint16_t>(file); // numEntriesThisDisk
auto totalEntries = read_int<uint16_t>(file); auto total_entries = read_int<uint16_t>(file);
read_int<uint32_t>(file); // centralDirSize read_int<uint32_t>(file); // centralDirSize
auto centralDirOffset = read_int<uint32_t>(file); auto central_dir_offset = read_int<uint32_t>(file);
read_int<uint16_t>(file); // commentLength read_int<uint16_t>(file); // commentLength
file->seekg(centralDirOffset); file->seekg(central_dir_offset);
for (uint16_t i = 0; i < totalEntries; i++) { for (uint16_t i = 0; i < total_entries; i++) {
if (read_int<uint32_t>(file) != CENTRAL_DIR_SIGNATURE) { if (read_int<uint32_t>(file) != CENTRAL_DIR_SIGNATURE) {
logger.error() << "invalid central directory entry"; logger.error() << "invalid central directory entry";
break; break;
@ -198,22 +198,22 @@ std::unique_ptr<std::istream> ZipFileDevice::read(std::string_view path) {
if (entry.blobOffset == 0) { if (entry.blobOffset == 0) {
findBlob(entry); findBlob(entry);
} }
std::unique_ptr<std::istream> srcStream; std::unique_ptr<std::istream> src_stream;
if (separateFunc) { if (separateFunc) {
// Create new istream for concurrent data reading // Create new istream for concurrent data reading
srcStream = separateFunc(); src_stream = separateFunc();
srcStream->seekg(entry.blobOffset); src_stream->seekg(entry.blobOffset);
} else { } else {
// Read compressed data to memory if istream cannot be separated // Read compressed data to memory if istream cannot be separated
file->seekg(entry.blobOffset); file->seekg(entry.blobOffset);
util::Buffer<char> buffer(entry.compressedSize); util::Buffer<char> buffer(entry.compressedSize);
file->read(buffer.data(), buffer.size()); file->read(buffer.data(), buffer.size());
srcStream = std::make_unique<memory_istream>(std::move(buffer)); src_stream = std::make_unique<memory_istream>(std::move(buffer));
} }
if (entry.compressionMethod == COMPRESSION_NONE) { if (entry.compressionMethod == COMPRESSION_NONE) {
return srcStream; return src_stream;
} else if (entry.compressionMethod == COMPRESSION_DEFLATE) { } else if (entry.compressionMethod == COMPRESSION_DEFLATE) {
return std::make_unique<deflate_istream>(std::move(srcStream)); return std::make_unique<deflate_istream>(std::move(src_stream));
} else { } else {
throw std::runtime_error( throw std::runtime_error(
"unsupported compression method [" + "unsupported compression method [" +
@ -301,17 +301,17 @@ std::unique_ptr<PathsGenerator> ZipFileDevice::list(std::string_view path) {
} }
} else { } else {
auto folder = std::string(path) + "/"; auto folder = std::string(path) + "/";
size_t folderLen = folder.length(); size_t folder_len = folder.length();
for (const auto& [name, entry] : entries) { for (const auto& [name, entry] : entries) {
if (name.find(folder) != 0) { if (name.find(folder) != 0) {
continue; continue;
} }
size_t pos = name.find('/', folderLen); size_t pos = name.find('/', folder_len);
if (pos == std::string::npos) { if (pos == std::string::npos) {
names.push_back(name.substr(folderLen, pos - folderLen)); names.push_back(name.substr(folder_len, pos - folder_len));
} }
if (pos == name.length() - 1) { if (pos == name.length() - 1) {
names.push_back(name.substr(folderLen, pos - folderLen)); names.push_back(name.substr(folder_len, pos - folder_len));
} }
} }
} }
@ -324,60 +324,59 @@ std::unique_ptr<PathsGenerator> ZipFileDevice::list(std::string_view path) {
static void write_headers( static void write_headers(
std::ostream& file, std::ostream& file,
const std::string& name, const std::string& name,
size_t srcSize, size_t source_Size,
size_t compressedSize, size_t compressed_size,
uint32_t crc, uint32_t crc,
int compressionMethod, int compression_method,
const file_time_type& modificationTime, const file_time_type& last_write_time,
ByteBuilder& centralDir ByteBuilder& central_dir
) { ) {
auto timestamp = to_ms_dos_timestamp(modificationTime); auto timestamp = to_ms_dos_timestamp(last_write_time);
ByteBuilder header; ByteBuilder header;
header.putInt32(LOCAL_FILE_SIGNATURE); header.putInt32(LOCAL_FILE_SIGNATURE);
header.putInt16(10); // version header.putInt16(10); // version
header.putInt16(0); // flags header.putInt16(0); // flags
header.putInt16(compressionMethod); // compression method header.putInt16(compression_method); // compression method
header.putInt32(timestamp); // last modification datetime header.putInt32(timestamp); // last modification datetime
header.putInt32(crc); // crc32 header.putInt32(crc); // crc32
header.putInt32(compressedSize); header.putInt32(compressed_size);
header.putInt32(srcSize); header.putInt32(source_Size);
header.putInt16(name.length()); header.putInt16(name.length());
header.putInt16(0); // extra field length header.putInt16(0); // extra field length
header.put(reinterpret_cast<const ubyte*>(name.data()), name.length()); header.put(reinterpret_cast<const ubyte*>(name.data()), name.length());
size_t localHeaderOffset = file.tellp(); size_t local_header_offset = file.tellp();
file.write(reinterpret_cast<const char*>(header.data()), header.size()); file.write(reinterpret_cast<const char*>(header.data()), header.size());
centralDir.putInt32(CENTRAL_DIR_SIGNATURE); central_dir.putInt32(CENTRAL_DIR_SIGNATURE);
centralDir.putInt16(10); // version central_dir.putInt16(10); // version
centralDir.putInt16(0); // version central_dir.putInt16(0); // version
centralDir.putInt16(0); // flags central_dir.putInt16(0); // flags
centralDir.putInt16(compressionMethod); // compression method central_dir.putInt16(compression_method); // compression method
centralDir.putInt32(timestamp); // last modification datetime central_dir.putInt32(timestamp); // last modification datetime
centralDir.putInt32(crc); // crc32 central_dir.putInt32(crc); // crc32
centralDir.putInt32(compressedSize); central_dir.putInt32(compressed_size);
centralDir.putInt32(srcSize); central_dir.putInt32(source_Size);
centralDir.putInt16(name.length()); central_dir.putInt16(name.length());
centralDir.putInt16(0); // extra field length central_dir.putInt16(0); // extra field length
centralDir.putInt16(0); // file comment length central_dir.putInt16(0); // file comment length
centralDir.putInt16(0); // disk number start central_dir.putInt16(0); // disk number start
centralDir.putInt16(0); // internal attributes central_dir.putInt16(0); // internal attributes
centralDir.putInt32(0); // external attributes central_dir.putInt32(0); // external attributes
centralDir.putInt32(localHeaderOffset); // local header offset central_dir.putInt32(local_header_offset); // local header offset
centralDir.put(reinterpret_cast<const ubyte*>(name.data()), name.length()); central_dir.put(reinterpret_cast<const ubyte*>(name.data()), name.length());
} }
static size_t write_zip( static size_t write_zip(
const std::string& root, const std::string& root,
const path& folder, const path& folder,
std::ostream& file, std::ostream& file,
ByteBuilder& centralDir ByteBuilder& central_dir
) { ) {
size_t entries = 0; size_t entries = 0;
ByteBuilder localHeader;
for (const auto& entry : io::directory_iterator(folder)) { for (const auto& entry : io::directory_iterator(folder)) {
auto name = entry.pathPart().substr(root.length() + 1); auto name = entry.pathPart().substr(root.length() + 1);
auto modificationTime = io::last_write_time(entry); auto last_write_time = io::last_write_time(entry);
if (io::is_directory(entry)) { if (io::is_directory(entry)) {
name = name + "/"; name = name + "/";
write_headers( write_headers(
@ -387,35 +386,35 @@ static size_t write_zip(
0, 0,
0, 0,
COMPRESSION_NONE, COMPRESSION_NONE,
modificationTime, last_write_time,
centralDir central_dir
); );
entries += write_zip(root, entry, file, centralDir) + 1; entries += write_zip(root, entry, file, central_dir) + 1;
} else { } else {
auto uncompressed = io::read_bytes_buffer(entry); auto uncompressed = io::read_bytes_buffer(entry);
uint32_t crc = crc32(0, uncompressed.data(), uncompressed.size()); uint32_t crc = crc32(0, uncompressed.data(), uncompressed.size());
memory_ostream memoryStream; memory_ostream memory_stream;
{ {
deflate_ostream deflateStream(memoryStream); deflate_ostream deflate_stream(memory_stream);
deflateStream.write( deflate_stream.write(
reinterpret_cast<char*>(uncompressed.data()), reinterpret_cast<char*>(uncompressed.data()),
uncompressed.size() uncompressed.size()
); );
deflateStream.flush(); deflate_stream.flush();
} }
auto data = memoryStream.release(); auto data = memory_stream.release();
size_t dataSize = data.size(); size_t data_size = data.size();
write_headers( write_headers(
file, file,
name, name,
uncompressed.size(), uncompressed.size(),
dataSize, data_size,
crc, crc,
COMPRESSION_DEFLATE, COMPRESSION_DEFLATE,
modificationTime, last_write_time,
centralDir central_dir
); );
file.write(reinterpret_cast<const char*>(data.data()), dataSize); file.write(reinterpret_cast<const char*>(data.data()), data_size);
entries++; entries++;
} }
} }
@ -423,12 +422,12 @@ static size_t write_zip(
} }
void io::write_zip(const path& folder, const path& file) { void io::write_zip(const path& folder, const path& file) {
ByteBuilder centralDir; ByteBuilder central_dir;
auto out = io::write(file); auto out = io::write(file);
size_t entries = write_zip(folder.pathPart(), folder, *out, centralDir); size_t entries = write_zip(folder.pathPart(), folder, *out, central_dir);
size_t centralDirOffset = out->tellp(); size_t central_dir_offset = out->tellp();
out->write(reinterpret_cast<const char*>(centralDir.data()), centralDir.size()); out->write(reinterpret_cast<const char*>(central_dir.data()), central_dir.size());
ByteBuilder eocd; ByteBuilder eocd;
eocd.putInt32(EOCD_SIGNATURE); eocd.putInt32(EOCD_SIGNATURE);
@ -436,8 +435,8 @@ void io::write_zip(const path& folder, const path& file) {
eocd.putInt16(0); // central dir disk eocd.putInt16(0); // central dir disk
eocd.putInt16(entries); // num entries eocd.putInt16(entries); // num entries
eocd.putInt16(entries); // total entries eocd.putInt16(entries); // total entries
eocd.putInt32(centralDir.size()); // central dir size eocd.putInt32(central_dir.size()); // central dir size
eocd.putInt32(centralDirOffset); // central dir offset eocd.putInt32(central_dir_offset); // central dir offset
eocd.putInt16(0); // comment length eocd.putInt16(0); // comment length
out->write(reinterpret_cast<const char*>(eocd.data()), eocd.size()); out->write(reinterpret_cast<const char*>(eocd.data()), eocd.size());
} }

View File

@ -23,7 +23,7 @@ public:
} }
size_t size() const { size_t size() const {
return pptr()-pbase(); return pptr() - pbase();
} }
protected: protected:
int_type overflow(int_type c) override { int_type overflow(int_type c) override {