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 */ 30typedef void* ZipEntry; 31 32/* 33 * One entry in the hash table. 34 */ 35struct 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 */ 59struct 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 */ 79enum { 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 */ 91int 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 */ 100int 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 */ 108void dexZipCloseArchive(ZipArchive* pArchive); 109 110/* 111 * Return the archive's file descriptor. 112 */ 113DEX_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 */ 121ZipEntry 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 */ 130int 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 */ 137DEX_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} 144DEX_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} 151DEX_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} 158DEX_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 */ 171int dexZipExtractEntryToFile(const ZipArchive* pArchive, 172 const ZipEntry entry, int fd); 173 174/* 175 * Utility function to compute a CRC-32. 176 */ 177u4 dexInitCrc32(void); 178u4 dexComputeCrc32(u4 crc, const void* buf, size_t len); 179 180#endif // LIBDEX_ZIPARCHIVE_H_ 181