• 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 #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