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