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 #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     int         fd;
     50     unsigned int numEntries;
     51     ZipEntry*   pEntries;
     52     HashTable*  pHash;          // maps file name to ZipEntry
     53     MemMapping  map;
     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(const char* fileName, 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  * Inflate all entries under zipDir to the directory specified by
    187  * targetDir, which must exist and be a writable directory.
    188  *
    189  * The immediate children of zipDir will become the immediate
    190  * children of targetDir; e.g., if the archive contains the entries
    191  *
    192  *     a/b/c/one
    193  *     a/b/c/two
    194  *     a/b/c/d/three
    195  *
    196  * and mzExtractRecursive(a, "a/b/c", "/tmp", ...) is called, the resulting
    197  * files will be
    198  *
    199  *     /tmp/one
    200  *     /tmp/two
    201  *     /tmp/d/three
    202  *
    203  * flags is zero or more of the following:
    204  *
    205  *     MZ_EXTRACT_FILES_ONLY - only unpack files, not directories or symlinks
    206  *     MZ_EXTRACT_DRY_RUN - don't do anything, but do invoke the callback
    207  *
    208  * If timestamp is non-NULL, file timestamps will be set accordingly.
    209  *
    210  * If callback is non-NULL, it will be invoked with each unpacked file.
    211  *
    212  * Returns true on success, false on failure.
    213  */
    214 enum { MZ_EXTRACT_FILES_ONLY = 1, MZ_EXTRACT_DRY_RUN = 2 };
    215 bool mzExtractRecursive(const ZipArchive *pArchive,
    216         const char *zipDir, const char *targetDir,
    217         int flags, const struct utimbuf *timestamp,
    218         void (*callback)(const char *fn, void*), void *cookie,
    219         struct selabel_handle *sehnd);
    220 
    221 #ifdef __cplusplus
    222 }
    223 #endif
    224 
    225 #endif /*_MINZIP_ZIP*/
    226