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 */ 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 */ 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 } 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 } 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 } 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