1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /*
18  * Read-only access to Zip archives, with minimal heap allocation.
19  */
20 #ifndef LIBZIPARCHIVE_ZIPARCHIVE_H_
21 #define LIBZIPARCHIVE_ZIPARCHIVE_H_
22 
23 #include <stdint.h>
24 #include <string.h>
25 #include <sys/cdefs.h>
26 #include <sys/types.h>
27 #include <utils/Compat.h>
28 
29 /* Zip compression methods we support */
30 enum {
31   kCompressStored     = 0,        // no compression
32   kCompressDeflated   = 8,        // standard deflate
33 };
34 
35 struct ZipString {
36   const uint8_t* name;
37   uint16_t name_length;
38 
ZipStringZipString39   ZipString() {}
40 
41   /*
42    * entry_name has to be an c-style string with only ASCII characters.
43    */
44   explicit ZipString(const char* entry_name);
45 
46   bool operator==(const ZipString& rhs) const {
47     return name && (name_length == rhs.name_length) &&
48         (memcmp(name, rhs.name, name_length) == 0);
49   }
50 
StartsWithZipString51   bool StartsWith(const ZipString& prefix) const {
52     return name && (name_length >= prefix.name_length) &&
53         (memcmp(name, prefix.name, prefix.name_length) == 0);
54   }
55 
EndsWithZipString56   bool EndsWith(const ZipString& suffix) const {
57     return name && (name_length >= suffix.name_length) &&
58         (memcmp(name + name_length - suffix.name_length, suffix.name,
59                 suffix.name_length) == 0);
60   }
61 };
62 
63 /*
64  * Represents information about a zip entry in a zip file.
65  */
66 struct ZipEntry {
67   // Compression method: One of kCompressStored or
68   // kCompressDeflated.
69   uint16_t method;
70 
71   // Modification time. The zipfile format specifies
72   // that the first two little endian bytes contain the time
73   // and the last two little endian bytes contain the date.
74   uint32_t mod_time;
75 
76   // 1 if this entry contains a data descriptor segment, 0
77   // otherwise.
78   uint8_t has_data_descriptor;
79 
80   // Crc32 value of this ZipEntry. This information might
81   // either be stored in the local file header or in a special
82   // Data descriptor footer at the end of the file entry.
83   uint32_t crc32;
84 
85   // Compressed length of this ZipEntry. Might be present
86   // either in the local file header or in the data descriptor
87   // footer.
88   uint32_t compressed_length;
89 
90   // Uncompressed length of this ZipEntry. Might be present
91   // either in the local file header or in the data descriptor
92   // footer.
93   uint32_t uncompressed_length;
94 
95   // The offset to the start of data for this ZipEntry.
96   off64_t offset;
97 };
98 
99 typedef void* ZipArchiveHandle;
100 
101 /*
102  * Open a Zip archive, and sets handle to the value of the opaque
103  * handle for the file. This handle must be released by calling
104  * CloseArchive with this handle.
105  *
106  * Returns 0 on success, and negative values on failure.
107  */
108 int32_t OpenArchive(const char* fileName, ZipArchiveHandle* handle);
109 
110 /*
111  * Like OpenArchive, but takes a file descriptor open for reading
112  * at the start of the file.  The descriptor must be mappable (this does
113  * not allow access to a stream).
114  *
115  * Sets handle to the value of the opaque handle for this file descriptor.
116  * This handle must be released by calling CloseArchive with this handle.
117  *
118  * If assume_ownership parameter is 'true' calling CloseArchive will close
119  * the file.
120  *
121  * This function maps and scans the central directory and builds a table
122  * of entries for future lookups.
123  *
124  * "debugFileName" will appear in error messages, but is not otherwise used.
125  *
126  * Returns 0 on success, and negative values on failure.
127  */
128 int32_t OpenArchiveFd(const int fd, const char* debugFileName,
129                       ZipArchiveHandle *handle, bool assume_ownership = true);
130 
131 int32_t OpenArchiveFromMemory(void* address, size_t length, const char* debugFileName,
132                               ZipArchiveHandle *handle);
133 /*
134  * Close archive, releasing resources associated with it. This will
135  * unmap the central directory of the zipfile and free all internal
136  * data structures associated with the file. It is an error to use
137  * this handle for any further operations without an intervening
138  * call to one of the OpenArchive variants.
139  */
140 void CloseArchive(ZipArchiveHandle handle);
141 
142 /*
143  * Find an entry in the Zip archive, by name. |entryName| must be a null
144  * terminated string, and |data| must point to a writeable memory location.
145  *
146  * Returns 0 if an entry is found, and populates |data| with information
147  * about this entry. Returns negative values otherwise.
148  *
149  * It's important to note that |data->crc32|, |data->compLen| and
150  * |data->uncompLen| might be set to values from the central directory
151  * if this file entry contains a data descriptor footer. To verify crc32s
152  * and length, a call to VerifyCrcAndLengths must be made after entry data
153  * has been processed.
154  *
155  * On non-Windows platforms this method does not modify internal state and
156  * can be called concurrently.
157  */
158 int32_t FindEntry(const ZipArchiveHandle handle, const ZipString& entryName,
159                   ZipEntry* data);
160 
161 /*
162  * Start iterating over all entries of a zip file. The order of iteration
163  * is not guaranteed to be the same as the order of elements
164  * in the central directory but is stable for a given zip file. |cookie| will
165  * contain the value of an opaque cookie which can be used to make one or more
166  * calls to Next. All calls to StartIteration must be matched by a call to
167  * EndIteration to free any allocated memory.
168  *
169  * This method also accepts optional prefix and suffix to restrict iteration to
170  * entry names that start with |optional_prefix| or end with |optional_suffix|.
171  *
172  * Returns 0 on success and negative values on failure.
173  */
174 int32_t StartIteration(ZipArchiveHandle handle, void** cookie_ptr,
175                        const ZipString* optional_prefix,
176                        const ZipString* optional_suffix);
177 
178 /*
179  * Advance to the next element in the zipfile in iteration order.
180  *
181  * Returns 0 on success, -1 if there are no more elements in this
182  * archive and lower negative values on failure.
183  */
184 int32_t Next(void* cookie, ZipEntry* data, ZipString* name);
185 
186 /*
187  * End iteration over all entries of a zip file and frees the memory allocated
188  * in StartIteration.
189  */
190 void EndIteration(void* cookie);
191 
192 /*
193  * Uncompress and write an entry to an open file identified by |fd|.
194  * |entry->uncompressed_length| bytes will be written to the file at
195  * its current offset, and the file will be truncated at the end of
196  * the uncompressed data (no truncation if |fd| references a block
197  * device).
198  *
199  * Returns 0 on success and negative values on failure.
200  */
201 int32_t ExtractEntryToFile(ZipArchiveHandle handle, ZipEntry* entry, int fd);
202 
203 /**
204  * Uncompress a given zip entry to the memory region at |begin| and of
205  * size |size|. This size is expected to be the same as the *declared*
206  * uncompressed length of the zip entry. It is an error if the *actual*
207  * number of uncompressed bytes differs from this number.
208  *
209  * Returns 0 on success and negative values on failure.
210  */
211 int32_t ExtractToMemory(ZipArchiveHandle handle, ZipEntry* entry,
212                         uint8_t* begin, uint32_t size);
213 
214 int GetFileDescriptor(const ZipArchiveHandle handle);
215 
216 const char* ErrorCodeString(int32_t error_code);
217 
218 #if !defined(_WIN32)
219 typedef bool (*ProcessZipEntryFunction)(const uint8_t* buf, size_t buf_size, void* cookie);
220 
221 /*
222  * Stream the uncompressed data through the supplied function,
223  * passing cookie to it each time it gets called.
224 */
225 int32_t ProcessZipEntryContents(ZipArchiveHandle handle, ZipEntry* entry,
226         ProcessZipEntryFunction func, void* cookie);
227 #endif
228 
229 #endif  // LIBZIPARCHIVE_ZIPARCHIVE_H_
230