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
This commit is contained in:
parent
41a9b3c81d
commit
8b8faed17d
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue