Merge "zip_archive: generalize deflate method." am: 661b3827a6
am: de0153c20b
Change-Id: I4251f36f21924af358eec85703cf1e87131b8d72
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index 1be4061..6965265 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -864,6 +864,34 @@
size_t total_bytes_written_;
};
+class Reader {
+ public:
+ virtual bool ReadAtOffset(uint8_t* buf, size_t len, uint32_t offset) const = 0;
+ virtual ~Reader() {}
+
+ protected:
+ Reader() = default;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Reader);
+};
+
+class EntryReader : public Reader {
+ public:
+ EntryReader(const MappedZipFile& zip_file, const ZipEntry* entry)
+ : Reader(), zip_file_(zip_file), entry_(entry) {}
+
+ virtual bool ReadAtOffset(uint8_t* buf, size_t len, uint32_t offset) const {
+ return zip_file_.ReadAtOffset(buf, len, entry_->offset + offset);
+ }
+
+ virtual ~EntryReader() {}
+
+ private:
+ const MappedZipFile& zip_file_;
+ const ZipEntry* entry_;
+};
+
// This method is using libz macros with old-style-casts
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
@@ -872,8 +900,9 @@
}
#pragma GCC diagnostic pop
-static int32_t InflateEntryToWriter(MappedZipFile& mapped_zip, const ZipEntry* entry,
- Writer* writer, uint64_t* crc_out) {
+static int32_t InflateReaderToWriter(const Reader& reader, const uint32_t compressed_length,
+ const uint32_t uncompressed_length, Writer* writer,
+ uint64_t* crc_out) {
const size_t kBufSize = 32768;
std::vector<uint8_t> read_buf(kBufSize);
std::vector<uint8_t> write_buf(kBufSize);
@@ -914,25 +943,23 @@
std::unique_ptr<z_stream, decltype(zstream_deleter)> zstream_guard(&zstream, zstream_deleter);
- const uint32_t uncompressed_length = entry->uncompressed_length;
-
uint64_t crc = 0;
- uint32_t compressed_length = entry->compressed_length;
+ uint32_t remaining_bytes = compressed_length;
do {
/* read as much as we can */
if (zstream.avail_in == 0) {
- const size_t getSize = (compressed_length > kBufSize) ? kBufSize : compressed_length;
- off64_t offset = entry->offset + (entry->compressed_length - compressed_length);
+ const size_t read_size = (remaining_bytes > kBufSize) ? kBufSize : remaining_bytes;
+ const uint32_t offset = (compressed_length - remaining_bytes);
// Make sure to read at offset to ensure concurrent access to the fd.
- if (!mapped_zip.ReadAtOffset(read_buf.data(), getSize, offset)) {
- ALOGW("Zip: inflate read failed, getSize = %zu: %s", getSize, strerror(errno));
+ if (!reader.ReadAtOffset(read_buf.data(), read_size, offset)) {
+ ALOGW("Zip: inflate read failed, getSize = %zu: %s", read_size, strerror(errno));
return kIoError;
}
- compressed_length -= getSize;
+ remaining_bytes -= read_size;
zstream.next_in = &read_buf[0];
- zstream.avail_in = getSize;
+ zstream.avail_in = read_size;
}
/* uncompress the data */
@@ -968,7 +995,7 @@
// the same manner that we have above.
*crc_out = crc;
- if (zstream.total_out != uncompressed_length || compressed_length != 0) {
+ if (zstream.total_out != uncompressed_length || remaining_bytes != 0) {
ALOGW("Zip: size mismatch on inflated file (%lu vs %" PRIu32 ")", zstream.total_out,
uncompressed_length);
return kInconsistentInformation;
@@ -977,6 +1004,14 @@
return 0;
}
+static int32_t InflateEntryToWriter(MappedZipFile& mapped_zip, const ZipEntry* entry,
+ Writer* writer, uint64_t* crc_out) {
+ const EntryReader reader(mapped_zip, entry);
+
+ return InflateReaderToWriter(reader, entry->compressed_length, entry->uncompressed_length, writer,
+ crc_out);
+}
+
static int32_t CopyEntryToWriter(MappedZipFile& mapped_zip, const ZipEntry* entry, Writer* writer,
uint64_t* crc_out) {
static const uint32_t kBufSize = 32768;
@@ -1134,7 +1169,7 @@
}
// Attempts to read |len| bytes into |buf| at offset |off|.
-bool MappedZipFile::ReadAtOffset(uint8_t* buf, size_t len, off64_t off) {
+bool MappedZipFile::ReadAtOffset(uint8_t* buf, size_t len, off64_t off) const {
if (has_fd_) {
if (!android::base::ReadFullyAtOffset(fd_, buf, len, off)) {
ALOGE("Zip: failed to read at offset %" PRId64 "\n", off);
diff --git a/libziparchive/zip_archive_private.h b/libziparchive/zip_archive_private.h
index 174aa3f..18e0229 100644
--- a/libziparchive/zip_archive_private.h
+++ b/libziparchive/zip_archive_private.h
@@ -106,7 +106,7 @@
off64_t GetFileLength() const;
- bool ReadAtOffset(uint8_t* buf, size_t len, off64_t off);
+ bool ReadAtOffset(uint8_t* buf, size_t len, off64_t off) const;
private:
// If has_fd_ is true, fd is valid and we'll read contents of a zip archive