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