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 */
mzZipEntryCount(const ZipArchive * pArchive)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*
mzGetZipEntryAt(const ZipArchive * pArchive,unsigned int index)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
mzGetZipEntryIndex(const ZipArchive * pArchive,const ZipEntry * pEntry)104 mzGetZipEntryIndex(const ZipArchive *pArchive, const ZipEntry *pEntry) {
105 return pEntry - pArchive->pEntries;
106 }
107
108 /*
109 * Simple accessors.
110 */
mzGetZipEntryFileName(const ZipEntry * pEntry)111 INLINE UnterminatedString mzGetZipEntryFileName(const ZipEntry* pEntry) {
112 UnterminatedString ret;
113 ret.str = pEntry->fileName;
114 ret.len = pEntry->fileNameLen;
115 return ret;
116 }
mzGetZipEntryOffset(const ZipEntry * pEntry)117 INLINE long mzGetZipEntryOffset(const ZipEntry* pEntry) {
118 return pEntry->offset;
119 }
mzGetZipEntryUncompLen(const ZipEntry * pEntry)120 INLINE long mzGetZipEntryUncompLen(const ZipEntry* pEntry) {
121 return pEntry->uncompLen;
122 }
mzGetZipEntryModTime(const ZipEntry * pEntry)123 INLINE long mzGetZipEntryModTime(const ZipEntry* pEntry) {
124 return pEntry->modTime;
125 }
mzGetZipEntryCrc32(const ZipEntry * pEntry)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 all entries under zipDir to the directory specified by
173 * targetDir, which must exist and be a writable directory.
174 *
175 * The immediate children of zipDir will become the immediate
176 * children of targetDir; e.g., if the archive contains the entries
177 *
178 * a/b/c/one
179 * a/b/c/two
180 * a/b/c/d/three
181 *
182 * and mzExtractRecursive(a, "a/b/c", "/tmp", ...) is called, the resulting
183 * files will be
184 *
185 * /tmp/one
186 * /tmp/two
187 * /tmp/d/three
188 *
189 * flags is zero or more of the following:
190 *
191 * MZ_EXTRACT_FILES_ONLY - only unpack files, not directories or symlinks
192 * MZ_EXTRACT_DRY_RUN - don't do anything, but do invoke the callback
193 *
194 * If timestamp is non-NULL, file timestamps will be set accordingly.
195 *
196 * If callback is non-NULL, it will be invoked with each unpacked file.
197 *
198 * Returns true on success, false on failure.
199 */
200 enum { MZ_EXTRACT_FILES_ONLY = 1, MZ_EXTRACT_DRY_RUN = 2 };
201 bool mzExtractRecursive(const ZipArchive *pArchive,
202 const char *zipDir, const char *targetDir,
203 int flags, const struct utimbuf *timestamp,
204 void (*callback)(const char *fn, void*), void *cookie);
205
206 #endif /*_MINZIP_ZIP*/
207