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