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