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