1e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris/* 2e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris * Copyright (C) 2015 The Android Open Source Project 3e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris * 4e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris * Licensed under the Apache License, Version 2.0 (the "License"); 5e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris * you may not use this file except in compliance with the License. 6e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris * You may obtain a copy of the License at 7e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris * 8e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris * http://www.apache.org/licenses/LICENSE-2.0 9e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris * 10e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris * Unless required by applicable law or agreed to in writing, software 11e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris * distributed under the License is distributed on an "AS IS" BASIS, 12e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris * See the License for the specific language governing permissions and 14e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris * limitations under the License. 15e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris */ 16e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 17ff2dcd9af994a23ed483939a416b48bdc10eefd5Mark Salyzyn#define LOG_TAG "ZIPARCHIVE" 18ff2dcd9af994a23ed483939a416b48bdc10eefd5Mark Salyzyn 19e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris// Read-only stream access to Zip Archive entries. 20e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris#include <errno.h> 21e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris#include <inttypes.h> 22e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris#include <string.h> 23e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris#include <sys/types.h> 24e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris#include <unistd.h> 25e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 26e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris#include <memory> 27e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris#include <vector> 28e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 29e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris#include <android-base/file.h> 3030f991f251940be3ed11566fb71139852286f68aMark Salyzyn#include <log/log.h> 3130f991f251940be3ed11566fb71139852286f68aMark Salyzyn 32e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris#include <ziparchive/zip_archive.h> 33e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris#include <ziparchive/zip_archive_stream_entry.h> 34e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris#include <zlib.h> 35e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 36e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris#include "zip_archive_private.h" 37e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 38e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferrisstatic constexpr size_t kBufSize = 65535; 39e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 40e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferrisbool ZipArchiveStreamEntry::Init(const ZipEntry& entry) { 41e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle_); 42e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris off64_t data_offset = entry.offset; 4318c25920c285bf2894b5a05868b79f1202c3a264Tianjie Xu if (!archive->mapped_zip.SeekToOffset(data_offset)) { 44e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris ALOGW("lseek to data at %" PRId64 " failed: %s", data_offset, strerror(errno)); 45e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris return false; 46e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } 47e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris crc32_ = entry.crc32; 48e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris return true; 49e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris} 50e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 51e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferrisclass ZipArchiveStreamEntryUncompressed : public ZipArchiveStreamEntry { 52e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris public: 533a114e0a81a482dbf48e8ff6b6310edd7c215fcfChih-Hung Hsieh explicit ZipArchiveStreamEntryUncompressed(ZipArchiveHandle handle) 543a114e0a81a482dbf48e8ff6b6310edd7c215fcfChih-Hung Hsieh : ZipArchiveStreamEntry(handle) {} 55e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris virtual ~ZipArchiveStreamEntryUncompressed() {} 56e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 57e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris const std::vector<uint8_t>* Read() override; 58e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 59e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris bool Verify() override; 60e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 61e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris protected: 62e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris bool Init(const ZipEntry& entry) override; 63e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 64e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris uint32_t length_; 65e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 66e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris private: 67e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris std::vector<uint8_t> data_; 68e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris uint32_t computed_crc32_; 69e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris}; 70e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 71e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferrisbool ZipArchiveStreamEntryUncompressed::Init(const ZipEntry& entry) { 72e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris if (!ZipArchiveStreamEntry::Init(entry)) { 73e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris return false; 74e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } 75e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 76e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris length_ = entry.uncompressed_length; 77e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 78e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris data_.resize(kBufSize); 79e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris computed_crc32_ = 0; 80e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 81e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris return true; 82e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris} 83e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 84e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferrisconst std::vector<uint8_t>* ZipArchiveStreamEntryUncompressed::Read() { 85e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris if (length_ == 0) { 86e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris return nullptr; 87e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } 88e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 89e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris size_t bytes = (length_ > data_.size()) ? data_.size() : length_; 90e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle_); 91e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris errno = 0; 9218c25920c285bf2894b5a05868b79f1202c3a264Tianjie Xu if (!archive->mapped_zip.ReadData(data_.data(), bytes)) { 93e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris if (errno != 0) { 94e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris ALOGE("Error reading from archive fd: %s", strerror(errno)); 95e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } else { 96e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris ALOGE("Short read of zip file, possibly corrupted zip?"); 97e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } 98e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris length_ = 0; 99e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris return nullptr; 100e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } 101e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 102e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris if (bytes < data_.size()) { 103e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris data_.resize(bytes); 104e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } 105e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris computed_crc32_ = crc32(computed_crc32_, data_.data(), data_.size()); 106e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris length_ -= bytes; 107e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris return &data_; 108e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris} 109e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 110e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferrisbool ZipArchiveStreamEntryUncompressed::Verify() { 111e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris return length_ == 0 && crc32_ == computed_crc32_; 112e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris} 113e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 114e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferrisclass ZipArchiveStreamEntryCompressed : public ZipArchiveStreamEntry { 115e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris public: 1163a114e0a81a482dbf48e8ff6b6310edd7c215fcfChih-Hung Hsieh explicit ZipArchiveStreamEntryCompressed(ZipArchiveHandle handle) 1173a114e0a81a482dbf48e8ff6b6310edd7c215fcfChih-Hung Hsieh : ZipArchiveStreamEntry(handle) {} 118e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris virtual ~ZipArchiveStreamEntryCompressed(); 119e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 120e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris const std::vector<uint8_t>* Read() override; 121e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 122e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris bool Verify() override; 123e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 124e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris protected: 125e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris bool Init(const ZipEntry& entry) override; 126e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 127e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris private: 128e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris bool z_stream_init_ = false; 129e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris z_stream z_stream_; 130e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris std::vector<uint8_t> in_; 131e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris std::vector<uint8_t> out_; 132e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris uint32_t uncompressed_length_; 133e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris uint32_t compressed_length_; 134e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris uint32_t computed_crc32_; 135e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris}; 136e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 137e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris// This method is using libz macros with old-style-casts 138e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris#pragma GCC diagnostic push 139e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris#pragma GCC diagnostic ignored "-Wold-style-cast" 140e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferrisstatic inline int zlib_inflateInit2(z_stream* stream, int window_bits) { 141e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris return inflateInit2(stream, window_bits); 142e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris} 143e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris#pragma GCC diagnostic pop 144e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 145e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferrisbool ZipArchiveStreamEntryCompressed::Init(const ZipEntry& entry) { 146e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris if (!ZipArchiveStreamEntry::Init(entry)) { 147e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris return false; 148e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } 149e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 150e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris // Initialize the zlib stream struct. 151e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris memset(&z_stream_, 0, sizeof(z_stream_)); 152e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris z_stream_.zalloc = Z_NULL; 153e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris z_stream_.zfree = Z_NULL; 154e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris z_stream_.opaque = Z_NULL; 155e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris z_stream_.next_in = nullptr; 156e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris z_stream_.avail_in = 0; 157e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris z_stream_.avail_out = 0; 158e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris z_stream_.data_type = Z_UNKNOWN; 159e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 160e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris // Use the undocumented "negative window bits" feature to tell zlib 161e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris // that there's no zlib header waiting for it. 162e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris int zerr = zlib_inflateInit2(&z_stream_, -MAX_WBITS); 163e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris if (zerr != Z_OK) { 164e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris if (zerr == Z_VERSION_ERROR) { 165e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris ALOGE("Installed zlib is not compatible with linked version (%s)", 166e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris ZLIB_VERSION); 167e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } else { 168e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris ALOGE("Call to inflateInit2 failed (zerr=%d)", zerr); 169e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } 170e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 171e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris return false; 172e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } 173e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 174e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris z_stream_init_ = true; 175e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 176e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris uncompressed_length_ = entry.uncompressed_length; 177e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris compressed_length_ = entry.compressed_length; 178e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 179e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris out_.resize(kBufSize); 180e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris in_.resize(kBufSize); 181e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 182e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris computed_crc32_ = 0; 183e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 184e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris return true; 185e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris} 186e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 187e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher FerrisZipArchiveStreamEntryCompressed::~ZipArchiveStreamEntryCompressed() { 188e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris if (z_stream_init_) { 189e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris inflateEnd(&z_stream_); 190e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris z_stream_init_ = false; 191e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } 192e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris} 193e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 194e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferrisbool ZipArchiveStreamEntryCompressed::Verify() { 195e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris return z_stream_init_ && uncompressed_length_ == 0 && compressed_length_ == 0 && 196e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris crc32_ == computed_crc32_; 197e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris} 198e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 199e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferrisconst std::vector<uint8_t>* ZipArchiveStreamEntryCompressed::Read() { 200e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris if (z_stream_.avail_out == 0) { 201e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris z_stream_.next_out = out_.data(); 202e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris z_stream_.avail_out = out_.size();; 203e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } 204e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 205e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris while (true) { 206e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris if (z_stream_.avail_in == 0) { 207e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris if (compressed_length_ == 0) { 208e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris return nullptr; 209e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } 210e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris size_t bytes = (compressed_length_ > in_.size()) ? in_.size() : compressed_length_; 211e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle_); 212e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris errno = 0; 21318c25920c285bf2894b5a05868b79f1202c3a264Tianjie Xu if (!archive->mapped_zip.ReadData(in_.data(), bytes)) { 214e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris if (errno != 0) { 215e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris ALOGE("Error reading from archive fd: %s", strerror(errno)); 216e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } else { 217e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris ALOGE("Short read of zip file, possibly corrupted zip?"); 218e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } 219e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris return nullptr; 220e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } 221e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 222e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris compressed_length_ -= bytes; 223e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris z_stream_.next_in = in_.data(); 224e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris z_stream_.avail_in = bytes; 225e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } 226e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 227e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris int zerr = inflate(&z_stream_, Z_NO_FLUSH); 228e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris if (zerr != Z_OK && zerr != Z_STREAM_END) { 229e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris ALOGE("inflate zerr=%d (nIn=%p aIn=%u nOut=%p aOut=%u)", 230e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris zerr, z_stream_.next_in, z_stream_.avail_in, 231e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris z_stream_.next_out, z_stream_.avail_out); 232e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris return nullptr; 233e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } 234e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 235e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris if (z_stream_.avail_out == 0) { 236e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris uncompressed_length_ -= out_.size(); 237e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris computed_crc32_ = crc32(computed_crc32_, out_.data(), out_.size()); 238e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris return &out_; 239e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } 240e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris if (zerr == Z_STREAM_END) { 241e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris if (z_stream_.avail_out != 0) { 242e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris // Resize the vector down to the actual size of the data. 243e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris out_.resize(out_.size() - z_stream_.avail_out); 244e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris computed_crc32_ = crc32(computed_crc32_, out_.data(), out_.size()); 245e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris uncompressed_length_ -= out_.size(); 246e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris return &out_; 247e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } 248e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris return nullptr; 249e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } 250e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } 251e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris return nullptr; 252e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris} 253e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 254e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferrisclass ZipArchiveStreamEntryRawCompressed : public ZipArchiveStreamEntryUncompressed { 255e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris public: 2563a114e0a81a482dbf48e8ff6b6310edd7c215fcfChih-Hung Hsieh explicit ZipArchiveStreamEntryRawCompressed(ZipArchiveHandle handle) 257e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris : ZipArchiveStreamEntryUncompressed(handle) {} 258e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris virtual ~ZipArchiveStreamEntryRawCompressed() {} 259e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 260e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris bool Verify() override; 261e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 262e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris protected: 263e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris bool Init(const ZipEntry& entry) override; 264e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris}; 265e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 266e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferrisbool ZipArchiveStreamEntryRawCompressed::Init(const ZipEntry& entry) { 267e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris if (!ZipArchiveStreamEntryUncompressed::Init(entry)) { 268e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris return false; 269e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } 270e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris length_ = entry.compressed_length; 271e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 272e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris return true; 273e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris} 274e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 275e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferrisbool ZipArchiveStreamEntryRawCompressed::Verify() { 276e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris return length_ == 0; 277e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris} 278e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 279e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher FerrisZipArchiveStreamEntry* ZipArchiveStreamEntry::Create( 280e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris ZipArchiveHandle handle, const ZipEntry& entry) { 281e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris ZipArchiveStreamEntry* stream = nullptr; 282e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris if (entry.method != kCompressStored) { 283e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris stream = new ZipArchiveStreamEntryCompressed(handle); 284e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } else { 285e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris stream = new ZipArchiveStreamEntryUncompressed(handle); 286e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } 287e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris if (stream && !stream->Init(entry)) { 288e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris delete stream; 289e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris stream = nullptr; 290e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } 291e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 292e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris return stream; 293e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris} 294e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris 295e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher FerrisZipArchiveStreamEntry* ZipArchiveStreamEntry::CreateRaw( 296e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris ZipArchiveHandle handle, const ZipEntry& entry) { 297e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris ZipArchiveStreamEntry* stream = nullptr; 298e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris if (entry.method == kCompressStored) { 299e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris // Not compressed, don't need to do anything special. 300e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris stream = new ZipArchiveStreamEntryUncompressed(handle); 301e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } else { 302e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris stream = new ZipArchiveStreamEntryRawCompressed(handle); 303e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } 304e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris if (stream && !stream->Init(entry)) { 305e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris delete stream; 306e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris stream = nullptr; 307e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris } 308e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris return stream; 309e6884ce56f07933d7292eb0ada1ff752f9c69e7aChristopher Ferris} 310