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