Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 661b3827 authored by Narayan Kamath's avatar Narayan Kamath Committed by Gerrit Code Review
Browse files

Merge "zip_archive: generalize deflate method."

parents 4adb4ce2 8b8faed1
Loading
Loading
Loading
Loading
+48 −13
Original line number Diff line number Diff line
@@ -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);
+1 −1
Original line number Diff line number Diff line
@@ -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