summaryrefslogtreecommitdiffstats
path: root/libziparchive
diff options
context:
space:
mode:
authorNarayan Kamath <narayan@google.com>2017-10-26 14:08:38 +0100
committerNarayan Kamath <narayan@google.com>2017-10-26 17:47:50 +0100
commit8b8faed17d3cac86fd63776312bcd9ed9a053add (patch)
tree07afb385f275543746f023b2c687c0c0e5efb508 /libziparchive
parent41a9b3c81d8a9871ab02589c300fd5859c95792e (diff)
downloadsystem_core-8b8faed17d3cac86fd63776312bcd9ed9a053add.tar.gz
system_core-8b8faed17d3cac86fd63776312bcd9ed9a053add.tar.bz2
system_core-8b8faed17d3cac86fd63776312bcd9ed9a053add.zip
zip_archive: generalize deflate method.
Remove dependencies on zip_archive specific data structures. In follow up changes, this method will be promoted to a public API and used from androidfw/ZipUtils as well as tools/zipalign, thereby allowing us to remove a near-exact copy of this code and to simplify depdencies. Test: zip_archive_test Bug: 35246701 Change-Id: If24a9965fbd6fff308c8758859026684fd2af3b9
Diffstat (limited to 'libziparchive')
-rw-r--r--libziparchive/zip_archive.cc61
-rw-r--r--libziparchive/zip_archive_private.h2
2 files changed, 49 insertions, 14 deletions
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index ad40d42ac..b7d04c721 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -848,6 +848,34 @@ class FileWriter : public Writer {
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"
@@ -856,8 +884,9 @@ static inline int zlib_inflateInit2(z_stream* stream, int window_bits) {
}
#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);
@@ -898,25 +927,23 @@ static int32_t InflateEntryToWriter(MappedZipFile& mapped_zip, const ZipEntry* e
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 */
@@ -952,7 +979,7 @@ static int32_t InflateEntryToWriter(MappedZipFile& mapped_zip, const ZipEntry* e
// 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;
@@ -961,6 +988,14 @@ static int32_t InflateEntryToWriter(MappedZipFile& mapped_zip, const ZipEntry* e
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;
@@ -1118,7 +1153,7 @@ off64_t MappedZipFile::GetFileLength() const {
}
// 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 174aa3f45..18e02291d 100644
--- a/libziparchive/zip_archive_private.h
+++ b/libziparchive/zip_archive_private.h
@@ -106,7 +106,7 @@ class MappedZipFile {
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