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