Added
Link Here
|
0 |
- |
1 |
Update contrib/zip to 0.1.18 to fix a build failure on 32 bit platforms. |
|
|
2 |
This patch is a combination of two upstream patches [1][2] slightly |
3 |
edited to fit FreeBSD conventions and to skip files not shipped in the |
4 |
distribution. See upstream issue 2954 [3] for details. |
5 |
|
6 |
[1]: https://github.com/assimp/assimp/commit/f78446b14aff46db2ef27d062a275b6a01fd68b1.diff |
7 |
[2]: https://github.com/assimp/assimp/commit/f78446b14aff46db2ef27d062a275b6a01fd68b1.diff |
8 |
[3]: https://github.com/assimp/assimp/issues/2954 |
9 |
|
10 |
diff -u contrib/zip/CMakeLists.txt contrib/zip/CMakeLists.txt |
11 |
--- contrib/zip/CMakeLists.txt |
12 |
+++ contrib/zip/CMakeLists.txt |
13 |
@@ -1,10 +1,14 @@ |
14 |
-cmake_minimum_required(VERSION 2.8) |
15 |
-project(zip) |
16 |
-enable_language(C) |
17 |
+cmake_minimum_required(VERSION 3.0) |
18 |
+ |
19 |
+project(zip |
20 |
+ LANGUAGES C |
21 |
+ VERSION "0.1.18") |
22 |
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) |
23 |
|
24 |
+option(CMAKE_DISABLE_TESTING "Disable test creation" OFF) |
25 |
+ |
26 |
if (MSVC) |
27 |
- # Use secure functions by defaualt and suppress warnings about "deprecated" functions |
28 |
+ # Use secure functions by default and suppress warnings about "deprecated" functions |
29 |
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1") |
30 |
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1") |
31 |
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_NONSTDC_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1") |
32 |
@@ -17,23 +21,71 @@ |
33 |
# zip |
34 |
set(SRC src/miniz.h src/zip.h src/zip.c) |
35 |
add_library(${PROJECT_NAME} ${SRC}) |
36 |
-target_include_directories(${PROJECT_NAME} INTERFACE src) |
37 |
+target_include_directories(${PROJECT_NAME} PUBLIC |
38 |
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src> |
39 |
+ $<INSTALL_INTERFACE:include> |
40 |
+) |
41 |
|
42 |
# test |
43 |
if (NOT CMAKE_DISABLE_TESTING) |
44 |
enable_testing() |
45 |
add_subdirectory(test) |
46 |
find_package(Sanitizers) |
47 |
- add_sanitizers(${PROJECT_NAME} test.exe) |
48 |
- add_sanitizers(${PROJECT_NAME} test_miniz.exe) |
49 |
+ add_sanitizers(${PROJECT_NAME} ${test_out}) |
50 |
endif() |
51 |
|
52 |
+#### |
53 |
+# Installation (https://github.com/forexample/package-example) { |
54 |
+ |
55 |
+set(CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}") |
56 |
+set(INCLUDE_INSTALL_DIR "include") |
57 |
+ |
58 |
+set(GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") |
59 |
+ |
60 |
+# Configuration |
61 |
+set(VERSION_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake") |
62 |
+set(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}Config.cmake") |
63 |
+set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets") |
64 |
+set(NAMESPACE "${PROJECT_NAME}::") |
65 |
+ |
66 |
+# Include module with fuction 'write_basic_package_version_file' |
67 |
+include(CMakePackageConfigHelpers) |
68 |
+ |
69 |
+# Note: PROJECT_VERSION is used as a VERSION |
70 |
+write_basic_package_version_file( |
71 |
+ "${VERSION_CONFIG}" COMPATIBILITY SameMajorVersion |
72 |
+) |
73 |
+ |
74 |
+# Use variables: |
75 |
+# * TARGETS_EXPORT_NAME |
76 |
+# * PROJECT_NAME |
77 |
+configure_package_config_file( |
78 |
+ "cmake/Config.cmake.in" |
79 |
+ "${PROJECT_CONFIG}" |
80 |
+ INSTALL_DESTINATION "${CONFIG_INSTALL_DIR}" |
81 |
+) |
82 |
+ |
83 |
+install( |
84 |
+ FILES "${PROJECT_CONFIG}" "${VERSION_CONFIG}" |
85 |
+ DESTINATION "${CONFIG_INSTALL_DIR}" |
86 |
+) |
87 |
+ |
88 |
+install( |
89 |
+ EXPORT "${TARGETS_EXPORT_NAME}" |
90 |
+ NAMESPACE "${NAMESPACE}" |
91 |
+ DESTINATION "${CONFIG_INSTALL_DIR}" |
92 |
+) |
93 |
+ |
94 |
+# } |
95 |
+ |
96 |
install(TARGETS ${PROJECT_NAME} |
97 |
+ EXPORT ${TARGETS_EXPORT_NAME} |
98 |
RUNTIME DESTINATION bin |
99 |
ARCHIVE DESTINATION lib |
100 |
LIBRARY DESTINATION lib |
101 |
- COMPONENT library) |
102 |
-install(FILES ${PROJECT_SOURCE_DIR}/src/zip.h DESTINATION include) |
103 |
+ INCLUDES DESTINATION ${INCLUDE_INSTALL_DIR} |
104 |
+) |
105 |
+install(FILES ${PROJECT_SOURCE_DIR}/src/zip.h DESTINATION ${INCLUDE_INSTALL_DIR}/zip) |
106 |
|
107 |
# uninstall target (https://gitlab.kitware.com/cmake/community/wikis/FAQ#can-i-do-make-uninstall-with-cmake) |
108 |
if(NOT TARGET uninstall) |
109 |
@@ -46,2 +98,11 @@ |
110 |
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake/cmake_uninstall.cmake) |
111 |
+endif() |
112 |
+ |
113 |
+find_package(Doxygen) |
114 |
+if(DOXYGEN_FOUND) |
115 |
+ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) |
116 |
+ add_custom_target(doc |
117 |
+ ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile |
118 |
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} |
119 |
+ COMMENT "Generating API documentation with Doxygen" VERBATIM) |
120 |
endif() |
121 |
diff -u contrib/zip/README.md contrib/zip/README.md |
122 |
--- contrib/zip/README.md |
123 |
+++ contrib/zip/README.md |
124 |
@@ -1,10 +1,8 @@ |
125 |
### A portable (OSX/Linux/Windows), simple zip library written in C |
126 |
This is done by hacking awesome [miniz](https://code.google.com/p/miniz) library and layering functions on top of the miniz v1.15 API. |
127 |
|
128 |
-[![Windows](https://ci.appveyor.com/api/projects/status/bph8dr3jacgmjv32/branch/master?svg=true&label=windows)](https://ci.appveyor.com/project/kuba--/zip) |
129 |
-[![Linux](https://travis-ci.org/kuba--/zip.svg?branch=master&label=linux%2fosx)](https://travis-ci.org/kuba--/zip) |
130 |
+[![Build](https://github.com/kuba--/zip/workflows/build/badge.svg)](https://github.com/kuba--/zip/actions?query=workflow%3Abuild) |
131 |
[![Version](https://badge.fury.io/gh/kuba--%2Fzip.svg)](https://github.com/kuba--/zip/releases) |
132 |
-[![Codecov](https://codecov.io/gh/kuba--/zip/branch/master/graph/badge.svg)](https://codecov.io/gh/kuba--/zip) |
133 |
|
134 |
|
135 |
# The Idea |
136 |
@@ -71,7 +69,7 @@ |
137 |
zip_extract("foo.zip", "/tmp", on_extract_entry, &arg); |
138 |
``` |
139 |
|
140 |
-* Extract a zip entry into memory. |
141 |
+* Extract a zip entry into memory. |
142 |
```c |
143 |
void *buf = NULL; |
144 |
size_t bufsize; |
145 |
@@ -89,7 +87,7 @@ |
146 |
free(buf); |
147 |
``` |
148 |
|
149 |
-* Extract a zip entry into memory (no internal allocation). |
150 |
+* Extract a zip entry into memory (no internal allocation). |
151 |
```c |
152 |
unsigned char *buf; |
153 |
size_t bufsize; |
154 |
@@ -110,7 +108,7 @@ |
155 |
free(buf); |
156 |
``` |
157 |
|
158 |
-* Extract a zip entry into memory using callback. |
159 |
+* Extract a zip entry into memory using callback. |
160 |
```c |
161 |
struct buffer_t { |
162 |
char *data; |
163 |
@@ -144,7 +142,7 @@ |
164 |
``` |
165 |
|
166 |
|
167 |
-* Extract a zip entry into a file. |
168 |
+* Extract a zip entry into a file. |
169 |
```c |
170 |
struct zip_t *zip = zip_open("foo.zip", 0, 'r'); |
171 |
{ |
172 |
@@ -157,7 +155,7 @@ |
173 |
zip_close(zip); |
174 |
``` |
175 |
|
176 |
-* List of all zip entries |
177 |
+* List of all zip entries |
178 |
```c |
179 |
struct zip_t *zip = zip_open("foo.zip", 0, 'r'); |
180 |
int i, n = zip_total_entries(zip); |
181 |
@@ -174,7 +172,7 @@ |
182 |
zip_close(zip); |
183 |
``` |
184 |
|
185 |
-## Bindings |
186 |
+# Bindings |
187 |
Compile zip library as a dynamic library. |
188 |
```shell |
189 |
$ mkdir build |
190 |
@@ -213,3 +211,50 @@ |
191 |
+} |
192 |
+``` |
193 |
+ |
194 |
+### Rust (ffi) |
195 |
+```rust |
196 |
+extern crate libc; |
197 |
+use std::ffi::CString; |
198 |
+ |
199 |
+#[repr(C)] |
200 |
+pub struct Zip { |
201 |
+ _private: [u8; 0], |
202 |
+} |
203 |
+ |
204 |
+#[link(name = "zip")] |
205 |
+extern "C" { |
206 |
+ fn zip_open(path: *const libc::c_char, level: libc::c_int, mode: libc::c_char) -> *mut Zip; |
207 |
+ fn zip_close(zip: *mut Zip) -> libc::c_void; |
208 |
+ |
209 |
+ fn zip_entry_open(zip: *mut Zip, entryname: *const libc::c_char) -> libc::c_int; |
210 |
+ fn zip_entry_close(zip: *mut Zip) -> libc::c_int; |
211 |
+ fn zip_entry_write( |
212 |
+ zip: *mut Zip, |
213 |
+ buf: *const libc::c_void, |
214 |
+ bufsize: libc::size_t, |
215 |
+ ) -> libc::c_int; |
216 |
+} |
217 |
+ |
218 |
+fn main() { |
219 |
+ let path = CString::new("/tmp/test.zip").unwrap(); |
220 |
+ let mode: libc::c_char = 'w' as libc::c_char; |
221 |
+ |
222 |
+ let entryname = CString::new("test.txt").unwrap(); |
223 |
+ let content = "test content\0"; |
224 |
+ |
225 |
+ unsafe { |
226 |
+ let zip: *mut Zip = zip_open(path.as_ptr(), 5, mode); |
227 |
+ { |
228 |
+ zip_entry_open(zip, entryname.as_ptr()); |
229 |
+ { |
230 |
+ let buf = content.as_ptr() as *const libc::c_void; |
231 |
+ let bufsize = content.len() as libc::size_t; |
232 |
+ zip_entry_write(zip, buf, bufsize); |
233 |
+ } |
234 |
+ zip_entry_close(zip); |
235 |
+ } |
236 |
+ zip_close(zip); |
237 |
+ } |
238 |
} |
239 |
``` |
240 |
|
241 |
unchanged: |
242 |
--- contrib/zip/src/miniz.h |
243 |
+++ contrib/zip/src/miniz.h |
244 |
@@ -221,6 +221,7 @@ |
245 |
#ifndef MINIZ_HEADER_INCLUDED |
246 |
#define MINIZ_HEADER_INCLUDED |
247 |
|
248 |
+#include <stdint.h> |
249 |
#include <stdlib.h> |
250 |
|
251 |
// Defines to completely disable specific portions of miniz.c: |
252 |
@@ -284,7 +285,8 @@ |
253 |
/* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES only if not set */ |
254 |
#if !defined(MINIZ_USE_UNALIGNED_LOADS_AND_STORES) |
255 |
#if MINIZ_X86_OR_X64_CPU |
256 |
-/* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses. */ |
257 |
+/* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient |
258 |
+ * integer loads and stores from unaligned addresses. */ |
259 |
#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1 |
260 |
#define MINIZ_UNALIGNED_USE_MEMCPY |
261 |
#else |
262 |
@@ -354,6 +356,44 @@ enum { |
263 |
MZ_FIXED = 4 |
264 |
}; |
265 |
|
266 |
+/* miniz error codes. Be sure to update mz_zip_get_error_string() if you add or |
267 |
+ * modify this enum. */ |
268 |
+typedef enum { |
269 |
+ MZ_ZIP_NO_ERROR = 0, |
270 |
+ MZ_ZIP_UNDEFINED_ERROR, |
271 |
+ MZ_ZIP_TOO_MANY_FILES, |
272 |
+ MZ_ZIP_FILE_TOO_LARGE, |
273 |
+ MZ_ZIP_UNSUPPORTED_METHOD, |
274 |
+ MZ_ZIP_UNSUPPORTED_ENCRYPTION, |
275 |
+ MZ_ZIP_UNSUPPORTED_FEATURE, |
276 |
+ MZ_ZIP_FAILED_FINDING_CENTRAL_DIR, |
277 |
+ MZ_ZIP_NOT_AN_ARCHIVE, |
278 |
+ MZ_ZIP_INVALID_HEADER_OR_CORRUPTED, |
279 |
+ MZ_ZIP_UNSUPPORTED_MULTIDISK, |
280 |
+ MZ_ZIP_DECOMPRESSION_FAILED, |
281 |
+ MZ_ZIP_COMPRESSION_FAILED, |
282 |
+ MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE, |
283 |
+ MZ_ZIP_CRC_CHECK_FAILED, |
284 |
+ MZ_ZIP_UNSUPPORTED_CDIR_SIZE, |
285 |
+ MZ_ZIP_ALLOC_FAILED, |
286 |
+ MZ_ZIP_FILE_OPEN_FAILED, |
287 |
+ MZ_ZIP_FILE_CREATE_FAILED, |
288 |
+ MZ_ZIP_FILE_WRITE_FAILED, |
289 |
+ MZ_ZIP_FILE_READ_FAILED, |
290 |
+ MZ_ZIP_FILE_CLOSE_FAILED, |
291 |
+ MZ_ZIP_FILE_SEEK_FAILED, |
292 |
+ MZ_ZIP_FILE_STAT_FAILED, |
293 |
+ MZ_ZIP_INVALID_PARAMETER, |
294 |
+ MZ_ZIP_INVALID_FILENAME, |
295 |
+ MZ_ZIP_BUF_TOO_SMALL, |
296 |
+ MZ_ZIP_INTERNAL_ERROR, |
297 |
+ MZ_ZIP_FILE_NOT_FOUND, |
298 |
+ MZ_ZIP_ARCHIVE_TOO_LARGE, |
299 |
+ MZ_ZIP_VALIDATION_FAILED, |
300 |
+ MZ_ZIP_WRITE_CALLBACK_FAILED, |
301 |
+ MZ_ZIP_TOTAL_ERRORS |
302 |
+} mz_zip_error; |
303 |
+ |
304 |
// Method |
305 |
#define MZ_DEFLATED 8 |
306 |
|
307 |
@@ -696,6 +736,7 @@ typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs, |
308 |
void *pBuf, size_t n); |
309 |
typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs, |
310 |
const void *pBuf, size_t n); |
311 |
+typedef mz_bool (*mz_file_needs_keepalive)(void *pOpaque); |
312 |
|
313 |
struct mz_zip_internal_state_tag; |
314 |
typedef struct mz_zip_internal_state_tag mz_zip_internal_state; |
315 |
@@ -707,13 +748,27 @@ typedef enum { |
316 |
MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3 |
317 |
} mz_zip_mode; |
318 |
|
319 |
-typedef struct mz_zip_archive_tag { |
320 |
+typedef enum { |
321 |
+ MZ_ZIP_TYPE_INVALID = 0, |
322 |
+ MZ_ZIP_TYPE_USER, |
323 |
+ MZ_ZIP_TYPE_MEMORY, |
324 |
+ MZ_ZIP_TYPE_HEAP, |
325 |
+ MZ_ZIP_TYPE_FILE, |
326 |
+ MZ_ZIP_TYPE_CFILE, |
327 |
+ MZ_ZIP_TOTAL_TYPES |
328 |
+} mz_zip_type; |
329 |
+ |
330 |
+typedef struct { |
331 |
mz_uint64 m_archive_size; |
332 |
mz_uint64 m_central_directory_file_ofs; |
333 |
- mz_uint m_total_files; |
334 |
+ |
335 |
+ /* We only support up to UINT32_MAX files in zip64 mode. */ |
336 |
+ mz_uint32 m_total_files; |
337 |
mz_zip_mode m_zip_mode; |
338 |
+ mz_zip_type m_zip_type; |
339 |
+ mz_zip_error m_last_error; |
340 |
|
341 |
- mz_uint m_file_offset_alignment; |
342 |
+ mz_uint64 m_file_offset_alignment; |
343 |
|
344 |
mz_alloc_func m_pAlloc; |
345 |
mz_free_func m_pFree; |
346 |
@@ -722,6 +777,7 @@ typedef struct mz_zip_archive_tag { |
347 |
|
348 |
mz_file_read_func m_pRead; |
349 |
mz_file_write_func m_pWrite; |
350 |
+ mz_file_needs_keepalive m_pNeeds_keepalive; |
351 |
void *m_pIO_opaque; |
352 |
|
353 |
mz_zip_internal_state *m_pState; |
354 |
@@ -1263,6 +1319,9 @@ mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, |
355 |
int strategy); |
356 |
#endif // #ifndef MINIZ_NO_ZLIB_APIS |
357 |
|
358 |
+#define MZ_UINT16_MAX (0xFFFFU) |
359 |
+#define MZ_UINT32_MAX (0xFFFFFFFFU) |
360 |
+ |
361 |
#ifdef __cplusplus |
362 |
} |
363 |
#endif |
364 |
@@ -1311,6 +1370,11 @@ typedef unsigned char mz_validate_uint64[sizeof(mz_uint64) == 8 ? 1 : -1]; |
365 |
((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U)) |
366 |
#endif |
367 |
|
368 |
+#define MZ_READ_LE64(p) \ |
369 |
+ (((mz_uint64)MZ_READ_LE32(p)) | \ |
370 |
+ (((mz_uint64)MZ_READ_LE32((const mz_uint8 *)(p) + sizeof(mz_uint32))) \ |
371 |
+ << 32U)) |
372 |
+ |
373 |
#ifdef _MSC_VER |
374 |
#define MZ_FORCEINLINE __forceinline |
375 |
#elif defined(__GNUC__) |
376 |
@@ -4160,6 +4224,17 @@ enum { |
377 |
MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30, |
378 |
MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46, |
379 |
MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22, |
380 |
+ |
381 |
+ /* ZIP64 archive identifier and record sizes */ |
382 |
+ MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06064b50, |
383 |
+ MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG = 0x07064b50, |
384 |
+ MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE = 56, |
385 |
+ MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE = 20, |
386 |
+ MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID = 0x0001, |
387 |
+ MZ_ZIP_DATA_DESCRIPTOR_ID = 0x08074b50, |
388 |
+ MZ_ZIP_DATA_DESCRIPTER_SIZE64 = 24, |
389 |
+ MZ_ZIP_DATA_DESCRIPTER_SIZE32 = 16, |
390 |
+ |
391 |
// Central directory header record offsets |
392 |
MZ_ZIP_CDH_SIG_OFS = 0, |
393 |
MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4, |
394 |
@@ -4199,6 +4274,31 @@ enum { |
395 |
MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12, |
396 |
MZ_ZIP_ECDH_CDIR_OFS_OFS = 16, |
397 |
MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20, |
398 |
+ |
399 |
+ /* ZIP64 End of central directory locator offsets */ |
400 |
+ MZ_ZIP64_ECDL_SIG_OFS = 0, /* 4 bytes */ |
401 |
+ MZ_ZIP64_ECDL_NUM_DISK_CDIR_OFS = 4, /* 4 bytes */ |
402 |
+ MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS = 8, /* 8 bytes */ |
403 |
+ MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS = 16, /* 4 bytes */ |
404 |
+ |
405 |
+ /* ZIP64 End of central directory header offsets */ |
406 |
+ MZ_ZIP64_ECDH_SIG_OFS = 0, /* 4 bytes */ |
407 |
+ MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS = 4, /* 8 bytes */ |
408 |
+ MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS = 12, /* 2 bytes */ |
409 |
+ MZ_ZIP64_ECDH_VERSION_NEEDED_OFS = 14, /* 2 bytes */ |
410 |
+ MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS = 16, /* 4 bytes */ |
411 |
+ MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS = 20, /* 4 bytes */ |
412 |
+ MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 24, /* 8 bytes */ |
413 |
+ MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS = 32, /* 8 bytes */ |
414 |
+ MZ_ZIP64_ECDH_CDIR_SIZE_OFS = 40, /* 8 bytes */ |
415 |
+ MZ_ZIP64_ECDH_CDIR_OFS_OFS = 48, /* 8 bytes */ |
416 |
+ MZ_ZIP_VERSION_MADE_BY_DOS_FILESYSTEM_ID = 0, |
417 |
+ MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG = 0x10, |
418 |
+ MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED = 1, |
419 |
+ MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG = 32, |
420 |
+ MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION = 64, |
421 |
+ MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED = 8192, |
422 |
+ MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8 = 1 << 11 |
423 |
}; |
424 |
|
425 |
typedef struct { |
426 |
@@ -4211,7 +4311,24 @@ struct mz_zip_internal_state_tag { |
427 |
mz_zip_array m_central_dir; |
428 |
mz_zip_array m_central_dir_offsets; |
429 |
mz_zip_array m_sorted_central_dir_offsets; |
430 |
+ |
431 |
+ /* The flags passed in when the archive is initially opened. */ |
432 |
+ uint32_t m_init_flags; |
433 |
+ |
434 |
+ /* MZ_TRUE if the archive has a zip64 end of central directory headers, etc. |
435 |
+ */ |
436 |
+ mz_bool m_zip64; |
437 |
+ |
438 |
+ /* MZ_TRUE if we found zip64 extended info in the central directory (m_zip64 |
439 |
+ * will also be slammed to true too, even if we didn't find a zip64 end of |
440 |
+ * central dir header, etc.) */ |
441 |
+ mz_bool m_zip64_has_extended_info_fields; |
442 |
+ |
443 |
+ /* These fields are used by the file, FILE, memory, and memory/heap read/write |
444 |
+ * helpers. */ |
445 |
MZ_FILE *m_pFile; |
446 |
+ mz_uint64 m_file_archive_start_ofs; |
447 |
+ |
448 |
void *m_pMem; |
449 |
size_t m_mem_size; |
450 |
size_t m_mem_capacity; |
451 |
@@ -4363,6 +4480,13 @@ static mz_bool mz_zip_set_file_times(const char *pFilename, time_t access_time, |
452 |
#endif /* #ifndef MINIZ_NO_STDIO */ |
453 |
#endif /* #ifndef MINIZ_NO_TIME */ |
454 |
|
455 |
+static MZ_FORCEINLINE mz_bool mz_zip_set_error(mz_zip_archive *pZip, |
456 |
+ mz_zip_error err_num) { |
457 |
+ if (pZip) |
458 |
+ pZip->m_last_error = err_num; |
459 |
+ return MZ_FALSE; |
460 |
+} |
461 |
+ |
462 |
static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, |
463 |
mz_uint32 flags) { |
464 |
(void)flags; |
465 |
@@ -4480,127 +4604,346 @@ mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip) { |
466 |
} |
467 |
} |
468 |
|
469 |
-static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, |
470 |
- mz_uint32 flags) { |
471 |
- mz_uint cdir_size, num_this_disk, cdir_disk_index; |
472 |
- mz_uint64 cdir_ofs; |
473 |
+static mz_bool mz_zip_reader_locate_header_sig(mz_zip_archive *pZip, |
474 |
+ mz_uint32 record_sig, |
475 |
+ mz_uint32 record_size, |
476 |
+ mz_int64 *pOfs) { |
477 |
mz_int64 cur_file_ofs; |
478 |
- const mz_uint8 *p; |
479 |
mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; |
480 |
mz_uint8 *pBuf = (mz_uint8 *)buf_u32; |
481 |
- mz_bool sort_central_dir = |
482 |
- ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0); |
483 |
- // Basic sanity checks - reject files which are too small, and check the first |
484 |
- // 4 bytes of the file to make sure a local header is there. |
485 |
- if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) |
486 |
+ |
487 |
+ /* Basic sanity checks - reject files which are too small */ |
488 |
+ if (pZip->m_archive_size < record_size) |
489 |
return MZ_FALSE; |
490 |
- // Find the end of central directory record by scanning the file from the end |
491 |
- // towards the beginning. |
492 |
+ |
493 |
+ /* Find the record by scanning the file from the end towards the beginning. */ |
494 |
cur_file_ofs = |
495 |
MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0); |
496 |
for (;;) { |
497 |
int i, |
498 |
n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs); |
499 |
+ |
500 |
if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n) |
501 |
return MZ_FALSE; |
502 |
- for (i = n - 4; i >= 0; --i) |
503 |
- if (MZ_READ_LE32(pBuf + i) == MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) |
504 |
- break; |
505 |
+ |
506 |
+ for (i = n - 4; i >= 0; --i) { |
507 |
+ mz_uint s = MZ_READ_LE32(pBuf + i); |
508 |
+ if (s == record_sig) { |
509 |
+ if ((pZip->m_archive_size - (cur_file_ofs + i)) >= record_size) |
510 |
+ break; |
511 |
+ } |
512 |
+ } |
513 |
+ |
514 |
if (i >= 0) { |
515 |
cur_file_ofs += i; |
516 |
break; |
517 |
} |
518 |
+ |
519 |
+ /* Give up if we've searched the entire file, or we've gone back "too far" |
520 |
+ * (~64kb) */ |
521 |
if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= |
522 |
- (0xFFFF + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE))) |
523 |
+ (MZ_UINT16_MAX + record_size))) |
524 |
return MZ_FALSE; |
525 |
+ |
526 |
cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0); |
527 |
} |
528 |
- // Read and verify the end of central directory record. |
529 |
+ |
530 |
+ *pOfs = cur_file_ofs; |
531 |
+ return MZ_TRUE; |
532 |
+} |
533 |
+ |
534 |
+static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, |
535 |
+ mz_uint flags) { |
536 |
+ mz_uint cdir_size = 0, cdir_entries_on_this_disk = 0, num_this_disk = 0, |
537 |
+ cdir_disk_index = 0; |
538 |
+ mz_uint64 cdir_ofs = 0; |
539 |
+ mz_int64 cur_file_ofs = 0; |
540 |
+ const mz_uint8 *p; |
541 |
+ |
542 |
+ mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; |
543 |
+ mz_uint8 *pBuf = (mz_uint8 *)buf_u32; |
544 |
+ mz_bool sort_central_dir = |
545 |
+ ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0); |
546 |
+ mz_uint32 zip64_end_of_central_dir_locator_u32 |
547 |
+ [(MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + sizeof(mz_uint32) - 1) / |
548 |
+ sizeof(mz_uint32)]; |
549 |
+ mz_uint8 *pZip64_locator = (mz_uint8 *)zip64_end_of_central_dir_locator_u32; |
550 |
+ |
551 |
+ mz_uint32 zip64_end_of_central_dir_header_u32 |
552 |
+ [(MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / |
553 |
+ sizeof(mz_uint32)]; |
554 |
+ mz_uint8 *pZip64_end_of_central_dir = |
555 |
+ (mz_uint8 *)zip64_end_of_central_dir_header_u32; |
556 |
+ |
557 |
+ mz_uint64 zip64_end_of_central_dir_ofs = 0; |
558 |
+ |
559 |
+ /* Basic sanity checks - reject files which are too small, and check the first |
560 |
+ * 4 bytes of the file to make sure a local header is there. */ |
561 |
+ if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) |
562 |
+ return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); |
563 |
+ |
564 |
+ if (!mz_zip_reader_locate_header_sig( |
565 |
+ pZip, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG, |
566 |
+ MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE, &cur_file_ofs)) |
567 |
+ return mz_zip_set_error(pZip, MZ_ZIP_FAILED_FINDING_CENTRAL_DIR); |
568 |
+ |
569 |
+ /* Read and verify the end of central directory record. */ |
570 |
if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, |
571 |
MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != |
572 |
MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) |
573 |
- return MZ_FALSE; |
574 |
- if ((MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != |
575 |
- MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) || |
576 |
- ((pZip->m_total_files = |
577 |
- MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS)) != |
578 |
- MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS))) |
579 |
- return MZ_FALSE; |
580 |
+ return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); |
581 |
+ |
582 |
+ if (MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != |
583 |
+ MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) |
584 |
+ return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); |
585 |
+ |
586 |
+ if (cur_file_ofs >= (MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + |
587 |
+ MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)) { |
588 |
+ if (pZip->m_pRead(pZip->m_pIO_opaque, |
589 |
+ cur_file_ofs - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE, |
590 |
+ pZip64_locator, |
591 |
+ MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) == |
592 |
+ MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) { |
593 |
+ if (MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_SIG_OFS) == |
594 |
+ MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG) { |
595 |
+ zip64_end_of_central_dir_ofs = MZ_READ_LE64( |
596 |
+ pZip64_locator + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS); |
597 |
+ if (zip64_end_of_central_dir_ofs > |
598 |
+ (pZip->m_archive_size - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)) |
599 |
+ return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); |
600 |
+ |
601 |
+ if (pZip->m_pRead(pZip->m_pIO_opaque, zip64_end_of_central_dir_ofs, |
602 |
+ pZip64_end_of_central_dir, |
603 |
+ MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) == |
604 |
+ MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) { |
605 |
+ if (MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIG_OFS) == |
606 |
+ MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG) { |
607 |
+ pZip->m_pState->m_zip64 = MZ_TRUE; |
608 |
+ } |
609 |
+ } |
610 |
+ } |
611 |
+ } |
612 |
+ } |
613 |
|
614 |
+ pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS); |
615 |
+ cdir_entries_on_this_disk = |
616 |
+ MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS); |
617 |
num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS); |
618 |
cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS); |
619 |
+ cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS); |
620 |
+ cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS); |
621 |
+ |
622 |
+ if (pZip->m_pState->m_zip64) { |
623 |
+ mz_uint32 zip64_total_num_of_disks = |
624 |
+ MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS); |
625 |
+ mz_uint64 zip64_cdir_total_entries = MZ_READ_LE64( |
626 |
+ pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS); |
627 |
+ mz_uint64 zip64_cdir_total_entries_on_this_disk = MZ_READ_LE64( |
628 |
+ pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS); |
629 |
+ mz_uint64 zip64_size_of_end_of_central_dir_record = MZ_READ_LE64( |
630 |
+ pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS); |
631 |
+ mz_uint64 zip64_size_of_central_directory = |
632 |
+ MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_SIZE_OFS); |
633 |
+ |
634 |
+ if (zip64_size_of_end_of_central_dir_record < |
635 |
+ (MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - 12)) |
636 |
+ return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); |
637 |
+ |
638 |
+ if (zip64_total_num_of_disks != 1U) |
639 |
+ return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK); |
640 |
+ |
641 |
+ /* Check for miniz's practical limits */ |
642 |
+ if (zip64_cdir_total_entries > MZ_UINT32_MAX) |
643 |
+ return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); |
644 |
+ |
645 |
+ pZip->m_total_files = (mz_uint32)zip64_cdir_total_entries; |
646 |
+ |
647 |
+ if (zip64_cdir_total_entries_on_this_disk > MZ_UINT32_MAX) |
648 |
+ return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); |
649 |
+ |
650 |
+ cdir_entries_on_this_disk = |
651 |
+ (mz_uint32)zip64_cdir_total_entries_on_this_disk; |
652 |
+ |
653 |
+ /* Check for miniz's current practical limits (sorry, this should be enough |
654 |
+ * for millions of files) */ |
655 |
+ if (zip64_size_of_central_directory > MZ_UINT32_MAX) |
656 |
+ return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE); |
657 |
+ |
658 |
+ cdir_size = (mz_uint32)zip64_size_of_central_directory; |
659 |
+ |
660 |
+ num_this_disk = MZ_READ_LE32(pZip64_end_of_central_dir + |
661 |
+ MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS); |
662 |
+ |
663 |
+ cdir_disk_index = MZ_READ_LE32(pZip64_end_of_central_dir + |
664 |
+ MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS); |
665 |
+ |
666 |
+ cdir_ofs = |
667 |
+ MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_OFS_OFS); |
668 |
+ } |
669 |
+ |
670 |
+ if (pZip->m_total_files != cdir_entries_on_this_disk) |
671 |
+ return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK); |
672 |
+ |
673 |
if (((num_this_disk | cdir_disk_index) != 0) && |
674 |
((num_this_disk != 1) || (cdir_disk_index != 1))) |
675 |
- return MZ_FALSE; |
676 |
+ return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK); |
677 |
|
678 |
- if ((cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS)) < |
679 |
- pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) |
680 |
- return MZ_FALSE; |
681 |
+ if (cdir_size < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) |
682 |
+ return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); |
683 |
|
684 |
- cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS); |
685 |
if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size) |
686 |
- return MZ_FALSE; |
687 |
+ return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); |
688 |
|
689 |
pZip->m_central_directory_file_ofs = cdir_ofs; |
690 |
|
691 |
if (pZip->m_total_files) { |
692 |
mz_uint i, n; |
693 |
- |
694 |
- // Read the entire central directory into a heap block, and allocate another |
695 |
- // heap block to hold the unsorted central dir file record offsets, and |
696 |
- // another to hold the sorted indices. |
697 |
+ /* Read the entire central directory into a heap block, and allocate another |
698 |
+ * heap block to hold the unsorted central dir file record offsets, and |
699 |
+ * possibly another to hold the sorted indices. */ |
700 |
if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, |
701 |
MZ_FALSE)) || |
702 |
(!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, |
703 |
pZip->m_total_files, MZ_FALSE))) |
704 |
- return MZ_FALSE; |
705 |
+ return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); |
706 |
|
707 |
if (sort_central_dir) { |
708 |
if (!mz_zip_array_resize(pZip, |
709 |
&pZip->m_pState->m_sorted_central_dir_offsets, |
710 |
pZip->m_total_files, MZ_FALSE)) |
711 |
- return MZ_FALSE; |
712 |
+ return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); |
713 |
} |
714 |
|
715 |
if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, |
716 |
pZip->m_pState->m_central_dir.m_p, |
717 |
cdir_size) != cdir_size) |
718 |
- return MZ_FALSE; |
719 |
+ return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); |
720 |
|
721 |
- // Now create an index into the central directory file records, do some |
722 |
- // basic sanity checking on each record, and check for zip64 entries (which |
723 |
- // are not yet supported). |
724 |
+ /* Now create an index into the central directory file records, do some |
725 |
+ * basic sanity checking on each record */ |
726 |
p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p; |
727 |
for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i) { |
728 |
- mz_uint total_header_size, comp_size, decomp_size, disk_index; |
729 |
+ mz_uint total_header_size, disk_index, bit_flags, filename_size, |
730 |
+ ext_data_size; |
731 |
+ mz_uint64 comp_size, decomp_size, local_header_ofs; |
732 |
+ |
733 |
if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || |
734 |
(MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG)) |
735 |
- return MZ_FALSE; |
736 |
+ return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); |
737 |
+ |
738 |
MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, |
739 |
i) = |
740 |
(mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p); |
741 |
+ |
742 |
if (sort_central_dir) |
743 |
MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, |
744 |
mz_uint32, i) = i; |
745 |
+ |
746 |
comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); |
747 |
decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); |
748 |
- if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && |
749 |
- (decomp_size != comp_size)) || |
750 |
- (decomp_size && !comp_size) || (decomp_size == 0xFFFFFFFF) || |
751 |
- (comp_size == 0xFFFFFFFF)) |
752 |
- return MZ_FALSE; |
753 |
+ local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS); |
754 |
+ filename_size = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); |
755 |
+ ext_data_size = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS); |
756 |
+ |
757 |
+ if ((!pZip->m_pState->m_zip64_has_extended_info_fields) && |
758 |
+ (ext_data_size) && |
759 |
+ (MZ_MAX(MZ_MAX(comp_size, decomp_size), local_header_ofs) == |
760 |
+ MZ_UINT32_MAX)) { |
761 |
+ /* Attempt to find zip64 extended information field in the entry's extra |
762 |
+ * data */ |
763 |
+ mz_uint32 extra_size_remaining = ext_data_size; |
764 |
+ |
765 |
+ if (extra_size_remaining) { |
766 |
+ const mz_uint8 *pExtra_data; |
767 |
+ void *buf = NULL; |
768 |
+ |
769 |
+ if (MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + ext_data_size > |
770 |
+ n) { |
771 |
+ buf = MZ_MALLOC(ext_data_size); |
772 |
+ if (buf == NULL) |
773 |
+ return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); |
774 |
+ |
775 |
+ if (pZip->m_pRead(pZip->m_pIO_opaque, |
776 |
+ cdir_ofs + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + |
777 |
+ filename_size, |
778 |
+ buf, ext_data_size) != ext_data_size) { |
779 |
+ MZ_FREE(buf); |
780 |
+ return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); |
781 |
+ } |
782 |
+ |
783 |
+ pExtra_data = (mz_uint8 *)buf; |
784 |
+ } else { |
785 |
+ pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size; |
786 |
+ } |
787 |
+ |
788 |
+ do { |
789 |
+ mz_uint32 field_id; |
790 |
+ mz_uint32 field_data_size; |
791 |
+ |
792 |
+ if (extra_size_remaining < (sizeof(mz_uint16) * 2)) { |
793 |
+ MZ_FREE(buf); |
794 |
+ return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); |
795 |
+ } |
796 |
+ |
797 |
+ field_id = MZ_READ_LE16(pExtra_data); |
798 |
+ field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16)); |
799 |
+ |
800 |
+ if ((field_data_size + sizeof(mz_uint16) * 2) > |
801 |
+ extra_size_remaining) { |
802 |
+ MZ_FREE(buf); |
803 |
+ return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); |
804 |
+ } |
805 |
+ |
806 |
+ if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) { |
807 |
+ /* Ok, the archive didn't have any zip64 headers but it uses a |
808 |
+ * zip64 extended information field so mark it as zip64 anyway |
809 |
+ * (this can occur with infozip's zip util when it reads |
810 |
+ * compresses files from stdin). */ |
811 |
+ pZip->m_pState->m_zip64 = MZ_TRUE; |
812 |
+ pZip->m_pState->m_zip64_has_extended_info_fields = MZ_TRUE; |
813 |
+ break; |
814 |
+ } |
815 |
+ |
816 |
+ pExtra_data += sizeof(mz_uint16) * 2 + field_data_size; |
817 |
+ extra_size_remaining = |
818 |
+ extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size; |
819 |
+ } while (extra_size_remaining); |
820 |
+ |
821 |
+ MZ_FREE(buf); |
822 |
+ } |
823 |
+ } |
824 |
+ |
825 |
+ /* I've seen archives that aren't marked as zip64 that uses zip64 ext |
826 |
+ * data, argh */ |
827 |
+ if ((comp_size != MZ_UINT32_MAX) && (decomp_size != MZ_UINT32_MAX)) { |
828 |
+ if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && |
829 |
+ (decomp_size != comp_size)) || |
830 |
+ (decomp_size && !comp_size)) |
831 |
+ return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); |
832 |
+ } |
833 |
+ |
834 |
disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS); |
835 |
- if ((disk_index != num_this_disk) && (disk_index != 1)) |
836 |
- return MZ_FALSE; |
837 |
- if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + |
838 |
- MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size) |
839 |
- return MZ_FALSE; |
840 |
+ if ((disk_index == MZ_UINT16_MAX) || |
841 |
+ ((disk_index != num_this_disk) && (disk_index != 1))) |
842 |
+ return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK); |
843 |
+ |
844 |
+ if (comp_size != MZ_UINT32_MAX) { |
845 |
+ if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + |
846 |
+ MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size) |
847 |
+ return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); |
848 |
+ } |
849 |
+ |
850 |
+ bit_flags = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); |
851 |
+ if (bit_flags & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED) |
852 |
+ return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION); |
853 |
+ |
854 |
if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + |
855 |
MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + |
856 |
MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + |
857 |
MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > |
858 |
n) |
859 |
- return MZ_FALSE; |
860 |
+ return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); |
861 |
+ |
862 |
n -= total_header_size; |
863 |
p += total_header_size; |
864 |
} |
865 |
diff -u contrib/zip/src/zip.c contrib/zip/src/zip.c |
866 |
--- contrib/zip/src/zip.c |
867 |
+++ contrib/zip/src/zip.c |
868 |
@@ -24,7 +24,6 @@ |
869 |
((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) && \ |
870 |
(P)[1] == ':') |
871 |
#define FILESYSTEM_PREFIX_LEN(P) (HAS_DEVICE(P) ? 2 : 0) |
872 |
-#define ISSLASH(C) ((C) == '/' || (C) == '\\') |
873 |
|
874 |
#else |
875 |
|
876 |
@@ -48,7 +47,7 @@ |
877 |
#endif |
878 |
|
879 |
#ifndef ISSLASH |
880 |
-#define ISSLASH(C) ((C) == '/') |
881 |
+#define ISSLASH(C) ((C) == '/' || (C) == '\\') |
882 |
#endif |
883 |
|
884 |
#define CLEANUP(ptr) \ |
885 |
@@ -78,26 +77,34 @@ |
886 |
return base; |
887 |
} |
888 |
|
889 |
-static int mkpath(const char *path) { |
890 |
- char const *p; |
891 |
+static int mkpath(char *path) { |
892 |
+ char *p; |
893 |
char npath[MAX_PATH + 1]; |
894 |
int len = 0; |
895 |
int has_device = HAS_DEVICE(path); |
896 |
|
897 |
memset(npath, 0, MAX_PATH + 1); |
898 |
- |
899 |
-#ifdef _WIN32 |
900 |
- // only on windows fix the path |
901 |
- npath[0] = path[0]; |
902 |
- npath[1] = path[1]; |
903 |
- len = 2; |
904 |
-#endif // _WIN32 |
905 |
- |
906 |
+ if (has_device) { |
907 |
+ // only on windows |
908 |
+ npath[0] = path[0]; |
909 |
+ npath[1] = path[1]; |
910 |
+ len = 2; |
911 |
+ } |
912 |
for (p = path + len; *p && len < MAX_PATH; p++) { |
913 |
if (ISSLASH(*p) && ((!has_device && len > 0) || (has_device && len > 2))) { |
914 |
- if (MKDIR(npath) == -1) |
915 |
- if (errno != EEXIST) |
916 |
+#if defined(_WIN32) || defined(__WIN32__) || defined(_MSC_VER) || \ |
917 |
+ defined(__MINGW32__) |
918 |
+#else |
919 |
+ if ('\\' == *p) { |
920 |
+ *p = '/'; |
921 |
+ } |
922 |
+#endif |
923 |
+ |
924 |
+ if (MKDIR(npath) == -1) { |
925 |
+ if (errno != EEXIST) { |
926 |
return -1; |
927 |
+ } |
928 |
+ } |
929 |
} |
930 |
npath[len++] = *p; |
931 |
} |
932 |
@@ -215,6 +222,20 @@ |
933 |
} |
934 |
} |
935 |
|
936 |
+int zip_is64(struct zip_t *zip) { |
937 |
+ if (!zip) { |
938 |
+ // zip_t handler is not initialized |
939 |
+ return -1; |
940 |
+ } |
941 |
+ |
942 |
+ if (!zip->archive.m_pState) { |
943 |
+ // zip state is not initialized |
944 |
+ return -1; |
945 |
+ } |
946 |
+ |
947 |
+ return (int)zip->archive.m_pState->m_zip64; |
948 |
+} |
949 |
+ |
950 |
int zip_entry_open(struct zip_t *zip, const char *entryname) { |
951 |
size_t entrylen = 0; |
952 |
mz_zip_archive *pzip = NULL; |
953 |
@@ -279,7 +300,14 @@ |
954 |
zip->entry.header_offset = zip->archive.m_archive_size; |
955 |
memset(zip->entry.header, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE * sizeof(mz_uint8)); |
956 |
zip->entry.method = 0; |
957 |
+ |
958 |
+ // UNIX or APPLE |
959 |
+#if MZ_PLATFORM == 3 || MZ_PLATFORM == 19 |
960 |
+ // regular file with rw-r--r-- persmissions |
961 |
+ zip->entry.external_attr = (mz_uint32)(0100644) << 16; |
962 |
+#else |
963 |
zip->entry.external_attr = 0; |
964 |
+#endif |
965 |
|
966 |
num_alignment_padding_bytes = |
967 |
mz_zip_writer_compute_padding_needed_for_file_alignment(pzip); |
968 |
@@ -660,7 +688,7 @@ |
969 |
} |
970 |
|
971 |
if (!mz_zip_reader_extract_to_mem_no_alloc(pzip, (mz_uint)zip->entry.index, |
972 |
- buf, bufsize, 0, NULL, 0)) { |
973 |
+ buf, bufsize, 0, NULL, 0)) { |
974 |
return -1; |
975 |
} |
976 |
|
977 |
@@ -670,10 +698,7 @@ |
978 |
int zip_entry_fread(struct zip_t *zip, const char *filename) { |
979 |
mz_zip_archive *pzip = NULL; |
980 |
mz_uint idx; |
981 |
-#if defined(_MSC_VER) |
982 |
-#else |
983 |
mz_uint32 xattr = 0; |
984 |
-#endif |
985 |
mz_zip_archive_file_stat info; |
986 |
|
987 |
if (!zip) { |
988 |
@@ -783,7 +808,8 @@ |
989 |
|
990 |
if (MZ_FILE_STAT(name, &file_stat) != 0) { |
991 |
// problem getting information - check errno |
992 |
- return -1; |
993 |
+ status = -1; |
994 |
+ break; |
995 |
} |
996 |
|
997 |
if ((file_stat.st_mode & 0200) == 0) { |
998 |
@@ -875,12 +901,19 @@ |
999 |
goto out; |
1000 |
} |
1001 |
|
1002 |
- if ((((info.m_version_made_by >> 8) == 3) || ((info.m_version_made_by >> 8) == 19)) // if zip is produced on Unix or macOS (3 and 19 from section 4.4.2.2 of zip standard) |
1003 |
- && info.m_external_attr & (0x20 << 24)) { // and has sym link attribute (0x80 is file, 0x40 is directory) |
1004 |
+ if ((((info.m_version_made_by >> 8) == 3) || |
1005 |
+ ((info.m_version_made_by >> 8) == |
1006 |
+ 19)) // if zip is produced on Unix or macOS (3 and 19 from |
1007 |
+ // section 4.4.2.2 of zip standard) |
1008 |
+ && info.m_external_attr & |
1009 |
+ (0x20 << 24)) { // and has sym link attribute (0x80 is file, 0x40 |
1010 |
+ // is directory) |
1011 |
#if defined(_WIN32) || defined(__WIN32__) || defined(_MSC_VER) || \ |
1012 |
defined(__MINGW32__) |
1013 |
-#else |
1014 |
- if (info.m_uncomp_size > MAX_PATH || !mz_zip_reader_extract_to_mem_no_alloc(&zip_archive, i, symlink_to, MAX_PATH, 0, NULL, 0)) { |
1015 |
+#else |
1016 |
+ if (info.m_uncomp_size > MAX_PATH || |
1017 |
+ !mz_zip_reader_extract_to_mem_no_alloc(&zip_archive, i, symlink_to, |
1018 |
+ MAX_PATH, 0, NULL, 0)) { |
1019 |
goto out; |
1020 |
} |
1021 |
symlink_to[info.m_uncomp_size] = '\0'; |
1022 |
diff -u contrib/zip/src/zip.h contrib/zip/src/zip.h |
1023 |
--- contrib/zip/src/zip.h |
1024 |
+++ contrib/zip/src/zip.h |
1025 |
@@ -20,241 +20,251 @@ |
1026 |
#endif |
1027 |
|
1028 |
#if !defined(_SSIZE_T_DEFINED) && !defined(_SSIZE_T_DEFINED_) && \ |
1029 |
- !defined(_SSIZE_T) && !defined(_SSIZE_T_) && !defined(__ssize_t_defined) |
1030 |
-#define _SSIZE_T |
1031 |
+ !defined(__DEFINED_ssize_t) && !defined(__ssize_t_defined) && \ |
1032 |
+ !defined(_SSIZE_T) && !defined(_SSIZE_T_) && !defined(_SSIZE_T_DECLARED) |
1033 |
+ |
1034 |
// 64-bit Windows is the only mainstream platform |
1035 |
// where sizeof(long) != sizeof(void*) |
1036 |
#ifdef _WIN64 |
1037 |
-typedef long long ssize_t; /* byte count or error */ |
1038 |
+typedef long long ssize_t; /* byte count or error */ |
1039 |
#else |
1040 |
-typedef long ssize_t; /* byte count or error */ |
1041 |
+typedef long ssize_t; /* byte count or error */ |
1042 |
#endif |
1043 |
+ |
1044 |
+#define _SSIZE_T_DEFINED |
1045 |
+#define _SSIZE_T_DEFINED_ |
1046 |
+#define __DEFINED_ssize_t |
1047 |
+#define __ssize_t_defined |
1048 |
+#define _SSIZE_T |
1049 |
+#define _SSIZE_T_ |
1050 |
+#define _SSIZE_T_DECLARED |
1051 |
+ |
1052 |
#endif |
1053 |
|
1054 |
#ifndef MAX_PATH |
1055 |
#define MAX_PATH 32767 /* # chars in a path name including NULL */ |
1056 |
#endif |
1057 |
|
1058 |
-#define ZIP_DEFAULT_COMPRESSION_LEVEL 6 |
1059 |
+/** |
1060 |
+ * @mainpage |
1061 |
+ * |
1062 |
+ * Documenation for @ref zip. |
1063 |
+ */ |
1064 |
|
1065 |
-/* |
1066 |
- This data structure is used throughout the library to represent zip archive |
1067 |
- - forward declaration. |
1068 |
-*/ |
1069 |
-struct zip_t; |
1070 |
+/** |
1071 |
+ * @addtogroup zip |
1072 |
+ * @{ |
1073 |
+ */ |
1074 |
|
1075 |
-/* |
1076 |
- Opens zip archive with compression level using the given mode. |
1077 |
+/** |
1078 |
+ * Default zip compression level. |
1079 |
+ */ |
1080 |
|
1081 |
- Args: |
1082 |
- zipname: zip archive file name. |
1083 |
- level: compression level (0-9 are the standard zlib-style levels). |
1084 |
- mode: file access mode. |
1085 |
- 'r': opens a file for reading/extracting (the file must exists). |
1086 |
- 'w': creates an empty file for writing. |
1087 |
- 'a': appends to an existing archive. |
1088 |
+#define ZIP_DEFAULT_COMPRESSION_LEVEL 6 |
1089 |
|
1090 |
- Returns: |
1091 |
- The zip archive handler or NULL on error |
1092 |
-*/ |
1093 |
+/** |
1094 |
+ * @struct zip_t |
1095 |
+ * |
1096 |
+ * This data structure is used throughout the library to represent zip archive - |
1097 |
+ * forward declaration. |
1098 |
+ */ |
1099 |
+struct zip_t; |
1100 |
+ |
1101 |
+/** |
1102 |
+ * Opens zip archive with compression level using the given mode. |
1103 |
+ * |
1104 |
+ * @param zipname zip archive file name. |
1105 |
+ * @param level compression level (0-9 are the standard zlib-style levels). |
1106 |
+ * @param mode file access mode. |
1107 |
+ * - 'r': opens a file for reading/extracting (the file must exists). |
1108 |
+ * - 'w': creates an empty file for writing. |
1109 |
+ * - 'a': appends to an existing archive. |
1110 |
+ * |
1111 |
+ * @return the zip archive handler or NULL on error |
1112 |
+ */ |
1113 |
extern struct zip_t *zip_open(const char *zipname, int level, char mode); |
1114 |
|
1115 |
-/* |
1116 |
- Closes the zip archive, releases resources - always finalize. |
1117 |
- |
1118 |
- Args: |
1119 |
- zip: zip archive handler. |
1120 |
-*/ |
1121 |
+/** |
1122 |
+ * Closes the zip archive, releases resources - always finalize. |
1123 |
+ * |
1124 |
+ * @param zip zip archive handler. |
1125 |
+ */ |
1126 |
extern void zip_close(struct zip_t *zip); |
1127 |
|
1128 |
-/* |
1129 |
- Opens an entry by name in the zip archive. |
1130 |
- For zip archive opened in 'w' or 'a' mode the function will append |
1131 |
- a new entry. In readonly mode the function tries to locate the entry |
1132 |
- in global dictionary. |
1133 |
+/** |
1134 |
+ * Determines if the archive has a zip64 end of central directory headers. |
1135 |
+ * |
1136 |
+ * @param zip zip archive handler. |
1137 |
+ * |
1138 |
+ * @return the return code - 1 (true), 0 (false), negative number (< 0) on |
1139 |
+ * error. |
1140 |
+ */ |
1141 |
+extern int zip_is64(struct zip_t *zip); |
1142 |
|
1143 |
- Args: |
1144 |
- zip: zip archive handler. |
1145 |
- entryname: an entry name in local dictionary. |
1146 |
- |
1147 |
- Returns: |
1148 |
- The return code - 0 on success, negative number (< 0) on error. |
1149 |
-*/ |
1150 |
+/** |
1151 |
+ * Opens an entry by name in the zip archive. |
1152 |
+ * |
1153 |
+ * For zip archive opened in 'w' or 'a' mode the function will append |
1154 |
+ * a new entry. In readonly mode the function tries to locate the entry |
1155 |
+ * in global dictionary. |
1156 |
+ * |
1157 |
+ * @param zip zip archive handler. |
1158 |
+ * @param entryname an entry name in local dictionary. |
1159 |
+ * |
1160 |
+ * @return the return code - 0 on success, negative number (< 0) on error. |
1161 |
+ */ |
1162 |
extern int zip_entry_open(struct zip_t *zip, const char *entryname); |
1163 |
|
1164 |
-/* |
1165 |
- Opens a new entry by index in the zip archive. |
1166 |
- This function is only valid if zip archive was opened in 'r' (readonly) mode. |
1167 |
- |
1168 |
- Args: |
1169 |
- zip: zip archive handler. |
1170 |
- index: index in local dictionary. |
1171 |
- |
1172 |
- Returns: |
1173 |
- The return code - 0 on success, negative number (< 0) on error. |
1174 |
-*/ |
1175 |
+/** |
1176 |
+ * Opens a new entry by index in the zip archive. |
1177 |
+ * |
1178 |
+ * This function is only valid if zip archive was opened in 'r' (readonly) mode. |
1179 |
+ * |
1180 |
+ * @param zip zip archive handler. |
1181 |
+ * @param index index in local dictionary. |
1182 |
+ * |
1183 |
+ * @return the return code - 0 on success, negative number (< 0) on error. |
1184 |
+ */ |
1185 |
extern int zip_entry_openbyindex(struct zip_t *zip, int index); |
1186 |
|
1187 |
-/* |
1188 |
- Closes a zip entry, flushes buffer and releases resources. |
1189 |
- |
1190 |
- Args: |
1191 |
- zip: zip archive handler. |
1192 |
- |
1193 |
- Returns: |
1194 |
- The return code - 0 on success, negative number (< 0) on error. |
1195 |
-*/ |
1196 |
+/** |
1197 |
+ * Closes a zip entry, flushes buffer and releases resources. |
1198 |
+ * |
1199 |
+ * @param zip zip archive handler. |
1200 |
+ * |
1201 |
+ * @return the return code - 0 on success, negative number (< 0) on error. |
1202 |
+ */ |
1203 |
extern int zip_entry_close(struct zip_t *zip); |
1204 |
|
1205 |
-/* |
1206 |
- Returns a local name of the current zip entry. |
1207 |
- The main difference between user's entry name and local entry name |
1208 |
- is optional relative path. |
1209 |
- Following .ZIP File Format Specification - the path stored MUST not contain |
1210 |
- a drive or device letter, or a leading slash. |
1211 |
- All slashes MUST be forward slashes '/' as opposed to backwards slashes '\' |
1212 |
- for compatibility with Amiga and UNIX file systems etc. |
1213 |
- |
1214 |
- Args: |
1215 |
- zip: zip archive handler. |
1216 |
- |
1217 |
- Returns: |
1218 |
- The pointer to the current zip entry name, or NULL on error. |
1219 |
-*/ |
1220 |
+/** |
1221 |
+ * Returns a local name of the current zip entry. |
1222 |
+ * |
1223 |
+ * The main difference between user's entry name and local entry name |
1224 |
+ * is optional relative path. |
1225 |
+ * Following .ZIP File Format Specification - the path stored MUST not contain |
1226 |
+ * a drive or device letter, or a leading slash. |
1227 |
+ * All slashes MUST be forward slashes '/' as opposed to backwards slashes '\' |
1228 |
+ * for compatibility with Amiga and UNIX file systems etc. |
1229 |
+ * |
1230 |
+ * @param zip: zip archive handler. |
1231 |
+ * |
1232 |
+ * @return the pointer to the current zip entry name, or NULL on error. |
1233 |
+ */ |
1234 |
extern const char *zip_entry_name(struct zip_t *zip); |
1235 |
|
1236 |
-/* |
1237 |
- Returns an index of the current zip entry. |
1238 |
- |
1239 |
- Args: |
1240 |
- zip: zip archive handler. |
1241 |
- |
1242 |
- Returns: |
1243 |
- The index on success, negative number (< 0) on error. |
1244 |
-*/ |
1245 |
+/** |
1246 |
+ * Returns an index of the current zip entry. |
1247 |
+ * |
1248 |
+ * @param zip zip archive handler. |
1249 |
+ * |
1250 |
+ * @return the index on success, negative number (< 0) on error. |
1251 |
+ */ |
1252 |
extern int zip_entry_index(struct zip_t *zip); |
1253 |
|
1254 |
-/* |
1255 |
- Determines if the current zip entry is a directory entry. |
1256 |
- |
1257 |
- Args: |
1258 |
- zip: zip archive handler. |
1259 |
- |
1260 |
- Returns: |
1261 |
- The return code - 1 (true), 0 (false), negative number (< 0) on error. |
1262 |
-*/ |
1263 |
+/** |
1264 |
+ * Determines if the current zip entry is a directory entry. |
1265 |
+ * |
1266 |
+ * @param zip zip archive handler. |
1267 |
+ * |
1268 |
+ * @return the return code - 1 (true), 0 (false), negative number (< 0) on |
1269 |
+ * error. |
1270 |
+ */ |
1271 |
extern int zip_entry_isdir(struct zip_t *zip); |
1272 |
|
1273 |
-/* |
1274 |
- Returns an uncompressed size of the current zip entry. |
1275 |
- |
1276 |
- Args: |
1277 |
- zip: zip archive handler. |
1278 |
- |
1279 |
- Returns: |
1280 |
- The uncompressed size in bytes. |
1281 |
-*/ |
1282 |
+/** |
1283 |
+ * Returns an uncompressed size of the current zip entry. |
1284 |
+ * |
1285 |
+ * @param zip zip archive handler. |
1286 |
+ * |
1287 |
+ * @return the uncompressed size in bytes. |
1288 |
+ */ |
1289 |
extern unsigned long long zip_entry_size(struct zip_t *zip); |
1290 |
|
1291 |
-/* |
1292 |
- Returns CRC-32 checksum of the current zip entry. |
1293 |
- |
1294 |
- Args: |
1295 |
- zip: zip archive handler. |
1296 |
- |
1297 |
- Returns: |
1298 |
- The CRC-32 checksum. |
1299 |
-*/ |
1300 |
+/** |
1301 |
+ * Returns CRC-32 checksum of the current zip entry. |
1302 |
+ * |
1303 |
+ * @param zip zip archive handler. |
1304 |
+ * |
1305 |
+ * @return the CRC-32 checksum. |
1306 |
+ */ |
1307 |
extern unsigned int zip_entry_crc32(struct zip_t *zip); |
1308 |
|
1309 |
-/* |
1310 |
- Compresses an input buffer for the current zip entry. |
1311 |
- |
1312 |
- Args: |
1313 |
- zip: zip archive handler. |
1314 |
- buf: input buffer. |
1315 |
- bufsize: input buffer size (in bytes). |
1316 |
- |
1317 |
- Returns: |
1318 |
- The return code - 0 on success, negative number (< 0) on error. |
1319 |
-*/ |
1320 |
+/** |
1321 |
+ * Compresses an input buffer for the current zip entry. |
1322 |
+ * |
1323 |
+ * @param zip zip archive handler. |
1324 |
+ * @param buf input buffer. |
1325 |
+ * @param bufsize input buffer size (in bytes). |
1326 |
+ * |
1327 |
+ * @return the return code - 0 on success, negative number (< 0) on error. |
1328 |
+ */ |
1329 |
extern int zip_entry_write(struct zip_t *zip, const void *buf, size_t bufsize); |
1330 |
|
1331 |
-/* |
1332 |
- Compresses a file for the current zip entry. |
1333 |
- |
1334 |
- Args: |
1335 |
- zip: zip archive handler. |
1336 |
- filename: input file. |
1337 |
- |
1338 |
- Returns: |
1339 |
- The return code - 0 on success, negative number (< 0) on error. |
1340 |
-*/ |
1341 |
+/** |
1342 |
+ * Compresses a file for the current zip entry. |
1343 |
+ * |
1344 |
+ * @param zip zip archive handler. |
1345 |
+ * @param filename input file. |
1346 |
+ * |
1347 |
+ * @return the return code - 0 on success, negative number (< 0) on error. |
1348 |
+ */ |
1349 |
extern int zip_entry_fwrite(struct zip_t *zip, const char *filename); |
1350 |
|
1351 |
-/* |
1352 |
- Extracts the current zip entry into output buffer. |
1353 |
- The function allocates sufficient memory for a output buffer. |
1354 |
- |
1355 |
- Args: |
1356 |
- zip: zip archive handler. |
1357 |
- buf: output buffer. |
1358 |
- bufsize: output buffer size (in bytes). |
1359 |
- |
1360 |
- Note: |
1361 |
- - remember to release memory allocated for a output buffer. |
1362 |
- - for large entries, please take a look at zip_entry_extract function. |
1363 |
- |
1364 |
- Returns: |
1365 |
- The return code - the number of bytes actually read on success. |
1366 |
- Otherwise a -1 on error. |
1367 |
-*/ |
1368 |
+/** |
1369 |
+ * Extracts the current zip entry into output buffer. |
1370 |
+ * |
1371 |
+ * The function allocates sufficient memory for a output buffer. |
1372 |
+ * |
1373 |
+ * @param zip zip archive handler. |
1374 |
+ * @param buf output buffer. |
1375 |
+ * @param bufsize output buffer size (in bytes). |
1376 |
+ * |
1377 |
+ * @note remember to release memory allocated for a output buffer. |
1378 |
+ * for large entries, please take a look at zip_entry_extract function. |
1379 |
+ * |
1380 |
+ * @return the return code - the number of bytes actually read on success. |
1381 |
+ * Otherwise a -1 on error. |
1382 |
+ */ |
1383 |
extern ssize_t zip_entry_read(struct zip_t *zip, void **buf, size_t *bufsize); |
1384 |
|
1385 |
-/* |
1386 |
- Extracts the current zip entry into a memory buffer using no memory |
1387 |
- allocation. |
1388 |
+/** |
1389 |
+ * Extracts the current zip entry into a memory buffer using no memory |
1390 |
+ * allocation. |
1391 |
+ * |
1392 |
+ * @param zip zip archive handler. |
1393 |
+ * @param buf preallocated output buffer. |
1394 |
+ * @param bufsize output buffer size (in bytes). |
1395 |
+ * |
1396 |
+ * @note ensure supplied output buffer is large enough. |
1397 |
+ * zip_entry_size function (returns uncompressed size for the current |
1398 |
+ * entry) can be handy to estimate how big buffer is needed. for large |
1399 |
+ * entries, please take a look at zip_entry_extract function. |
1400 |
+ * |
1401 |
+ * @return the return code - the number of bytes actually read on success. |
1402 |
+ * Otherwise a -1 on error (e.g. bufsize is not large enough). |
1403 |
+ */ |
1404 |
+extern ssize_t zip_entry_noallocread(struct zip_t *zip, void *buf, |
1405 |
+ size_t bufsize); |
1406 |
|
1407 |
- Args: |
1408 |
- zip: zip archive handler. |
1409 |
- buf: preallocated output buffer. |
1410 |
- bufsize: output buffer size (in bytes). |
1411 |
- |
1412 |
- Note: |
1413 |
- - ensure supplied output buffer is large enough. |
1414 |
- - zip_entry_size function (returns uncompressed size for the current entry) |
1415 |
- can be handy to estimate how big buffer is needed. |
1416 |
- - for large entries, please take a look at zip_entry_extract function. |
1417 |
- |
1418 |
- Returns: |
1419 |
- The return code - the number of bytes actually read on success. |
1420 |
- Otherwise a -1 on error (e.g. bufsize is not large enough). |
1421 |
-*/ |
1422 |
-extern ssize_t zip_entry_noallocread(struct zip_t *zip, void *buf, size_t bufsize); |
1423 |
- |
1424 |
-/* |
1425 |
- Extracts the current zip entry into output file. |
1426 |
- |
1427 |
- Args: |
1428 |
- zip: zip archive handler. |
1429 |
- filename: output file. |
1430 |
- |
1431 |
- Returns: |
1432 |
- The return code - 0 on success, negative number (< 0) on error. |
1433 |
-*/ |
1434 |
+/** |
1435 |
+ * Extracts the current zip entry into output file. |
1436 |
+ * |
1437 |
+ * @param zip zip archive handler. |
1438 |
+ * @param filename output file. |
1439 |
+ * |
1440 |
+ * @return the return code - 0 on success, negative number (< 0) on error. |
1441 |
+ */ |
1442 |
extern int zip_entry_fread(struct zip_t *zip, const char *filename); |
1443 |
|
1444 |
-/* |
1445 |
- Extracts the current zip entry using a callback function (on_extract). |
1446 |
- |
1447 |
- Args: |
1448 |
- zip: zip archive handler. |
1449 |
- on_extract: callback function. |
1450 |
- arg: opaque pointer (optional argument, |
1451 |
- which you can pass to the on_extract callback) |
1452 |
- |
1453 |
- Returns: |
1454 |
- The return code - 0 on success, negative number (< 0) on error. |
1455 |
+/** |
1456 |
+ * Extracts the current zip entry using a callback function (on_extract). |
1457 |
+ * |
1458 |
+ * @param zip zip archive handler. |
1459 |
+ * @param on_extract callback function. |
1460 |
+ * @param arg opaque pointer (optional argument, which you can pass to the |
1461 |
+ * on_extract callback) |
1462 |
+ * |
1463 |
+ * @return the return code - 0 on success, negative number (< 0) on error. |
1464 |
*/ |
1465 |
extern int |
1466 |
zip_entry_extract(struct zip_t *zip, |
1467 |
@@ -262,52 +272,48 @@ |
1468 |
const void *data, size_t size), |
1469 |
void *arg); |
1470 |
|
1471 |
-/* |
1472 |
- Returns the number of all entries (files and directories) in the zip archive. |
1473 |
- |
1474 |
- Args: |
1475 |
- zip: zip archive handler. |
1476 |
- |
1477 |
- Returns: |
1478 |
- The return code - the number of entries on success, |
1479 |
- negative number (< 0) on error. |
1480 |
-*/ |
1481 |
+/** |
1482 |
+ * Returns the number of all entries (files and directories) in the zip archive. |
1483 |
+ * |
1484 |
+ * @param zip zip archive handler. |
1485 |
+ * |
1486 |
+ * @return the return code - the number of entries on success, negative number |
1487 |
+ * (< 0) on error. |
1488 |
+ */ |
1489 |
extern int zip_total_entries(struct zip_t *zip); |
1490 |
|
1491 |
-/* |
1492 |
- Creates a new archive and puts files into a single zip archive. |
1493 |
- |
1494 |
- Args: |
1495 |
- zipname: zip archive file. |
1496 |
- filenames: input files. |
1497 |
- len: number of input files. |
1498 |
- |
1499 |
- Returns: |
1500 |
- The return code - 0 on success, negative number (< 0) on error. |
1501 |
-*/ |
1502 |
+/** |
1503 |
+ * Creates a new archive and puts files into a single zip archive. |
1504 |
+ * |
1505 |
+ * @param zipname zip archive file. |
1506 |
+ * @param filenames input files. |
1507 |
+ * @param len: number of input files. |
1508 |
+ * |
1509 |
+ * @return the return code - 0 on success, negative number (< 0) on error. |
1510 |
+ */ |
1511 |
extern int zip_create(const char *zipname, const char *filenames[], size_t len); |
1512 |
|
1513 |
-/* |
1514 |
- Extracts a zip archive file into directory. |
1515 |
- |
1516 |
- If on_extract_entry is not NULL, the callback will be called after |
1517 |
- successfully extracted each zip entry. |
1518 |
- Returning a negative value from the callback will cause abort and return an |
1519 |
- error. The last argument (void *arg) is optional, which you can use to pass |
1520 |
- data to the on_extract_entry callback. |
1521 |
- |
1522 |
- Args: |
1523 |
- zipname: zip archive file. |
1524 |
- dir: output directory. |
1525 |
- on_extract_entry: on extract callback. |
1526 |
- arg: opaque pointer. |
1527 |
- |
1528 |
- Returns: |
1529 |
- The return code - 0 on success, negative number (< 0) on error. |
1530 |
-*/ |
1531 |
+/** |
1532 |
+ * Extracts a zip archive file into directory. |
1533 |
+ * |
1534 |
+ * If on_extract_entry is not NULL, the callback will be called after |
1535 |
+ * successfully extracted each zip entry. |
1536 |
+ * Returning a negative value from the callback will cause abort and return an |
1537 |
+ * error. The last argument (void *arg) is optional, which you can use to pass |
1538 |
+ * data to the on_extract_entry callback. |
1539 |
+ * |
1540 |
+ * @param zipname zip archive file. |
1541 |
+ * @param dir output directory. |
1542 |
+ * @param on_extract_entry on extract callback. |
1543 |
+ * @param arg opaque pointer. |
1544 |
+ * |
1545 |
+ * @return the return code - 0 on success, negative number (< 0) on error. |
1546 |
+ */ |
1547 |
extern int zip_extract(const char *zipname, const char *dir, |
1548 |
int (*on_extract_entry)(const char *filename, void *arg), |
1549 |
void *arg); |
1550 |
+ |
1551 |
+/** @} */ |
1552 |
|
1553 |
#ifdef __cplusplus |
1554 |
} |
1555 |
diff -u contrib/zip/test/CMakeLists.txt contrib/zip/test/CMakeLists.txt |
1556 |
--- contrib/zip/test/CMakeLists.txt |
1557 |
+++ contrib/zip/test/CMakeLists.txt |
1558 |
@@ -1,19 +1,11 @@ |
1559 |
cmake_minimum_required(VERSION 2.8) |
1560 |
|
1561 |
-if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang") |
1562 |
- if(ENABLE_COVERAGE) |
1563 |
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g ") |
1564 |
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0") |
1565 |
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs") |
1566 |
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftest-coverage") |
1567 |
- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage") |
1568 |
- endif() |
1569 |
-endif () |
1570 |
- |
1571 |
# test |
1572 |
-include_directories(../src) |
1573 |
-add_executable(test.exe test.c ../src/zip.c) |
1574 |
-add_executable(test_miniz.exe test_miniz.c) |
1575 |
+set(test_out test.out) |
1576 |
|
1577 |
-add_test(NAME test COMMAND test.exe) |
1578 |
-add_test(NAME test_miniz COMMAND test_miniz.exe) |
1579 |
+add_executable(${test_out} test.c) |
1580 |
+target_link_libraries(${test_out} zip) |
1581 |
+ |
1582 |
+add_test(NAME ${test_out} COMMAND ${test_out}) |
1583 |
+ |
1584 |
+set(test_out ${test_out} PARENT_SCOPE) |
1585 |
diff -u contrib/zip/test/test.c contrib/zip/test/test.c |
1586 |
--- contrib/zip/test/test.c |
1587 |
+++ contrib/zip/test/test.c |
1588 |
@@ -29,6 +29,8 @@ |
1589 |
#define XFILE "7.txt\0" |
1590 |
#define XMODE 0100777 |
1591 |
|
1592 |
+#define UNIXMODE 0100644 |
1593 |
+ |
1594 |
#define UNUSED(x) (void)x |
1595 |
|
1596 |
static int total_entries = 0; |
1597 |
@@ -45,7 +47,7 @@ |
1598 |
assert(CRC32DATA1 == zip_entry_crc32(zip)); |
1599 |
++total_entries; |
1600 |
assert(0 == zip_entry_close(zip)); |
1601 |
- |
1602 |
+ assert(0 == zip_is64(zip)); |
1603 |
zip_close(zip); |
1604 |
} |
1605 |
|
1606 |
@@ -90,6 +92,7 @@ |
1607 |
size_t buftmp; |
1608 |
struct zip_t *zip = zip_open(ZIPNAME, 0, 'r'); |
1609 |
assert(zip != NULL); |
1610 |
+ assert(0 == zip_is64(zip)); |
1611 |
|
1612 |
assert(0 == zip_entry_open(zip, "test\\test-1.txt")); |
1613 |
assert(strlen(TESTDATA1) == zip_entry_size(zip)); |
1614 |
@@ -102,7 +105,8 @@ |
1615 |
assert(0 == zip_entry_close(zip)); |
1616 |
free(buf); |
1617 |
buf = NULL; |
1618 |
- |
1619 |
+ bufsize = 0; |
1620 |
+ |
1621 |
assert(0 == zip_entry_open(zip, "test/test-2.txt")); |
1622 |
assert(strlen(TESTDATA2) == zip_entry_size(zip)); |
1623 |
assert(CRC32DATA2 == zip_entry_crc32(zip)); |
1624 |
@@ -131,7 +135,8 @@ |
1625 |
assert(0 == zip_entry_close(zip)); |
1626 |
free(buf); |
1627 |
buf = NULL; |
1628 |
- |
1629 |
+ bufsize = 0; |
1630 |
+ |
1631 |
buftmp = strlen(TESTDATA1); |
1632 |
buf = calloc(buftmp, sizeof(char)); |
1633 |
assert(0 == zip_entry_open(zip, "test/test-1.txt")); |
1634 |
@@ -306,6 +311,7 @@ |
1635 |
assert(0 == zip_entry_open(zip, WFILE)); |
1636 |
assert(0 == zip_entry_fwrite(zip, WFILE)); |
1637 |
assert(0 == zip_entry_close(zip)); |
1638 |
+ assert(0 == zip_is64(zip)); |
1639 |
|
1640 |
zip_close(zip); |
1641 |
remove(WFILE); |
1642 |
@@ -433,6 +439,35 @@ |
1643 |
remove(ZIPNAME); |
1644 |
} |
1645 |
|
1646 |
+static void test_unix_permissions(void) { |
1647 |
+#if defined(_WIN64) || defined(_WIN32) || defined(__WIN32__) |
1648 |
+#else |
1649 |
+ // UNIX or APPLE |
1650 |
+ struct MZ_FILE_STAT_STRUCT file_stats; |
1651 |
+ |
1652 |
+ remove(ZIPNAME); |
1653 |
+ |
1654 |
+ struct zip_t *zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w'); |
1655 |
+ assert(zip != NULL); |
1656 |
+ |
1657 |
+ assert(0 == zip_entry_open(zip, RFILE)); |
1658 |
+ assert(0 == zip_entry_write(zip, TESTDATA1, strlen(TESTDATA1))); |
1659 |
+ assert(0 == zip_entry_close(zip)); |
1660 |
+ |
1661 |
+ zip_close(zip); |
1662 |
+ |
1663 |
+ remove(RFILE); |
1664 |
+ |
1665 |
+ assert(0 == zip_extract(ZIPNAME, ".", NULL, NULL)); |
1666 |
+ |
1667 |
+ assert(0 == MZ_FILE_STAT(RFILE, &file_stats)); |
1668 |
+ assert(UNIXMODE == file_stats.st_mode); |
1669 |
+ |
1670 |
+ remove(RFILE); |
1671 |
+ remove(ZIPNAME); |
1672 |
+#endif |
1673 |
+} |
1674 |
+ |
1675 |
int main(int argc, char *argv[]) { |
1676 |
UNUSED(argc); |
1677 |
UNUSED(argv); |
1678 |
@@ -453,6 +488,7 @@ |
1679 |
test_write_permissions(); |
1680 |
test_exe_permissions(); |
1681 |
test_mtime(); |
1682 |
+ test_unix_permissions(); |
1683 |
|
1684 |
remove(ZIPNAME); |
1685 |
return 0; |
1686 |
unchanged: |
1687 |
--- contrib/zip/test/test_miniz.c |
1688 |
+++ contrib/zip/test/test_miniz.c |
1689 |
@@ -23,16 +23,39 @@ int main(int argc, char *argv[]) { |
1690 |
uint step = 0; |
1691 |
int cmp_status; |
1692 |
uLong src_len = (uLong)strlen(s_pStr); |
1693 |
- uLong cmp_len = compressBound(src_len); |
1694 |
uLong uncomp_len = src_len; |
1695 |
+ uLong cmp_len; |
1696 |
uint8 *pCmp, *pUncomp; |
1697 |
+ size_t sz; |
1698 |
uint total_succeeded = 0; |
1699 |
(void)argc, (void)argv; |
1700 |
|
1701 |
printf("miniz.c version: %s\n", MZ_VERSION); |
1702 |
|
1703 |
do { |
1704 |
+ pCmp = (uint8 *)tdefl_compress_mem_to_heap(s_pStr, src_len, &cmp_len, 0); |
1705 |
+ if (!pCmp) { |
1706 |
+ printf("tdefl_compress_mem_to_heap failed\n"); |
1707 |
+ return EXIT_FAILURE; |
1708 |
+ } |
1709 |
+ if (src_len <= cmp_len) { |
1710 |
+ printf("tdefl_compress_mem_to_heap failed: from %u to %u bytes\n", |
1711 |
+ (mz_uint32)uncomp_len, (mz_uint32)cmp_len); |
1712 |
+ free(pCmp); |
1713 |
+ return EXIT_FAILURE; |
1714 |
+ } |
1715 |
+ |
1716 |
+ sz = tdefl_compress_mem_to_mem(pCmp, cmp_len, s_pStr, src_len, 0); |
1717 |
+ if (sz != cmp_len) { |
1718 |
+ printf("tdefl_compress_mem_to_mem failed: expected %u, got %u\n", |
1719 |
+ (mz_uint32)cmp_len, (mz_uint32)sz); |
1720 |
+ free(pCmp); |
1721 |
+ return EXIT_FAILURE; |
1722 |
+ } |
1723 |
+ |
1724 |
// Allocate buffers to hold compressed and uncompressed data. |
1725 |
+ free(pCmp); |
1726 |
+ cmp_len = compressBound(src_len); |
1727 |
pCmp = (mz_uint8 *)malloc((size_t)cmp_len); |
1728 |
pUncomp = (mz_uint8 *)malloc((size_t)src_len); |
1729 |
if ((!pCmp) || (!pUncomp)) { |