1 /*
2  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
3  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
4  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
5  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
6  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
7  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8  * OTHER DEALINGS IN THE SOFTWARE.
9  */
10 
11 #pragma once
12 #ifndef ZIP_H
13 #define ZIP_H
14 
15 #include <string.h>
16 #include <sys/types.h>
17 
18 #ifndef ZIP_SHARED
19 #  define ZIP_EXPORT
20 #else
21 #  ifdef _WIN32
22 #    ifdef ZIP_BUILD_SHARED
23 #      define ZIP_EXPORT __declspec(dllexport)
24 #    else
25 #      define ZIP_EXPORT __declspec(dllimport)
26 #    endif
27 #  else
28 #    define ZIP_EXPORT __attribute__ ((visibility ("default")))
29 #  endif
30 #endif
31 
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35 
36 #if !defined(_POSIX_C_SOURCE) && defined(_MSC_VER)
37 // 64-bit Windows is the only mainstream platform
38 // where sizeof(long) != sizeof(void*)
39 #ifdef _WIN64
40 typedef long long ssize_t; /* byte count or error */
41 #else
42 typedef long ssize_t; /* byte count or error */
43 #endif
44 #endif
45 
46 #ifndef MAX_PATH
47 #define MAX_PATH 32767 /* # chars in a path name including NULL */
48 #endif
49 
50 /**
51  * @mainpage
52  *
53  * Documenation for @ref zip.
54  */
55 
56 /**
57  * @addtogroup zip
58  * @{
59  */
60 
61 /**
62  * Default zip compression level.
63  */
64 #define ZIP_DEFAULT_COMPRESSION_LEVEL 6
65 
66 /**
67  * Error codes
68  */
69 #define ZIP_ENOINIT -1      // not initialized
70 #define ZIP_EINVENTNAME -2  // invalid entry name
71 #define ZIP_ENOENT -3       // entry not found
72 #define ZIP_EINVMODE -4     // invalid zip mode
73 #define ZIP_EINVLVL -5      // invalid compression level
74 #define ZIP_ENOSUP64 -6     // no zip 64 support
75 #define ZIP_EMEMSET -7      // memset error
76 #define ZIP_EWRTENT -8      // cannot write data to entry
77 #define ZIP_ETDEFLINIT -9   // cannot initialize tdefl compressor
78 #define ZIP_EINVIDX -10     // invalid index
79 #define ZIP_ENOHDR -11      // header not found
80 #define ZIP_ETDEFLBUF -12   // cannot flush tdefl buffer
81 #define ZIP_ECRTHDR -13     // cannot create entry header
82 #define ZIP_EWRTHDR -14     // cannot write entry header
83 #define ZIP_EWRTDIR -15     // cannot write to central dir
84 #define ZIP_EOPNFILE -16    // cannot open file
85 #define ZIP_EINVENTTYPE -17 // invalid entry type
86 #define ZIP_EMEMNOALLOC -18 // extracting data using no memory allocation
87 #define ZIP_ENOFILE -19     // file not found
88 #define ZIP_ENOPERM -20     // no permission
89 #define ZIP_EOOMEM -21      // out of memory
90 #define ZIP_EINVZIPNAME -22 // invalid zip archive name
91 #define ZIP_EMKDIR -23      // make dir error
92 #define ZIP_ESYMLINK -24    // symlink error
93 #define ZIP_ECLSZIP -25     // close archive error
94 #define ZIP_ECAPSIZE -26    // capacity size too small
95 #define ZIP_EFSEEK -27      // fseek error
96 #define ZIP_EFREAD -28      // fread error
97 #define ZIP_EFWRITE -29     // fwrite error
98 
99 /**
100  * Looks up the error message string coresponding to an error number.
101  * @param errnum error number
102  * @return error message string coresponding to errnum or NULL if error is not
103  * found.
104  */
105 extern ZIP_EXPORT const char *zip_strerror(int errnum);
106 
107 /**
108  * @struct zip_t
109  *
110  * This data structure is used throughout the library to represent zip archive -
111  * forward declaration.
112  */
113 struct zip_t;
114 
115 /**
116  * Opens zip archive with compression level using the given mode.
117  *
118  * @param zipname zip archive file name.
119  * @param level compression level (0-9 are the standard zlib-style levels).
120  * @param mode file access mode.
121  *        - 'r': opens a file for reading/extracting (the file must exists).
122  *        - 'w': creates an empty file for writing.
123  *        - 'a': appends to an existing archive.
124  *
125  * @return the zip archive handler or NULL on error
126  */
127 extern ZIP_EXPORT struct zip_t *zip_open(const char *zipname, int level,
128                                          char mode);
129 
130 /**
131  * Closes the zip archive, releases resources - always finalize.
132  *
133  * @param zip zip archive handler.
134  */
135 extern ZIP_EXPORT void zip_close(struct zip_t *zip);
136 
137 /**
138  * Determines if the archive has a zip64 end of central directory headers.
139  *
140  * @param zip zip archive handler.
141  *
142  * @return the return code - 1 (true), 0 (false), negative number (< 0) on
143  *         error.
144  */
145 extern ZIP_EXPORT int zip_is64(struct zip_t *zip);
146 
147 /**
148  * Opens an entry by name in the zip archive.
149  *
150  * For zip archive opened in 'w' or 'a' mode the function will append
151  * a new entry. In readonly mode the function tries to locate the entry
152  * in global dictionary.
153  *
154  * @param zip zip archive handler.
155  * @param entryname an entry name in local dictionary.
156  *
157  * @return the return code - 0 on success, negative number (< 0) on error.
158  */
159 extern ZIP_EXPORT int zip_entry_open(struct zip_t *zip, const char *entryname);
160 
161 /**
162  * Opens a new entry by index in the zip archive.
163  *
164  * This function is only valid if zip archive was opened in 'r' (readonly) mode.
165  *
166  * @param zip zip archive handler.
167  * @param index index in local dictionary.
168  *
169  * @return the return code - 0 on success, negative number (< 0) on error.
170  */
171 extern ZIP_EXPORT int zip_entry_openbyindex(struct zip_t *zip, int index);
172 
173 /**
174  * Closes a zip entry, flushes buffer and releases resources.
175  *
176  * @param zip zip archive handler.
177  *
178  * @return the return code - 0 on success, negative number (< 0) on error.
179  */
180 extern ZIP_EXPORT int zip_entry_close(struct zip_t *zip);
181 
182 /**
183  * Returns a local name of the current zip entry.
184  *
185  * The main difference between user's entry name and local entry name
186  * is optional relative path.
187  * Following .ZIP File Format Specification - the path stored MUST not contain
188  * a drive or device letter, or a leading slash.
189  * All slashes MUST be forward slashes '/' as opposed to backwards slashes '\'
190  * for compatibility with Amiga and UNIX file systems etc.
191  *
192  * @param zip: zip archive handler.
193  *
194  * @return the pointer to the current zip entry name, or NULL on error.
195  */
196 extern ZIP_EXPORT const char *zip_entry_name(struct zip_t *zip);
197 
198 /**
199  * Returns an index of the current zip entry.
200  *
201  * @param zip zip archive handler.
202  *
203  * @return the index on success, negative number (< 0) on error.
204  */
205 extern ZIP_EXPORT int zip_entry_index(struct zip_t *zip);
206 
207 /**
208  * Determines if the current zip entry is a directory entry.
209  *
210  * @param zip zip archive handler.
211  *
212  * @return the return code - 1 (true), 0 (false), negative number (< 0) on
213  *         error.
214  */
215 extern ZIP_EXPORT int zip_entry_isdir(struct zip_t *zip);
216 
217 /**
218  * Returns an uncompressed size of the current zip entry.
219  *
220  * @param zip zip archive handler.
221  *
222  * @return the uncompressed size in bytes.
223  */
224 extern ZIP_EXPORT unsigned long long zip_entry_size(struct zip_t *zip);
225 
226 /**
227  * Returns CRC-32 checksum of the current zip entry.
228  *
229  * @param zip zip archive handler.
230  *
231  * @return the CRC-32 checksum.
232  */
233 extern ZIP_EXPORT unsigned int zip_entry_crc32(struct zip_t *zip);
234 
235 /**
236  * Compresses an input buffer for the current zip entry.
237  *
238  * @param zip zip archive handler.
239  * @param buf input buffer.
240  * @param bufsize input buffer size (in bytes).
241  *
242  * @return the return code - 0 on success, negative number (< 0) on error.
243  */
244 extern ZIP_EXPORT int zip_entry_write(struct zip_t *zip, const void *buf,
245                                       size_t bufsize);
246 
247 /**
248  * Compresses a file for the current zip entry.
249  *
250  * @param zip zip archive handler.
251  * @param filename input file.
252  *
253  * @return the return code - 0 on success, negative number (< 0) on error.
254  */
255 extern ZIP_EXPORT int zip_entry_fwrite(struct zip_t *zip, const char *filename);
256 
257 /**
258  * Extracts the current zip entry into output buffer.
259  *
260  * The function allocates sufficient memory for a output buffer.
261  *
262  * @param zip zip archive handler.
263  * @param buf output buffer.
264  * @param bufsize output buffer size (in bytes).
265  *
266  * @note remember to release memory allocated for a output buffer.
267  *       for large entries, please take a look at zip_entry_extract function.
268  *
269  * @return the return code - the number of bytes actually read on success.
270  *         Otherwise a negative number (< 0) on error.
271  */
272 extern ZIP_EXPORT ssize_t zip_entry_read(struct zip_t *zip, void **buf,
273                                          size_t *bufsize);
274 
275 /**
276  * Extracts the current zip entry into a memory buffer using no memory
277  * allocation.
278  *
279  * @param zip zip archive handler.
280  * @param buf preallocated output buffer.
281  * @param bufsize output buffer size (in bytes).
282  *
283  * @note ensure supplied output buffer is large enough.
284  *       zip_entry_size function (returns uncompressed size for the current
285  *       entry) can be handy to estimate how big buffer is needed.
286  *       For large entries, please take a look at zip_entry_extract function.
287  *
288  * @return the return code - the number of bytes actually read on success.
289  *         Otherwise a negative number (< 0) on error (e.g. bufsize is not large enough).
290  */
291 extern ZIP_EXPORT ssize_t zip_entry_noallocread(struct zip_t *zip, void *buf,
292                                                 size_t bufsize);
293 
294 /**
295  * Extracts the current zip entry into output file.
296  *
297  * @param zip zip archive handler.
298  * @param filename output file.
299  *
300  * @return the return code - 0 on success, negative number (< 0) on error.
301  */
302 extern ZIP_EXPORT int zip_entry_fread(struct zip_t *zip, const char *filename);
303 
304 /**
305  * Extracts the current zip entry using a callback function (on_extract).
306  *
307  * @param zip zip archive handler.
308  * @param on_extract callback function.
309  * @param arg opaque pointer (optional argument, which you can pass to the
310  *        on_extract callback)
311  *
312  * @return the return code - 0 on success, negative number (< 0) on error.
313  */
314 extern ZIP_EXPORT int
315 zip_entry_extract(struct zip_t *zip,
316                   size_t (*on_extract)(void *arg, unsigned long long offset,
317                                        const void *data, size_t size),
318                   void *arg);
319 
320 /**
321  * Returns the number of all entries (files and directories) in the zip archive.
322  *
323  * @param zip zip archive handler.
324  *
325  * @return the return code - the number of entries on success, negative number
326  *         (< 0) on error.
327  */
328 extern ZIP_EXPORT int zip_entries_total(struct zip_t *zip);
329 
330 /**
331  * Deletes zip archive entries.
332  *
333  * @param zip zip archive handler.
334  * @param entries array of zip archive entries to be deleted.
335  * @param len the number of entries to be deleted.
336  * @return the number of deleted entries, or negative number (< 0) on error.
337  */
338 extern ZIP_EXPORT int zip_entries_delete(struct zip_t *zip,
339                                          char *const entries[], size_t len);
340 
341 /**
342  * Extracts a zip archive stream into directory.
343  *
344  * If on_extract is not NULL, the callback will be called after
345  * successfully extracted each zip entry.
346  * Returning a negative value from the callback will cause abort and return an
347  * error. The last argument (void *arg) is optional, which you can use to pass
348  * data to the on_extract callback.
349  *
350  * @param stream zip archive stream.
351  * @param size stream size.
352  * @param dir output directory.
353  * @param on_extract on extract callback.
354  * @param arg opaque pointer.
355  *
356  * @return the return code - 0 on success, negative number (< 0) on error.
357  */
358 extern ZIP_EXPORT int
359 zip_stream_extract(const char *stream, size_t size, const char *dir,
360                    int (*on_extract)(const char *filename, void *arg),
361                    void *arg);
362 
363 /**
364  * Opens zip archive stream into memory.
365  *
366  * @param stream zip archive stream.
367  * @param size stream size.
368  *
369  * @return the zip archive handler or NULL on error
370  */
371 extern ZIP_EXPORT struct zip_t *zip_stream_open(const char *stream, size_t size,
372                                                 int level, char mode);
373 
374 /**
375  * Copy zip archive stream output buffer.
376  *
377  * @param zip zip archive handler.
378  * @param buf output buffer. User should free buf.
379  * @param bufsize output buffer size (in bytes).
380  *
381  * @return copy size
382  */
383 extern ZIP_EXPORT ssize_t zip_stream_copy(struct zip_t *zip, void **buf,
384                                           size_t *bufsize);
385 
386 /**
387  * Close zip archive releases resources.
388  *
389  * @param zip zip archive handler.
390  *
391  * @return
392  */
393 extern ZIP_EXPORT void zip_stream_close(struct zip_t *zip);
394 
395 /**
396  * Creates a new archive and puts files into a single zip archive.
397  *
398  * @param zipname zip archive file.
399  * @param filenames input files.
400  * @param len: number of input files.
401  *
402  * @return the return code - 0 on success, negative number (< 0) on error.
403  */
404 extern ZIP_EXPORT int zip_create(const char *zipname, const char *filenames[],
405                                  size_t len);
406 
407 /**
408  * Extracts a zip archive file into directory.
409  *
410  * If on_extract_entry is not NULL, the callback will be called after
411  * successfully extracted each zip entry.
412  * Returning a negative value from the callback will cause abort and return an
413  * error. The last argument (void *arg) is optional, which you can use to pass
414  * data to the on_extract_entry callback.
415  *
416  * @param zipname zip archive file.
417  * @param dir output directory.
418  * @param on_extract_entry on extract callback.
419  * @param arg opaque pointer.
420  *
421  * @return the return code - 0 on success, negative number (< 0) on error.
422  */
423 extern ZIP_EXPORT int zip_extract(const char *zipname, const char *dir,
424                                   int (*on_extract_entry)(const char *filename,
425                                                           void *arg),
426                                   void *arg);
427 
428 /** @} */
429 #ifdef __cplusplus
430 }
431 #endif
432 
433 #endif
434