1 /* 2 * Copyright 2006 The Android Open Source Project 3 * 4 * Simple Zip archive support. 5 */ 6 #ifndef _MINZIP_ZIP 7 #define _MINZIP_ZIP 8 9 #include "inline_magic.h" 10 11 #include <stdlib.h> 12 #include <utime.h> 13 14 #include "Hash.h" 15 #include "SysUtil.h" 16 17 /* 18 * One entry in the Zip archive. Treat this as opaque -- use accessors below. 19 * 20 * TODO: we're now keeping the pages mapped so we don't have to copy the 21 * filename. We can change the accessors to retrieve the various pieces 22 * directly from the source file instead of copying them out, for a very 23 * slight speed hit and a modest reduction in memory usage. 24 */ 25 typedef struct ZipEntry { 26 unsigned int fileNameLen; 27 const char* fileName; // not null-terminated 28 long offset; 29 long compLen; 30 long uncompLen; 31 int compression; 32 long modTime; 33 long crc32; 34 int versionMadeBy; 35 long externalFileAttributes; 36 } ZipEntry; 37 38 /* 39 * One Zip archive. Treat as opaque. 40 */ 41 typedef struct ZipArchive { 42 int fd; 43 unsigned int numEntries; 44 ZipEntry* pEntries; 45 HashTable* pHash; // maps file name to ZipEntry 46 MemMapping map; 47 } ZipArchive; 48 49 /* 50 * Represents a non-NUL-terminated string, 51 * which is how entry names are stored. 52 */ 53 typedef struct { 54 const char *str; 55 size_t len; 56 } UnterminatedString; 57 58 /* 59 * Open a Zip archive. 60 * 61 * On success, returns 0 and populates "pArchive". Returns nonzero errno 62 * value on failure. 63 */ 64 int mzOpenZipArchive(const char* fileName, ZipArchive* pArchive); 65 66 /* 67 * Close archive, releasing resources associated with it. 68 * 69 * Depending on the implementation this could unmap pages used by classes 70 * stored in a Jar. This should only be done after unloading classes. 71 */ 72 void mzCloseZipArchive(ZipArchive* pArchive); 73 74 75 /* 76 * Find an entry in the Zip archive, by name. 77 */ 78 const ZipEntry* mzFindZipEntry(const ZipArchive* pArchive, 79 const char* entryName); 80 81 /* 82 * Get the number of entries in the Zip archive. 83 */ 84 INLINE unsigned int mzZipEntryCount(const ZipArchive* pArchive) { 85 return pArchive->numEntries; 86 } 87 88 /* 89 * Get an entry by index. Returns NULL if the index is out-of-bounds. 90 */ 91 INLINE const ZipEntry* 92 mzGetZipEntryAt(const ZipArchive* pArchive, unsigned int index) 93 { 94 if (index < pArchive->numEntries) { 95 return pArchive->pEntries + index; 96 } 97 return NULL; 98 } 99 100 /* 101 * Get the index number of an entry in the archive. 102 */ 103 INLINE unsigned int 104 mzGetZipEntryIndex(const ZipArchive *pArchive, const ZipEntry *pEntry) { 105 return pEntry - pArchive->pEntries; 106 } 107 108 /* 109 * Simple accessors. 110 */ 111 INLINE UnterminatedString mzGetZipEntryFileName(const ZipEntry* pEntry) { 112 UnterminatedString ret; 113 ret.str = pEntry->fileName; 114 ret.len = pEntry->fileNameLen; 115 return ret; 116 } 117 INLINE long mzGetZipEntryOffset(const ZipEntry* pEntry) { 118 return pEntry->offset; 119 } 120 INLINE long mzGetZipEntryUncompLen(const ZipEntry* pEntry) { 121 return pEntry->uncompLen; 122 } 123 INLINE long mzGetZipEntryModTime(const ZipEntry* pEntry) { 124 return pEntry->modTime; 125 } 126 INLINE long mzGetZipEntryCrc32(const ZipEntry* pEntry) { 127 return pEntry->crc32; 128 } 129 bool mzIsZipEntrySymlink(const ZipEntry* pEntry); 130 131 132 /* 133 * Type definition for the callback function used by 134 * mzProcessZipEntryContents(). 135 */ 136 typedef bool (*ProcessZipEntryContentsFunction)(const unsigned char *data, 137 int dataLen, void *cookie); 138 139 /* 140 * Stream the uncompressed data through the supplied function, 141 * passing cookie to it each time it gets called. processFunction 142 * may be called more than once. 143 * 144 * If processFunction returns false, the operation is abandoned and 145 * mzProcessZipEntryContents() immediately returns false. 146 * 147 * This is useful for calculating the hash of an entry's uncompressed contents. 148 */ 149 bool mzProcessZipEntryContents(const ZipArchive *pArchive, 150 const ZipEntry *pEntry, ProcessZipEntryContentsFunction processFunction, 151 void *cookie); 152 153 /* 154 * Read an entry into a buffer allocated by the caller. 155 */ 156 bool mzReadZipEntry(const ZipArchive* pArchive, const ZipEntry* pEntry, 157 char* buf, int bufLen); 158 159 /* 160 * Check the CRC on this entry; return true if it is correct. 161 * May do other internal checks as well. 162 */ 163 bool mzIsZipEntryIntact(const ZipArchive *pArchive, const ZipEntry *pEntry); 164 165 /* 166 * Inflate and write an entry to a file. 167 */ 168 bool mzExtractZipEntryToFile(const ZipArchive *pArchive, 169 const ZipEntry *pEntry, int fd); 170 171 /* 172 * Inflate and write an entry to a memory buffer, which must be long 173 * enough to hold mzGetZipEntryUncomplen(pEntry) bytes. 174 */ 175 bool mzExtractZipEntryToBuffer(const ZipArchive *pArchive, 176 const ZipEntry *pEntry, unsigned char* buffer); 177 178 /* 179 * Inflate all entries under zipDir to the directory specified by 180 * targetDir, which must exist and be a writable directory. 181 * 182 * The immediate children of zipDir will become the immediate 183 * children of targetDir; e.g., if the archive contains the entries 184 * 185 * a/b/c/one 186 * a/b/c/two 187 * a/b/c/d/three 188 * 189 * and mzExtractRecursive(a, "a/b/c", "/tmp", ...) is called, the resulting 190 * files will be 191 * 192 * /tmp/one 193 * /tmp/two 194 * /tmp/d/three 195 * 196 * flags is zero or more of the following: 197 * 198 * MZ_EXTRACT_FILES_ONLY - only unpack files, not directories or symlinks 199 * MZ_EXTRACT_DRY_RUN - don't do anything, but do invoke the callback 200 * 201 * If timestamp is non-NULL, file timestamps will be set accordingly. 202 * 203 * If callback is non-NULL, it will be invoked with each unpacked file. 204 * 205 * Returns true on success, false on failure. 206 */ 207 enum { MZ_EXTRACT_FILES_ONLY = 1, MZ_EXTRACT_DRY_RUN = 2 }; 208 bool mzExtractRecursive(const ZipArchive *pArchive, 209 const char *zipDir, const char *targetDir, 210 int flags, const struct utimbuf *timestamp, 211 void (*callback)(const char *fn, void*), void *cookie); 212 213 #endif /*_MINZIP_ZIP*/ 214