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
17fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#ifndef ART_RUNTIME_ZIP_ARCHIVE_H_
18fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#define ART_RUNTIME_ZIP_ARCHIVE_H_
19b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
20b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom#include <stdint.h>
21b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom#include <zlib.h>
22b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
2307ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h"
24e222ee0b794f941af4fb1b32fb8224e32942ea7bElliott Hughes#include "base/stringpiece.h"
25761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/unix_file/random_access_file.h"
26b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom#include "globals.h"
27db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom#include "mem_map.h"
28761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "os.h"
29a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes#include "safe_map.h"
30e5448b5a12003b405b22cde3b94f962ab4888a87Elliott Hughes#include "UniquePtr.h"
31b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
32b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstromnamespace art {
33b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
34b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstromclass ZipArchive;
35b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstromclass MemMap;
36b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
37b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstromclass ZipEntry {
38b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom public:
3989521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom  bool ExtractToFile(File& file);
404922e9d4e5f86e40ca89fb097cec40e191dae0a1Brian Carlstrom  bool ExtractToMemory(uint8_t* begin, size_t size);
414922e9d4e5f86e40ca89fb097cec40e191dae0a1Brian Carlstrom  MemMap* ExtractToMemMap(const char* entry_filename);
42b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
4389521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom  uint32_t GetUncompressedLength();
44b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  uint32_t GetCrc32();
45b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
46b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom private:
47a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  ZipEntry(const ZipArchive* zip_archive, const byte* ptr) : zip_archive_(zip_archive), ptr_(ptr) {}
48b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
49b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  // Zip compression methods
50b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  enum {
51b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom    kCompressStored     = 0,        // no compression
52b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom    kCompressDeflated   = 8,        // standard deflate
53b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  };
54b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
55b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  // kCompressStored, kCompressDeflated, ...
56b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  uint16_t GetCompressionMethod();
57b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
58b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  uint32_t GetCompressedLength();
59b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
60b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  // returns -1 on error
6172fcca2477e02da2d3970aefc75465ba1f20ce9cKenny Root  off64_t GetDataOffset();
62b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
63a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  const ZipArchive* zip_archive_;
64b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
65b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  // pointer to zip entry within central directory
66db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  const byte* ptr_;
67b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
68b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  friend class ZipArchive;
69a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes  DISALLOW_COPY_AND_ASSIGN(ZipEntry);
70b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom};
71b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
72b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstromclass ZipArchive {
73b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom public:
74b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  // Zip file constants.
7572fcca2477e02da2d3970aefc75465ba1f20ce9cKenny Root  static const uint32_t kEOCDSignature      = 0x06054b50;
7672fcca2477e02da2d3970aefc75465ba1f20ce9cKenny Root  static const int32_t kEOCDLen             = 22;
7772fcca2477e02da2d3970aefc75465ba1f20ce9cKenny Root  static const int32_t kEOCDDiskNumber      =  4;              // number of the current disk
7872fcca2477e02da2d3970aefc75465ba1f20ce9cKenny Root  static const int32_t kEOCDDiskNumberForCD =  6;              // disk number with the Central Directory
7972fcca2477e02da2d3970aefc75465ba1f20ce9cKenny Root  static const int32_t kEOCDNumEntries      =  8;              // offset to #of entries in file
8072fcca2477e02da2d3970aefc75465ba1f20ce9cKenny Root  static const int32_t kEOCDTotalNumEntries = 10;              // offset to total #of entries in spanned archives
8172fcca2477e02da2d3970aefc75465ba1f20ce9cKenny Root  static const int32_t kEOCDSize            = 12;              // size of the central directory
8272fcca2477e02da2d3970aefc75465ba1f20ce9cKenny Root  static const int32_t kEOCDFileOffset      = 16;              // offset to central directory
8372fcca2477e02da2d3970aefc75465ba1f20ce9cKenny Root  static const int32_t kEOCDCommentSize     = 20;              // offset to the length of the file comment
84b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
85b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  static const int32_t kMaxCommentLen = 65535;  // longest possible in uint16_t
86b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  static const int32_t kMaxEOCDSearch = (kMaxCommentLen + kEOCDLen);
87b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
88b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  static const uint32_t kLFHSignature = 0x04034b50;
89b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  static const int32_t kLFHLen        = 30;  // excluding variable-len fields
9072fcca2477e02da2d3970aefc75465ba1f20ce9cKenny Root  static const int32_t kLFHGPBFlags   = 6;   // offset to GPB flags
91b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  static const int32_t kLFHNameLen    = 26;  // offset to filename length
92b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  static const int32_t kLFHExtraLen   = 28;  // offset to extra length
93b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
94b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  static const uint32_t kCDESignature   = 0x02014b50;
95b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  static const int32_t kCDELen          = 46;  // excluding variable-len fields
9672fcca2477e02da2d3970aefc75465ba1f20ce9cKenny Root  static const int32_t kCDEGPBFlags     = 8;   // offset to GPB flags
97b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  static const int32_t kCDEMethod       = 10;  // offset to compression method
98b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  static const int32_t kCDEModWhen      = 12;  // offset to modification timestamp
99b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  static const int32_t kCDECRC          = 16;  // offset to entry CRC
100b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  static const int32_t kCDECompLen      = 20;  // offset to compressed length
101b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  static const int32_t kCDEUncompLen    = 24;  // offset to uncompressed length
102b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  static const int32_t kCDENameLen      = 28;  // offset to filename length
103b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  static const int32_t kCDEExtraLen     = 30;  // offset to extra length
104b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  static const int32_t kCDECommentLen   = 32;  // offset to comment length
105b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  static const int32_t kCDELocalOffset  = 42;  // offset to local hdr
106b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
10772fcca2477e02da2d3970aefc75465ba1f20ce9cKenny Root  // General Purpose Bit Flag
10872fcca2477e02da2d3970aefc75465ba1f20ce9cKenny Root  static const int32_t kGPFEncryptedFlag   = (1 << 0);
10972fcca2477e02da2d3970aefc75465ba1f20ce9cKenny Root  static const int32_t kGPFUnsupportedMask = (kGPFEncryptedFlag);
11072fcca2477e02da2d3970aefc75465ba1f20ce9cKenny Root
111b7bbba49d88eae58223d9878da4069bf6d7140bfBrian Carlstrom  // return new ZipArchive instance on success, NULL on error.
112b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  static ZipArchive* Open(const std::string& filename);
113a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  static ZipArchive* OpenFromFd(int fd);
114b7bbba49d88eae58223d9878da4069bf6d7140bfBrian Carlstrom
115a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  ZipEntry* Find(const char* name) const;
116b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
117b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  ~ZipArchive() {
118b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom    Close();
119b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  }
120b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
121b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom private:
122a51a3dd5603daf3d368b7735067e1d9eb54c4c40Elliott Hughes  explicit ZipArchive(int fd) : fd_(fd), num_entries_(0), dir_offset_(0) {}
123b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
124b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  bool MapCentralDirectory();
125b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  bool Parse();
126b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  void Close();
127b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
128b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  int fd_;
129b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  uint16_t num_entries_;
13072fcca2477e02da2d3970aefc75465ba1f20ce9cKenny Root  off64_t dir_offset_;
13190a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes  UniquePtr<MemMap> dir_map_;
132a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  typedef SafeMap<StringPiece, const byte*> DirEntries;
1337e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom  DirEntries dir_entries_;
134b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
135b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  friend class ZipEntry;
136a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes
137a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes  DISALLOW_COPY_AND_ASSIGN(ZipArchive);
138b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom};
139b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
140b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom}  // namespace art
141b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
142fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#endif  // ART_RUNTIME_ZIP_ARCHIVE_H_
143