| /* |
| * Copyright 2006 The Android Open Source Project |
| * |
| * Simple Zip archive support. |
| */ |
| #ifndef _MINZIP_ZIP |
| #define _MINZIP_ZIP |
| |
| #include "inline_magic.h" |
| |
| #include <stdlib.h> |
| #include <utime.h> |
| |
| #include "Hash.h" |
| #include "SysUtil.h" |
| |
| /* |
| * One entry in the Zip archive. Treat this as opaque -- use accessors below. |
| * |
| * TODO: we're now keeping the pages mapped so we don't have to copy the |
| * filename. We can change the accessors to retrieve the various pieces |
| * directly from the source file instead of copying them out, for a very |
| * slight speed hit and a modest reduction in memory usage. |
| */ |
| typedef struct ZipEntry { |
| unsigned int fileNameLen; |
| const char* fileName; // not null-terminated |
| long offset; |
| long compLen; |
| long uncompLen; |
| int compression; |
| long modTime; |
| long crc32; |
| int versionMadeBy; |
| long externalFileAttributes; |
| } ZipEntry; |
| |
| /* |
| * One Zip archive. Treat as opaque. |
| */ |
| typedef struct ZipArchive { |
| int fd; |
| unsigned int numEntries; |
| ZipEntry* pEntries; |
| HashTable* pHash; // maps file name to ZipEntry |
| MemMapping map; |
| } ZipArchive; |
| |
| /* |
| * Represents a non-NUL-terminated string, |
| * which is how entry names are stored. |
| */ |
| typedef struct { |
| const char *str; |
| size_t len; |
| } UnterminatedString; |
| |
| /* |
| * Open a Zip archive. |
| * |
| * On success, returns 0 and populates "pArchive". Returns nonzero errno |
| * value on failure. |
| */ |
| int mzOpenZipArchive(const char* fileName, ZipArchive* pArchive); |
| |
| /* |
| * Close archive, releasing resources associated with it. |
| * |
| * Depending on the implementation this could unmap pages used by classes |
| * stored in a Jar. This should only be done after unloading classes. |
| */ |
| void mzCloseZipArchive(ZipArchive* pArchive); |
| |
| |
| /* |
| * Find an entry in the Zip archive, by name. |
| */ |
| const ZipEntry* mzFindZipEntry(const ZipArchive* pArchive, |
| const char* entryName); |
| |
| /* |
| * Get the number of entries in the Zip archive. |
| */ |
| INLINE unsigned int mzZipEntryCount(const ZipArchive* pArchive) { |
| return pArchive->numEntries; |
| } |
| |
| /* |
| * Get an entry by index. Returns NULL if the index is out-of-bounds. |
| */ |
| INLINE const ZipEntry* |
| mzGetZipEntryAt(const ZipArchive* pArchive, unsigned int index) |
| { |
| if (index < pArchive->numEntries) { |
| return pArchive->pEntries + index; |
| } |
| return NULL; |
| } |
| |
| /* |
| * Get the index number of an entry in the archive. |
| */ |
| INLINE unsigned int |
| mzGetZipEntryIndex(const ZipArchive *pArchive, const ZipEntry *pEntry) { |
| return pEntry - pArchive->pEntries; |
| } |
| |
| /* |
| * Simple accessors. |
| */ |
| INLINE UnterminatedString mzGetZipEntryFileName(const ZipEntry* pEntry) { |
| UnterminatedString ret; |
| ret.str = pEntry->fileName; |
| ret.len = pEntry->fileNameLen; |
| return ret; |
| } |
| INLINE long mzGetZipEntryOffset(const ZipEntry* pEntry) { |
| return pEntry->offset; |
| } |
| INLINE long mzGetZipEntryUncompLen(const ZipEntry* pEntry) { |
| return pEntry->uncompLen; |
| } |
| INLINE long mzGetZipEntryModTime(const ZipEntry* pEntry) { |
| return pEntry->modTime; |
| } |
| INLINE long mzGetZipEntryCrc32(const ZipEntry* pEntry) { |
| return pEntry->crc32; |
| } |
| bool mzIsZipEntrySymlink(const ZipEntry* pEntry); |
| |
| |
| /* |
| * Type definition for the callback function used by |
| * mzProcessZipEntryContents(). |
| */ |
| typedef bool (*ProcessZipEntryContentsFunction)(const unsigned char *data, |
| int dataLen, void *cookie); |
| |
| /* |
| * Stream the uncompressed data through the supplied function, |
| * passing cookie to it each time it gets called. processFunction |
| * may be called more than once. |
| * |
| * If processFunction returns false, the operation is abandoned and |
| * mzProcessZipEntryContents() immediately returns false. |
| * |
| * This is useful for calculating the hash of an entry's uncompressed contents. |
| */ |
| bool mzProcessZipEntryContents(const ZipArchive *pArchive, |
| const ZipEntry *pEntry, ProcessZipEntryContentsFunction processFunction, |
| void *cookie); |
| |
| /* |
| * Read an entry into a buffer allocated by the caller. |
| */ |
| bool mzReadZipEntry(const ZipArchive* pArchive, const ZipEntry* pEntry, |
| char* buf, int bufLen); |
| |
| /* |
| * Check the CRC on this entry; return true if it is correct. |
| * May do other internal checks as well. |
| */ |
| bool mzIsZipEntryIntact(const ZipArchive *pArchive, const ZipEntry *pEntry); |
| |
| /* |
| * Inflate and write an entry to a file. |
| */ |
| bool mzExtractZipEntryToFile(const ZipArchive *pArchive, |
| const ZipEntry *pEntry, int fd); |
| |
| /* |
| * Inflate all entries under zipDir to the directory specified by |
| * targetDir, which must exist and be a writable directory. |
| * |
| * The immediate children of zipDir will become the immediate |
| * children of targetDir; e.g., if the archive contains the entries |
| * |
| * a/b/c/one |
| * a/b/c/two |
| * a/b/c/d/three |
| * |
| * and mzExtractRecursive(a, "a/b/c", "/tmp", ...) is called, the resulting |
| * files will be |
| * |
| * /tmp/one |
| * /tmp/two |
| * /tmp/d/three |
| * |
| * flags is zero or more of the following: |
| * |
| * MZ_EXTRACT_FILES_ONLY - only unpack files, not directories or symlinks |
| * MZ_EXTRACT_DRY_RUN - don't do anything, but do invoke the callback |
| * |
| * If timestamp is non-NULL, file timestamps will be set accordingly. |
| * |
| * If callback is non-NULL, it will be invoked with each unpacked file. |
| * |
| * Returns true on success, false on failure. |
| */ |
| enum { MZ_EXTRACT_FILES_ONLY = 1, MZ_EXTRACT_DRY_RUN = 2 }; |
| bool mzExtractRecursive(const ZipArchive *pArchive, |
| const char *zipDir, const char *targetDir, |
| int flags, const struct utimbuf *timestamp, |
| void (*callback)(const char *fn, void*), void *cookie); |
| |
| #endif /*_MINZIP_ZIP*/ |