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