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 */
mzZipEntryCount(const ZipArchive * pArchive)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*
mzGetZipEntryAt(const ZipArchive * pArchive,unsigned int index)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
mzGetZipEntryIndex(const ZipArchive * pArchive,const ZipEntry * pEntry)111 mzGetZipEntryIndex(const ZipArchive *pArchive, const ZipEntry *pEntry) {
112 return pEntry - pArchive->pEntries;
113 }
114
115 /*
116 * Simple accessors.
117 */
mzGetZipEntryFileName(const ZipEntry * pEntry)118 INLINE UnterminatedString mzGetZipEntryFileName(const ZipEntry* pEntry) {
119 UnterminatedString ret;
120 ret.str = pEntry->fileName;
121 ret.len = pEntry->fileNameLen;
122 return ret;
123 }
mzGetZipEntryOffset(const ZipEntry * pEntry)124 INLINE long mzGetZipEntryOffset(const ZipEntry* pEntry) {
125 return pEntry->offset;
126 }
mzGetZipEntryUncompLen(const ZipEntry * pEntry)127 INLINE long mzGetZipEntryUncompLen(const ZipEntry* pEntry) {
128 return pEntry->uncompLen;
129 }
mzGetZipEntryModTime(const ZipEntry * pEntry)130 INLINE long mzGetZipEntryModTime(const ZipEntry* pEntry) {
131 return pEntry->modTime;
132 }
mzGetZipEntryCrc32(const ZipEntry * pEntry)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