zip_archive.h revision 7e93b50433cde2a44d99212e8040299bde498546
1b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom/* 2b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom * Copyright (C) 2008 The Android Open Source Project 3b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom * 4b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License"); 5b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom * you may not use this file except in compliance with the License. 6b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom * You may obtain a copy of the License at 7b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom * 8b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom * http://www.apache.org/licenses/LICENSE-2.0 9b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom * 10b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom * Unless required by applicable law or agreed to in writing, software 11b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS, 12b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom * See the License for the specific language governing permissions and 14b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom * limitations under the License. 15b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom */ 16b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 17b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom#ifndef ART_SRC_ZIP_ARCHIVE_H_ 18b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom#define ART_SRC_ZIP_ARCHIVE_H_ 19b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 20b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom#include <map> 21b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom#include <stdint.h> 22b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom#include <sys/mman.h> 23b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom#include <zlib.h> 24b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 25b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom#include "globals.h" 26b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom#include "logging.h" 27b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom#include "scoped_ptr.h" 28b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom#include "stringpiece.h" 297e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom#include "unordered_map.h" 30b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 31b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstromnamespace art { 32b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 33b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstromclass ZipArchive; 34b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstromclass MemMap; 35b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 36b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstromclass ZipEntry { 37b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 38b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom public: 39b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom // Uncompress an entry, in its entirety, to an open file descriptor. 40b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom bool Extract(int fd); 41b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 42b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom uint32_t GetCrc32(); 43b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 44b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom private: 45b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 46b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom ZipEntry(ZipArchive* zip_archive, const uint8_t* ptr) : zip_archive_(zip_archive), ptr_(ptr) {}; 47b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 48b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom // Zip compression methods 49b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom enum { 50b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom kCompressStored = 0, // no compression 51b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom kCompressDeflated = 8, // standard deflate 52b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom }; 53b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 54b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom // kCompressStored, kCompressDeflated, ... 55b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom uint16_t GetCompressionMethod(); 56b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 57b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom uint32_t GetCompressedLength(); 58b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 59b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom uint32_t GetUncompressedLength(); 60b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 61b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom // returns -1 on error 62b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom off_t GetDataOffset(); 63b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 64b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom ZipArchive* zip_archive_; 65b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 66b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom // pointer to zip entry within central directory 67b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom const uint8_t* ptr_; 68b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 69b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom friend class ZipArchive; 70b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom}; 71b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 72b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom// Used to keep track of unaligned mmap segments. 73b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstromclass MemMap { 74b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom public: 75b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 76b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom // Map part of a file into a shared, read-only memory segment. The "start" 77b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom // offset is absolute, not relative. 78b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom // 79b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom // On success, returns returns a MemMap instance. On failure, returns a NULL; 80b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom static MemMap* Map(int fd, off_t start, size_t length) { 81b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom // adjust to be page-aligned 82b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom int page_offset = start % kPageSize; 83b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom off_t page_aligned_offset = start - page_offset; 84b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom size_t page_aligned_size = length + page_offset; 85b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom uint8_t* addr = reinterpret_cast<uint8_t*>(mmap(NULL, 86b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom page_aligned_size, 87b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom PROT_READ, 88b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom MAP_FILE | MAP_SHARED, 89b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom fd, 90b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom page_aligned_offset)); 91b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom if (addr == MAP_FAILED) { 92b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom return NULL; 93b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom } 94b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom return new MemMap(addr+page_offset, length, addr, page_aligned_size); 95b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom } 96b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 97b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom ~MemMap() { 98b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom Unmap(); 99b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom }; 100b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 101b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom // Release a memory mapping, returning true on success or it was previously unmapped. 102b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom bool Unmap() { 103b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom if (base_addr_ == NULL && base_length_ == 0) { 104b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom return true; 105b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom } 106b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom int result = munmap(base_addr_, base_length_); 107b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom if (result != 0) { 108b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom return false; 109b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom } 110b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom base_addr_ = NULL; 111b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom base_length_ = 0; 112b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom return true; 113b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom } 114b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 115b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom void* GetAddress() { 116b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom return addr_; 117b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom } 118b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 119b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom size_t GetLength() { 120b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom return length_; 121b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom } 122b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 123b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom private: 124b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom MemMap(void* addr, size_t length, void* base_addr, size_t base_length) 125b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom : addr_(addr), length_(length), base_addr_(base_addr), base_length_(base_length) { 126b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom CHECK(addr_ != NULL); 127b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom CHECK(length_ != 0); 128b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom CHECK(base_addr_ != NULL); 129b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom CHECK(base_length_ != 0); 130b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom }; 131b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 132b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom void* addr_; // start of data 133b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom size_t length_; // length of data 134b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 135b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom void* base_addr_; // page-aligned base address 136b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom size_t base_length_; // length of mapping 137b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom}; 138b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 139b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstromclass ZipArchive { 140b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom public: 141b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 142b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom // Zip file constants. 143b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom static const uint32_t kEOCDSignature = 0x06054b50; 144b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom static const int32_t kEOCDLen = 22; 145b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom static const int32_t kEOCDNumEntries = 8; // offset to #of entries in file 146b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom static const int32_t kEOCDSize = 12; // size of the central directory 147b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom static const int32_t kEOCDFileOffset = 16; // offset to central directory 148b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 149b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom static const int32_t kMaxCommentLen = 65535; // longest possible in uint16_t 150b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom static const int32_t kMaxEOCDSearch = (kMaxCommentLen + kEOCDLen); 151b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 152b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom static const uint32_t kLFHSignature = 0x04034b50; 153b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom static const int32_t kLFHLen = 30; // excluding variable-len fields 154b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom static const int32_t kLFHNameLen = 26; // offset to filename length 155b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom static const int32_t kLFHExtraLen = 28; // offset to extra length 156b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 157b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom static const uint32_t kCDESignature = 0x02014b50; 158b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom static const int32_t kCDELen = 46; // excluding variable-len fields 159b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom static const int32_t kCDEMethod = 10; // offset to compression method 160b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom static const int32_t kCDEModWhen = 12; // offset to modification timestamp 161b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom static const int32_t kCDECRC = 16; // offset to entry CRC 162b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom static const int32_t kCDECompLen = 20; // offset to compressed length 163b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom static const int32_t kCDEUncompLen = 24; // offset to uncompressed length 164b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom static const int32_t kCDENameLen = 28; // offset to filename length 165b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom static const int32_t kCDEExtraLen = 30; // offset to extra length 166b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom static const int32_t kCDECommentLen = 32; // offset to comment length 167b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom static const int32_t kCDELocalOffset = 42; // offset to local hdr 168b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 169b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom static ZipArchive* Open(const std::string& filename); 170b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom ZipEntry* Find(const char * name); 171b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 172b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom ~ZipArchive() { 173b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom Close(); 174b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom } 175b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 176b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom private: 177b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom ZipArchive(int fd) : fd_(fd), num_entries_(0), dir_offset_(0) {} 178b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 179b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom bool MapCentralDirectory(); 180b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom bool Parse(); 181b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom void Close(); 182b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 183b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom int fd_; 184b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom uint16_t num_entries_; 185b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom off_t dir_offset_; 186b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom scoped_ptr<MemMap> dir_map_; 1877e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom typedef std::tr1::unordered_map<StringPiece, const uint8_t*> DirEntries; 1887e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom DirEntries dir_entries_; 189b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 190b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom friend class ZipEntry; 191b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom}; 192b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 193b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom} // namespace art 194b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 195b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom#endif // ART_SRC_ZIP_ARCHIVE_H_ 196