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