From mboxrd@z Thu Jan 1 00:00:00 1970 From: Peter Seiderer Date: Tue, 29 Dec 2020 21:54:43 +0100 Subject: [Buildroot] [PATCH 3/3] package/assimp: fix build on musl In-Reply-To: <20201228120102.3055620-3-fontaine.fabrice@gmail.com> References: <20201228120102.3055620-1-fontaine.fabrice@gmail.com> <20201228120102.3055620-3-fontaine.fabrice@gmail.com> Message-ID: <20201229215443.637e0715@gmx.net> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: buildroot@busybox.net Hello Fabrice, Yann, On Mon, 28 Dec 2020 13:01:02 +0100, Fabrice Fontaine wrote: > Fixes: > - http://autobuild.buildroot.net/results/7c2db184ee200d1719308f38f42382bb39d8d5c6 > > Signed-off-by: Fabrice Fontaine > --- > ...p-to-fix-gcc-build-for-v9-2-0-32-bit.patch | 1638 +++++++++++++++++ > ...oses-2954-upgrade-to-latest-greatest.patch | 243 +++ > 2 files changed, 1881 insertions(+) > create mode 100644 package/assimp/0002-closes-2733-update-of-zlip-to-fix-gcc-build-for-v9-2-0-32-bit.patch Note that this patch is enough to re-fix the musl compile (as it is the complete one from which the small patch was extracted which you removed/reverted with '[PATCH 1/3] Revert "package/assimp: fix musl zlib/zip related compile failure"' Regards, Peter > create mode 100644 package/assimp/0003-closes-2954-upgrade-to-latest-greatest.patch > > diff --git a/package/assimp/0002-closes-2733-update-of-zlip-to-fix-gcc-build-for-v9-2-0-32-bit.patch b/package/assimp/0002-closes-2733-update-of-zlip-to-fix-gcc-build-for-v9-2-0-32-bit.patch > new file mode 100644 > index 0000000000..4b86cc584f > --- /dev/null > +++ b/package/assimp/0002-closes-2733-update-of-zlip-to-fix-gcc-build-for-v9-2-0-32-bit.patch > @@ -0,0 +1,1638 @@ > +From f78446b14aff46db2ef27d062a275b6a01fd68b1 Mon Sep 17 00:00:00 2001 > +From: Kim Kulling > +Date: Tue, 19 Nov 2019 20:30:40 +0100 > +Subject: [PATCH] closes https://github.com/assimp/assimp/issues/2733: update > + of zlip to fix gcc build for v9.2.0 32 bit > + > +[Retrieved (and updated to remove .gitignore and appveyor.yml) from: > +https://github.com/assimp/assimp/commit/f78446b14aff46db2ef27d062a275b6a01fd68b1] > +Signed-off-by: Fabrice Fontaine > +--- > + contrib/zip/.gitignore | 2 + > + contrib/zip/CMakeLists.txt | 83 +++++- > + contrib/zip/README.md | 12 +- > + contrib/zip/appveyor.yml | 2 +- > + contrib/zip/src/miniz.h | 457 ++++++++++++++++++++++++++++---- > + contrib/zip/src/zip.c | 62 +++-- > + contrib/zip/src/zip.h | 457 ++++++++++++++++---------------- > + contrib/zip/test/CMakeLists.txt | 27 +- > + contrib/zip/test/test.c | 38 ++- > + contrib/zip/test/test_miniz.c | 25 +- > + 10 files changed, 821 insertions(+), 344 deletions(-) > + > +diff --git a/contrib/zip/CMakeLists.txt b/contrib/zip/CMakeLists.txt > +index b46dbb1db0..77916d2e14 100644 > +--- a/contrib/zip/CMakeLists.txt > ++++ b/contrib/zip/CMakeLists.txt > +@@ -1,10 +1,14 @@ > +-cmake_minimum_required(VERSION 2.8) > +-project(zip) > +-enable_language(C) > ++cmake_minimum_required(VERSION 3.0) > ++ > ++project(zip > ++ LANGUAGES C > ++ VERSION "0.1.15") > + set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) > + > ++option(CMAKE_DISABLE_TESTING "Disable test creation" OFF) > ++ > + if (MSVC) > +- # Use secure functions by defaualt and suppress warnings about "deprecated" functions > ++ # Use secure functions by default and suppress warnings about "deprecated" functions > + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1") > + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1") > + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_NONSTDC_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1") > +@@ -12,28 +16,80 @@ elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR > + "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR > + "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang") > + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wall -Wextra -Werror -pedantic") > ++ if(ENABLE_COVERAGE) > ++ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage") > ++ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage") > ++ endif() > + endif (MSVC) > + > + # zip > + set(SRC src/miniz.h src/zip.h src/zip.c) > + add_library(${PROJECT_NAME} ${SRC}) > +-target_include_directories(${PROJECT_NAME} INTERFACE src) > ++target_include_directories(${PROJECT_NAME} PUBLIC > ++ $ > ++ $ > ++) > + > + # test > + if (NOT CMAKE_DISABLE_TESTING) > + enable_testing() > + add_subdirectory(test) > + find_package(Sanitizers) > +- add_sanitizers(${PROJECT_NAME} test.exe) > +- add_sanitizers(${PROJECT_NAME} test_miniz.exe) > ++ add_sanitizers(${PROJECT_NAME} ${test_out} ${test_miniz_out}) > + endif() > + > ++#### > ++# Installation (https://github.com/forexample/package-example) { > ++ > ++set(CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}") > ++set(INCLUDE_INSTALL_DIR "include") > ++ > ++set(GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") > ++ > ++# Configuration > ++set(VERSION_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake") > ++set(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}Config.cmake") > ++set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets") > ++set(NAMESPACE "${PROJECT_NAME}::") > ++ > ++# Include module with fuction 'write_basic_package_version_file' > ++include(CMakePackageConfigHelpers) > ++ > ++# Note: PROJECT_VERSION is used as a VERSION > ++write_basic_package_version_file( > ++ "${VERSION_CONFIG}" COMPATIBILITY SameMajorVersion > ++) > ++ > ++# Use variables: > ++# * TARGETS_EXPORT_NAME > ++# * PROJECT_NAME > ++configure_package_config_file( > ++ "cmake/Config.cmake.in" > ++ "${PROJECT_CONFIG}" > ++ INSTALL_DESTINATION "${CONFIG_INSTALL_DIR}" > ++) > ++ > ++install( > ++ FILES "${PROJECT_CONFIG}" "${VERSION_CONFIG}" > ++ DESTINATION "${CONFIG_INSTALL_DIR}" > ++) > ++ > ++install( > ++ EXPORT "${TARGETS_EXPORT_NAME}" > ++ NAMESPACE "${NAMESPACE}" > ++ DESTINATION "${CONFIG_INSTALL_DIR}" > ++) > ++ > ++# } > ++ > + install(TARGETS ${PROJECT_NAME} > ++ EXPORT ${TARGETS_EXPORT_NAME} > + RUNTIME DESTINATION bin > + ARCHIVE DESTINATION lib > + LIBRARY DESTINATION lib > +- COMPONENT library) > +-install(FILES ${PROJECT_SOURCE_DIR}/src/zip.h DESTINATION include) > ++ INCLUDES DESTINATION ${INCLUDE_INSTALL_DIR} > ++) > ++install(FILES ${PROJECT_SOURCE_DIR}/src/zip.h DESTINATION ${INCLUDE_INSTALL_DIR}/zip) > + > + # uninstall target (https://gitlab.kitware.com/cmake/community/wikis/FAQ#can-i-do-make-uninstall-with-cmake) > + if(NOT TARGET uninstall) > +@@ -45,3 +101,12 @@ if(NOT TARGET uninstall) > + add_custom_target(uninstall > + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake/cmake_uninstall.cmake) > + endif() > ++ > ++find_package(Doxygen) > ++if(DOXYGEN_FOUND) > ++ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) > ++ add_custom_target(doc > ++ ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile > ++ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} > ++ COMMENT "Generating API documentation with Doxygen" VERBATIM) > ++endif() > +diff --git a/contrib/zip/README.md b/contrib/zip/README.md > +index d5fb8cd203..14eb9a34c8 100644 > +--- a/contrib/zip/README.md > ++++ b/contrib/zip/README.md > +@@ -71,7 +71,7 @@ int arg = 2; > + zip_extract("foo.zip", "/tmp", on_extract_entry, &arg); > + ``` > + > +-* Extract a zip entry into memory. > ++* Extract a zip entry into memory. > + ```c > + void *buf = NULL; > + size_t bufsize; > +@@ -89,7 +89,7 @@ zip_close(zip); > + free(buf); > + ``` > + > +-* Extract a zip entry into memory (no internal allocation). > ++* Extract a zip entry into memory (no internal allocation). > + ```c > + unsigned char *buf; > + size_t bufsize; > +@@ -110,7 +110,7 @@ zip_close(zip); > + free(buf); > + ``` > + > +-* Extract a zip entry into memory using callback. > ++* Extract a zip entry into memory using callback. > + ```c > + struct buffer_t { > + char *data; > +@@ -144,7 +144,7 @@ free(buf.data); > + ``` > + > + > +-* Extract a zip entry into a file. > ++* Extract a zip entry into a file. > + ```c > + struct zip_t *zip = zip_open("foo.zip", 0, 'r'); > + { > +@@ -157,7 +157,7 @@ struct zip_t *zip = zip_open("foo.zip", 0, 'r'); > + zip_close(zip); > + ``` > + > +-* List of all zip entries > ++* List of all zip entries > + ```c > + struct zip_t *zip = zip_open("foo.zip", 0, 'r'); > + int i, n = zip_total_entries(zip); > +@@ -174,7 +174,7 @@ for (i = 0; i < n; ++i) { > + zip_close(zip); > + ``` > + > +-## Bindings > ++# Bindings > + Compile zip library as a dynamic library. > + ```shell > + $ mkdir build > +diff --git a/contrib/zip/src/miniz.h b/contrib/zip/src/miniz.h > +index 2c27a94d8d..c4fcfb83e6 100644 > +--- a/contrib/zip/src/miniz.h > ++++ b/contrib/zip/src/miniz.h > +@@ -221,6 +221,7 @@ > + #ifndef MINIZ_HEADER_INCLUDED > + #define MINIZ_HEADER_INCLUDED > + > ++#include > + #include > + > + // Defines to completely disable specific portions of miniz.c: > +@@ -284,7 +285,8 @@ > + /* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES only if not set */ > + #if !defined(MINIZ_USE_UNALIGNED_LOADS_AND_STORES) > + #if MINIZ_X86_OR_X64_CPU > +-/* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses. */ > ++/* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient > ++ * integer loads and stores from unaligned addresses. */ > + #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1 > + #define MINIZ_UNALIGNED_USE_MEMCPY > + #else > +@@ -354,6 +356,44 @@ enum { > + MZ_FIXED = 4 > + }; > + > ++/* miniz error codes. Be sure to update mz_zip_get_error_string() if you add or > ++ * modify this enum. */ > ++typedef enum { > ++ MZ_ZIP_NO_ERROR = 0, > ++ MZ_ZIP_UNDEFINED_ERROR, > ++ MZ_ZIP_TOO_MANY_FILES, > ++ MZ_ZIP_FILE_TOO_LARGE, > ++ MZ_ZIP_UNSUPPORTED_METHOD, > ++ MZ_ZIP_UNSUPPORTED_ENCRYPTION, > ++ MZ_ZIP_UNSUPPORTED_FEATURE, > ++ MZ_ZIP_FAILED_FINDING_CENTRAL_DIR, > ++ MZ_ZIP_NOT_AN_ARCHIVE, > ++ MZ_ZIP_INVALID_HEADER_OR_CORRUPTED, > ++ MZ_ZIP_UNSUPPORTED_MULTIDISK, > ++ MZ_ZIP_DECOMPRESSION_FAILED, > ++ MZ_ZIP_COMPRESSION_FAILED, > ++ MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE, > ++ MZ_ZIP_CRC_CHECK_FAILED, > ++ MZ_ZIP_UNSUPPORTED_CDIR_SIZE, > ++ MZ_ZIP_ALLOC_FAILED, > ++ MZ_ZIP_FILE_OPEN_FAILED, > ++ MZ_ZIP_FILE_CREATE_FAILED, > ++ MZ_ZIP_FILE_WRITE_FAILED, > ++ MZ_ZIP_FILE_READ_FAILED, > ++ MZ_ZIP_FILE_CLOSE_FAILED, > ++ MZ_ZIP_FILE_SEEK_FAILED, > ++ MZ_ZIP_FILE_STAT_FAILED, > ++ MZ_ZIP_INVALID_PARAMETER, > ++ MZ_ZIP_INVALID_FILENAME, > ++ MZ_ZIP_BUF_TOO_SMALL, > ++ MZ_ZIP_INTERNAL_ERROR, > ++ MZ_ZIP_FILE_NOT_FOUND, > ++ MZ_ZIP_ARCHIVE_TOO_LARGE, > ++ MZ_ZIP_VALIDATION_FAILED, > ++ MZ_ZIP_WRITE_CALLBACK_FAILED, > ++ MZ_ZIP_TOTAL_ERRORS > ++} mz_zip_error; > ++ > + // Method > + #define MZ_DEFLATED 8 > + > +@@ -696,6 +736,7 @@ typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs, > + void *pBuf, size_t n); > + typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs, > + const void *pBuf, size_t n); > ++typedef mz_bool (*mz_file_needs_keepalive)(void *pOpaque); > + > + struct mz_zip_internal_state_tag; > + typedef struct mz_zip_internal_state_tag mz_zip_internal_state; > +@@ -707,13 +748,27 @@ typedef enum { > + MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3 > + } mz_zip_mode; > + > +-typedef struct mz_zip_archive_tag { > ++typedef enum { > ++ MZ_ZIP_TYPE_INVALID = 0, > ++ MZ_ZIP_TYPE_USER, > ++ MZ_ZIP_TYPE_MEMORY, > ++ MZ_ZIP_TYPE_HEAP, > ++ MZ_ZIP_TYPE_FILE, > ++ MZ_ZIP_TYPE_CFILE, > ++ MZ_ZIP_TOTAL_TYPES > ++} mz_zip_type; > ++ > ++typedef struct { > + mz_uint64 m_archive_size; > + mz_uint64 m_central_directory_file_ofs; > +- mz_uint m_total_files; > ++ > ++ /* We only support up to UINT32_MAX files in zip64 mode. */ > ++ mz_uint32 m_total_files; > + mz_zip_mode m_zip_mode; > ++ mz_zip_type m_zip_type; > ++ mz_zip_error m_last_error; > + > +- mz_uint m_file_offset_alignment; > ++ mz_uint64 m_file_offset_alignment; > + > + mz_alloc_func m_pAlloc; > + mz_free_func m_pFree; > +@@ -722,6 +777,7 @@ typedef struct mz_zip_archive_tag { > + > + mz_file_read_func m_pRead; > + mz_file_write_func m_pWrite; > ++ mz_file_needs_keepalive m_pNeeds_keepalive; > + void *m_pIO_opaque; > + > + mz_zip_internal_state *m_pState; > +@@ -1263,6 +1319,9 @@ mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, > + int strategy); > + #endif // #ifndef MINIZ_NO_ZLIB_APIS > + > ++#define MZ_UINT16_MAX (0xFFFFU) > ++#define MZ_UINT32_MAX (0xFFFFFFFFU) > ++ > + #ifdef __cplusplus > + } > + #endif > +@@ -1311,6 +1370,11 @@ typedef unsigned char mz_validate_uint64[sizeof(mz_uint64) == 8 ? 1 : -1]; > + ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U)) > + #endif > + > ++#define MZ_READ_LE64(p) \ > ++ (((mz_uint64)MZ_READ_LE32(p)) | \ > ++ (((mz_uint64)MZ_READ_LE32((const mz_uint8 *)(p) + sizeof(mz_uint32))) \ > ++ << 32U)) > ++ > + #ifdef _MSC_VER > + #define MZ_FORCEINLINE __forceinline > + #elif defined(__GNUC__) > +@@ -4160,6 +4224,17 @@ enum { > + MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30, > + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46, > + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22, > ++ > ++ /* ZIP64 archive identifier and record sizes */ > ++ MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06064b50, > ++ MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG = 0x07064b50, > ++ MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE = 56, > ++ MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE = 20, > ++ MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID = 0x0001, > ++ MZ_ZIP_DATA_DESCRIPTOR_ID = 0x08074b50, > ++ MZ_ZIP_DATA_DESCRIPTER_SIZE64 = 24, > ++ MZ_ZIP_DATA_DESCRIPTER_SIZE32 = 16, > ++ > + // Central directory header record offsets > + MZ_ZIP_CDH_SIG_OFS = 0, > + MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4, > +@@ -4199,6 +4274,31 @@ enum { > + MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12, > + MZ_ZIP_ECDH_CDIR_OFS_OFS = 16, > + MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20, > ++ > ++ /* ZIP64 End of central directory locator offsets */ > ++ MZ_ZIP64_ECDL_SIG_OFS = 0, /* 4 bytes */ > ++ MZ_ZIP64_ECDL_NUM_DISK_CDIR_OFS = 4, /* 4 bytes */ > ++ MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS = 8, /* 8 bytes */ > ++ MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS = 16, /* 4 bytes */ > ++ > ++ /* ZIP64 End of central directory header offsets */ > ++ MZ_ZIP64_ECDH_SIG_OFS = 0, /* 4 bytes */ > ++ MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS = 4, /* 8 bytes */ > ++ MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS = 12, /* 2 bytes */ > ++ MZ_ZIP64_ECDH_VERSION_NEEDED_OFS = 14, /* 2 bytes */ > ++ MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS = 16, /* 4 bytes */ > ++ MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS = 20, /* 4 bytes */ > ++ MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 24, /* 8 bytes */ > ++ MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS = 32, /* 8 bytes */ > ++ MZ_ZIP64_ECDH_CDIR_SIZE_OFS = 40, /* 8 bytes */ > ++ MZ_ZIP64_ECDH_CDIR_OFS_OFS = 48, /* 8 bytes */ > ++ MZ_ZIP_VERSION_MADE_BY_DOS_FILESYSTEM_ID = 0, > ++ MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG = 0x10, > ++ MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED = 1, > ++ MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG = 32, > ++ MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION = 64, > ++ MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED = 8192, > ++ MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8 = 1 << 11 > + }; > + > + typedef struct { > +@@ -4211,7 +4311,24 @@ struct mz_zip_internal_state_tag { > + mz_zip_array m_central_dir; > + mz_zip_array m_central_dir_offsets; > + mz_zip_array m_sorted_central_dir_offsets; > ++ > ++ /* The flags passed in when the archive is initially opened. */ > ++ uint32_t m_init_flags; > ++ > ++ /* MZ_TRUE if the archive has a zip64 end of central directory headers, etc. > ++ */ > ++ mz_bool m_zip64; > ++ > ++ /* MZ_TRUE if we found zip64 extended info in the central directory (m_zip64 > ++ * will also be slammed to true too, even if we didn't find a zip64 end of > ++ * central dir header, etc.) */ > ++ mz_bool m_zip64_has_extended_info_fields; > ++ > ++ /* These fields are used by the file, FILE, memory, and memory/heap read/write > ++ * helpers. */ > + MZ_FILE *m_pFile; > ++ mz_uint64 m_file_archive_start_ofs; > ++ > + void *m_pMem; > + size_t m_mem_size; > + size_t m_mem_capacity; > +@@ -4363,6 +4480,13 @@ static mz_bool mz_zip_set_file_times(const char *pFilename, time_t access_time, > + #endif /* #ifndef MINIZ_NO_STDIO */ > + #endif /* #ifndef MINIZ_NO_TIME */ > + > ++static MZ_FORCEINLINE mz_bool mz_zip_set_error(mz_zip_archive *pZip, > ++ mz_zip_error err_num) { > ++ if (pZip) > ++ pZip->m_last_error = err_num; > ++ return MZ_FALSE; > ++} > ++ > + static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, > + mz_uint32 flags) { > + (void)flags; > +@@ -4480,127 +4604,346 @@ mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip) { > + } > + } > + > +-static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, > +- mz_uint32 flags) { > +- mz_uint cdir_size, num_this_disk, cdir_disk_index; > +- mz_uint64 cdir_ofs; > ++static mz_bool mz_zip_reader_locate_header_sig(mz_zip_archive *pZip, > ++ mz_uint32 record_sig, > ++ mz_uint32 record_size, > ++ mz_int64 *pOfs) { > + mz_int64 cur_file_ofs; > +- const mz_uint8 *p; > + mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; > + mz_uint8 *pBuf = (mz_uint8 *)buf_u32; > +- mz_bool sort_central_dir = > +- ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0); > +- // Basic sanity checks - reject files which are too small, and check the first > +- // 4 bytes of the file to make sure a local header is there. > +- if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > ++ > ++ /* Basic sanity checks - reject files which are too small */ > ++ if (pZip->m_archive_size < record_size) > + return MZ_FALSE; > +- // Find the end of central directory record by scanning the file from the end > +- // towards the beginning. > ++ > ++ /* Find the record by scanning the file from the end towards the beginning. */ > + cur_file_ofs = > + MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0); > + for (;;) { > + int i, > + n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs); > ++ > + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n) > + return MZ_FALSE; > +- for (i = n - 4; i >= 0; --i) > +- if (MZ_READ_LE32(pBuf + i) == MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) > +- break; > ++ > ++ for (i = n - 4; i >= 0; --i) { > ++ mz_uint s = MZ_READ_LE32(pBuf + i); > ++ if (s == record_sig) { > ++ if ((pZip->m_archive_size - (cur_file_ofs + i)) >= record_size) > ++ break; > ++ } > ++ } > ++ > + if (i >= 0) { > + cur_file_ofs += i; > + break; > + } > ++ > ++ /* Give up if we've searched the entire file, or we've gone back "too far" > ++ * (~64kb) */ > + if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= > +- (0xFFFF + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE))) > ++ (MZ_UINT16_MAX + record_size))) > + return MZ_FALSE; > ++ > + cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0); > + } > +- // Read and verify the end of central directory record. > ++ > ++ *pOfs = cur_file_ofs; > ++ return MZ_TRUE; > ++} > ++ > ++static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, > ++ mz_uint flags) { > ++ mz_uint cdir_size = 0, cdir_entries_on_this_disk = 0, num_this_disk = 0, > ++ cdir_disk_index = 0; > ++ mz_uint64 cdir_ofs = 0; > ++ mz_int64 cur_file_ofs = 0; > ++ const mz_uint8 *p; > ++ > ++ mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; > ++ mz_uint8 *pBuf = (mz_uint8 *)buf_u32; > ++ mz_bool sort_central_dir = > ++ ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0); > ++ mz_uint32 zip64_end_of_central_dir_locator_u32 > ++ [(MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + sizeof(mz_uint32) - 1) / > ++ sizeof(mz_uint32)]; > ++ mz_uint8 *pZip64_locator = (mz_uint8 *)zip64_end_of_central_dir_locator_u32; > ++ > ++ mz_uint32 zip64_end_of_central_dir_header_u32 > ++ [(MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / > ++ sizeof(mz_uint32)]; > ++ mz_uint8 *pZip64_end_of_central_dir = > ++ (mz_uint8 *)zip64_end_of_central_dir_header_u32; > ++ > ++ mz_uint64 zip64_end_of_central_dir_ofs = 0; > ++ > ++ /* Basic sanity checks - reject files which are too small, and check the first > ++ * 4 bytes of the file to make sure a local header is there. */ > ++ if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > ++ return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); > ++ > ++ if (!mz_zip_reader_locate_header_sig( > ++ pZip, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG, > ++ MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE, &cur_file_ofs)) > ++ return mz_zip_set_error(pZip, MZ_ZIP_FAILED_FINDING_CENTRAL_DIR); > ++ > ++ /* Read and verify the end of central directory record. */ > + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, > + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != > + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > +- return MZ_FALSE; > +- if ((MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != > +- MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) || > +- ((pZip->m_total_files = > +- MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS)) != > +- MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS))) > +- return MZ_FALSE; > ++ return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); > ++ > ++ if (MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != > ++ MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) > ++ return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); > ++ > ++ if (cur_file_ofs >= (MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + > ++ MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)) { > ++ if (pZip->m_pRead(pZip->m_pIO_opaque, > ++ cur_file_ofs - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE, > ++ pZip64_locator, > ++ MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) == > ++ MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) { > ++ if (MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_SIG_OFS) == > ++ MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG) { > ++ zip64_end_of_central_dir_ofs = MZ_READ_LE64( > ++ pZip64_locator + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS); > ++ if (zip64_end_of_central_dir_ofs > > ++ (pZip->m_archive_size - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)) > ++ return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); > ++ > ++ if (pZip->m_pRead(pZip->m_pIO_opaque, zip64_end_of_central_dir_ofs, > ++ pZip64_end_of_central_dir, > ++ MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) == > ++ MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) { > ++ if (MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIG_OFS) == > ++ MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG) { > ++ pZip->m_pState->m_zip64 = MZ_TRUE; > ++ } > ++ } > ++ } > ++ } > ++ } > + > ++ pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS); > ++ cdir_entries_on_this_disk = > ++ MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS); > + num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS); > + cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS); > ++ cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS); > ++ cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS); > ++ > ++ if (pZip->m_pState->m_zip64) { > ++ mz_uint32 zip64_total_num_of_disks = > ++ MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS); > ++ mz_uint64 zip64_cdir_total_entries = MZ_READ_LE64( > ++ pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS); > ++ mz_uint64 zip64_cdir_total_entries_on_this_disk = MZ_READ_LE64( > ++ pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS); > ++ mz_uint64 zip64_size_of_end_of_central_dir_record = MZ_READ_LE64( > ++ pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS); > ++ mz_uint64 zip64_size_of_central_directory = > ++ MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_SIZE_OFS); > ++ > ++ if (zip64_size_of_end_of_central_dir_record < > ++ (MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - 12)) > ++ return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); > ++ > ++ if (zip64_total_num_of_disks != 1U) > ++ return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK); > ++ > ++ /* Check for miniz's practical limits */ > ++ if (zip64_cdir_total_entries > MZ_UINT32_MAX) > ++ return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); > ++ > ++ pZip->m_total_files = (mz_uint32)zip64_cdir_total_entries; > ++ > ++ if (zip64_cdir_total_entries_on_this_disk > MZ_UINT32_MAX) > ++ return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); > ++ > ++ cdir_entries_on_this_disk = > ++ (mz_uint32)zip64_cdir_total_entries_on_this_disk; > ++ > ++ /* Check for miniz's current practical limits (sorry, this should be enough > ++ * for millions of files) */ > ++ if (zip64_size_of_central_directory > MZ_UINT32_MAX) > ++ return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE); > ++ > ++ cdir_size = (mz_uint32)zip64_size_of_central_directory; > ++ > ++ num_this_disk = MZ_READ_LE32(pZip64_end_of_central_dir + > ++ MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS); > ++ > ++ cdir_disk_index = MZ_READ_LE32(pZip64_end_of_central_dir + > ++ MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS); > ++ > ++ cdir_ofs = > ++ MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_OFS_OFS); > ++ } > ++ > ++ if (pZip->m_total_files != cdir_entries_on_this_disk) > ++ return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK); > ++ > + if (((num_this_disk | cdir_disk_index) != 0) && > + ((num_this_disk != 1) || (cdir_disk_index != 1))) > +- return MZ_FALSE; > ++ return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK); > + > +- if ((cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS)) < > +- pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) > +- return MZ_FALSE; > ++ if (cdir_size < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) > ++ return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); > + > +- cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS); > + if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size) > +- return MZ_FALSE; > ++ return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); > + > + pZip->m_central_directory_file_ofs = cdir_ofs; > + > + if (pZip->m_total_files) { > + mz_uint i, n; > +- > +- // Read the entire central directory into a heap block, and allocate another > +- // heap block to hold the unsorted central dir file record offsets, and > +- // another to hold the sorted indices. > ++ /* Read the entire central directory into a heap block, and allocate another > ++ * heap block to hold the unsorted central dir file record offsets, and > ++ * possibly another to hold the sorted indices. */ > + if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, > + MZ_FALSE)) || > + (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, > + pZip->m_total_files, MZ_FALSE))) > +- return MZ_FALSE; > ++ return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); > + > + if (sort_central_dir) { > + if (!mz_zip_array_resize(pZip, > + &pZip->m_pState->m_sorted_central_dir_offsets, > + pZip->m_total_files, MZ_FALSE)) > +- return MZ_FALSE; > ++ return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); > + } > + > + if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, > + pZip->m_pState->m_central_dir.m_p, > + cdir_size) != cdir_size) > +- return MZ_FALSE; > ++ return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); > + > +- // Now create an index into the central directory file records, do some > +- // basic sanity checking on each record, and check for zip64 entries (which > +- // are not yet supported). > ++ /* Now create an index into the central directory file records, do some > ++ * basic sanity checking on each record */ > + p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p; > + for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i) { > +- mz_uint total_header_size, comp_size, decomp_size, disk_index; > ++ mz_uint total_header_size, disk_index, bit_flags, filename_size, > ++ ext_data_size; > ++ mz_uint64 comp_size, decomp_size, local_header_ofs; > ++ > + if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || > + (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG)) > +- return MZ_FALSE; > ++ return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); > ++ > + MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, > + i) = > + (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p); > ++ > + if (sort_central_dir) > + MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, > + mz_uint32, i) = i; > ++ > + comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); > + decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); > +- if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && > +- (decomp_size != comp_size)) || > +- (decomp_size && !comp_size) || (decomp_size == 0xFFFFFFFF) || > +- (comp_size == 0xFFFFFFFF)) > +- return MZ_FALSE; > ++ local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS); > ++ filename_size = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); > ++ ext_data_size = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS); > ++ > ++ if ((!pZip->m_pState->m_zip64_has_extended_info_fields) && > ++ (ext_data_size) && > ++ (MZ_MAX(MZ_MAX(comp_size, decomp_size), local_header_ofs) == > ++ MZ_UINT32_MAX)) { > ++ /* Attempt to find zip64 extended information field in the entry's extra > ++ * data */ > ++ mz_uint32 extra_size_remaining = ext_data_size; > ++ > ++ if (extra_size_remaining) { > ++ const mz_uint8 *pExtra_data; > ++ void *buf = NULL; > ++ > ++ if (MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + ext_data_size > > ++ n) { > ++ buf = MZ_MALLOC(ext_data_size); > ++ if (buf == NULL) > ++ return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); > ++ > ++ if (pZip->m_pRead(pZip->m_pIO_opaque, > ++ cdir_ofs + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + > ++ filename_size, > ++ buf, ext_data_size) != ext_data_size) { > ++ MZ_FREE(buf); > ++ return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); > ++ } > ++ > ++ pExtra_data = (mz_uint8 *)buf; > ++ } else { > ++ pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size; > ++ } > ++ > ++ do { > ++ mz_uint32 field_id; > ++ mz_uint32 field_data_size; > ++ > ++ if (extra_size_remaining < (sizeof(mz_uint16) * 2)) { > ++ MZ_FREE(buf); > ++ return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); > ++ } > ++ > ++ field_id = MZ_READ_LE16(pExtra_data); > ++ field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16)); > ++ > ++ if ((field_data_size + sizeof(mz_uint16) * 2) > > ++ extra_size_remaining) { > ++ MZ_FREE(buf); > ++ return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); > ++ } > ++ > ++ if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) { > ++ /* Ok, the archive didn't have any zip64 headers but it uses a > ++ * zip64 extended information field so mark it as zip64 anyway > ++ * (this can occur with infozip's zip util when it reads > ++ * compresses files from stdin). */ > ++ pZip->m_pState->m_zip64 = MZ_TRUE; > ++ pZip->m_pState->m_zip64_has_extended_info_fields = MZ_TRUE; > ++ break; > ++ } > ++ > ++ pExtra_data += sizeof(mz_uint16) * 2 + field_data_size; > ++ extra_size_remaining = > ++ extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size; > ++ } while (extra_size_remaining); > ++ > ++ MZ_FREE(buf); > ++ } > ++ } > ++ > ++ /* I've seen archives that aren't marked as zip64 that uses zip64 ext > ++ * data, argh */ > ++ if ((comp_size != MZ_UINT32_MAX) && (decomp_size != MZ_UINT32_MAX)) { > ++ if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && > ++ (decomp_size != comp_size)) || > ++ (decomp_size && !comp_size)) > ++ return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); > ++ } > ++ > + disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS); > +- if ((disk_index != num_this_disk) && (disk_index != 1)) > +- return MZ_FALSE; > +- if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + > +- MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size) > +- return MZ_FALSE; > ++ if ((disk_index == MZ_UINT16_MAX) || > ++ ((disk_index != num_this_disk) && (disk_index != 1))) > ++ return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK); > ++ > ++ if (comp_size != MZ_UINT32_MAX) { > ++ if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + > ++ MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size) > ++ return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); > ++ } > ++ > ++ bit_flags = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); > ++ if (bit_flags & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED) > ++ return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION); > ++ > + if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + > + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + > + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + > + MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > > + n) > +- return MZ_FALSE; > ++ return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); > ++ > + n -= total_header_size; > + p += total_header_size; > + } > +diff --git a/contrib/zip/src/zip.c b/contrib/zip/src/zip.c > +index ff3a8fe1e6..1abcfd8fd1 100644 > +--- a/contrib/zip/src/zip.c > ++++ b/contrib/zip/src/zip.c > +@@ -24,7 +24,6 @@ > + ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) && \ > + (P)[1] == ':') > + #define FILESYSTEM_PREFIX_LEN(P) (HAS_DEVICE(P) ? 2 : 0) > +-#define ISSLASH(C) ((C) == '/' || (C) == '\\') > + > + #else > + > +@@ -48,7 +47,7 @@ int symlink(const char *target, const char *linkpath); // needed on Linux > + #endif > + > + #ifndef ISSLASH > +-#define ISSLASH(C) ((C) == '/') > ++#define ISSLASH(C) ((C) == '/' || (C) == '\\') > + #endif > + > + #define CLEANUP(ptr) \ > +@@ -78,26 +77,34 @@ static const char *base_name(const char *name) { > + return base; > + } > + > +-static int mkpath(const char *path) { > +- char const *p; > ++static int mkpath(char *path) { > ++ char *p; > + char npath[MAX_PATH + 1]; > + int len = 0; > + int has_device = HAS_DEVICE(path); > + > + memset(npath, 0, MAX_PATH + 1); > +- > +-#ifdef _WIN32 > +- // only on windows fix the path > +- npath[0] = path[0]; > +- npath[1] = path[1]; > +- len = 2; > +-#endif // _WIN32 > +- > ++ if (has_device) { > ++ // only on windows > ++ npath[0] = path[0]; > ++ npath[1] = path[1]; > ++ len = 2; > ++ } > + for (p = path + len; *p && len < MAX_PATH; p++) { > + if (ISSLASH(*p) && ((!has_device && len > 0) || (has_device && len > 2))) { > +- if (MKDIR(npath) == -1) > +- if (errno != EEXIST) > ++#if defined(_WIN32) || defined(__WIN32__) || defined(_MSC_VER) || \ > ++ defined(__MINGW32__) > ++#else > ++ if ('\\' == *p) { > ++ *p = '/'; > ++ } > ++#endif > ++ > ++ if (MKDIR(npath) == -1) { > ++ if (errno != EEXIST) { > + return -1; > ++ } > ++ } > + } > + npath[len++] = *p; > + } > +@@ -279,7 +286,14 @@ int zip_entry_open(struct zip_t *zip, const char *entryname) { > + zip->entry.header_offset = zip->archive.m_archive_size; > + memset(zip->entry.header, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE * sizeof(mz_uint8)); > + zip->entry.method = 0; > ++ > ++ // UNIX or APPLE > ++#if MZ_PLATFORM == 3 || MZ_PLATFORM == 19 > ++ // regular file with rw-r--r-- persmissions > ++ zip->entry.external_attr = (mz_uint32)(0100644) << 16; > ++#else > + zip->entry.external_attr = 0; > ++#endif > + > + num_alignment_padding_bytes = > + mz_zip_writer_compute_padding_needed_for_file_alignment(pzip); > +@@ -660,7 +674,7 @@ ssize_t zip_entry_noallocread(struct zip_t *zip, void *buf, size_t bufsize) { > + } > + > + if (!mz_zip_reader_extract_to_mem_no_alloc(pzip, (mz_uint)zip->entry.index, > +- buf, bufsize, 0, NULL, 0)) { > ++ buf, bufsize, 0, NULL, 0)) { > + return -1; > + } > + > +@@ -670,10 +684,7 @@ ssize_t zip_entry_noallocread(struct zip_t *zip, void *buf, size_t bufsize) { > + int zip_entry_fread(struct zip_t *zip, const char *filename) { > + mz_zip_archive *pzip = NULL; > + mz_uint idx; > +-#if defined(_MSC_VER) > +-#else > + mz_uint32 xattr = 0; > +-#endif > + mz_zip_archive_file_stat info; > + > + if (!zip) { > +@@ -875,12 +886,19 @@ int zip_extract(const char *zipname, const char *dir, > + goto out; > + } > + > +- 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) > +- && info.m_external_attr & (0x20 << 24)) { // and has sym link attribute (0x80 is file, 0x40 is directory) > ++ 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) > ++ && info.m_external_attr & > ++ (0x20 << 24)) { // and has sym link attribute (0x80 is file, 0x40 > ++ // is directory) > + #if defined(_WIN32) || defined(__WIN32__) || defined(_MSC_VER) || \ > + defined(__MINGW32__) > +-#else > +- 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)) { > ++#else > ++ 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)) { > + goto out; > + } > + symlink_to[info.m_uncomp_size] = '\0'; > +diff --git a/contrib/zip/src/zip.h b/contrib/zip/src/zip.h > +index 5f39df50ad..a48d64d6de 100644 > +--- a/contrib/zip/src/zip.h > ++++ b/contrib/zip/src/zip.h > +@@ -20,241 +20,240 @@ extern "C" { > + #endif > + > + #if !defined(_SSIZE_T_DEFINED) && !defined(_SSIZE_T_DEFINED_) && \ > +- !defined(_SSIZE_T) && !defined(_SSIZE_T_) && !defined(__ssize_t_defined) > +-#define _SSIZE_T > ++ !defined(__DEFINED_ssize_t) && !defined(__ssize_t_defined) && \ > ++ !defined(_SSIZE_T) && !defined(_SSIZE_T_) > ++ > + // 64-bit Windows is the only mainstream platform > + // where sizeof(long) != sizeof(void*) > + #ifdef _WIN64 > +-typedef long long ssize_t; /* byte count or error */ > ++typedef long long ssize_t; /* byte count or error */ > + #else > +-typedef long ssize_t; /* byte count or error */ > ++typedef long ssize_t; /* byte count or error */ > + #endif > ++ > ++#define _SSIZE_T_DEFINED > ++#define _SSIZE_T_DEFINED_ > ++#define __DEFINED_ssize_t > ++#define __ssize_t_defined > ++#define _SSIZE_T > ++#define _SSIZE_T_ > ++ > + #endif > + > + #ifndef MAX_PATH > + #define MAX_PATH 32767 /* # chars in a path name including NULL */ > + #endif > + > ++/** > ++ * @mainpage > ++ * > ++ * Documenation for @ref zip. > ++ */ > ++ > ++/** > ++ * @addtogroup zip > ++ * @{ > ++ */ > ++ > ++/** > ++ * Default zip compression level. > ++ */ > ++ > + #define ZIP_DEFAULT_COMPRESSION_LEVEL 6 > + > +-/* > +- This data structure is used throughout the library to represent zip archive > +- - forward declaration. > +-*/ > ++/** > ++ * @struct zip_t > ++ * > ++ * This data structure is used throughout the library to represent zip archive - > ++ * forward declaration. > ++ */ > + struct zip_t; > + > +-/* > +- Opens zip archive with compression level using the given mode. > +- > +- Args: > +- zipname: zip archive file name. > +- level: compression level (0-9 are the standard zlib-style levels). > +- mode: file access mode. > +- 'r': opens a file for reading/extracting (the file must exists). > +- 'w': creates an empty file for writing. > +- 'a': appends to an existing archive. > +- > +- Returns: > +- The zip archive handler or NULL on error > +-*/ > ++/** > ++ * Opens zip archive with compression level using the given mode. > ++ * > ++ * @param zipname zip archive file name. > ++ * @param level compression level (0-9 are the standard zlib-style levels). > ++ * @param mode file access mode. > ++ * - 'r': opens a file for reading/extracting (the file must exists). > ++ * - 'w': creates an empty file for writing. > ++ * - 'a': appends to an existing archive. > ++ * > ++ * @return the zip archive handler or NULL on error > ++ */ > + extern struct zip_t *zip_open(const char *zipname, int level, char mode); > + > +-/* > +- Closes the zip archive, releases resources - always finalize. > +- > +- Args: > +- zip: zip archive handler. > +-*/ > ++/** > ++ * Closes the zip archive, releases resources - always finalize. > ++ * > ++ * @param zip zip archive handler. > ++ */ > + extern void zip_close(struct zip_t *zip); > + > +-/* > +- Opens an entry by name in the zip archive. > +- For zip archive opened in 'w' or 'a' mode the function will append > +- a new entry. In readonly mode the function tries to locate the entry > +- in global dictionary. > +- > +- Args: > +- zip: zip archive handler. > +- entryname: an entry name in local dictionary. > +- > +- Returns: > +- The return code - 0 on success, negative number (< 0) on error. > +-*/ > ++/** > ++ * Opens an entry by name in the zip archive. > ++ * > ++ * For zip archive opened in 'w' or 'a' mode the function will append > ++ * a new entry. In readonly mode the function tries to locate the entry > ++ * in global dictionary. > ++ * > ++ * @param zip zip archive handler. > ++ * @param entryname an entry name in local dictionary. > ++ * > ++ * @return the return code - 0 on success, negative number (< 0) on error. > ++ */ > + extern int zip_entry_open(struct zip_t *zip, const char *entryname); > + > +-/* > +- Opens a new entry by index in the zip archive. > +- This function is only valid if zip archive was opened in 'r' (readonly) mode. > +- > +- Args: > +- zip: zip archive handler. > +- index: index in local dictionary. > +- > +- Returns: > +- The return code - 0 on success, negative number (< 0) on error. > +-*/ > ++/** > ++ * Opens a new entry by index in the zip archive. > ++ * > ++ * This function is only valid if zip archive was opened in 'r' (readonly) mode. > ++ * > ++ * @param zip zip archive handler. > ++ * @param index index in local dictionary. > ++ * > ++ * @return the return code - 0 on success, negative number (< 0) on error. > ++ */ > + extern int zip_entry_openbyindex(struct zip_t *zip, int index); > + > +-/* > +- Closes a zip entry, flushes buffer and releases resources. > +- > +- Args: > +- zip: zip archive handler. > +- > +- Returns: > +- The return code - 0 on success, negative number (< 0) on error. > +-*/ > ++/** > ++ * Closes a zip entry, flushes buffer and releases resources. > ++ * > ++ * @param zip zip archive handler. > ++ * > ++ * @return the return code - 0 on success, negative number (< 0) on error. > ++ */ > + extern int zip_entry_close(struct zip_t *zip); > + > +-/* > +- Returns a local name of the current zip entry. > +- The main difference between user's entry name and local entry name > +- is optional relative path. > +- Following .ZIP File Format Specification - the path stored MUST not contain > +- a drive or device letter, or a leading slash. > +- All slashes MUST be forward slashes '/' as opposed to backwards slashes '\' > +- for compatibility with Amiga and UNIX file systems etc. > +- > +- Args: > +- zip: zip archive handler. > +- > +- Returns: > +- The pointer to the current zip entry name, or NULL on error. > +-*/ > ++/** > ++ * Returns a local name of the current zip entry. > ++ * > ++ * The main difference between user's entry name and local entry name > ++ * is optional relative path. > ++ * Following .ZIP File Format Specification - the path stored MUST not contain > ++ * a drive or device letter, or a leading slash. > ++ * All slashes MUST be forward slashes '/' as opposed to backwards slashes '\' > ++ * for compatibility with Amiga and UNIX file systems etc. > ++ * > ++ * @param zip: zip archive handler. > ++ * > ++ * @return the pointer to the current zip entry name, or NULL on error. > ++ */ > + extern const char *zip_entry_name(struct zip_t *zip); > + > +-/* > +- Returns an index of the current zip entry. > +- > +- Args: > +- zip: zip archive handler. > +- > +- Returns: > +- The index on success, negative number (< 0) on error. > +-*/ > ++/** > ++ * Returns an index of the current zip entry. > ++ * > ++ * @param zip zip archive handler. > ++ * > ++ * @return the index on success, negative number (< 0) on error. > ++ */ > + extern int zip_entry_index(struct zip_t *zip); > + > +-/* > +- Determines if the current zip entry is a directory entry. > +- > +- Args: > +- zip: zip archive handler. > +- > +- Returns: > +- The return code - 1 (true), 0 (false), negative number (< 0) on error. > +-*/ > ++/** > ++ * Determines if the current zip entry is a directory entry. > ++ * > ++ * @param zip zip archive handler. > ++ * > ++ * @return the return code - 1 (true), 0 (false), negative number (< 0) on > ++ * error. > ++ */ > + extern int zip_entry_isdir(struct zip_t *zip); > + > +-/* > +- Returns an uncompressed size of the current zip entry. > +- > +- Args: > +- zip: zip archive handler. > +- > +- Returns: > +- The uncompressed size in bytes. > +-*/ > ++/** > ++ * Returns an uncompressed size of the current zip entry. > ++ * > ++ * @param zip zip archive handler. > ++ * > ++ * @return the uncompressed size in bytes. > ++ */ > + extern unsigned long long zip_entry_size(struct zip_t *zip); > + > +-/* > +- Returns CRC-32 checksum of the current zip entry. > +- > +- Args: > +- zip: zip archive handler. > +- > +- Returns: > +- The CRC-32 checksum. > +-*/ > ++/** > ++ * Returns CRC-32 checksum of the current zip entry. > ++ * > ++ * @param zip zip archive handler. > ++ * > ++ * @return the CRC-32 checksum. > ++ */ > + extern unsigned int zip_entry_crc32(struct zip_t *zip); > + > +-/* > +- Compresses an input buffer for the current zip entry. > +- > +- Args: > +- zip: zip archive handler. > +- buf: input buffer. > +- bufsize: input buffer size (in bytes). > +- > +- Returns: > +- The return code - 0 on success, negative number (< 0) on error. > +-*/ > ++/** > ++ * Compresses an input buffer for the current zip entry. > ++ * > ++ * @param zip zip archive handler. > ++ * @param buf input buffer. > ++ * @param bufsize input buffer size (in bytes). > ++ * > ++ * @return the return code - 0 on success, negative number (< 0) on error. > ++ */ > + extern int zip_entry_write(struct zip_t *zip, const void *buf, size_t bufsize); > + > +-/* > +- Compresses a file for the current zip entry. > +- > +- Args: > +- zip: zip archive handler. > +- filename: input file. > +- > +- Returns: > +- The return code - 0 on success, negative number (< 0) on error. > +-*/ > ++/** > ++ * Compresses a file for the current zip entry. > ++ * > ++ * @param zip zip archive handler. > ++ * @param filename input file. > ++ * > ++ * @return the return code - 0 on success, negative number (< 0) on error. > ++ */ > + extern int zip_entry_fwrite(struct zip_t *zip, const char *filename); > + > +-/* > +- Extracts the current zip entry into output buffer. > +- The function allocates sufficient memory for a output buffer. > +- > +- Args: > +- zip: zip archive handler. > +- buf: output buffer. > +- bufsize: output buffer size (in bytes). > +- > +- Note: > +- - remember to release memory allocated for a output buffer. > +- - for large entries, please take a look at zip_entry_extract function. > +- > +- Returns: > +- The return code - the number of bytes actually read on success. > +- Otherwise a -1 on error. > +-*/ > ++/** > ++ * Extracts the current zip entry into output buffer. > ++ * > ++ * The function allocates sufficient memory for a output buffer. > ++ * > ++ * @param zip zip archive handler. > ++ * @param buf output buffer. > ++ * @param bufsize output buffer size (in bytes). > ++ * > ++ * @note remember to release memory allocated for a output buffer. > ++ * for large entries, please take a look at zip_entry_extract function. > ++ * > ++ * @return the return code - the number of bytes actually read on success. > ++ * Otherwise a -1 on error. > ++ */ > + extern ssize_t zip_entry_read(struct zip_t *zip, void **buf, size_t *bufsize); > + > +-/* > +- Extracts the current zip entry into a memory buffer using no memory > +- allocation. > +- > +- Args: > +- zip: zip archive handler. > +- buf: preallocated output buffer. > +- bufsize: output buffer size (in bytes). > +- > +- Note: > +- - ensure supplied output buffer is large enough. > +- - zip_entry_size function (returns uncompressed size for the current entry) > +- can be handy to estimate how big buffer is needed. > +- - for large entries, please take a look at zip_entry_extract function. > +- > +- Returns: > +- The return code - the number of bytes actually read on success. > +- Otherwise a -1 on error (e.g. bufsize is not large enough). > +-*/ > +-extern ssize_t zip_entry_noallocread(struct zip_t *zip, void *buf, size_t bufsize); > +- > +-/* > +- Extracts the current zip entry into output file. > +- > +- Args: > +- zip: zip archive handler. > +- filename: output file. > +- > +- Returns: > +- The return code - 0 on success, negative number (< 0) on error. > +-*/ > ++/** > ++ * Extracts the current zip entry into a memory buffer using no memory > ++ * allocation. > ++ * > ++ * @param zip zip archive handler. > ++ * @param buf preallocated output buffer. > ++ * @param bufsize output buffer size (in bytes). > ++ * > ++ * @note ensure supplied output buffer is large enough. > ++ * zip_entry_size function (returns uncompressed size for the current > ++ * entry) can be handy to estimate how big buffer is needed. for large > ++ * entries, please take a look at zip_entry_extract function. > ++ * > ++ * @return the return code - the number of bytes actually read on success. > ++ * Otherwise a -1 on error (e.g. bufsize is not large enough). > ++ */ > ++extern ssize_t zip_entry_noallocread(struct zip_t *zip, void *buf, > ++ size_t bufsize); > ++ > ++/** > ++ * Extracts the current zip entry into output file. > ++ * > ++ * @param zip zip archive handler. > ++ * @param filename output file. > ++ * > ++ * @return the return code - 0 on success, negative number (< 0) on error. > ++ */ > + extern int zip_entry_fread(struct zip_t *zip, const char *filename); > + > +-/* > +- Extracts the current zip entry using a callback function (on_extract). > +- > +- Args: > +- zip: zip archive handler. > +- on_extract: callback function. > +- arg: opaque pointer (optional argument, > +- which you can pass to the on_extract callback) > +- > +- Returns: > +- The return code - 0 on success, negative number (< 0) on error. > ++/** > ++ * Extracts the current zip entry using a callback function (on_extract). > ++ * > ++ * @param zip zip archive handler. > ++ * @param on_extract callback function. > ++ * @param arg opaque pointer (optional argument, which you can pass to the > ++ * on_extract callback) > ++ * > ++ * @return the return code - 0 on success, negative number (< 0) on error. > + */ > + extern int > + zip_entry_extract(struct zip_t *zip, > +@@ -262,53 +261,49 @@ zip_entry_extract(struct zip_t *zip, > + const void *data, size_t size), > + void *arg); > + > +-/* > +- Returns the number of all entries (files and directories) in the zip archive. > +- > +- Args: > +- zip: zip archive handler. > +- > +- Returns: > +- The return code - the number of entries on success, > +- negative number (< 0) on error. > +-*/ > ++/** > ++ * Returns the number of all entries (files and directories) in the zip archive. > ++ * > ++ * @param zip zip archive handler. > ++ * > ++ * @return the return code - the number of entries on success, negative number > ++ * (< 0) on error. > ++ */ > + extern int zip_total_entries(struct zip_t *zip); > + > +-/* > +- Creates a new archive and puts files into a single zip archive. > +- > +- Args: > +- zipname: zip archive file. > +- filenames: input files. > +- len: number of input files. > +- > +- Returns: > +- The return code - 0 on success, negative number (< 0) on error. > +-*/ > ++/** > ++ * Creates a new archive and puts files into a single zip archive. > ++ * > ++ * @param zipname zip archive file. > ++ * @param filenames input files. > ++ * @param len: number of input files. > ++ * > ++ * @return the return code - 0 on success, negative number (< 0) on error. > ++ */ > + extern int zip_create(const char *zipname, const char *filenames[], size_t len); > + > +-/* > +- Extracts a zip archive file into directory. > +- > +- If on_extract_entry is not NULL, the callback will be called after > +- successfully extracted each zip entry. > +- Returning a negative value from the callback will cause abort and return an > +- error. The last argument (void *arg) is optional, which you can use to pass > +- data to the on_extract_entry callback. > +- > +- Args: > +- zipname: zip archive file. > +- dir: output directory. > +- on_extract_entry: on extract callback. > +- arg: opaque pointer. > +- > +- Returns: > +- The return code - 0 on success, negative number (< 0) on error. > +-*/ > ++/** > ++ * Extracts a zip archive file into directory. > ++ * > ++ * If on_extract_entry is not NULL, the callback will be called after > ++ * successfully extracted each zip entry. > ++ * Returning a negative value from the callback will cause abort and return an > ++ * error. The last argument (void *arg) is optional, which you can use to pass > ++ * data to the on_extract_entry callback. > ++ * > ++ * @param zipname zip archive file. > ++ * @param dir output directory. > ++ * @param on_extract_entry on extract callback. > ++ * @param arg opaque pointer. > ++ * > ++ * @return the return code - 0 on success, negative number (< 0) on error. > ++ */ > + extern int zip_extract(const char *zipname, const char *dir, > + int (*on_extract_entry)(const char *filename, void *arg), > + void *arg); > + > ++/** @} */ > ++ > + #ifdef __cplusplus > + } > + #endif > +diff --git a/contrib/zip/test/CMakeLists.txt b/contrib/zip/test/CMakeLists.txt > +index 9b2a8db106..cc060b00fe 100644 > +--- a/contrib/zip/test/CMakeLists.txt > ++++ b/contrib/zip/test/CMakeLists.txt > +@@ -1,19 +1,16 @@ > + cmake_minimum_required(VERSION 2.8) > + > +-if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang") > +- if(ENABLE_COVERAGE) > +- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g ") > +- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0") > +- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs") > +- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftest-coverage") > +- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage") > +- endif() > +-endif () > +- > + # test > +-include_directories(../src) > +-add_executable(test.exe test.c ../src/zip.c) > +-add_executable(test_miniz.exe test_miniz.c) > ++set(test_out test.out) > ++set(test_miniz_out test_miniz.out) > ++ > ++add_executable(${test_out} test.c) > ++target_link_libraries(${test_out} zip) > ++add_executable(${test_miniz_out} test_miniz.c) > ++target_link_libraries(${test_miniz_out} zip) > ++ > ++add_test(NAME ${test_out} COMMAND ${test_out}) > ++add_test(NAME ${test_miniz_out} COMMAND ${test_miniz_out}) > + > +-add_test(NAME test COMMAND test.exe) > +-add_test(NAME test_miniz COMMAND test_miniz.exe) > ++set(test_out ${test_out} PARENT_SCOPE) > ++set(test_miniz_out ${test_miniz_out} PARENT_SCOPE) > +diff --git a/contrib/zip/test/test.c b/contrib/zip/test/test.c > +index 454430533a..a9b2ddab1e 100644 > +--- a/contrib/zip/test/test.c > ++++ b/contrib/zip/test/test.c > +@@ -29,6 +29,8 @@ > + #define XFILE "7.txt\0" > + #define XMODE 0100777 > + > ++#define UNIXMODE 0100644 > ++ > + #define UNUSED(x) (void)x > + > + static int total_entries = 0; > +@@ -102,7 +104,8 @@ static void test_read(void) { > + assert(0 == zip_entry_close(zip)); > + free(buf); > + buf = NULL; > +- > ++ bufsize = 0; > ++ > + assert(0 == zip_entry_open(zip, "test/test-2.txt")); > + assert(strlen(TESTDATA2) == zip_entry_size(zip)); > + assert(CRC32DATA2 == zip_entry_crc32(zip)); > +@@ -131,7 +134,8 @@ static void test_read(void) { > + assert(0 == zip_entry_close(zip)); > + free(buf); > + buf = NULL; > +- > ++ bufsize = 0; > ++ > + buftmp = strlen(TESTDATA1); > + buf = calloc(buftmp, sizeof(char)); > + assert(0 == zip_entry_open(zip, "test/test-1.txt")); > +@@ -433,6 +437,35 @@ static void test_mtime(void) { > + remove(ZIPNAME); > + } > + > ++static void test_unix_permissions(void) { > ++#if defined(_WIN64) || defined(_WIN32) || defined(__WIN32__) > ++#else > ++ // UNIX or APPLE > ++ struct MZ_FILE_STAT_STRUCT file_stats; > ++ > ++ remove(ZIPNAME); > ++ > ++ struct zip_t *zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w'); > ++ assert(zip != NULL); > ++ > ++ assert(0 == zip_entry_open(zip, RFILE)); > ++ assert(0 == zip_entry_write(zip, TESTDATA1, strlen(TESTDATA1))); > ++ assert(0 == zip_entry_close(zip)); > ++ > ++ zip_close(zip); > ++ > ++ remove(RFILE); > ++ > ++ assert(0 == zip_extract(ZIPNAME, ".", NULL, NULL)); > ++ > ++ assert(0 == MZ_FILE_STAT(RFILE, &file_stats)); > ++ assert(UNIXMODE == file_stats.st_mode); > ++ > ++ remove(RFILE); > ++ remove(ZIPNAME); > ++#endif > ++} > ++ > + int main(int argc, char *argv[]) { > + UNUSED(argc); > + UNUSED(argv); > +@@ -453,6 +486,7 @@ int main(int argc, char *argv[]) { > + test_write_permissions(); > + test_exe_permissions(); > + test_mtime(); > ++ test_unix_permissions(); > + > + remove(ZIPNAME); > + return 0; > +diff --git a/contrib/zip/test/test_miniz.c b/contrib/zip/test/test_miniz.c > +index ebc0564dc3..babcaecdb6 100644 > +--- a/contrib/zip/test/test_miniz.c > ++++ b/contrib/zip/test/test_miniz.c > +@@ -23,16 +23,39 @@ int main(int argc, char *argv[]) { > + uint step = 0; > + int cmp_status; > + uLong src_len = (uLong)strlen(s_pStr); > +- uLong cmp_len = compressBound(src_len); > + uLong uncomp_len = src_len; > ++ uLong cmp_len; > + uint8 *pCmp, *pUncomp; > ++ size_t sz; > + uint total_succeeded = 0; > + (void)argc, (void)argv; > + > + printf("miniz.c version: %s\n", MZ_VERSION); > + > + do { > ++ pCmp = (uint8 *)tdefl_compress_mem_to_heap(s_pStr, src_len, &cmp_len, 0); > ++ if (!pCmp) { > ++ printf("tdefl_compress_mem_to_heap failed\n"); > ++ return EXIT_FAILURE; > ++ } > ++ if (src_len <= cmp_len) { > ++ printf("tdefl_compress_mem_to_heap failed: from %u to %u bytes\n", > ++ (mz_uint32)uncomp_len, (mz_uint32)cmp_len); > ++ free(pCmp); > ++ return EXIT_FAILURE; > ++ } > ++ > ++ sz = tdefl_compress_mem_to_mem(pCmp, cmp_len, s_pStr, src_len, 0); > ++ if (sz != cmp_len) { > ++ printf("tdefl_compress_mem_to_mem failed: expected %u, got %u\n", > ++ (mz_uint32)cmp_len, (mz_uint32)sz); > ++ free(pCmp); > ++ return EXIT_FAILURE; > ++ } > ++ > + // Allocate buffers to hold compressed and uncompressed data. > ++ free(pCmp); > ++ cmp_len = compressBound(src_len); > + pCmp = (mz_uint8 *)malloc((size_t)cmp_len); > + pUncomp = (mz_uint8 *)malloc((size_t)src_len); > + if ((!pCmp) || (!pUncomp)) { > diff --git a/package/assimp/0003-closes-2954-upgrade-to-latest-greatest.patch b/package/assimp/0003-closes-2954-upgrade-to-latest-greatest.patch > new file mode 100644 > index 0000000000..9bd24630c5 > --- /dev/null > +++ b/package/assimp/0003-closes-2954-upgrade-to-latest-greatest.patch > @@ -0,0 +1,243 @@ > +From bb3db0ebaffc6b76de256e597ec1d1e4d2a6663f Mon Sep 17 00:00:00 2001 > +From: kimkulling > +Date: Mon, 9 Mar 2020 10:51:26 +0100 > +Subject: [PATCH] closes https://github.com/assimp/assimp/issues/2954: upgrade > + to latest greatest. > + > +[Retrieved from: > +https://github.com/assimp/assimp/commit/bb3db0ebaffc6b76de256e597ec1d1e4d2a6663f] > +Signed-off-by: Fabrice Fontaine > +--- > + contrib/zip/CMakeLists.txt | 8 ++---- > + contrib/zip/README.md | 51 +++++++++++++++++++++++++++++++-- > + contrib/zip/src/zip.c | 17 ++++++++++- > + contrib/zip/src/zip.h | 13 ++++++++- > + contrib/zip/test/CMakeLists.txt | 5 ---- > + contrib/zip/test/test.c | 4 ++- > + 6 files changed, 81 insertions(+), 17 deletions(-) > + > +diff --git a/contrib/zip/CMakeLists.txt b/contrib/zip/CMakeLists.txt > +index 77916d2e14..f194649ede 100644 > +--- a/contrib/zip/CMakeLists.txt > ++++ b/contrib/zip/CMakeLists.txt > +@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0) > + > + project(zip > + LANGUAGES C > +- VERSION "0.1.15") > ++ VERSION "0.1.18") > + set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) > + > + option(CMAKE_DISABLE_TESTING "Disable test creation" OFF) > +@@ -16,10 +16,6 @@ elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR > + "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR > + "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang") > + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wall -Wextra -Werror -pedantic") > +- if(ENABLE_COVERAGE) > +- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage") > +- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage") > +- endif() > + endif (MSVC) > + > + # zip > +@@ -35,7 +31,7 @@ if (NOT CMAKE_DISABLE_TESTING) > + enable_testing() > + add_subdirectory(test) > + find_package(Sanitizers) > +- add_sanitizers(${PROJECT_NAME} ${test_out} ${test_miniz_out}) > ++ add_sanitizers(${PROJECT_NAME} ${test_out}) > + endif() > + > + #### > +diff --git a/contrib/zip/README.md b/contrib/zip/README.md > +index 14eb9a34c8..bdd0822b67 100644 > +--- a/contrib/zip/README.md > ++++ b/contrib/zip/README.md > +@@ -1,10 +1,8 @@ > + ### A portable (OSX/Linux/Windows), simple zip library written in C > + 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. > + > +-[![Windows](https://ci.appveyor.com/api/projects/status/bph8dr3jacgmjv32/branch/master?svg=true&label=windows)](https://ci.appveyor.com/project/kuba--/zip) > +-[![Linux](https://travis-ci.org/kuba--/zip.svg?branch=master&label=linux%2fosx)](https://travis-ci.org/kuba--/zip) > ++[![Build](https://github.com/kuba--/zip/workflows/build/badge.svg)](https://github.com/kuba--/zip/actions?query=workflow%3Abuild) > + [![Version](https://badge.fury.io/gh/kuba--%2Fzip.svg)](https://github.com/kuba--/zip/releases) > +-[![Codecov](https://codecov.io/gh/kuba--/zip/branch/master/graph/badge.svg)](https://codecov.io/gh/kuba--/zip) > + > + > + # The Idea > +@@ -213,6 +211,53 @@ func main() { > + } > + ``` > + > ++### Rust (ffi) > ++```rust > ++extern crate libc; > ++use std::ffi::CString; > ++ > ++#[repr(C)] > ++pub struct Zip { > ++ _private: [u8; 0], > ++} > ++ > ++#[link(name = "zip")] > ++extern "C" { > ++ fn zip_open(path: *const libc::c_char, level: libc::c_int, mode: libc::c_char) -> *mut Zip; > ++ fn zip_close(zip: *mut Zip) -> libc::c_void; > ++ > ++ fn zip_entry_open(zip: *mut Zip, entryname: *const libc::c_char) -> libc::c_int; > ++ fn zip_entry_close(zip: *mut Zip) -> libc::c_int; > ++ fn zip_entry_write( > ++ zip: *mut Zip, > ++ buf: *const libc::c_void, > ++ bufsize: libc::size_t, > ++ ) -> libc::c_int; > ++} > ++ > ++fn main() { > ++ let path = CString::new("/tmp/test.zip").unwrap(); > ++ let mode: libc::c_char = 'w' as libc::c_char; > ++ > ++ let entryname = CString::new("test.txt").unwrap(); > ++ let content = "test content\0"; > ++ > ++ unsafe { > ++ let zip: *mut Zip = zip_open(path.as_ptr(), 5, mode); > ++ { > ++ zip_entry_open(zip, entryname.as_ptr()); > ++ { > ++ let buf = content.as_ptr() as *const libc::c_void; > ++ let bufsize = content.len() as libc::size_t; > ++ zip_entry_write(zip, buf, bufsize); > ++ } > ++ zip_entry_close(zip); > ++ } > ++ zip_close(zip); > ++ } > ++} > ++``` > ++ > + ### Ruby (ffi) > + Install _ffi_ gem. > + ```shell > +diff --git a/contrib/zip/src/zip.c b/contrib/zip/src/zip.c > +index 1abcfd8fd1..3b2821e6a3 100644 > +--- a/contrib/zip/src/zip.c > ++++ b/contrib/zip/src/zip.c > +@@ -222,6 +222,20 @@ void zip_close(struct zip_t *zip) { > + } > + } > + > ++int zip_is64(struct zip_t *zip) { > ++ if (!zip) { > ++ // zip_t handler is not initialized > ++ return -1; > ++ } > ++ > ++ if (!zip->archive.m_pState) { > ++ // zip state is not initialized > ++ return -1; > ++ } > ++ > ++ return (int)zip->archive.m_pState->m_zip64; > ++} > ++ > + int zip_entry_open(struct zip_t *zip, const char *entryname) { > + size_t entrylen = 0; > + mz_zip_archive *pzip = NULL; > +@@ -794,7 +808,8 @@ int zip_create(const char *zipname, const char *filenames[], size_t len) { > + > + if (MZ_FILE_STAT(name, &file_stat) != 0) { > + // problem getting information - check errno > +- return -1; > ++ status = -1; > ++ break; > + } > + > + if ((file_stat.st_mode & 0200) == 0) { > +diff --git a/contrib/zip/src/zip.h b/contrib/zip/src/zip.h > +index a48d64d6de..cd3ab5cd00 100644 > +--- a/contrib/zip/src/zip.h > ++++ b/contrib/zip/src/zip.h > +@@ -21,7 +21,7 @@ extern "C" { > + > + #if !defined(_SSIZE_T_DEFINED) && !defined(_SSIZE_T_DEFINED_) && \ > + !defined(__DEFINED_ssize_t) && !defined(__ssize_t_defined) && \ > +- !defined(_SSIZE_T) && !defined(_SSIZE_T_) > ++ !defined(_SSIZE_T) && !defined(_SSIZE_T_) && !defined(_SSIZE_T_DECLARED) > + > + // 64-bit Windows is the only mainstream platform > + // where sizeof(long) != sizeof(void*) > +@@ -37,6 +37,7 @@ typedef long ssize_t; /* byte count or error */ > + #define __ssize_t_defined > + #define _SSIZE_T > + #define _SSIZE_T_ > ++#define _SSIZE_T_DECLARED > + > + #endif > + > +@@ -90,6 +91,16 @@ extern struct zip_t *zip_open(const char *zipname, int level, char mode); > + */ > + extern void zip_close(struct zip_t *zip); > + > ++/** > ++ * Determines if the archive has a zip64 end of central directory headers. > ++ * > ++ * @param zip zip archive handler. > ++ * > ++ * @return the return code - 1 (true), 0 (false), negative number (< 0) on > ++ * error. > ++ */ > ++extern int zip_is64(struct zip_t *zip); > ++ > + /** > + * Opens an entry by name in the zip archive. > + * > +diff --git a/contrib/zip/test/CMakeLists.txt b/contrib/zip/test/CMakeLists.txt > +index cc060b00fe..1224115858 100644 > +--- a/contrib/zip/test/CMakeLists.txt > ++++ b/contrib/zip/test/CMakeLists.txt > +@@ -2,15 +2,10 @@ cmake_minimum_required(VERSION 2.8) > + > + # test > + set(test_out test.out) > +-set(test_miniz_out test_miniz.out) > + > + add_executable(${test_out} test.c) > + target_link_libraries(${test_out} zip) > +-add_executable(${test_miniz_out} test_miniz.c) > +-target_link_libraries(${test_miniz_out} zip) > + > + add_test(NAME ${test_out} COMMAND ${test_out}) > +-add_test(NAME ${test_miniz_out} COMMAND ${test_miniz_out}) > + > + set(test_out ${test_out} PARENT_SCOPE) > +-set(test_miniz_out ${test_miniz_out} PARENT_SCOPE) > +diff --git a/contrib/zip/test/test.c b/contrib/zip/test/test.c > +index a9b2ddab1e..9cc2248ac0 100644 > +--- a/contrib/zip/test/test.c > ++++ b/contrib/zip/test/test.c > +@@ -47,7 +47,7 @@ static void test_write(void) { > + assert(CRC32DATA1 == zip_entry_crc32(zip)); > + ++total_entries; > + assert(0 == zip_entry_close(zip)); > +- > ++ assert(0 == zip_is64(zip)); > + zip_close(zip); > + } > + > +@@ -92,6 +92,7 @@ static void test_read(void) { > + size_t buftmp; > + struct zip_t *zip = zip_open(ZIPNAME, 0, 'r'); > + assert(zip != NULL); > ++ assert(0 == zip_is64(zip)); > + > + assert(0 == zip_entry_open(zip, "test\\test-1.txt")); > + assert(strlen(TESTDATA1) == zip_entry_size(zip)); > +@@ -310,6 +311,7 @@ static void test_fwrite(void) { > + assert(0 == zip_entry_open(zip, WFILE)); > + assert(0 == zip_entry_fwrite(zip, WFILE)); > + assert(0 == zip_entry_close(zip)); > ++ assert(0 == zip_is64(zip)); > + > + zip_close(zip); > + remove(WFILE);