Home | History | Annotate | Download | only in libziparchive
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *    http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /*
     18  * Read-only access to Zip archives, with minimal heap allocation.
     19  */
     20 
     21 #include <assert.h>
     22 #include <errno.h>
     23 #include <fcntl.h>
     24 #include <inttypes.h>
     25 #include <limits.h>
     26 #include <stdlib.h>
     27 #include <string.h>
     28 #include <unistd.h>
     29 
     30 #include <memory>
     31 #include <vector>
     32 
     33 #include "base/file.h"
     34 #include "base/macros.h"  // TEMP_FAILURE_RETRY may or may not be in unistd
     35 #include "base/memory.h"
     36 #include "log/log.h"
     37 #include "utils/Compat.h"
     38 #include "utils/FileMap.h"
     39 #include "zlib.h"
     40 
     41 #include "entry_name_utils-inl.h"
     42 #include "ziparchive/zip_archive.h"
     43 
     44 using android::base::get_unaligned;
     45 
     46 // This is for windows. If we don't open a file in binary mode, weird
     47 // things will happen.
     48 #ifndef O_BINARY
     49 #define O_BINARY 0
     50 #endif
     51 
     52 // The "end of central directory" (EOCD) record. Each archive
     53 // contains exactly once such record which appears at the end of
     54 // the archive. It contains archive wide information like the
     55 // number of entries in the archive and the offset to the central
     56 // directory of the offset.
     57 struct EocdRecord {
     58   static const uint32_t kSignature = 0x06054b50;
     59 
     60   // End of central directory signature, should always be
     61   // |kSignature|.
     62   uint32_t eocd_signature;
     63   // The number of the current "disk", i.e, the "disk" that this
     64   // central directory is on.
     65   //
     66   // This implementation assumes that each archive spans a single
     67   // disk only. i.e, that disk_num == 1.
     68   uint16_t disk_num;
     69   // The disk where the central directory starts.
     70   //
     71   // This implementation assumes that each archive spans a single
     72   // disk only. i.e, that cd_start_disk == 1.
     73   uint16_t cd_start_disk;
     74   // The number of central directory records on this disk.
     75   //
     76   // This implementation assumes that each archive spans a single
     77   // disk only. i.e, that num_records_on_disk == num_records.
     78   uint16_t num_records_on_disk;
     79   // The total number of central directory records.
     80   uint16_t num_records;
     81   // The size of the central directory (in bytes).
     82   uint32_t cd_size;
     83   // The offset of the start of the central directory, relative
     84   // to the start of the file.
     85   uint32_t cd_start_offset;
     86   // Length of the central directory comment.
     87   uint16_t comment_length;
     88  private:
     89   EocdRecord() = default;
     90   DISALLOW_COPY_AND_ASSIGN(EocdRecord);
     91 } __attribute__((packed));
     92 
     93 // A structure representing the fixed length fields for a single
     94 // record in the central directory of the archive. In addition to
     95 // the fixed length fields listed here, each central directory
     96 // record contains a variable length "file_name" and "extra_field"
     97 // whose lengths are given by |file_name_length| and |extra_field_length|
     98 // respectively.
     99 struct CentralDirectoryRecord {
    100   static const uint32_t kSignature = 0x02014b50;
    101 
    102   // The start of record signature. Must be |kSignature|.
    103   uint32_t record_signature;
    104   // Tool version. Ignored by this implementation.
    105   uint16_t version_made_by;
    106   // Tool version. Ignored by this implementation.
    107   uint16_t version_needed;
    108   // The "general purpose bit flags" for this entry. The only
    109   // flag value that we currently check for is the "data descriptor"
    110   // flag.
    111   uint16_t gpb_flags;
    112   // The compression method for this entry, one of |kCompressStored|
    113   // and |kCompressDeflated|.
    114   uint16_t compression_method;
    115   // The file modification time and date for this entry.
    116   uint16_t last_mod_time;
    117   uint16_t last_mod_date;
    118   // The CRC-32 checksum for this entry.
    119   uint32_t crc32;
    120   // The compressed size (in bytes) of this entry.
    121   uint32_t compressed_size;
    122   // The uncompressed size (in bytes) of this entry.
    123   uint32_t uncompressed_size;
    124   // The length of the entry file name in bytes. The file name
    125   // will appear immediately after this record.
    126   uint16_t file_name_length;
    127   // The length of the extra field info (in bytes). This data
    128   // will appear immediately after the entry file name.
    129   uint16_t extra_field_length;
    130   // The length of the entry comment (in bytes). This data will
    131   // appear immediately after the extra field.
    132   uint16_t comment_length;
    133   // The start disk for this entry. Ignored by this implementation).
    134   uint16_t file_start_disk;
    135   // File attributes. Ignored by this implementation.
    136   uint16_t internal_file_attributes;
    137   // File attributes. Ignored by this implementation.
    138   uint32_t external_file_attributes;
    139   // The offset to the local file header for this entry, from the
    140   // beginning of this archive.
    141   uint32_t local_file_header_offset;
    142  private:
    143   CentralDirectoryRecord() = default;
    144   DISALLOW_COPY_AND_ASSIGN(CentralDirectoryRecord);
    145 } __attribute__((packed));
    146 
    147 // The local file header for a given entry. This duplicates information
    148 // present in the central directory of the archive. It is an error for
    149 // the information here to be different from the central directory
    150 // information for a given entry.
    151 struct LocalFileHeader {
    152   static const uint32_t kSignature = 0x04034b50;
    153 
    154   // The local file header signature, must be |kSignature|.
    155   uint32_t lfh_signature;
    156   // Tool version. Ignored by this implementation.
    157   uint16_t version_needed;
    158   // The "general purpose bit flags" for this entry. The only
    159   // flag value that we currently check for is the "data descriptor"
    160   // flag.
    161   uint16_t gpb_flags;
    162   // The compression method for this entry, one of |kCompressStored|
    163   // and |kCompressDeflated|.
    164   uint16_t compression_method;
    165   // The file modification time and date for this entry.
    166   uint16_t last_mod_time;
    167   uint16_t last_mod_date;
    168   // The CRC-32 checksum for this entry.
    169   uint32_t crc32;
    170   // The compressed size (in bytes) of this entry.
    171   uint32_t compressed_size;
    172   // The uncompressed size (in bytes) of this entry.
    173   uint32_t uncompressed_size;
    174   // The length of the entry file name in bytes. The file name
    175   // will appear immediately after this record.
    176   uint16_t file_name_length;
    177   // The length of the extra field info (in bytes). This data
    178   // will appear immediately after the entry file name.
    179   uint16_t extra_field_length;
    180  private:
    181   LocalFileHeader() = default;
    182   DISALLOW_COPY_AND_ASSIGN(LocalFileHeader);
    183 } __attribute__((packed));
    184 
    185 struct DataDescriptor {
    186   // The *optional* data descriptor start signature.
    187   static const uint32_t kOptSignature = 0x08074b50;
    188 
    189   // CRC-32 checksum of the entry.
    190   uint32_t crc32;
    191   // Compressed size of the entry.
    192   uint32_t compressed_size;
    193   // Uncompressed size of the entry.
    194   uint32_t uncompressed_size;
    195  private:
    196   DataDescriptor() = default;
    197   DISALLOW_COPY_AND_ASSIGN(DataDescriptor);
    198 } __attribute__((packed));
    199 
    200 
    201 static const uint32_t kGPBDDFlagMask = 0x0008;         // mask value that signifies that the entry has a DD
    202 
    203 // The maximum size of a central directory or a file
    204 // comment in bytes.
    205 static const uint32_t kMaxCommentLen = 65535;
    206 
    207 // The maximum number of bytes to scan backwards for the EOCD start.
    208 static const uint32_t kMaxEOCDSearch = kMaxCommentLen + sizeof(EocdRecord);
    209 
    210 static const char* kErrorMessages[] = {
    211   "Unknown return code.",
    212   "Iteration ended",
    213   "Zlib error",
    214   "Invalid file",
    215   "Invalid handle",
    216   "Duplicate entries in archive",
    217   "Empty archive",
    218   "Entry not found",
    219   "Invalid offset",
    220   "Inconsistent information",
    221   "Invalid entry name",
    222   "I/O Error",
    223   "File mapping failed"
    224 };
    225 
    226 static const int32_t kErrorMessageUpperBound = 0;
    227 
    228 static const int32_t kIterationEnd = -1;
    229 
    230 // We encountered a Zlib error when inflating a stream from this file.
    231 // Usually indicates file corruption.
    232 static const int32_t kZlibError = -2;
    233 
    234 // The input file cannot be processed as a zip archive. Usually because
    235 // it's too small, too large or does not have a valid signature.
    236 static const int32_t kInvalidFile = -3;
    237 
    238 // An invalid iteration / ziparchive handle was passed in as an input
    239 // argument.
    240 static const int32_t kInvalidHandle = -4;
    241 
    242 // The zip archive contained two (or possibly more) entries with the same
    243 // name.
    244 static const int32_t kDuplicateEntry = -5;
    245 
    246 // The zip archive contains no entries.
    247 static const int32_t kEmptyArchive = -6;
    248 
    249 // The specified entry was not found in the archive.
    250 static const int32_t kEntryNotFound = -7;
    251 
    252 // The zip archive contained an invalid local file header pointer.
    253 static const int32_t kInvalidOffset = -8;
    254 
    255 // The zip archive contained inconsistent entry information. This could
    256 // be because the central directory & local file header did not agree, or
    257 // if the actual uncompressed length or crc32 do not match their declared
    258 // values.
    259 static const int32_t kInconsistentInformation = -9;
    260 
    261 // An invalid entry name was encountered.
    262 static const int32_t kInvalidEntryName = -10;
    263 
    264 // An I/O related system call (read, lseek, ftruncate, map) failed.
    265 static const int32_t kIoError = -11;
    266 
    267 // We were not able to mmap the central directory or entry contents.
    268 static const int32_t kMmapFailed = -12;
    269 
    270 static const int32_t kErrorMessageLowerBound = -13;
    271 
    272 /*
    273  * A Read-only Zip archive.
    274  *
    275  * We want "open" and "find entry by name" to be fast operations, and
    276  * we want to use as little memory as possible.  We memory-map the zip
    277  * central directory, and load a hash table with pointers to the filenames
    278  * (which aren't null-terminated).  The other fields are at a fixed offset
    279  * from the filename, so we don't need to extract those (but we do need
    280  * to byte-read and endian-swap them every time we want them).
    281  *
    282  * It's possible that somebody has handed us a massive (~1GB) zip archive,
    283  * so we can't expect to mmap the entire file.
    284  *
    285  * To speed comparisons when doing a lookup by name, we could make the mapping
    286  * "private" (copy-on-write) and null-terminate the filenames after verifying
    287  * the record structure.  However, this requires a private mapping of
    288  * every page that the Central Directory touches.  Easier to tuck a copy
    289  * of the string length into the hash table entry.
    290  */
    291 struct ZipArchive {
    292   /* open Zip archive */
    293   const int fd;
    294   const bool close_file;
    295 
    296   /* mapped central directory area */
    297   off64_t directory_offset;
    298   android::FileMap directory_map;
    299 
    300   /* number of entries in the Zip archive */
    301   uint16_t num_entries;
    302 
    303   /*
    304    * We know how many entries are in the Zip archive, so we can have a
    305    * fixed-size hash table. We define a load factor of 0.75 and overallocat
    306    * so the maximum number entries can never be higher than
    307    * ((4 * UINT16_MAX) / 3 + 1) which can safely fit into a uint32_t.
    308    */
    309   uint32_t hash_table_size;
    310   ZipEntryName* hash_table;
    311 
    312   ZipArchive(const int fd, bool assume_ownership) :
    313       fd(fd),
    314       close_file(assume_ownership),
    315       directory_offset(0),
    316       num_entries(0),
    317       hash_table_size(0),
    318       hash_table(NULL) {}
    319 
    320   ~ZipArchive() {
    321     if (close_file && fd >= 0) {
    322       close(fd);
    323     }
    324 
    325     free(hash_table);
    326   }
    327 };
    328 
    329 /*
    330  * Round up to the next highest power of 2.
    331  *
    332  * Found on http://graphics.stanford.edu/~seander/bithacks.html.
    333  */
    334 static uint32_t RoundUpPower2(uint32_t val) {
    335   val--;
    336   val |= val >> 1;
    337   val |= val >> 2;
    338   val |= val >> 4;
    339   val |= val >> 8;
    340   val |= val >> 16;
    341   val++;
    342 
    343   return val;
    344 }
    345 
    346 static uint32_t ComputeHash(const ZipEntryName& name) {
    347   uint32_t hash = 0;
    348   uint16_t len = name.name_length;
    349   const uint8_t* str = name.name;
    350 
    351   while (len--) {
    352     hash = hash * 31 + *str++;
    353   }
    354 
    355   return hash;
    356 }
    357 
    358 /*
    359  * Convert a ZipEntry to a hash table index, verifying that it's in a
    360  * valid range.
    361  */
    362 static int64_t EntryToIndex(const ZipEntryName* hash_table,
    363                             const uint32_t hash_table_size,
    364                             const ZipEntryName& name) {
    365   const uint32_t hash = ComputeHash(name);
    366 
    367   // NOTE: (hash_table_size - 1) is guaranteed to be non-negative.
    368   uint32_t ent = hash & (hash_table_size - 1);
    369   while (hash_table[ent].name != NULL) {
    370     if (hash_table[ent].name_length == name.name_length &&
    371         memcmp(hash_table[ent].name, name.name, name.name_length) == 0) {
    372       return ent;
    373     }
    374 
    375     ent = (ent + 1) & (hash_table_size - 1);
    376   }
    377 
    378   ALOGV("Zip: Unable to find entry %.*s", name.name_length, name.name);
    379   return kEntryNotFound;
    380 }
    381 
    382 /*
    383  * Add a new entry to the hash table.
    384  */
    385 static int32_t AddToHash(ZipEntryName *hash_table, const uint64_t hash_table_size,
    386                          const ZipEntryName& name) {
    387   const uint64_t hash = ComputeHash(name);
    388   uint32_t ent = hash & (hash_table_size - 1);
    389 
    390   /*
    391    * We over-allocated the table, so we're guaranteed to find an empty slot.
    392    * Further, we guarantee that the hashtable size is not 0.
    393    */
    394   while (hash_table[ent].name != NULL) {
    395     if (hash_table[ent].name_length == name.name_length &&
    396         memcmp(hash_table[ent].name, name.name, name.name_length) == 0) {
    397       // We've found a duplicate entry. We don't accept it
    398       ALOGW("Zip: Found duplicate entry %.*s", name.name_length, name.name);
    399       return kDuplicateEntry;
    400     }
    401     ent = (ent + 1) & (hash_table_size - 1);
    402   }
    403 
    404   hash_table[ent].name = name.name;
    405   hash_table[ent].name_length = name.name_length;
    406   return 0;
    407 }
    408 
    409 static int32_t MapCentralDirectory0(int fd, const char* debug_file_name,
    410                                     ZipArchive* archive, off64_t file_length,
    411                                     off64_t read_amount, uint8_t* scan_buffer) {
    412   const off64_t search_start = file_length - read_amount;
    413 
    414   if (lseek64(fd, search_start, SEEK_SET) != search_start) {
    415     ALOGW("Zip: seek %" PRId64 " failed: %s", static_cast<int64_t>(search_start),
    416           strerror(errno));
    417     return kIoError;
    418   }
    419   ssize_t actual = TEMP_FAILURE_RETRY(
    420       read(fd, scan_buffer, static_cast<size_t>(read_amount)));
    421   if (actual != static_cast<ssize_t>(read_amount)) {
    422     ALOGW("Zip: read %" PRId64 " failed: %s", static_cast<int64_t>(read_amount),
    423           strerror(errno));
    424     return kIoError;
    425   }
    426 
    427   /*
    428    * Scan backward for the EOCD magic.  In an archive without a trailing
    429    * comment, we'll find it on the first try.  (We may want to consider
    430    * doing an initial minimal read; if we don't find it, retry with a
    431    * second read as above.)
    432    */
    433   int i = read_amount - sizeof(EocdRecord);
    434   for (; i >= 0; i--) {
    435     if (scan_buffer[i] == 0x50) {
    436       uint32_t* sig_addr = reinterpret_cast<uint32_t*>(&scan_buffer[i]);
    437       if (get_unaligned<uint32_t>(sig_addr) == EocdRecord::kSignature) {
    438         ALOGV("+++ Found EOCD at buf+%d", i);
    439         break;
    440       }
    441     }
    442   }
    443   if (i < 0) {
    444     ALOGD("Zip: EOCD not found, %s is not zip", debug_file_name);
    445     return kInvalidFile;
    446   }
    447 
    448   const off64_t eocd_offset = search_start + i;
    449   const EocdRecord* eocd = reinterpret_cast<const EocdRecord*>(scan_buffer + i);
    450   /*
    451    * Verify that there's no trailing space at the end of the central directory
    452    * and its comment.
    453    */
    454   const off64_t calculated_length = eocd_offset + sizeof(EocdRecord)
    455       + eocd->comment_length;
    456   if (calculated_length != file_length) {
    457     ALOGW("Zip: %" PRId64 " extraneous bytes at the end of the central directory",
    458           static_cast<int64_t>(file_length - calculated_length));
    459     return kInvalidFile;
    460   }
    461 
    462   /*
    463    * Grab the CD offset and size, and the number of entries in the
    464    * archive and verify that they look reasonable.
    465    */
    466   if (eocd->cd_start_offset + eocd->cd_size > eocd_offset) {
    467     ALOGW("Zip: bad offsets (dir %" PRIu32 ", size %" PRIu32 ", eocd %" PRId64 ")",
    468         eocd->cd_start_offset, eocd->cd_size, static_cast<int64_t>(eocd_offset));
    469     return kInvalidOffset;
    470   }
    471   if (eocd->num_records == 0) {
    472     ALOGW("Zip: empty archive?");
    473     return kEmptyArchive;
    474   }
    475 
    476   ALOGV("+++ num_entries=%" PRIu32 "dir_size=%" PRIu32 " dir_offset=%" PRIu32,
    477         eocd->num_records, eocd->cd_size, eocd->cd_start_offset);
    478 
    479   /*
    480    * It all looks good.  Create a mapping for the CD, and set the fields
    481    * in archive.
    482    */
    483   if (!archive->directory_map.create(debug_file_name, fd,
    484           static_cast<off64_t>(eocd->cd_start_offset),
    485           static_cast<size_t>(eocd->cd_size), true /* read only */) ) {
    486     return kMmapFailed;
    487   }
    488 
    489   archive->num_entries = eocd->num_records;
    490   archive->directory_offset = eocd->cd_start_offset;
    491 
    492   return 0;
    493 }
    494 
    495 /*
    496  * Find the zip Central Directory and memory-map it.
    497  *
    498  * On success, returns 0 after populating fields from the EOCD area:
    499  *   directory_offset
    500  *   directory_map
    501  *   num_entries
    502  */
    503 static int32_t MapCentralDirectory(int fd, const char* debug_file_name,
    504                                    ZipArchive* archive) {
    505 
    506   // Test file length. We use lseek64 to make sure the file
    507   // is small enough to be a zip file (Its size must be less than
    508   // 0xffffffff bytes).
    509   off64_t file_length = lseek64(fd, 0, SEEK_END);
    510   if (file_length == -1) {
    511     ALOGV("Zip: lseek on fd %d failed", fd);
    512     return kInvalidFile;
    513   }
    514 
    515   if (file_length > static_cast<off64_t>(0xffffffff)) {
    516     ALOGV("Zip: zip file too long %" PRId64, static_cast<int64_t>(file_length));
    517     return kInvalidFile;
    518   }
    519 
    520   if (file_length < static_cast<off64_t>(sizeof(EocdRecord))) {
    521     ALOGV("Zip: length %" PRId64 " is too small to be zip", static_cast<int64_t>(file_length));
    522     return kInvalidFile;
    523   }
    524 
    525   /*
    526    * Perform the traditional EOCD snipe hunt.
    527    *
    528    * We're searching for the End of Central Directory magic number,
    529    * which appears at the start of the EOCD block.  It's followed by
    530    * 18 bytes of EOCD stuff and up to 64KB of archive comment.  We
    531    * need to read the last part of the file into a buffer, dig through
    532    * it to find the magic number, parse some values out, and use those
    533    * to determine the extent of the CD.
    534    *
    535    * We start by pulling in the last part of the file.
    536    */
    537   off64_t read_amount = kMaxEOCDSearch;
    538   if (file_length < read_amount) {
    539     read_amount = file_length;
    540   }
    541 
    542   uint8_t* scan_buffer = reinterpret_cast<uint8_t*>(malloc(read_amount));
    543   int32_t result = MapCentralDirectory0(fd, debug_file_name, archive,
    544                                         file_length, read_amount, scan_buffer);
    545 
    546   free(scan_buffer);
    547   return result;
    548 }
    549 
    550 /*
    551  * Parses the Zip archive's Central Directory.  Allocates and populates the
    552  * hash table.
    553  *
    554  * Returns 0 on success.
    555  */
    556 static int32_t ParseZipArchive(ZipArchive* archive) {
    557   const uint8_t* const cd_ptr =
    558       reinterpret_cast<const uint8_t*>(archive->directory_map.getDataPtr());
    559   const size_t cd_length = archive->directory_map.getDataLength();
    560   const uint16_t num_entries = archive->num_entries;
    561 
    562   /*
    563    * Create hash table.  We have a minimum 75% load factor, possibly as
    564    * low as 50% after we round off to a power of 2.  There must be at
    565    * least one unused entry to avoid an infinite loop during creation.
    566    */
    567   archive->hash_table_size = RoundUpPower2(1 + (num_entries * 4) / 3);
    568   archive->hash_table = reinterpret_cast<ZipEntryName*>(calloc(archive->hash_table_size,
    569       sizeof(ZipEntryName)));
    570 
    571   /*
    572    * Walk through the central directory, adding entries to the hash
    573    * table and verifying values.
    574    */
    575   const uint8_t* const cd_end = cd_ptr + cd_length;
    576   const uint8_t* ptr = cd_ptr;
    577   for (uint16_t i = 0; i < num_entries; i++) {
    578     const CentralDirectoryRecord* cdr =
    579         reinterpret_cast<const CentralDirectoryRecord*>(ptr);
    580     if (cdr->record_signature != CentralDirectoryRecord::kSignature) {
    581       ALOGW("Zip: missed a central dir sig (at %" PRIu16 ")", i);
    582       return -1;
    583     }
    584 
    585     if (ptr + sizeof(CentralDirectoryRecord) > cd_end) {
    586       ALOGW("Zip: ran off the end (at %" PRIu16 ")", i);
    587       return -1;
    588     }
    589 
    590     const off64_t local_header_offset = cdr->local_file_header_offset;
    591     if (local_header_offset >= archive->directory_offset) {
    592       ALOGW("Zip: bad LFH offset %" PRId64 " at entry %" PRIu16,
    593           static_cast<int64_t>(local_header_offset), i);
    594       return -1;
    595     }
    596 
    597     const uint16_t file_name_length = cdr->file_name_length;
    598     const uint16_t extra_length = cdr->extra_field_length;
    599     const uint16_t comment_length = cdr->comment_length;
    600     const uint8_t* file_name = ptr + sizeof(CentralDirectoryRecord);
    601 
    602     /* check that file name is valid UTF-8 and doesn't contain NUL (U+0000) characters */
    603     if (!IsValidEntryName(file_name, file_name_length)) {
    604       return -1;
    605     }
    606 
    607     /* add the CDE filename to the hash table */
    608     ZipEntryName entry_name;
    609     entry_name.name = file_name;
    610     entry_name.name_length = file_name_length;
    611     const int add_result = AddToHash(archive->hash_table,
    612         archive->hash_table_size, entry_name);
    613     if (add_result != 0) {
    614       ALOGW("Zip: Error adding entry to hash table %d", add_result);
    615       return add_result;
    616     }
    617 
    618     ptr += sizeof(CentralDirectoryRecord) + file_name_length + extra_length + comment_length;
    619     if ((ptr - cd_ptr) > static_cast<int64_t>(cd_length)) {
    620       ALOGW("Zip: bad CD advance (%tu vs %zu) at entry %" PRIu16,
    621           ptr - cd_ptr, cd_length, i);
    622       return -1;
    623     }
    624   }
    625   ALOGV("+++ zip good scan %" PRIu16 " entries", num_entries);
    626 
    627   return 0;
    628 }
    629 
    630 static int32_t OpenArchiveInternal(ZipArchive* archive,
    631                                    const char* debug_file_name) {
    632   int32_t result = -1;
    633   if ((result = MapCentralDirectory(archive->fd, debug_file_name, archive))) {
    634     return result;
    635   }
    636 
    637   if ((result = ParseZipArchive(archive))) {
    638     return result;
    639   }
    640 
    641   return 0;
    642 }
    643 
    644 int32_t OpenArchiveFd(int fd, const char* debug_file_name,
    645                       ZipArchiveHandle* handle, bool assume_ownership) {
    646   ZipArchive* archive = new ZipArchive(fd, assume_ownership);
    647   *handle = archive;
    648   return OpenArchiveInternal(archive, debug_file_name);
    649 }
    650 
    651 int32_t OpenArchive(const char* fileName, ZipArchiveHandle* handle) {
    652   const int fd = open(fileName, O_RDONLY | O_BINARY, 0);
    653   ZipArchive* archive = new ZipArchive(fd, true);
    654   *handle = archive;
    655 
    656   if (fd < 0) {
    657     ALOGW("Unable to open '%s': %s", fileName, strerror(errno));
    658     return kIoError;
    659   }
    660 
    661   return OpenArchiveInternal(archive, fileName);
    662 }
    663 
    664 /*
    665  * Close a ZipArchive, closing the file and freeing the contents.
    666  */
    667 void CloseArchive(ZipArchiveHandle handle) {
    668   ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle);
    669   ALOGV("Closing archive %p", archive);
    670   delete archive;
    671 }
    672 
    673 static int32_t UpdateEntryFromDataDescriptor(int fd,
    674                                              ZipEntry *entry) {
    675   uint8_t ddBuf[sizeof(DataDescriptor) + sizeof(DataDescriptor::kOptSignature)];
    676   ssize_t actual = TEMP_FAILURE_RETRY(read(fd, ddBuf, sizeof(ddBuf)));
    677   if (actual != sizeof(ddBuf)) {
    678     return kIoError;
    679   }
    680 
    681   const uint32_t ddSignature = *(reinterpret_cast<const uint32_t*>(ddBuf));
    682   const uint16_t offset = (ddSignature == DataDescriptor::kOptSignature) ? 4 : 0;
    683   const DataDescriptor* descriptor = reinterpret_cast<const DataDescriptor*>(ddBuf + offset);
    684 
    685   entry->crc32 = descriptor->crc32;
    686   entry->compressed_length = descriptor->compressed_size;
    687   entry->uncompressed_length = descriptor->uncompressed_size;
    688 
    689   return 0;
    690 }
    691 
    692 // Attempts to read |len| bytes into |buf| at offset |off|.
    693 //
    694 // This method uses pread64 on platforms that support it and
    695 // lseek64 + read on platforms that don't. This implies that
    696 // callers should not rely on the |fd| offset being incremented
    697 // as a side effect of this call.
    698 static inline ssize_t ReadAtOffset(int fd, uint8_t* buf, size_t len,
    699                                    off64_t off) {
    700 #if !defined(_WIN32)
    701   return TEMP_FAILURE_RETRY(pread64(fd, buf, len, off));
    702 #else
    703   // The only supported platform that doesn't support pread at the moment
    704   // is Windows. Only recent versions of windows support unix like forks,
    705   // and even there the semantics are quite different.
    706   if (lseek64(fd, off, SEEK_SET) != off) {
    707     ALOGW("Zip: failed seek to offset %" PRId64, off);
    708     return kIoError;
    709   }
    710 
    711   return TEMP_FAILURE_RETRY(read(fd, buf, len));
    712 #endif
    713 }
    714 
    715 static int32_t FindEntry(const ZipArchive* archive, const int ent,
    716                          ZipEntry* data) {
    717   const uint16_t nameLen = archive->hash_table[ent].name_length;
    718 
    719   // Recover the start of the central directory entry from the filename
    720   // pointer.  The filename is the first entry past the fixed-size data,
    721   // so we can just subtract back from that.
    722   const uint8_t* ptr = archive->hash_table[ent].name;
    723   ptr -= sizeof(CentralDirectoryRecord);
    724 
    725   // This is the base of our mmapped region, we have to sanity check that
    726   // the name that's in the hash table is a pointer to a location within
    727   // this mapped region.
    728   const uint8_t* base_ptr = reinterpret_cast<const uint8_t*>(
    729     archive->directory_map.getDataPtr());
    730   if (ptr < base_ptr || ptr > base_ptr + archive->directory_map.getDataLength()) {
    731     ALOGW("Zip: Invalid entry pointer");
    732     return kInvalidOffset;
    733   }
    734 
    735   const CentralDirectoryRecord *cdr =
    736       reinterpret_cast<const CentralDirectoryRecord*>(ptr);
    737 
    738   // The offset of the start of the central directory in the zipfile.
    739   // We keep this lying around so that we can sanity check all our lengths
    740   // and our per-file structures.
    741   const off64_t cd_offset = archive->directory_offset;
    742 
    743   // Fill out the compression method, modification time, crc32
    744   // and other interesting attributes from the central directory. These
    745   // will later be compared against values from the local file header.
    746   data->method = cdr->compression_method;
    747   data->mod_time = cdr->last_mod_time;
    748   data->crc32 = cdr->crc32;
    749   data->compressed_length = cdr->compressed_size;
    750   data->uncompressed_length = cdr->uncompressed_size;
    751 
    752   // Figure out the local header offset from the central directory. The
    753   // actual file data will begin after the local header and the name /
    754   // extra comments.
    755   const off64_t local_header_offset = cdr->local_file_header_offset;
    756   if (local_header_offset + static_cast<off64_t>(sizeof(LocalFileHeader)) >= cd_offset) {
    757     ALOGW("Zip: bad local hdr offset in zip");
    758     return kInvalidOffset;
    759   }
    760 
    761   uint8_t lfh_buf[sizeof(LocalFileHeader)];
    762   ssize_t actual = ReadAtOffset(archive->fd, lfh_buf, sizeof(lfh_buf),
    763                                  local_header_offset);
    764   if (actual != sizeof(lfh_buf)) {
    765     ALOGW("Zip: failed reading lfh name from offset %" PRId64,
    766         static_cast<int64_t>(local_header_offset));
    767     return kIoError;
    768   }
    769 
    770   const LocalFileHeader *lfh = reinterpret_cast<const LocalFileHeader*>(lfh_buf);
    771 
    772   if (lfh->lfh_signature != LocalFileHeader::kSignature) {
    773     ALOGW("Zip: didn't find signature at start of lfh, offset=%" PRId64,
    774         static_cast<int64_t>(local_header_offset));
    775     return kInvalidOffset;
    776   }
    777 
    778   // Paranoia: Match the values specified in the local file header
    779   // to those specified in the central directory.
    780   if ((lfh->gpb_flags & kGPBDDFlagMask) == 0) {
    781     data->has_data_descriptor = 0;
    782     if (data->compressed_length != lfh->compressed_size
    783         || data->uncompressed_length != lfh->uncompressed_size
    784         || data->crc32 != lfh->crc32) {
    785       ALOGW("Zip: size/crc32 mismatch. expected {%" PRIu32 ", %" PRIu32
    786         ", %" PRIx32 "}, was {%" PRIu32 ", %" PRIu32 ", %" PRIx32 "}",
    787         data->compressed_length, data->uncompressed_length, data->crc32,
    788         lfh->compressed_size, lfh->uncompressed_size, lfh->crc32);
    789       return kInconsistentInformation;
    790     }
    791   } else {
    792     data->has_data_descriptor = 1;
    793   }
    794 
    795   // Check that the local file header name matches the declared
    796   // name in the central directory.
    797   if (lfh->file_name_length == nameLen) {
    798     const off64_t name_offset = local_header_offset + sizeof(LocalFileHeader);
    799     if (name_offset + lfh->file_name_length > cd_offset) {
    800       ALOGW("Zip: Invalid declared length");
    801       return kInvalidOffset;
    802     }
    803 
    804     uint8_t* name_buf = reinterpret_cast<uint8_t*>(malloc(nameLen));
    805     ssize_t actual = ReadAtOffset(archive->fd, name_buf, nameLen,
    806                                   name_offset);
    807 
    808     if (actual != nameLen) {
    809       ALOGW("Zip: failed reading lfh name from offset %" PRId64, static_cast<int64_t>(name_offset));
    810       free(name_buf);
    811       return kIoError;
    812     }
    813 
    814     if (memcmp(archive->hash_table[ent].name, name_buf, nameLen)) {
    815       free(name_buf);
    816       return kInconsistentInformation;
    817     }
    818 
    819     free(name_buf);
    820   } else {
    821     ALOGW("Zip: lfh name did not match central directory.");
    822     return kInconsistentInformation;
    823   }
    824 
    825   const off64_t data_offset = local_header_offset + sizeof(LocalFileHeader)
    826       + lfh->file_name_length + lfh->extra_field_length;
    827   if (data_offset > cd_offset) {
    828     ALOGW("Zip: bad data offset %" PRId64 " in zip", static_cast<int64_t>(data_offset));
    829     return kInvalidOffset;
    830   }
    831 
    832   if (static_cast<off64_t>(data_offset + data->compressed_length) > cd_offset) {
    833     ALOGW("Zip: bad compressed length in zip (%" PRId64 " + %" PRIu32 " > %" PRId64 ")",
    834       static_cast<int64_t>(data_offset), data->compressed_length, static_cast<int64_t>(cd_offset));
    835     return kInvalidOffset;
    836   }
    837 
    838   if (data->method == kCompressStored &&
    839     static_cast<off64_t>(data_offset + data->uncompressed_length) > cd_offset) {
    840      ALOGW("Zip: bad uncompressed length in zip (%" PRId64 " + %" PRIu32 " > %" PRId64 ")",
    841        static_cast<int64_t>(data_offset), data->uncompressed_length,
    842        static_cast<int64_t>(cd_offset));
    843      return kInvalidOffset;
    844   }
    845 
    846   data->offset = data_offset;
    847   return 0;
    848 }
    849 
    850 struct IterationHandle {
    851   uint32_t position;
    852   // We're not using vector here because this code is used in the Windows SDK
    853   // where the STL is not available.
    854   const uint8_t* prefix;
    855   const uint16_t prefix_len;
    856   const uint8_t* suffix;
    857   const uint16_t suffix_len;
    858   ZipArchive* archive;
    859 
    860   IterationHandle(const ZipEntryName* prefix_name,
    861                   const ZipEntryName* suffix_name)
    862     : prefix(NULL),
    863       prefix_len(prefix_name ? prefix_name->name_length : 0),
    864       suffix(NULL),
    865       suffix_len(suffix_name ? suffix_name->name_length : 0) {
    866     if (prefix_name) {
    867       uint8_t* prefix_copy = new uint8_t[prefix_len];
    868       memcpy(prefix_copy, prefix_name->name, prefix_len);
    869       prefix = prefix_copy;
    870     }
    871     if (suffix_name) {
    872       uint8_t* suffix_copy = new uint8_t[suffix_len];
    873       memcpy(suffix_copy, suffix_name->name, suffix_len);
    874       suffix = suffix_copy;
    875     }
    876   }
    877 
    878   ~IterationHandle() {
    879     delete[] prefix;
    880     delete[] suffix;
    881   }
    882 };
    883 
    884 int32_t StartIteration(ZipArchiveHandle handle, void** cookie_ptr,
    885                        const ZipEntryName* optional_prefix,
    886                        const ZipEntryName* optional_suffix) {
    887   ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle);
    888 
    889   if (archive == NULL || archive->hash_table == NULL) {
    890     ALOGW("Zip: Invalid ZipArchiveHandle");
    891     return kInvalidHandle;
    892   }
    893 
    894   IterationHandle* cookie = new IterationHandle(optional_prefix, optional_suffix);
    895   cookie->position = 0;
    896   cookie->archive = archive;
    897 
    898   *cookie_ptr = cookie ;
    899   return 0;
    900 }
    901 
    902 void EndIteration(void* cookie) {
    903   delete reinterpret_cast<IterationHandle*>(cookie);
    904 }
    905 
    906 int32_t FindEntry(const ZipArchiveHandle handle, const ZipEntryName& entryName,
    907                   ZipEntry* data) {
    908   const ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle);
    909   if (entryName.name_length == 0) {
    910     ALOGW("Zip: Invalid filename %.*s", entryName.name_length, entryName.name);
    911     return kInvalidEntryName;
    912   }
    913 
    914   const int64_t ent = EntryToIndex(archive->hash_table,
    915     archive->hash_table_size, entryName);
    916 
    917   if (ent < 0) {
    918     ALOGV("Zip: Could not find entry %.*s", entryName.name_length, entryName.name);
    919     return ent;
    920   }
    921 
    922   return FindEntry(archive, ent, data);
    923 }
    924 
    925 int32_t Next(void* cookie, ZipEntry* data, ZipEntryName* name) {
    926   IterationHandle* handle = reinterpret_cast<IterationHandle*>(cookie);
    927   if (handle == NULL) {
    928     return kInvalidHandle;
    929   }
    930 
    931   ZipArchive* archive = handle->archive;
    932   if (archive == NULL || archive->hash_table == NULL) {
    933     ALOGW("Zip: Invalid ZipArchiveHandle");
    934     return kInvalidHandle;
    935   }
    936 
    937   const uint32_t currentOffset = handle->position;
    938   const uint32_t hash_table_length = archive->hash_table_size;
    939   const ZipEntryName *hash_table = archive->hash_table;
    940 
    941   for (uint32_t i = currentOffset; i < hash_table_length; ++i) {
    942     if (hash_table[i].name != NULL &&
    943         (handle->prefix_len == 0 ||
    944          (hash_table[i].name_length >= handle->prefix_len &&
    945           memcmp(handle->prefix, hash_table[i].name, handle->prefix_len) == 0)) &&
    946         (handle->suffix_len == 0 ||
    947          (hash_table[i].name_length >= handle->suffix_len &&
    948           memcmp(handle->suffix,
    949                  hash_table[i].name + hash_table[i].name_length - handle->suffix_len,
    950                  handle->suffix_len) == 0))) {
    951       handle->position = (i + 1);
    952       const int error = FindEntry(archive, i, data);
    953       if (!error) {
    954         name->name = hash_table[i].name;
    955         name->name_length = hash_table[i].name_length;
    956       }
    957 
    958       return error;
    959     }
    960   }
    961 
    962   handle->position = 0;
    963   return kIterationEnd;
    964 }
    965 
    966 class Writer {
    967  public:
    968   virtual bool Append(uint8_t* buf, size_t buf_size) = 0;
    969   virtual ~Writer() {}
    970  protected:
    971   Writer() = default;
    972  private:
    973   DISALLOW_COPY_AND_ASSIGN(Writer);
    974 };
    975 
    976 // A Writer that writes data to a fixed size memory region.
    977 // The size of the memory region must be equal to the total size of
    978 // the data appended to it.
    979 class MemoryWriter : public Writer {
    980  public:
    981   MemoryWriter(uint8_t* buf, size_t size) : Writer(),
    982       buf_(buf), size_(size), bytes_written_(0) {
    983   }
    984 
    985   virtual bool Append(uint8_t* buf, size_t buf_size) override {
    986     if (bytes_written_ + buf_size > size_) {
    987       ALOGW("Zip: Unexpected size " ZD " (declared) vs " ZD " (actual)",
    988             size_, bytes_written_ + buf_size);
    989       return false;
    990     }
    991 
    992     memcpy(buf_ + bytes_written_, buf, buf_size);
    993     bytes_written_ += buf_size;
    994     return true;
    995   }
    996 
    997  private:
    998   uint8_t* const buf_;
    999   const size_t size_;
   1000   size_t bytes_written_;
   1001 };
   1002 
   1003 // A Writer that appends data to a file |fd| at its current position.
   1004 // The file will be truncated to the end of the written data.
   1005 class FileWriter : public Writer {
   1006  public:
   1007 
   1008   // Creates a FileWriter for |fd| and prepare to write |entry| to it,
   1009   // guaranteeing that the file descriptor is valid and that there's enough
   1010   // space on the volume to write out the entry completely and that the file
   1011   // is truncated to the correct length.
   1012   //
   1013   // Returns a valid FileWriter on success, |nullptr| if an error occurred.
   1014   static std::unique_ptr<FileWriter> Create(int fd, const ZipEntry* entry) {
   1015     const uint32_t declared_length = entry->uncompressed_length;
   1016     const off64_t current_offset = lseek64(fd, 0, SEEK_CUR);
   1017     if (current_offset == -1) {
   1018       ALOGW("Zip: unable to seek to current location on fd %d: %s", fd, strerror(errno));
   1019       return nullptr;
   1020     }
   1021 
   1022     int result = 0;
   1023 #if defined(__linux__)
   1024     if (declared_length > 0) {
   1025       // Make sure we have enough space on the volume to extract the compressed
   1026       // entry. Note that the call to ftruncate below will change the file size but
   1027       // will not allocate space on disk and this call to fallocate will not
   1028       // change the file size.
   1029       // Note: fallocate is only supported by the following filesystems -
   1030       // btrfs, ext4, ocfs2, and xfs. Therefore fallocate might fail with
   1031       // EOPNOTSUPP error when issued in other filesystems.
   1032       // Hence, check for the return error code before concluding that the
   1033       // disk does not have enough space.
   1034       result = TEMP_FAILURE_RETRY(fallocate(fd, 0, current_offset, declared_length));
   1035       if (result == -1 && errno == ENOSPC) {
   1036         ALOGW("Zip: unable to allocate space for file to %" PRId64 ": %s",
   1037               static_cast<int64_t>(declared_length + current_offset), strerror(errno));
   1038         return std::unique_ptr<FileWriter>(nullptr);
   1039       }
   1040     }
   1041 #endif  // __linux__
   1042 
   1043     result = TEMP_FAILURE_RETRY(ftruncate(fd, declared_length + current_offset));
   1044     if (result == -1) {
   1045       ALOGW("Zip: unable to truncate file to %" PRId64 ": %s",
   1046             static_cast<int64_t>(declared_length + current_offset), strerror(errno));
   1047       return std::unique_ptr<FileWriter>(nullptr);
   1048     }
   1049 
   1050     return std::unique_ptr<FileWriter>(new FileWriter(fd, declared_length));
   1051   }
   1052 
   1053   virtual bool Append(uint8_t* buf, size_t buf_size) override {
   1054     if (total_bytes_written_ + buf_size > declared_length_) {
   1055       ALOGW("Zip: Unexpected size " ZD " (declared) vs " ZD " (actual)",
   1056             declared_length_, total_bytes_written_ + buf_size);
   1057       return false;
   1058     }
   1059 
   1060     const bool result = android::base::WriteFully(fd_, buf, buf_size);
   1061     if (result) {
   1062       total_bytes_written_ += buf_size;
   1063     } else {
   1064       ALOGW("Zip: unable to write " ZD " bytes to file; %s", buf_size, strerror(errno));
   1065     }
   1066 
   1067     return result;
   1068   }
   1069  private:
   1070   FileWriter(const int fd, const size_t declared_length) :
   1071       Writer(),
   1072       fd_(fd),
   1073       declared_length_(declared_length),
   1074       total_bytes_written_(0) {
   1075   }
   1076 
   1077   const int fd_;
   1078   const size_t declared_length_;
   1079   size_t total_bytes_written_;
   1080 };
   1081 
   1082 // This method is using libz macros with old-style-casts
   1083 #pragma GCC diagnostic push
   1084 #pragma GCC diagnostic ignored "-Wold-style-cast"
   1085 static inline int zlib_inflateInit2(z_stream* stream, int window_bits) {
   1086   return inflateInit2(stream, window_bits);
   1087 }
   1088 #pragma GCC diagnostic pop
   1089 
   1090 static int32_t InflateEntryToWriter(int fd, const ZipEntry* entry,
   1091                                     Writer* writer, uint64_t* crc_out) {
   1092   const size_t kBufSize = 32768;
   1093   std::vector<uint8_t> read_buf(kBufSize);
   1094   std::vector<uint8_t> write_buf(kBufSize);
   1095   z_stream zstream;
   1096   int zerr;
   1097 
   1098   /*
   1099    * Initialize the zlib stream struct.
   1100    */
   1101   memset(&zstream, 0, sizeof(zstream));
   1102   zstream.zalloc = Z_NULL;
   1103   zstream.zfree = Z_NULL;
   1104   zstream.opaque = Z_NULL;
   1105   zstream.next_in = NULL;
   1106   zstream.avail_in = 0;
   1107   zstream.next_out = &write_buf[0];
   1108   zstream.avail_out = kBufSize;
   1109   zstream.data_type = Z_UNKNOWN;
   1110 
   1111   /*
   1112    * Use the undocumented "negative window bits" feature to tell zlib
   1113    * that there's no zlib header waiting for it.
   1114    */
   1115   zerr = zlib_inflateInit2(&zstream, -MAX_WBITS);
   1116   if (zerr != Z_OK) {
   1117     if (zerr == Z_VERSION_ERROR) {
   1118       ALOGE("Installed zlib is not compatible with linked version (%s)",
   1119         ZLIB_VERSION);
   1120     } else {
   1121       ALOGW("Call to inflateInit2 failed (zerr=%d)", zerr);
   1122     }
   1123 
   1124     return kZlibError;
   1125   }
   1126 
   1127   auto zstream_deleter = [](z_stream* stream) {
   1128     inflateEnd(stream);  /* free up any allocated structures */
   1129   };
   1130 
   1131   std::unique_ptr<z_stream, decltype(zstream_deleter)> zstream_guard(&zstream, zstream_deleter);
   1132 
   1133   const uint32_t uncompressed_length = entry->uncompressed_length;
   1134 
   1135   uint32_t compressed_length = entry->compressed_length;
   1136   do {
   1137     /* read as much as we can */
   1138     if (zstream.avail_in == 0) {
   1139       const ZD_TYPE getSize = (compressed_length > kBufSize) ? kBufSize : compressed_length;
   1140       const ZD_TYPE actual = TEMP_FAILURE_RETRY(read(fd, &read_buf[0], getSize));
   1141       if (actual != getSize) {
   1142         ALOGW("Zip: inflate read failed (" ZD " vs " ZD ")", actual, getSize);
   1143         return kIoError;
   1144       }
   1145 
   1146       compressed_length -= getSize;
   1147 
   1148       zstream.next_in = &read_buf[0];
   1149       zstream.avail_in = getSize;
   1150     }
   1151 
   1152     /* uncompress the data */
   1153     zerr = inflate(&zstream, Z_NO_FLUSH);
   1154     if (zerr != Z_OK && zerr != Z_STREAM_END) {
   1155       ALOGW("Zip: inflate zerr=%d (nIn=%p aIn=%u nOut=%p aOut=%u)",
   1156           zerr, zstream.next_in, zstream.avail_in,
   1157           zstream.next_out, zstream.avail_out);
   1158       return kZlibError;
   1159     }
   1160 
   1161     /* write when we're full or when we're done */
   1162     if (zstream.avail_out == 0 ||
   1163       (zerr == Z_STREAM_END && zstream.avail_out != kBufSize)) {
   1164       const size_t write_size = zstream.next_out - &write_buf[0];
   1165       if (!writer->Append(&write_buf[0], write_size)) {
   1166         // The file might have declared a bogus length.
   1167         return kInconsistentInformation;
   1168       }
   1169 
   1170       zstream.next_out = &write_buf[0];
   1171       zstream.avail_out = kBufSize;
   1172     }
   1173   } while (zerr == Z_OK);
   1174 
   1175   assert(zerr == Z_STREAM_END);     /* other errors should've been caught */
   1176 
   1177   // stream.adler holds the crc32 value for such streams.
   1178   *crc_out = zstream.adler;
   1179 
   1180   if (zstream.total_out != uncompressed_length || compressed_length != 0) {
   1181     ALOGW("Zip: size mismatch on inflated file (%lu vs %" PRIu32 ")",
   1182         zstream.total_out, uncompressed_length);
   1183     return kInconsistentInformation;
   1184   }
   1185 
   1186   return 0;
   1187 }
   1188 
   1189 static int32_t CopyEntryToWriter(int fd, const ZipEntry* entry, Writer* writer,
   1190                                  uint64_t *crc_out) {
   1191   static const uint32_t kBufSize = 32768;
   1192   std::vector<uint8_t> buf(kBufSize);
   1193 
   1194   const uint32_t length = entry->uncompressed_length;
   1195   uint32_t count = 0;
   1196   uint64_t crc = 0;
   1197   while (count < length) {
   1198     uint32_t remaining = length - count;
   1199 
   1200     // Safe conversion because kBufSize is narrow enough for a 32 bit signed
   1201     // value.
   1202     const ssize_t block_size = (remaining > kBufSize) ? kBufSize : remaining;
   1203     const ssize_t actual = TEMP_FAILURE_RETRY(read(fd, &buf[0], block_size));
   1204 
   1205     if (actual != block_size) {
   1206       ALOGW("CopyFileToFile: copy read failed (" ZD " vs " ZD ")", actual, block_size);
   1207       return kIoError;
   1208     }
   1209 
   1210     if (!writer->Append(&buf[0], block_size)) {
   1211       return kIoError;
   1212     }
   1213     crc = crc32(crc, &buf[0], block_size);
   1214     count += block_size;
   1215   }
   1216 
   1217   *crc_out = crc;
   1218 
   1219   return 0;
   1220 }
   1221 
   1222 int32_t ExtractToWriter(ZipArchiveHandle handle,
   1223                         ZipEntry* entry, Writer* writer) {
   1224   ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle);
   1225   const uint16_t method = entry->method;
   1226   off64_t data_offset = entry->offset;
   1227 
   1228   if (lseek64(archive->fd, data_offset, SEEK_SET) != data_offset) {
   1229     ALOGW("Zip: lseek to data at %" PRId64 " failed", static_cast<int64_t>(data_offset));
   1230     return kIoError;
   1231   }
   1232 
   1233   // this should default to kUnknownCompressionMethod.
   1234   int32_t return_value = -1;
   1235   uint64_t crc = 0;
   1236   if (method == kCompressStored) {
   1237     return_value = CopyEntryToWriter(archive->fd, entry, writer, &crc);
   1238   } else if (method == kCompressDeflated) {
   1239     return_value = InflateEntryToWriter(archive->fd, entry, writer, &crc);
   1240   }
   1241 
   1242   if (!return_value && entry->has_data_descriptor) {
   1243     return_value = UpdateEntryFromDataDescriptor(archive->fd, entry);
   1244     if (return_value) {
   1245       return return_value;
   1246     }
   1247   }
   1248 
   1249   // TODO: Fix this check by passing the right flags to inflate2 so that
   1250   // it calculates the CRC for us.
   1251   if (entry->crc32 != crc && false) {
   1252     ALOGW("Zip: crc mismatch: expected %" PRIu32 ", was %" PRIu64, entry->crc32, crc);
   1253     return kInconsistentInformation;
   1254   }
   1255 
   1256   return return_value;
   1257 }
   1258 
   1259 int32_t ExtractToMemory(ZipArchiveHandle handle, ZipEntry* entry,
   1260                         uint8_t* begin, uint32_t size) {
   1261   std::unique_ptr<Writer> writer(new MemoryWriter(begin, size));
   1262   return ExtractToWriter(handle, entry, writer.get());
   1263 }
   1264 
   1265 int32_t ExtractEntryToFile(ZipArchiveHandle handle,
   1266                            ZipEntry* entry, int fd) {
   1267   std::unique_ptr<Writer> writer(FileWriter::Create(fd, entry));
   1268   if (writer.get() == nullptr) {
   1269     return kIoError;
   1270   }
   1271 
   1272   return ExtractToWriter(handle, entry, writer.get());
   1273 }
   1274 
   1275 const char* ErrorCodeString(int32_t error_code) {
   1276   if (error_code > kErrorMessageLowerBound && error_code < kErrorMessageUpperBound) {
   1277     return kErrorMessages[error_code * -1];
   1278   }
   1279 
   1280   return kErrorMessages[0];
   1281 }
   1282 
   1283 int GetFileDescriptor(const ZipArchiveHandle handle) {
   1284   return reinterpret_cast<ZipArchive*>(handle)->fd;
   1285 }
   1286