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