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
18extern "C" {
19#endif
20
21#ifdef HAVE_SELINUX
22#include <selinux/selinux.h>
23#include <selinux/label.h>
24#else
25struct 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 */
36typedef 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 */
52typedef 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 */
64typedef 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 */
75int 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 */
83void mzCloseZipArchive(ZipArchive* pArchive);
84
85
86/*
87 * Find an entry in the Zip archive, by name.
88 */
89const ZipEntry* mzFindZipEntry(const ZipArchive* pArchive,
90        const char* entryName);
91
92/*
93 * Get the number of entries in the Zip archive.
94 */
95INLINE 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 */
102INLINE const ZipEntry*
103mzGetZipEntryAt(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 */
114INLINE unsigned int
115mzGetZipEntryIndex(const ZipArchive *pArchive, const ZipEntry *pEntry) {
116    return pEntry - pArchive->pEntries;
117}
118
119/*
120 * Simple accessors.
121 */
122INLINE UnterminatedString mzGetZipEntryFileName(const ZipEntry* pEntry) {
123    UnterminatedString ret;
124    ret.str = pEntry->fileName;
125    ret.len = pEntry->fileNameLen;
126    return ret;
127}
128INLINE long mzGetZipEntryOffset(const ZipEntry* pEntry) {
129    return pEntry->offset;
130}
131INLINE long mzGetZipEntryUncompLen(const ZipEntry* pEntry) {
132    return pEntry->uncompLen;
133}
134INLINE long mzGetZipEntryModTime(const ZipEntry* pEntry) {
135    return pEntry->modTime;
136}
137INLINE long mzGetZipEntryCrc32(const ZipEntry* pEntry) {
138    return pEntry->crc32;
139}
140bool mzIsZipEntrySymlink(const ZipEntry* pEntry);
141
142
143/*
144 * Type definition for the callback function used by
145 * mzProcessZipEntryContents().
146 */
147typedef 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 */
160bool 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 */
167bool 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 */
174bool mzIsZipEntryIntact(const ZipArchive *pArchive, const ZipEntry *pEntry);
175
176/*
177 * Inflate and write an entry to a file.
178 */
179bool 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 */
186bool 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 */
218enum { MZ_EXTRACT_FILES_ONLY = 1, MZ_EXTRACT_DRY_RUN = 2 };
219bool 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