• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef LIBDEX_ZIPARCHIVE_H_
21 #define LIBDEX_ZIPARCHIVE_H_
22 
23 #include "SysUtil.h"
24 #include "DexFile.h"            // need DEX_INLINE
25 
26 /*
27  * Trivial typedef to ensure that ZipEntry is not treated as a simple
28  * integer.  We use NULL to indicate an invalid value.
29  */
30 typedef void* ZipEntry;
31 
32 /*
33  * One entry in the hash table.
34  */
35 struct ZipHashEntry {
36     const char*     name;
37     unsigned short  nameLen;
38 };
39 
40 /*
41  * Read-only Zip archive.
42  *
43  * We want "open" and "find entry by name" to be fast operations, and
44  * we want to use as little memory as possible.  We memory-map the zip
45  * central directory, and load a hash table with pointers to the filenames
46  * (which aren't null-terminated).  The other fields are at a fixed offset
47  * from the filename, so we don't need to extract those (but we do need
48  * to byte-read and endian-swap them every time we want them).
49  *
50  * It's possible that somebody has handed us a massive (~1GB) zip archive,
51  * so we can't expect to mmap the entire file.
52  *
53  * To speed comparisons when doing a lookup by name, we could make the mapping
54  * "private" (copy-on-write) and null-terminate the filenames after verifying
55  * the record structure.  However, this requires a private mapping of
56  * every page that the Central Directory touches.  Easier to tuck a copy
57  * of the string length into the hash table entry.
58  */
59 struct ZipArchive {
60     /* open Zip archive */
61     int         mFd;
62 
63     /* mapped central directory area */
64     off_t       mDirectoryOffset;
65     MemMapping  mDirectoryMap;
66 
67     /* number of entries in the Zip archive */
68     int         mNumEntries;
69 
70     /*
71      * We know how many entries are in the Zip archive, so we can have a
72      * fixed-size hash table.  We probe on collisions.
73      */
74     int         mHashTableSize;
75     ZipHashEntry* mHashTable;
76 };
77 
78 /* Zip compression methods we support */
79 enum {
80     kCompressStored     = 0,        // no compression
81     kCompressDeflated   = 8,        // standard deflate
82 };
83 
84 
85 /*
86  * Open a Zip archive.
87  *
88  * On success, returns 0 and populates "pArchive".  Returns nonzero errno
89  * value on failure.
90  */
91 int dexZipOpenArchive(const char* fileName, ZipArchive* pArchive);
92 
93 /*
94  * Like dexZipOpenArchive, but takes a file descriptor open for reading
95  * at the start of the file.  The descriptor must be mappable (this does
96  * not allow access to a stream).
97  *
98  * "debugFileName" will appear in error messages, but is not otherwise used.
99  */
100 int dexZipPrepArchive(int fd, const char* debugFileName, ZipArchive* pArchive);
101 
102 /*
103  * Close archive, releasing resources associated with it.
104  *
105  * Depending on the implementation this could unmap pages used by classes
106  * stored in a Jar.  This should only be done after unloading classes.
107  */
108 void dexZipCloseArchive(ZipArchive* pArchive);
109 
110 /*
111  * Return the archive's file descriptor.
112  */
dexZipGetArchiveFd(const ZipArchive * pArchive)113 DEX_INLINE int dexZipGetArchiveFd(const ZipArchive* pArchive) {
114     return pArchive->mFd;
115 }
116 
117 /*
118  * Find an entry in the Zip archive, by name.  Returns NULL if the entry
119  * was not found.
120  */
121 ZipEntry dexZipFindEntry(const ZipArchive* pArchive,
122     const char* entryName);
123 
124 /*
125  * Retrieve one or more of the "interesting" fields.  Non-NULL pointers
126  * are filled in.
127  *
128  * Returns 0 on success.
129  */
130 int dexZipGetEntryInfo(const ZipArchive* pArchive, ZipEntry entry,
131     int* pMethod, size_t* pUncompLen, size_t* pCompLen, off_t* pOffset,
132     long* pModWhen, long* pCrc32);
133 
134 /*
135  * Simple accessors.
136  */
dexGetZipEntryOffset(const ZipArchive * pArchive,const ZipEntry entry)137 DEX_INLINE long dexGetZipEntryOffset(const ZipArchive* pArchive,
138     const ZipEntry entry)
139 {
140     off_t val = 0;
141     dexZipGetEntryInfo(pArchive, entry, NULL, NULL, NULL, &val, NULL, NULL);
142     return (long) val;
143 }
dexGetZipEntryUncompLen(const ZipArchive * pArchive,const ZipEntry entry)144 DEX_INLINE size_t dexGetZipEntryUncompLen(const ZipArchive* pArchive,
145     const ZipEntry entry)
146 {
147     size_t val = 0;
148     dexZipGetEntryInfo(pArchive, entry, NULL, &val, NULL, NULL, NULL, NULL);
149     return val;
150 }
dexGetZipEntryModTime(const ZipArchive * pArchive,const ZipEntry entry)151 DEX_INLINE long dexGetZipEntryModTime(const ZipArchive* pArchive,
152     const ZipEntry entry)
153 {
154     long val = 0;
155     dexZipGetEntryInfo(pArchive, entry, NULL, NULL, NULL, NULL, &val, NULL);
156     return val;
157 }
dexGetZipEntryCrc32(const ZipArchive * pArchive,const ZipEntry entry)158 DEX_INLINE long dexGetZipEntryCrc32(const ZipArchive* pArchive,
159     const ZipEntry entry)
160 {
161     long val = 0;
162     dexZipGetEntryInfo(pArchive, entry, NULL, NULL, NULL, NULL, NULL, &val);
163     return val;
164 }
165 
166 /*
167  * Uncompress and write an entry to a file descriptor.
168  *
169  * Returns 0 on success.
170  */
171 int dexZipExtractEntryToFile(const ZipArchive* pArchive,
172     const ZipEntry entry, int fd);
173 
174 /*
175  * Utility function to compute a CRC-32.
176  */
177 u4 dexInitCrc32(void);
178 u4 dexComputeCrc32(u4 crc, const void* buf, size_t len);
179 
180 #endif  // LIBDEX_ZIPARCHIVE_H_
181