Home | History | Annotate | Download | only in minzip
      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