View | Details | Raw Unified | Return to bug 259483
Collapse All | Expand All

(-)b/multimedia/assimp/Makefile (-3 / +1 lines)
Lines 1-6 Link Here
1
PORTNAME=	assimp
1
PORTNAME=	assimp
2
DISTVERSIONPREFIX=	v
2
DISTVERSIONPREFIX=	v
3
DISTVERSION=	5.0.1
3
DISTVERSION=	5.0.1
4
PORTREVISION=	1
4
CATEGORIES=	multimedia
5
CATEGORIES=	multimedia
5
6
6
MAINTAINER=	yuri@FreeBSD.org
7
MAINTAINER=	yuri@FreeBSD.org
Lines 9-17 COMMENT= Library to import various 3D model formats in a uniform manner Link Here
9
LICENSE=	BSD3CLAUSE
10
LICENSE=	BSD3CLAUSE
10
LICENSE_FILE=	${WRKSRC}/LICENSE
11
LICENSE_FILE=	${WRKSRC}/LICENSE
11
12
12
BROKEN_i386=	typedef redefinition with different types, see https://github.com/assimp/assimp/issues/2954
13
BROKEN_powerpc=	typedef redefinition with different types, see https://github.com/assimp/assimp/issues/2954
14
15
LIB_DEPENDS=	libminizip.so:archivers/minizip
13
LIB_DEPENDS=	libminizip.so:archivers/minizip
16
14
17
USES=		cmake compiler:c++11-lib localbase:ldflags pkgconfig
15
USES=		cmake compiler:c++11-lib localbase:ldflags pkgconfig
(-)b/multimedia/assimp/files/patch-contrib-zip (-1 / +1729 lines)
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)) {

Return to bug 259483