├── .clang-format ├── .codecov.yaml ├── .github ├── FUNDING.yml ├── dependabot.yml └── workflows │ ├── build.yml │ ├── codeql.yml │ ├── fuzz.yml │ └── lint.yml ├── .gitignore ├── CMakeLists.txt ├── INDEX.md ├── LICENSE ├── README.md ├── cmake ├── FindZLIBNG.cmake ├── clone-repo.cmake └── detect-sanitizer.cmake ├── compat ├── crypt.h ├── ioapi.c ├── ioapi.h ├── unzip.c ├── unzip.h ├── zip.c └── zip.h ├── doc ├── README.md ├── mz_compress_level.md ├── mz_compress_method.md ├── mz_encoding.md ├── mz_error.md ├── mz_extrafield.md ├── mz_hash.md ├── mz_host_system.md ├── mz_open_mode.md ├── mz_os.md ├── mz_seek.md ├── mz_zip.md ├── mz_zip64.md ├── mz_zip_file.md ├── mz_zip_rw.md └── zip │ ├── appnote.iz.txt │ ├── appnote.txt │ ├── extra.fld.txt │ ├── winzip_aes.md │ └── winzip_aes_attack.pdf ├── minigzip.c ├── minizip.c ├── minizip.pc.cmakein ├── mz.h ├── mz_crypt.c ├── mz_crypt.h ├── mz_crypt_apple.c ├── mz_crypt_openssl.c ├── mz_crypt_winvista.c ├── mz_crypt_winxp.c ├── mz_os.c ├── mz_os.h ├── mz_os_posix.c ├── mz_os_win32.c ├── mz_strm.c ├── mz_strm.h ├── mz_strm_buf.c ├── mz_strm_buf.h ├── mz_strm_bzip.c ├── mz_strm_bzip.h ├── mz_strm_libcomp.c ├── mz_strm_libcomp.h ├── mz_strm_lzma.c ├── mz_strm_lzma.h ├── mz_strm_mem.c ├── mz_strm_mem.h ├── mz_strm_os.h ├── mz_strm_os_posix.c ├── mz_strm_os_win32.c ├── mz_strm_pkcrypt.c ├── mz_strm_pkcrypt.h ├── mz_strm_split.c ├── mz_strm_split.h ├── mz_strm_wzaes.c ├── mz_strm_wzaes.h ├── mz_strm_zlib.c ├── mz_strm_zlib.h ├── mz_strm_zstd.c ├── mz_strm_zstd.h ├── mz_zip.c ├── mz_zip.h ├── mz_zip_rw.c ├── mz_zip_rw.h └── test ├── CMakeLists.txt ├── empty.txt ├── fuzz ├── standalone.c ├── unzip_fuzzer.c ├── unzip_fuzzer.dict ├── unzip_fuzzer_seed_corpus │ ├── as.zip │ ├── bzip2.zip │ ├── comments.zip │ ├── corpus.zip │ ├── dot_dot_backslash_name.zip │ ├── encrypted_pkcrypt.zip │ ├── encrypted_wzaes.zip │ ├── gh.zip │ ├── gh_739.zip │ ├── gh_740.zip │ ├── incorrect_number_entries.zip │ ├── infozip_symlinks.zip │ ├── large_cd_comment.zip │ ├── license_zstd.zip │ ├── lzma.zip │ ├── permissions.zip │ ├── signed.zip │ ├── storeonly.zip │ ├── tiny.zip │ ├── unsupported_permissions.zip │ ├── xz.zip │ └── zip64.zip └── zip_fuzzer.c ├── random.bin ├── single.txt ├── test.p12 ├── test.pem ├── test_compat.cc ├── test_crypt.cc ├── test_encoding.cc ├── test_file.cc ├── test_main.cc ├── test_path.cc ├── test_stream.cc ├── test_stream_compress.cc ├── test_stream_crypt.cc └── uniform.bin /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: Google 3 | 4 | AccessModifierOffset: -2 5 | AlignArrayOfStructures: Right 6 | AlignConsecutiveBitFields: AcrossEmptyLines 7 | AlignConsecutiveMacros: AcrossEmptyLines 8 | AlignEscapedNewlines: Right 9 | AlignOperands: DontAlign 10 | AllowShortFunctionsOnASingleLine: Empty 11 | AllowShortIfStatementsOnASingleLine: Never 12 | AllowShortLambdasOnASingleLine: Empty 13 | AllowShortLoopsOnASingleLine: false 14 | ColumnLimit: 120 15 | DerivePointerAlignment: false 16 | IndentCaseLabels: false 17 | IndentPPDirectives: AfterHash 18 | IndentWidth: 4 19 | InsertNewlineAtEOF: true 20 | PointerAlignment: Right 21 | PPIndentWidth: 2 22 | SortIncludes: Never 23 | -------------------------------------------------------------------------------- /.codecov.yaml: -------------------------------------------------------------------------------- 1 | codecov: 2 | max_report_age: off 3 | notify: 4 | wait_for_ci: false 5 | require_ci_to_pass: false 6 | comment: 7 | require_base: false 8 | require_head: false 9 | coverage: 10 | status: 11 | project: 12 | default: 13 | threshold: 0.07 14 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: nmoinvaz 2 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "monthly" 7 | target-branch: "develop" 8 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | name: CodeQL 2 | on: 3 | push: 4 | pull_request: 5 | schedule: 6 | - cron: '0 1 * * 4' 7 | concurrency: 8 | group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} 9 | cancel-in-progress: true 10 | jobs: 11 | analyze: 12 | name: Analyze 13 | runs-on: ubuntu-latest 14 | permissions: 15 | actions: read 16 | contents: read 17 | security-events: write 18 | steps: 19 | - name: Checkout repository 20 | uses: actions/checkout@v4 21 | with: 22 | # We must fetch at least the immediate parents so that if this is 23 | # a pull request then we can checkout the head. 24 | fetch-depth: 2 25 | 26 | # Initializes the CodeQL tools for scanning. 27 | - name: Initialize CodeQL 28 | uses: github/codeql-action/init@v3 29 | 30 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 31 | # If this step fails, then you should remove it and run the build manually (see below) 32 | - name: Autobuild 33 | uses: github/codeql-action/autobuild@v3 34 | 35 | - name: Perform CodeQL Analysis 36 | uses: github/codeql-action/analyze@v3 37 | -------------------------------------------------------------------------------- /.github/workflows/fuzz.yml: -------------------------------------------------------------------------------- 1 | name: OSS-Fuzz 2 | on: [pull_request] 3 | concurrency: 4 | group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} 5 | cancel-in-progress: true 6 | jobs: 7 | Fuzzing: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Build Fuzzers 11 | uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master 12 | with: 13 | oss-fuzz-project-name: 'minizip' 14 | dry-run: true 15 | 16 | - name: Run Fuzzers 17 | uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master 18 | with: 19 | oss-fuzz-project-name: 'minizip' 20 | fuzz-seconds: 600 21 | dry-run: true 22 | 23 | - name: Upload Crash 24 | uses: actions/upload-artifact@v4 25 | if: failure() 26 | with: 27 | name: artifacts 28 | path: ./out/artifacts 29 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | on: [workflow_dispatch, pull_request] 3 | env: 4 | TERM: xterm-256color 5 | CLANG_VERSION: 19 6 | 7 | jobs: 8 | clang-format: 9 | name: Clang-Format 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Install clang-format 13 | run: | 14 | wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - 15 | UBCN=$(lsb_release --short --codename) 16 | sudo add-apt-repository "deb https://apt.llvm.org/${UBCN}/ llvm-toolchain-${UBCN}-${CLANG_VERSION} main" 17 | sudo apt update || true 18 | sudo apt install -y clang-format-${CLANG_VERSION} 19 | 20 | - name: Checkout repository 21 | uses: actions/checkout@v4 22 | with: 23 | fetch-depth: 0 24 | lfs: true 25 | 26 | - name: Run clang-format 27 | run: | 28 | if ! git clang-format-${CLANG_VERSION} --binary=clang-format-${CLANG_VERSION} --diff --commit=origin/develop 29 | then 30 | echo -e "\033[1;31mCode style does not match clang-format" 31 | exit 1 32 | fi 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # builds 2 | _deps/ 3 | build/ 4 | CMakeFiles/ 5 | lib/ 6 | Testing/ 7 | third_party/ 8 | 9 | # IDE 10 | .vscode 11 | -------------------------------------------------------------------------------- /INDEX.md: -------------------------------------------------------------------------------- 1 | 2 | ## Contents 3 | 4 | | File(s) | Description | 5 | |:-------------------|:------------------------------------------------| 6 | | minizip.c | Sample application | 7 | | mz_compat.\* | Minizip 1.x compatibility layer | 8 | | mz.h | Error codes and flags | 9 | | mz_os\* | Platform specific file/utility functions | 10 | | mz_crypt\* | Configuration specific crypto/hashing functions | 11 | | mz_strm.\* | Stream interface | 12 | | mz_strm_buf.\* | Buffered stream | 13 | | mz_strm_bzip.\* | BZIP2 stream using libbzip2 | 14 | | mz_strm_libcomp.\* | Apple compression stream | 15 | | mz_strm_lzma.\* | LZMA stream using liblzma | 16 | | mz_strm_mem.\* | Memory stream | 17 | | mz_strm_split.\* | Disk splitting stream | 18 | | mz_strm_pkcrypt.\* | PKWARE traditional encryption stream | 19 | | mz_strm_os\* | Platform specific file stream | 20 | | mz_strm_wzaes.\* | WinZIP AES stream | 21 | | mz_strm_zlib.\* | Deflate stream using zlib | 22 | | mz_strm_zstd.\* | ZSTD stream | 23 | | mz_zip.\* | Zip format | 24 | | mz_zip_rw.\* | Zip reader/writer | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Condition of use and distribution are the same as zlib: 2 | 3 | This software is provided 'as-is', without any express or implied 4 | warranty. In no event will the authors be held liable for any damages 5 | arising from the use of this software. 6 | 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it 9 | freely, subject to the following restrictions: 10 | 11 | 1. The origin of this software must not be misrepresented; you must not 12 | claim that you wrote the original software. If you use this software 13 | in a product, an acknowledgement in the product documentation would be 14 | appreciated but is not required. 15 | 2. Altered source versions must be plainly marked as such, and must not be 16 | misrepresented as being the original software. 17 | 3. This notice may not be removed or altered from any source distribution. 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # minizip-ng 2 | 3 | minizip-ng is a zip manipulation library written in C that is supported on Windows, macOS, and Linux. 4 | 5 | [![Master Branch Status](https://github.com/zlib-ng/minizip-ng/workflows/Build/badge.svg)](https://github.com/zlib-ng/minizip-ng/actions) 6 | [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/minizip.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:minizip) 7 | [![License: Zlib](https://img.shields.io/badge/license-zlib-lightgrey.svg)](https://github.com/zlib-ng/minizip-ng/blob/master/LICENSE) 8 | [![codecov.io](https://codecov.io/github/zlib-ng/minizip-ng/coverage.svg?branch=develop)](https://codecov.io/github/zlib-ng/minizip-ng/) 9 | [![Packaging status](https://repology.org/badge/tiny-repos/minizip-ng.svg)](https://repology.org/project/minizip-ng/versions) 10 | 11 | Developed and maintained by Nathan Moinvaziri. 12 | 13 | ## Branches 14 | 15 | | Name | Description | 16 | |:--------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 17 | | [develop](https://github.com/zlib-ng/minizip-ng/tree/develop) | Latest development code. | 18 | | [master](https://github.com/zlib-ng/minizip-ng/tree/master) | Most recent stable release. | 19 | | [1.2](https://github.com/zlib-ng/minizip-ng/tree/1.2) | Old changes to original minizip that includes WinZip AES encryption, disk splitting, I/O buffering and some additional fixes. Not ABI compatible with original minizip. | 20 | | [1.1](https://github.com/zlib-ng/minizip-ng/tree/1.1) | Original minizip as of zlib 1.2.11. | 21 | 22 | ## History 23 | 24 | Minizip was originally developed by [Gilles Vollant](https://www.winimage.com/zLibDll/minizip.html) in 1998. It was first included in the zlib distribution as an additional code contribution starting in zlib 1.1.2. Since that time, it has been continually improved upon and contributed to by many people. The original [project](https://github.com/madler/zlib/tree/master/contrib/minizip) can still be found in the zlib distribution that is maintained by Mark Adler. 25 | 26 | The motivation behind this repository has been the need for new features and bug fixes to the original library which had 27 | not been maintained for a long period of time. The code has been largely refactored and rewritten in order to help improve maintainability and readability. A compatibility layer has been provided for consumers of the original minizip library. 28 | 29 | ## Features 30 | 31 | + Creating and extracting zip archives. 32 | + Adding and removing entries from zip archives. 33 | + Read and write raw zip entry data. 34 | + Reading and writing zip archives from memory. 35 | + Support for large files with ZIP64 extension. 36 | + Zlib, BZIP2, LZMA, XZ, and ZSTD compression methods. 37 | + Password protection through Traditional PKWARE and [WinZIP AES](https://www.winzip.com/aes_info.htm) encryption. 38 | + Buffered streaming for improved I/O performance. 39 | + NTFS timestamp support for UTC last modified, last accessed, and creation dates. 40 | + Disk split support for splitting zip archives into multiple files. 41 | + Preservation of file attributes across file systems. 42 | + Follow and store symbolic links. 43 | + Unicode filename support through UTF-8 encoding. 44 | + Legacy character encoding support CP437, CP932, CP936, CP950. 45 | + Turn off compilation of compression, decompression, or encryption. 46 | + Windows (Win32 & WinRT), macOS and Linux platform support. 47 | + Streaming interface for easy implementation of additional platforms. 48 | + Support for Apple's compression library ZLIB and XZ implementations. 49 | + Zero out local file header information. 50 | + Zip/unzip of central directory to reduce size. 51 | + Recover the central directory if it is corrupt or missing. 52 | + Example minizip and minigzip command line tools. 53 | 54 | ## Build 55 | 56 | To generate project files for your platform: 57 | 58 | 1. [Download and install](https://cmake.org/install/) cmake (version 3.11 or later recommended). 59 | 2. Run cmake in the minizip directory. 60 | 61 | ``` 62 | cmake -S . -B build -D MZ_BUILD_TESTS=ON 63 | cmake --build build 64 | ``` 65 | 66 | ## Build Options 67 | 68 | | Name | Description | Default Value | 69 | |:--------------------|:---------------------------------------------------------------|:-------------:| 70 | | MZ_COMPAT | Enables compatibility layer | ON | 71 | | MZ_ZLIB | Enables ZLIB compression | ON | 72 | | MZ_BZIP2 | Enables BZIP2 compression | ON | 73 | | MZ_LZMA | Enables LZMA & XZ compression | ON | 74 | | MZ_ZSTD | Enables ZSTD compression | ON | 75 | | MZ_LIBCOMP | Enables Apple compression | APPLE | 76 | | MZ_FETCH_LIBS | Enables fetching third-party libraries if not found | WIN32 | 77 | | MZ_FORCE_FETCH_LIBS | Enables fetching third-party libraries always | OFF | 78 | | MZ_PKCRYPT | Enables PKWARE traditional encryption | ON | 79 | | MZ_WZAES | Enables WinZIP AES encryption | ON | 80 | | MZ_OPENSSL | Enables OpenSSL encryption | UNIX | 81 | | MZ_LIBBSD | Builds with libbsd crypto random | UNIX | 82 | | MZ_ICONV | Enables iconv encoding conversion | ON | 83 | | MZ_COMPRESS_ONLY | Only support compression | OFF | 84 | | MZ_DECOMPRESS_ONLY | Only support decompression | OFF | 85 | | MZ_FILE32_API | Builds using posix 32-bit file api | OFF | 86 | | MZ_BUILD_TESTS | Builds minizip test executable | OFF | 87 | | MZ_BUILD_UNIT_TESTS | Builds minizip unit test project | OFF | 88 | | MZ_BUILD_FUZZ_TESTS | Builds minizip fuzz executables | OFF | 89 | | MZ_CODE_COVERAGE | Build with code coverage flags | OFF | 90 | | MZ_SANITIZER | Build with code sanitizer (Memory, Thread, Address, Undefined) | | 91 | | MZ_LIB_SUFFIX | Library name suffix for packaging | | 92 | 93 | ## Third-Party Libraries 94 | 95 | Third-party libraries may be required based on the CMake options selected. If the system already has the library 96 | installed then it will be used, otherwise CMake will retrieve the source code for the library from its official git repository and compile it in when the `MZ_FETCH_LIBS` option is enabled. 97 | 98 | |Project|License|CMake Option|Comments| 99 | |-|-|-|-| 100 | [bzip2](https://www.sourceware.org/bzip2/)|[license](https://github.com/zlib-ng/minizip-ng/blob/develop/lib/bzip2/LICENSE)|`MZ_BZIP2`|Written by Julian Seward.| 101 | |[liblzma](https://tukaani.org/xz/)|Public domain|`MZ_LZMA`|Written by Igor Pavlov and Lasse Collin.| 102 | |[zlib](https://zlib.net/)|zlib|`MZ_ZLIB`|Written by Mark Adler and Jean-loup Gailly. Or alternatively, [zlib-ng](https://github.com/zlib-ng/zlib-ng) by Hans Kristian Rosbach.| 103 | |[zstd](https://github.com/facebook/zstd)|[BSD](https://github.com/facebook/zstd/blob/dev/LICENSE)|`MZ_ZSTD`|Written by Facebook.| 104 | 105 | This project uses the zlib [license](LICENSE). 106 | 107 | ## Acknowledgments 108 | 109 | Thanks go out to all the people who have taken the time to contribute code reviews, testing and/or patches. This project would not have been as good without you. 110 | 111 | Thanks to [Gilles Vollant](https://www.winimage.com/zLibDll/minizip.html) on which this work is originally based on. 112 | 113 | The [ZIP format](https://github.com/zlib-ng/minizip-ng/blob/master/doc/zip/appnote.txt) was defined by Phil Katz of PKWARE. 114 | -------------------------------------------------------------------------------- /cmake/FindZLIBNG.cmake: -------------------------------------------------------------------------------- 1 | find_path(ZLIBNG_INCLUDE_DIRS NAMES zlib-ng.h) 2 | 3 | if(ZLIB_INCLUDE_DIRS) 4 | set(ZLIBNG_LIBRARY_DIRS ${ZLIBNG_INCLUDE_DIRS}) 5 | 6 | if("${ZLIBNG_LIBRARY_DIRS}" MATCHES "/include$") 7 | # Strip off the trailing "/include" in the path. 8 | get_filename_component(ZLIBNG_LIBRARY_DIRS ${ZLIBNG_LIBRARY_DIRS} PATH) 9 | endif() 10 | 11 | if(EXISTS "${ZLIBNG_LIBRARY_DIRS}/lib") 12 | set(ZLIBNG_LIBRARY_DIRS ${ZLIBNG_LIBRARY_DIRS}/lib) 13 | endif() 14 | endif() 15 | 16 | find_library(ZLIBNG_LIBRARY NAMES z-ng libz-ng libz-ng.a) 17 | 18 | set(ZLIBNG_LIBRARIES ${ZLIBNG_LIBRARY}) 19 | set(ZLIBNG_INCLUDE_DIRS ${ZLIBNG_INCLUDE_DIRS}) 20 | 21 | include(FindPackageHandleStandardArgs) 22 | find_package_handle_standard_args(ZLIBNG DEFAULT_MSG ZLIBNG_LIBRARY ZLIBNG_INCLUDE_DIRS) 23 | 24 | if(ZLIBNG_INCLUDE_DIRS AND ZLIBNG_LIBRARIES) 25 | set(ZLIBNG_FOUND ON) 26 | else(ZLIBNG_INCLUDE_DIRS AND ZLIBNG_LIBRARIES) 27 | set(ZLIBNG_FOUND OFF) 28 | endif() 29 | 30 | if(ZLIBNG_FOUND) 31 | message(STATUS "Found zlib-ng: ${ZLIBNG_LIBRARIES}, ${ZLIBNG_INCLUDE_DIRS}") 32 | endif() 33 | -------------------------------------------------------------------------------- /cmake/clone-repo.cmake: -------------------------------------------------------------------------------- 1 | # Checkout remote repository 2 | macro(clone_repo name url tag) 3 | string(TOLOWER ${name} name_lower) 4 | string(TOUPPER ${name} name_upper) 5 | 6 | if(NOT ${name_upper}_REPOSITORY) 7 | set(${name_upper}_REPOSITORY ${url}) 8 | endif() 9 | if(NOT ${name_upper}_TAG) 10 | set(${name_upper}_TAG ${tag}) 11 | endif() 12 | 13 | message(STATUS "Fetching ${name} ${${name_upper}_REPOSITORY} ${${name_upper}_TAG}") 14 | 15 | # Check for FetchContent cmake support 16 | if(${CMAKE_VERSION} VERSION_LESS "3.11") 17 | message(FATAL_ERROR "CMake 3.11 required to fetch ${name}") 18 | else() 19 | include(FetchContent) 20 | 21 | FetchContent_Declare(${name} 22 | GIT_REPOSITORY ${${name_upper}_REPOSITORY} 23 | GIT_TAG ${${name_upper}_TAG} 24 | SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/${name_lower}) 25 | 26 | FetchContent_GetProperties(${name} POPULATED ${name_lower}_POPULATED) 27 | 28 | if(NOT ${name_lower}_POPULATED) 29 | FetchContent_Populate(${name}) 30 | endif() 31 | 32 | set(${name_upper}_SOURCE_DIR ${${name_lower}_SOURCE_DIR}) 33 | set(${name_upper}_BINARY_DIR ${${name_lower}_BINARY_DIR}) 34 | endif() 35 | endmacro() -------------------------------------------------------------------------------- /cmake/detect-sanitizer.cmake: -------------------------------------------------------------------------------- 1 | # detect-sanitizer.cmake -- Detect supported compiler sanitizer flags 2 | # Licensed under the Zlib license, see LICENSE.md for details 3 | 4 | macro(add_common_sanitizer_flags) 5 | if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") 6 | add_compile_options(-g3) 7 | endif() 8 | # check_c_compiler_flag(-fno-omit-frame-pointer HAVE_NO_OMIT_FRAME_POINTER) 9 | # if(HAVE_NO_OMIT_FRAME_POINTER) 10 | add_compile_options(-fno-omit-frame-pointer) 11 | add_link_options(-fno-omit-frame-pointer) 12 | # endif() 13 | # check_c_compiler_flag(-fno-optimize-sibling-calls HAVE_NO_OPTIMIZE_SIBLING_CALLS) 14 | # if(HAVE_NO_OPTIMIZE_SIBLING_CALLS) 15 | add_compile_options(-fno-optimize-sibling-calls) 16 | add_link_options(-fno-optimize-sibling-calls) 17 | # endif() 18 | endmacro() 19 | 20 | macro(check_sanitizer_support known_checks supported_checks) 21 | set(available_checks "") 22 | 23 | # Build list of supported sanitizer flags by incrementally trying compilation with 24 | # known sanitizer checks 25 | 26 | foreach(check ${known_checks}) 27 | if(available_checks STREQUAL "") 28 | set(compile_checks "${check}") 29 | else() 30 | set(compile_checks "${available_checks},${check}") 31 | endif() 32 | 33 | set(CMAKE_REQUIRED_FLAGS -fsanitize=${compile_checks}) 34 | 35 | check_c_source_compiles("int main() { return 0; }" HAVE_SANITIZER_${check} 36 | FAIL_REGEX "not supported|unrecognized command|unknown option") 37 | 38 | set(CMAKE_REQUIRED_FLAGS) 39 | 40 | if(HAVE_SANITIZER_${check}) 41 | set(available_checks ${compile_checks}) 42 | endif() 43 | endforeach() 44 | 45 | set(${supported_checks} ${available_checks}) 46 | endmacro() 47 | 48 | macro(add_address_sanitizer) 49 | set(known_checks 50 | address 51 | pointer-compare 52 | pointer-subtract 53 | ) 54 | 55 | check_sanitizer_support("${known_checks}" supported_checks) 56 | if(NOT ${supported_checks} STREQUAL "") 57 | message(STATUS "Address sanitizer is enabled: ${supported_checks}") 58 | add_compile_options(-fsanitize=${supported_checks}) 59 | add_link_options(-fsanitize=${supported_checks}) 60 | add_common_sanitizer_flags() 61 | else() 62 | message(STATUS "Address sanitizer is not supported") 63 | endif() 64 | 65 | if(CMAKE_CROSSCOMPILING_EMULATOR) 66 | # Only check for leak sanitizer if not cross-compiling due to qemu crash 67 | message(WARNING "Leak sanitizer is not supported when cross compiling") 68 | else() 69 | # Leak sanitizer requires address sanitizer 70 | check_sanitizer_support("leak" supported_checks) 71 | if(NOT ${supported_checks} STREQUAL "") 72 | message(STATUS "Leak sanitizer is enabled: ${supported_checks}") 73 | add_compile_options(-fsanitize=${supported_checks}) 74 | add_link_options(-fsanitize=${supported_checks}) 75 | add_common_sanitizer_flags() 76 | else() 77 | message(STATUS "Leak sanitizer is not supported") 78 | endif() 79 | endif() 80 | endmacro() 81 | 82 | macro(add_memory_sanitizer) 83 | check_sanitizer_support("memory" supported_checks) 84 | if(NOT ${supported_checks} STREQUAL "") 85 | message(STATUS "Memory sanitizer is enabled: ${supported_checks}") 86 | add_compile_options(-fsanitize=${supported_checks}) 87 | add_link_options(-fsanitize=${supported_checks}) 88 | add_common_sanitizer_flags() 89 | 90 | check_c_compiler_flag(-fsanitize-memory-track-origins HAVE_MEMORY_TRACK_ORIGINS) 91 | if(HAVE_MEMORY_TRACK_ORIGINS) 92 | add_compile_options(-fsanitize-memory-track-origins) 93 | add_link_options(-fsanitize-memory-track-origins) 94 | endif() 95 | else() 96 | message(STATUS "Memory sanitizer is not supported") 97 | endif() 98 | endmacro() 99 | 100 | macro(add_thread_sanitizer) 101 | check_sanitizer_support("thread" supported_checks) 102 | if(NOT ${supported_checks} STREQUAL "") 103 | message(STATUS "Thread sanitizer is enabled: ${supported_checks}") 104 | add_compile_options(-fsanitize=${supported_checks}) 105 | add_link_options(-fsanitize=${supported_checks}) 106 | add_common_sanitizer_flags() 107 | else() 108 | message(STATUS "Thread sanitizer is not supported") 109 | endif() 110 | endmacro() 111 | 112 | macro(add_undefined_sanitizer) 113 | set(known_checks 114 | array-bounds 115 | bool 116 | bounds 117 | builtin 118 | enum 119 | float-cast-overflow 120 | float-divide-by-zero 121 | function 122 | integer-divide-by-zero 123 | local-bounds 124 | null 125 | nonnull-attribute 126 | pointer-overflow 127 | return 128 | returns-nonnull-attribute 129 | shift 130 | shift-base 131 | shift-exponent 132 | signed-integer-overflow 133 | undefined 134 | unsigned-integer-overflow 135 | unsigned-shift-base 136 | vla-bound 137 | vptr 138 | ) 139 | 140 | # Only check for alignment sanitizer flag if unaligned access is not supported 141 | if(NOT WITH_UNALIGNED) 142 | list(APPEND known_checks alignment) 143 | endif() 144 | # Object size sanitizer has no effect at -O0 and produces compiler warning if enabled 145 | if(NOT CMAKE_C_FLAGS MATCHES "-O0") 146 | list(APPEND known_checks object-size) 147 | endif() 148 | 149 | check_sanitizer_support("${known_checks}" supported_checks) 150 | 151 | if(NOT ${supported_checks} STREQUAL "") 152 | message(STATUS "Undefined behavior sanitizer is enabled: ${supported_checks}") 153 | add_compile_options(-fsanitize=${supported_checks}) 154 | add_link_options(-fsanitize=${supported_checks}) 155 | 156 | # Group sanitizer flag -fsanitize=undefined will automatically add alignment, even if 157 | # it is not in our sanitize flag list, so we need to explicitly disable alignment sanitizing. 158 | if(WITH_UNALIGNED) 159 | add_compile_options(-fno-sanitize=alignment) 160 | endif() 161 | 162 | add_common_sanitizer_flags() 163 | else() 164 | message(STATUS "Undefined behavior sanitizer is not supported") 165 | endif() 166 | endmacro() -------------------------------------------------------------------------------- /compat/crypt.h: -------------------------------------------------------------------------------- 1 | /* crypt.h -- base code for crypt/uncrypt ZIPfile 2 | Version 1.01e, February 12th, 2005 3 | 4 | Copyright (C) 1998-2005 Gilles Vollant 5 | 6 | This code is a modified version of crypting code in Infozip distribution 7 | 8 | The encryption/decryption parts of this source code (as opposed to the 9 | non-echoing password parts) were originally written in Europe. The 10 | whole source package can be freely distributed, including from the USA. 11 | (Prior to January 2000, re-export from the US was a violation of US law.) 12 | 13 | This encryption code is a direct transcription of the algorithm from 14 | Roger Schlafly, described by Phil Katz in the file appnote.txt. This 15 | file (appnote.txt) is distributed with the PKZIP program (even in the 16 | version without encryption capabilities). 17 | 18 | If you don't need crypting in your application, just define symbols 19 | NOCRYPT and NOUNCRYPT. 20 | 21 | This code support the "Traditional PKWARE Encryption". 22 | 23 | The new AES encryption added on Zip format by Winzip (see the page 24 | http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong 25 | Encryption is not supported. 26 | */ 27 | 28 | #ifndef ZLIB_VERNUM 29 | /* No zlib */ 30 | typedef uint32_t z_crc_t; 31 | #elif (ZLIB_VERNUM & 0xf != 0xf) && (ZLIB_VERNUM < 0x1270) 32 | /* Define z_crc_t in zlib 1.2.6 and less */ 33 | typedef unsigned long z_crc_t; 34 | #elif (ZLIB_VERNUM & 0xf == 0xf) && (ZLIB_VERNUM < 0x12df) 35 | /* Define z_crc_t in zlib-ng 2.0.7 and less */ 36 | typedef unsigned int z_crc_t; 37 | #endif 38 | 39 | #define CRC32(c, b) ((*(pcrc_32_tab + (((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) 40 | 41 | /***************************************************************************/ 42 | /* Return the next byte in the pseudo-random sequence */ 43 | 44 | static int decrypt_byte(unsigned long *pkeys, const z_crc_t *pcrc_32_tab) { 45 | unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an 46 | * unpredictable manner on 16-bit systems; not a problem 47 | * with any known compiler so far, though */ 48 | 49 | (void)pcrc_32_tab; 50 | temp = ((unsigned)(*(pkeys + 2)) & 0xffff) | 2; 51 | return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); 52 | } 53 | 54 | /***************************************************************************/ 55 | /* Update the encryption keys with the next byte of plain text */ 56 | 57 | static int update_keys(unsigned long *pkeys, const z_crc_t *pcrc_32_tab, int c) { 58 | (*(pkeys + 0)) = CRC32((*(pkeys + 0)), c); 59 | (*(pkeys + 1)) += (*(pkeys + 0)) & 0xff; 60 | (*(pkeys + 1)) = (*(pkeys + 1)) * 134775813L + 1; 61 | { 62 | int keyshift = (int)((*(pkeys + 1)) >> 24); 63 | (*(pkeys + 2)) = CRC32((*(pkeys + 2)), keyshift); 64 | } 65 | return c; 66 | } 67 | 68 | /***************************************************************************/ 69 | /* Initialize the encryption keys and the random header according to the password. */ 70 | 71 | static void init_keys(const char *passwd, unsigned long *pkeys, const z_crc_t *pcrc_32_tab) { 72 | *(pkeys + 0) = 305419896L; 73 | *(pkeys + 1) = 591751049L; 74 | *(pkeys + 2) = 878082192L; 75 | while (*passwd != '\0') { 76 | update_keys(pkeys, pcrc_32_tab, (int)*passwd); 77 | passwd++; 78 | } 79 | } 80 | 81 | #define zdecode(pkeys, pcrc_32_tab, c) (update_keys(pkeys, pcrc_32_tab, c ^= decrypt_byte(pkeys, pcrc_32_tab))) 82 | 83 | #define zencode(pkeys, pcrc_32_tab, c, t) \ 84 | (t = decrypt_byte(pkeys, pcrc_32_tab), update_keys(pkeys, pcrc_32_tab, c), (Byte)t ^ (c)) 85 | -------------------------------------------------------------------------------- /compat/ioapi.c: -------------------------------------------------------------------------------- 1 | #include "mz.h" 2 | #include "mz_strm.h" 3 | #include "mz_strm_mem.h" 4 | 5 | #include "ioapi.h" 6 | 7 | typedef struct mz_stream_ioapi_s { 8 | mz_stream stream; 9 | void *handle; 10 | zlib_filefunc_def filefunc; 11 | zlib_filefunc64_def filefunc64; 12 | } mz_stream_ioapi; 13 | 14 | /***************************************************************************/ 15 | 16 | static int32_t mz_stream_ioapi_open(void *stream, const char *path, int32_t mode); 17 | static int32_t mz_stream_ioapi_is_open(void *stream); 18 | static int32_t mz_stream_ioapi_read(void *stream, void *buf, int32_t size); 19 | static int32_t mz_stream_ioapi_write(void *stream, const void *buf, int32_t size); 20 | static int64_t mz_stream_ioapi_tell(void *stream); 21 | static int32_t mz_stream_ioapi_seek(void *stream, int64_t offset, int32_t origin); 22 | static int32_t mz_stream_ioapi_close(void *stream); 23 | static int32_t mz_stream_ioapi_error(void *stream); 24 | 25 | /***************************************************************************/ 26 | 27 | static mz_stream_vtbl mz_stream_ioapi_vtbl = {mz_stream_ioapi_open, 28 | mz_stream_ioapi_is_open, 29 | mz_stream_ioapi_read, 30 | mz_stream_ioapi_write, 31 | mz_stream_ioapi_tell, 32 | mz_stream_ioapi_seek, 33 | mz_stream_ioapi_close, 34 | mz_stream_ioapi_error, 35 | mz_stream_ioapi_create, 36 | mz_stream_ioapi_delete, 37 | NULL, 38 | NULL}; 39 | 40 | /***************************************************************************/ 41 | 42 | static int32_t mz_stream_ioapi_open(void *stream, const char *path, int32_t mode) { 43 | mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; 44 | int32_t ioapi_mode = 0; 45 | 46 | if ((mode & MZ_OPEN_MODE_READWRITE) == MZ_OPEN_MODE_READ) 47 | ioapi_mode = ZLIB_FILEFUNC_MODE_READ; 48 | else if (mode & MZ_OPEN_MODE_APPEND) 49 | ioapi_mode = ZLIB_FILEFUNC_MODE_EXISTING; 50 | else if (mode & MZ_OPEN_MODE_CREATE) 51 | ioapi_mode = ZLIB_FILEFUNC_MODE_CREATE; 52 | else 53 | return MZ_OPEN_ERROR; 54 | 55 | if (ioapi->filefunc64.zopen64_file) 56 | ioapi->handle = ioapi->filefunc64.zopen64_file(ioapi->filefunc64.opaque, path, ioapi_mode); 57 | else if (ioapi->filefunc.zopen_file) 58 | ioapi->handle = ioapi->filefunc.zopen_file(ioapi->filefunc.opaque, path, ioapi_mode); 59 | 60 | if (!ioapi->handle) 61 | return MZ_PARAM_ERROR; 62 | 63 | return MZ_OK; 64 | } 65 | 66 | static int32_t mz_stream_ioapi_is_open(void *stream) { 67 | mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; 68 | if (!ioapi->handle) 69 | return MZ_OPEN_ERROR; 70 | return MZ_OK; 71 | } 72 | 73 | static int32_t mz_stream_ioapi_read(void *stream, void *buf, int32_t size) { 74 | mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; 75 | read_file_func zread = NULL; 76 | void *opaque = NULL; 77 | 78 | if (mz_stream_ioapi_is_open(stream) != MZ_OK) 79 | return MZ_OPEN_ERROR; 80 | 81 | if (ioapi->filefunc64.zread_file) { 82 | zread = ioapi->filefunc64.zread_file; 83 | opaque = ioapi->filefunc64.opaque; 84 | } else if (ioapi->filefunc.zread_file) { 85 | zread = ioapi->filefunc.zread_file; 86 | opaque = ioapi->filefunc.opaque; 87 | } else 88 | return MZ_PARAM_ERROR; 89 | 90 | return (int32_t)zread(opaque, ioapi->handle, buf, size); 91 | } 92 | 93 | static int32_t mz_stream_ioapi_write(void *stream, const void *buf, int32_t size) { 94 | mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; 95 | write_file_func zwrite = NULL; 96 | int32_t written = 0; 97 | void *opaque = NULL; 98 | 99 | if (mz_stream_ioapi_is_open(stream) != MZ_OK) 100 | return MZ_OPEN_ERROR; 101 | 102 | if (ioapi->filefunc64.zwrite_file) { 103 | zwrite = ioapi->filefunc64.zwrite_file; 104 | opaque = ioapi->filefunc64.opaque; 105 | } else if (ioapi->filefunc.zwrite_file) { 106 | zwrite = ioapi->filefunc.zwrite_file; 107 | opaque = ioapi->filefunc.opaque; 108 | } else 109 | return MZ_PARAM_ERROR; 110 | 111 | written = (int32_t)zwrite(opaque, ioapi->handle, buf, size); 112 | return written; 113 | } 114 | 115 | static int64_t mz_stream_ioapi_tell(void *stream) { 116 | mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; 117 | 118 | if (mz_stream_ioapi_is_open(stream) != MZ_OK) 119 | return MZ_OPEN_ERROR; 120 | 121 | if (ioapi->filefunc64.ztell64_file) 122 | return ioapi->filefunc64.ztell64_file(ioapi->filefunc64.opaque, ioapi->handle); 123 | else if (ioapi->filefunc.ztell_file) 124 | return ioapi->filefunc.ztell_file(ioapi->filefunc.opaque, ioapi->handle); 125 | 126 | return MZ_INTERNAL_ERROR; 127 | } 128 | 129 | static int32_t mz_stream_ioapi_seek(void *stream, int64_t offset, int32_t origin) { 130 | mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; 131 | 132 | if (mz_stream_ioapi_is_open(stream) != MZ_OK) 133 | return MZ_OPEN_ERROR; 134 | 135 | if (ioapi->filefunc64.zseek64_file) { 136 | if (ioapi->filefunc64.zseek64_file(ioapi->filefunc64.opaque, ioapi->handle, offset, origin) != 0) 137 | return MZ_INTERNAL_ERROR; 138 | } else if (ioapi->filefunc.zseek_file) { 139 | if (ioapi->filefunc.zseek_file(ioapi->filefunc.opaque, ioapi->handle, (int32_t)offset, origin) != 0) 140 | return MZ_INTERNAL_ERROR; 141 | } else 142 | return MZ_PARAM_ERROR; 143 | 144 | return MZ_OK; 145 | } 146 | 147 | static int32_t mz_stream_ioapi_close(void *stream) { 148 | mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; 149 | close_file_func zclose = NULL; 150 | void *opaque = NULL; 151 | 152 | if (mz_stream_ioapi_is_open(stream) != MZ_OK) 153 | return MZ_OPEN_ERROR; 154 | 155 | if (ioapi->filefunc.zclose_file) { 156 | zclose = ioapi->filefunc.zclose_file; 157 | opaque = ioapi->filefunc.opaque; 158 | } else if (ioapi->filefunc64.zclose_file) { 159 | zclose = ioapi->filefunc64.zclose_file; 160 | opaque = ioapi->filefunc64.opaque; 161 | } else 162 | return MZ_PARAM_ERROR; 163 | 164 | if (zclose(opaque, ioapi->handle) != 0) 165 | return MZ_CLOSE_ERROR; 166 | ioapi->handle = NULL; 167 | return MZ_OK; 168 | } 169 | 170 | static int32_t mz_stream_ioapi_error(void *stream) { 171 | mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; 172 | testerror_file_func zerror = NULL; 173 | void *opaque = NULL; 174 | 175 | if (mz_stream_ioapi_is_open(stream) != MZ_OK) 176 | return MZ_OPEN_ERROR; 177 | 178 | if (ioapi->filefunc.zerror_file) { 179 | zerror = ioapi->filefunc.zerror_file; 180 | opaque = ioapi->filefunc.opaque; 181 | } else if (ioapi->filefunc64.zerror_file) { 182 | zerror = ioapi->filefunc64.zerror_file; 183 | opaque = ioapi->filefunc64.opaque; 184 | } else 185 | return MZ_PARAM_ERROR; 186 | 187 | return zerror(opaque, ioapi->handle); 188 | } 189 | 190 | int32_t mz_stream_ioapi_set_filefunc(void *stream, zlib_filefunc_def *filefunc) { 191 | mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; 192 | memcpy(&ioapi->filefunc, filefunc, sizeof(zlib_filefunc_def)); 193 | return MZ_OK; 194 | } 195 | 196 | int32_t mz_stream_ioapi_set_filefunc64(void *stream, zlib_filefunc64_def *filefunc) { 197 | mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; 198 | memcpy(&ioapi->filefunc64, filefunc, sizeof(zlib_filefunc64_def)); 199 | return MZ_OK; 200 | } 201 | 202 | void *mz_stream_ioapi_create(void) { 203 | mz_stream_ioapi *ioapi = (mz_stream_ioapi *)calloc(1, sizeof(mz_stream_ioapi)); 204 | if (ioapi) 205 | ioapi->stream.vtbl = &mz_stream_ioapi_vtbl; 206 | return ioapi; 207 | } 208 | 209 | void mz_stream_ioapi_delete(void **stream) { 210 | mz_stream_ioapi *ioapi = NULL; 211 | if (!stream) 212 | return; 213 | ioapi = (mz_stream_ioapi *)*stream; 214 | free(ioapi); 215 | *stream = NULL; 216 | } 217 | 218 | /***************************************************************************/ 219 | 220 | void fill_fopen_filefunc(zlib_filefunc_def *pzlib_filefunc_def) { 221 | /* For 32-bit file support only, compile with MZ_FILE32_API */ 222 | if (pzlib_filefunc_def) 223 | memset(pzlib_filefunc_def, 0, sizeof(zlib_filefunc_def)); 224 | } 225 | 226 | void fill_fopen64_filefunc(zlib_filefunc64_def *pzlib_filefunc_def) { 227 | /* All mz_stream_os_* support large files if compilation supports it */ 228 | if (pzlib_filefunc_def) 229 | memset(pzlib_filefunc_def, 0, sizeof(zlib_filefunc64_def)); 230 | } 231 | 232 | void fill_win32_filefunc(zlib_filefunc_def *pzlib_filefunc_def) { 233 | /* Handled by mz_stream_os_win32 */ 234 | if (pzlib_filefunc_def) 235 | memset(pzlib_filefunc_def, 0, sizeof(zlib_filefunc_def)); 236 | } 237 | 238 | void fill_win32_filefunc64(zlib_filefunc64_def *pzlib_filefunc_def) { 239 | /* Automatically supported in mz_stream_os_win32 */ 240 | if (pzlib_filefunc_def) 241 | memset(pzlib_filefunc_def, 0, sizeof(zlib_filefunc64_def)); 242 | } 243 | 244 | void fill_win32_filefunc64A(zlib_filefunc64_def *pzlib_filefunc_def) { 245 | /* Automatically supported in mz_stream_os_win32 */ 246 | if (pzlib_filefunc_def) 247 | memset(pzlib_filefunc_def, 0, sizeof(zlib_filefunc64_def)); 248 | } 249 | 250 | /* NOTE: fill_win32_filefunc64W is no longer necessary since wide-character 251 | support is automatically handled by the underlying os stream. Do not 252 | pass wide-characters to zipOpen or unzOpen. */ 253 | 254 | void fill_memory_filefunc(zlib_filefunc_def *pzlib_filefunc_def) { 255 | /* Use opaque to indicate which stream interface to create */ 256 | if (pzlib_filefunc_def) { 257 | memset(pzlib_filefunc_def, 0, sizeof(zlib_filefunc_def)); 258 | pzlib_filefunc_def->opaque = mz_stream_mem_get_interface(); 259 | } 260 | } 261 | -------------------------------------------------------------------------------- /compat/ioapi.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef ZLIBIOAPI64_H 3 | #define ZLIBIOAPI64_H 4 | 5 | #include 6 | 7 | typedef uint64_t ZPOS64_T; 8 | 9 | #ifndef ZEXPORT 10 | # define ZEXPORT 11 | #endif 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | /***************************************************************************/ 18 | 19 | #define ZLIB_FILEFUNC_SEEK_SET (0) 20 | #define ZLIB_FILEFUNC_SEEK_CUR (1) 21 | #define ZLIB_FILEFUNC_SEEK_END (2) 22 | 23 | #define ZLIB_FILEFUNC_MODE_READ (1) 24 | #define ZLIB_FILEFUNC_MODE_WRITE (2) 25 | #define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) 26 | 27 | #define ZLIB_FILEFUNC_MODE_EXISTING (4) 28 | #define ZLIB_FILEFUNC_MODE_CREATE (8) 29 | 30 | #ifndef ZCALLBACK 31 | # define ZCALLBACK 32 | #endif 33 | 34 | /***************************************************************************/ 35 | 36 | typedef void *(ZCALLBACK *open_file_func)(void *opaque, const char *filename, int mode); 37 | typedef void *(ZCALLBACK *open64_file_func)(void *opaque, const void *filename, int mode); 38 | typedef unsigned long(ZCALLBACK *read_file_func)(void *opaque, void *stream, void *buf, unsigned long size); 39 | typedef unsigned long(ZCALLBACK *write_file_func)(void *opaque, void *stream, const void *buf, unsigned long size); 40 | typedef int(ZCALLBACK *close_file_func)(void *opaque, void *stream); 41 | typedef int(ZCALLBACK *testerror_file_func)(void *opaque, void *stream); 42 | typedef long(ZCALLBACK *tell_file_func)(void *opaque, void *stream); 43 | typedef ZPOS64_T(ZCALLBACK *tell64_file_func)(void *opaque, void *stream); 44 | typedef long(ZCALLBACK *seek_file_func)(void *opaque, void *stream, unsigned long offset, int origin); 45 | typedef long(ZCALLBACK *seek64_file_func)(void *opaque, void *stream, ZPOS64_T offset, int origin); 46 | 47 | /***************************************************************************/ 48 | 49 | typedef struct zlib_filefunc_def_s { 50 | open_file_func zopen_file; 51 | read_file_func zread_file; 52 | write_file_func zwrite_file; 53 | tell_file_func ztell_file; 54 | seek_file_func zseek_file; 55 | close_file_func zclose_file; 56 | testerror_file_func zerror_file; 57 | void *opaque; 58 | } zlib_filefunc_def; 59 | 60 | typedef struct zlib_filefunc64_def_s { 61 | open64_file_func zopen64_file; 62 | read_file_func zread_file; 63 | write_file_func zwrite_file; 64 | tell64_file_func ztell64_file; 65 | seek64_file_func zseek64_file; 66 | close_file_func zclose_file; 67 | testerror_file_func zerror_file; 68 | void *opaque; 69 | } zlib_filefunc64_def; 70 | 71 | /***************************************************************************/ 72 | 73 | /* Compatibility layer with the original minizip library (ioapi.h and iowin32.h). */ 74 | ZEXPORT void fill_fopen_filefunc(zlib_filefunc_def *pzlib_filefunc_def); 75 | ZEXPORT void fill_fopen64_filefunc(zlib_filefunc64_def *pzlib_filefunc_def); 76 | ZEXPORT void fill_win32_filefunc(zlib_filefunc_def *pzlib_filefunc_def); 77 | ZEXPORT void fill_win32_filefunc64(zlib_filefunc64_def *pzlib_filefunc_def); 78 | ZEXPORT void fill_win32_filefunc64A(zlib_filefunc64_def *pzlib_filefunc_def); 79 | 80 | /* Compatibility layer with older minizip-ng (ioapi_mem.h). */ 81 | ZEXPORT void fill_memory_filefunc(zlib_filefunc_def *pzlib_filefunc_def); 82 | 83 | /***************************************************************************/ 84 | 85 | int32_t mz_stream_ioapi_set_filefunc(void *stream, zlib_filefunc_def *filefunc); 86 | int32_t mz_stream_ioapi_set_filefunc64(void *stream, zlib_filefunc64_def *filefunc); 87 | 88 | void *mz_stream_ioapi_create(void); 89 | void mz_stream_ioapi_delete(void **stream); 90 | 91 | /***************************************************************************/ 92 | 93 | #ifdef __cplusplus 94 | } 95 | #endif 96 | 97 | #endif 98 | -------------------------------------------------------------------------------- /compat/zip.h: -------------------------------------------------------------------------------- 1 | /* zip.h -- Backwards compatible zip interface 2 | part of the minizip-ng project 3 | 4 | Copyright (C) Nathan Moinvaziri 5 | https://github.com/zlib-ng/minizip-ng 6 | Copyright (C) 1998-2010 Gilles Vollant 7 | https://www.winimage.com/zLibDll/minizip.html 8 | 9 | This program is distributed under the terms of the same license as zlib. 10 | See the accompanying LICENSE file for the full text of the license. 11 | */ 12 | 13 | #ifndef _zip64_H 14 | #define _zip64_H 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | #include 21 | 22 | #if !defined(_ZLIB_H) && !defined(ZLIB_H) && !defined(ZLIB_H_) 23 | # if __has_include() 24 | # include 25 | # elif __has_include() 26 | # include 27 | # endif 28 | #endif 29 | 30 | #ifndef _ZLIBIOAPI_H 31 | # include "ioapi.h" 32 | #endif 33 | 34 | /***************************************************************************/ 35 | 36 | #if defined(STRICTZIP) || defined(STRICTZIPUNZIP) 37 | /* like the STRICT of WIN32, we define a pointer that cannot be converted 38 | from (void*) without cast */ 39 | typedef struct TagzipFile__ { 40 | int unused; 41 | } zipFile__; 42 | typedef zipFile__ *zipFile; 43 | #else 44 | typedef void *zipFile; 45 | #endif 46 | 47 | /***************************************************************************/ 48 | 49 | #define ZIP_OK (0) 50 | #define ZIP_EOF (0) 51 | #define ZIP_ERRNO (-1) /* Z_ERRNO */ 52 | #define ZIP_PARAMERROR (-102) 53 | #define ZIP_BADZIPFILE (-103) 54 | #define ZIP_INTERNALERROR (-104) 55 | 56 | /***************************************************************************/ 57 | /* default memLevel */ 58 | #ifndef DEF_MEM_LEVEL 59 | # if MAX_MEM_LEVEL >= 8 60 | # define DEF_MEM_LEVEL 8 61 | # else 62 | # define DEF_MEM_LEVEL MAX_MEM_LEVEL 63 | # endif 64 | #endif 65 | 66 | /***************************************************************************/ 67 | /* tm_zip contain date/time info */ 68 | typedef struct tm_zip_s { 69 | int tm_sec; /* seconds after the minute - [0,59] */ 70 | int tm_min; /* minutes after the hour - [0,59] */ 71 | int tm_hour; /* hours since midnight - [0,23] */ 72 | int tm_mday; /* day of the month - [1,31] */ 73 | int tm_mon; /* months since January - [0,11] */ 74 | int tm_year; /* years - [1980..2044] */ 75 | } tm_zip; 76 | 77 | /***************************************************************************/ 78 | 79 | #if !defined(MZ_COMPAT_VERSION) || MZ_COMPAT_VERSION <= 110 80 | # define mz_dos_date dosDate 81 | #else 82 | # define mz_dos_date dos_date 83 | #endif 84 | 85 | typedef struct { 86 | tm_zip tmz_date; /* date in understandable format */ 87 | unsigned long mz_dos_date; /* if dos_date == 0, tmz_date is used */ 88 | unsigned long internal_fa; /* internal file attributes 2 bytes */ 89 | unsigned long external_fa; /* external file attributes 4 bytes */ 90 | } zip_fileinfo; 91 | 92 | typedef const char *zipcharpc; 93 | 94 | #define APPEND_STATUS_CREATE (0) 95 | #define APPEND_STATUS_CREATEAFTER (1) 96 | #define APPEND_STATUS_ADDINZIP (2) 97 | 98 | /***************************************************************************/ 99 | /* Writing a zip file */ 100 | 101 | /* Compatibility layer with the original minizip library (zip.h). */ 102 | ZEXPORT zipFile zipOpen(const char *path, int append); 103 | ZEXPORT zipFile zipOpen64(const void *path, int append); 104 | 105 | ZEXPORT zipFile zipOpen2(const char *path, int append, zipcharpc *globalcomment, zlib_filefunc_def *pzlib_filefunc_def); 106 | ZEXPORT zipFile zipOpen2_64(const void *path, int append, zipcharpc *globalcomment, 107 | zlib_filefunc64_def *pzlib_filefunc_def); 108 | /* zipOpen3 is not supported */ 109 | 110 | ZEXPORT int zipOpenNewFileInZip(zipFile file, const char *filename, const zip_fileinfo *zipfi, 111 | const void *extrafield_local, uint16_t size_extrafield_local, 112 | const void *extrafield_global, uint16_t size_extrafield_global, const char *comment, 113 | int compression_method, int level); 114 | ZEXPORT int zipOpenNewFileInZip64(zipFile file, const char *filename, const zip_fileinfo *zipfi, 115 | const void *extrafield_local, uint16_t size_extrafield_local, 116 | const void *extrafield_global, uint16_t size_extrafield_global, const char *comment, 117 | int compression_method, int level, int zip64); 118 | ZEXPORT int zipOpenNewFileInZip2(zipFile file, const char *filename, const zip_fileinfo *zipfi, 119 | const void *extrafield_local, uint16_t size_extrafield_local, 120 | const void *extrafield_global, uint16_t size_extrafield_global, const char *comment, 121 | int compression_method, int level, int raw); 122 | ZEXPORT int zipOpenNewFileInZip2_64(zipFile file, const char *filename, const zip_fileinfo *zipfi, 123 | const void *extrafield_local, uint16_t size_extrafield_local, 124 | const void *extrafield_global, uint16_t size_extrafield_global, const char *comment, 125 | int compression_method, int level, int raw, int zip64); 126 | ZEXPORT int zipOpenNewFileInZip3(zipFile file, const char *filename, const zip_fileinfo *zipfi, 127 | const void *extrafield_local, uint16_t size_extrafield_local, 128 | const void *extrafield_global, uint16_t size_extrafield_global, const char *comment, 129 | int compression_method, int level, int raw, int windowBits, int memLevel, int strategy, 130 | const char *password, unsigned long crc_for_crypting); 131 | ZEXPORT int zipOpenNewFileInZip3_64(zipFile file, const char *filename, const zip_fileinfo *zipfi, 132 | const void *extrafield_local, uint16_t size_extrafield_local, 133 | const void *extrafield_global, uint16_t size_extrafield_global, const char *comment, 134 | int compression_method, int level, int raw, int windowBits, int memLevel, 135 | int strategy, const char *password, unsigned long crc_for_crypting, int zip64); 136 | ZEXPORT int zipOpenNewFileInZip4(zipFile file, const char *filename, const zip_fileinfo *zipfi, 137 | const void *extrafield_local, uint16_t size_extrafield_local, 138 | const void *extrafield_global, uint16_t size_extrafield_global, const char *comment, 139 | int compression_method, int level, int raw, int windowBits, int memLevel, int strategy, 140 | const char *password, unsigned long crc_for_crypting, unsigned long version_madeby, 141 | unsigned long flag_base); 142 | ZEXPORT int zipOpenNewFileInZip4_64(zipFile file, const char *filename, const zip_fileinfo *zipfi, 143 | const void *extrafield_local, uint16_t size_extrafield_local, 144 | const void *extrafield_global, uint16_t size_extrafield_global, const char *comment, 145 | int compression_method, int level, int raw, int windowBits, int memLevel, 146 | int strategy, const char *password, unsigned long crc_for_crypting, 147 | unsigned long version_madeby, unsigned long flag_base, int zip64); 148 | ZEXPORT int zipWriteInFileInZip(zipFile file, const void *buf, uint32_t len); 149 | ZEXPORT int zipCloseFileInZipRaw(zipFile file, unsigned long uncompressed_size, unsigned long crc32); 150 | ZEXPORT int zipCloseFileInZipRaw64(zipFile file, uint64_t uncompressed_size, unsigned long crc32); 151 | ZEXPORT int zipCloseFileInZip(zipFile file); 152 | /* zipAlreadyThere is too new */ 153 | ZEXPORT int zipClose(zipFile file, const char *global_comment); 154 | /* zipRemoveExtraInfoBlock is not supported */ 155 | 156 | /* Compatibility layer with older minizip-ng (mz_zip.h). */ 157 | ZEXPORT zipFile zipOpen_MZ(void *stream, int append, zipcharpc *globalcomment); 158 | ZEXPORT void *zipGetHandle_MZ(zipFile); 159 | ZEXPORT void *zipGetStream_MZ(zipFile file); 160 | ZEXPORT int zipOpenNewFileInZip_64(zipFile file, const char *filename, const zip_fileinfo *zipfi, 161 | const void *extrafield_local, uint16_t size_extrafield_local, 162 | const void *extrafield_global, uint16_t size_extrafield_global, const char *comment, 163 | int compression_method, int level, int zip64); 164 | ZEXPORT int zipOpenNewFileInZip5(zipFile file, const char *filename, const zip_fileinfo *zipfi, 165 | const void *extrafield_local, uint16_t size_extrafield_local, 166 | const void *extrafield_global, uint16_t size_extrafield_global, const char *comment, 167 | int compression_method, int level, int raw, int windowBits, int memLevel, int strategy, 168 | const char *password, unsigned long crc_for_crypting, unsigned long version_madeby, 169 | unsigned long flag_base, int zip64); 170 | ZEXPORT int zipCloseFileInZip64(zipFile file); 171 | ZEXPORT int zipClose_64(zipFile file, const char *global_comment); 172 | ZEXPORT int zipClose2_64(zipFile file, const char *global_comment, uint16_t version_madeby); 173 | int zipClose_MZ(zipFile file, const char *global_comment); 174 | int zipClose2_MZ(zipFile file, const char *global_comment, uint16_t version_madeby); 175 | 176 | #ifdef __cplusplus 177 | } 178 | #endif 179 | 180 | #endif /* _zip64_H */ 181 | -------------------------------------------------------------------------------- /doc/mz_compress_level.md: -------------------------------------------------------------------------------- 1 | # MZ_COMPRESS_LEVEL 2 | 3 | Compression level enumeration. 4 | 5 | |Name|Code|Description| 6 | |-|-|-| 7 | |MZ_COMPRESS_LEVEL_DEFAULT|-1|Default compression level (6)| 8 | |MZ_COMPRESS_LEVEL_FAST|2|Fast compression level| 9 | |MZ_COMPRESS_LEVEL_NORMAL|6|Mid compression level| 10 | |MZ_COMPRESS_LEVEL_BEST|9|Slow compression level| -------------------------------------------------------------------------------- /doc/mz_compress_method.md: -------------------------------------------------------------------------------- 1 | # MZ_COMPRESS_METHOD 2 | 3 | Compression method enumeration. 4 | 5 | |Name|Code|Description| 6 | |-|-|-| 7 | |MZ_COMPRESS_METHOD_STORE|0|No compression| 8 | |MZ_COMPRESS_METHOD_DEFLATE|8|Deflate compression| 9 | |MZ_COMPRESS_METHOD_BZIP2|12|Bzip2 compression| 10 | |MZ_COMPRESS_METHOD_LZMA|14|LZMA1 compression| 11 | |MZ_COMPRESS_METHOD_ZSTD|93|ZSTD compression| 12 | |MZ_COMPRESS_METHOD_XZ|95|XZ compression| 13 | 14 | _MZ_COMPRESS_METHOD_AES_ is only for internal use. 15 | -------------------------------------------------------------------------------- /doc/mz_encoding.md: -------------------------------------------------------------------------------- 1 | # MZ_ENCODING 2 | 3 | Character encoding enumeration. Older zip files may store the filename in a different character encoding. 4 | 5 | |Name|Code|Description| 6 | |-|-|-| 7 | |MZ_ENCODING_CODEPAGE_437|437|[Code page 437](https://en.wikipedia.org/wiki/Code_page_437)| 8 | |MZ_ENCODING_CODEPAGE_932|932|[Code page 932](https://en.wikipedia.org/wiki/Code_page_932)| 9 | |MZ_ENCODING_CODEPAGE_936|936|[Code page 936](https://en.wikipedia.org/wiki/Code_page_936)| 10 | |MZ_ENCODING_CODEPAGE_950|950|[Code page 950](https://en.wikipedia.org/wiki/Code_page_950)| 11 | |MZ_ENCODING_CODEPAGE_UTF8|65001|[UTF-8](https://en.wikipedia.org/wiki/UTF-8)| 12 | -------------------------------------------------------------------------------- /doc/mz_error.md: -------------------------------------------------------------------------------- 1 | # MZ_ERROR 2 | 3 | Error code enumeration. These errors codes are compatible with and extend zlib error codes. 4 | 5 | |Name|Code|Description| 6 | |-|-|-| 7 | |MZ_OK|0|OK error (zlib)| 8 | |MZ_STREAM_ERROR|-1|Stream error (zlib)| 9 | |MZ_DATA_ERROR|-3|Data error (zlib)| 10 | |MZ_MEM_ERROR|-4|Memory allocation error (zlib)| 11 | |MZ_BUF_ERROR|-5|Buffer error (zlib)| 12 | |MZ_VERSION_ERROR|-6|Version error (zlib)| 13 | |MZ_END_OF_LIST|-100|End of list error| 14 | |MZ_END_OF_STREAM|-101|End of stream error| 15 | |MZ_PARAM_ERROR|-102|Invalid parameter error| 16 | |MZ_FORMAT_ERROR|-103|File format error| 17 | |MZ_INTERNAL_ERROR|-104|Library internal error| 18 | |MZ_CRC_ERROR|-105|CRC error| 19 | |MZ_CRYPT_ERROR|-106|Cryptography error| 20 | |MZ_EXIST_ERROR|-107|Does not exist error| 21 | |MZ_PASSWORD_ERROR|-108|Invalid password error| 22 | |MZ_SUPPORT_ERROR|-109|Library support error| 23 | |MZ_HASH_ERROR|-110|Hash error| 24 | |MZ_OPEN_ERROR|-111|Stream open error| 25 | |MZ_CLOSE_ERROR|-112|Stream close error| 26 | |MZ_SEEK_ERROR|-113|Stream seek error| 27 | |MZ_TELL_ERROR|-114|Stream tell error| 28 | |MZ_READ_ERROR|-115|Stream read error| 29 | |MZ_WRITE_ERROR|-116|Stream write error| 30 | |MZ_SIGN_ERROR|-117|Signing error| 31 | |MZ_SYMLINK_ERROR|-118|Symbolic link error| 32 | -------------------------------------------------------------------------------- /doc/mz_extrafield.md: -------------------------------------------------------------------------------- 1 | # Extrafields 2 | 3 | These are proposals for additional extrafields that are not in the ZIP specification. 4 | 5 | ## Hash (0x1a51) 6 | 7 | |Size|Type|Description| 8 | |-|-|:-| 9 | |2|uint16_t|Algorithm| 10 | |2|uint16_t|Digest size| 11 | |*|uint8_t*|Digest| 12 | 13 | |Value|Description| 14 | |-|:-| 15 | |10|MD5| 16 | |20|SHA1| 17 | |23|SHA256| 18 | 19 | By default, the ZIP specification only includes a CRC hash of the uncompressed content. The Hash extrafield allows additional hash digests of the uncompressed content to be stored with the central directory or local file headers. If there are multiple Hash extrafields stored for an entry, they should be sorted in order of most secure to least secure. So that the first Hash extrafield that appears for the entry is always the one considered the most secure and the one used for signing. 20 | 21 | ## Central Directory (0xcdcd) 22 | 23 | |Size|Type|Description| 24 | |-|-|:-| 25 | |8|uint64_t|Number of entries| 26 | 27 | If the zip entry is the central directory for the archive, then this record contains information about that central directory. 28 | -------------------------------------------------------------------------------- /doc/mz_hash.md: -------------------------------------------------------------------------------- 1 | # MZ_HASH 2 | 3 | Hash algorithm enumeration. The _mz_zip_reader_ and _mz_zip_writer_ instances support storing more secure hash algorithms for each zip entry. 4 | 5 | |Name|Code|Description| 6 | |-|-|-| 7 | |MZ_HASH_MD5|10|MD5 algorithm identifier| 8 | |MZ_HASH_MD5_SIZE|16|MD5 digest size| 9 | |MZ_HASH_SHA1|20|SHA1 algorithm identifier| 10 | |MZ_HASH_SHA1_SIZE|20|SHA1 digest size| 11 | |MZ_HASH_SHA256|23|SHA256 algorithm identifer| 12 | |MZ_HASH_SHA256_SIZE|32|SHA256 digest size| 13 | -------------------------------------------------------------------------------- /doc/mz_host_system.md: -------------------------------------------------------------------------------- 1 | # MZ_HOST_SYSTEM 2 | 3 | Host system enumeration. These values correspond to section 4.4.2.2 of the [PKWARE zip app note](zip/appnote.txt). 4 | 5 | |Name|Code|Description| 6 | |-|-|-| 7 | |MZ_HOST_SYSTEM_MSDOS|0|MS-DOS| 8 | |MZ_HOST_SYSTEM_UNIX|3|UNIX| 9 | |MZ_HOST_SYSTEM_WINDOWS_NTFS|10|Windows NTFS| 10 | |MZ_HOST_SYSTEM_RISCOS|13|RISC OS| 11 | |MZ_HOST_SYSTEM_OSX_DARWIN|19|Darwin| 12 | 13 | The host system information is available in the _version_madeby_ field in _mz_zip_file_. 14 | 15 | **Example** 16 | ``` 17 | mz_zip_file *file_info = NULL; 18 | mz_zip_entry_get_info(zip_handle, &file_info); 19 | int32_t host_sys = MZ_HOST_SYSTEM(file_info->version_madeby); 20 | printf("Host system value: %d\n", host_sys); 21 | if (host_sys == MZ_HOST_SYSTEM_MSDOS) { 22 | printf("Zip entry attributes are MS-DOS compatible\n"); 23 | } 24 | ``` -------------------------------------------------------------------------------- /doc/mz_open_mode.md: -------------------------------------------------------------------------------- 1 | # MZ_OPEN 2 | 3 | Stream open flag enumeration. 4 | 5 | |Name|Code|Description| 6 | |-|-|-| 7 | |MZ_OPEN_MODE_READ|0x01|Open for reading| 8 | |MZ_OPEN_MODE_WRITE|0x02|Open for writing| 9 | |MZ_OPEN_MODE_READWRITE|0x03|Open for reading and writing| 10 | |MZ_OPEN_MODE_APPEND|0x04|Open for appending| 11 | |MZ_OPEN_MODE_CREATE|0x08|Open for creating| 12 | |MZ_OPEN_MODE_EXISTING|0x10|Open existing| -------------------------------------------------------------------------------- /doc/mz_seek.md: -------------------------------------------------------------------------------- 1 | # MZ_SEEK 2 | 3 | Stream seek origin enumeration. 4 | 5 | |Name|Code|Description| 6 | |-|-|-| 7 | |MZ_SEEK_SET|0|Seek from beginning| 8 | |MZ_SEEK_CUR|1|Seek from current position| 9 | |MZ_SEEK_END|2|Seek from end| -------------------------------------------------------------------------------- /doc/mz_zip64.md: -------------------------------------------------------------------------------- 1 | # MZ_ZIP64 2 | 3 | Zip64 mode enumeration. The zip64 extension is documented in [PKWARE zip app note](zip/appnote.txt) section 4.5.3 and provides support for zip files and entries greater than 4GB. These modes are only supported while writing a zip entry. 4 | 5 | |Name|Code|Description| 6 | |-|-|-| 7 | |MZ_ZIP64_AUTO|0|Only store and use zip64 extrafield if compressed size, uncompressed size, or disk offset is greater than -UINT32_MAX_.| 8 | |MZ_ZIP64_FORCE|1|Always use and store zip64 extrafield even if it is not necessary.| 9 | |MZ_ZIP64_DISABLE|2|Never use or store zip64 extrafield. If zip64 is required to write the entry it will result in MZ_PARAM_ERROR.| 10 | -------------------------------------------------------------------------------- /doc/mz_zip_file.md: -------------------------------------------------------------------------------- 1 | # MZ_ZIP_FILE 2 | 3 | Zip entry information structure. The _mz_zip_file_ structure is populated when reading zip entry information and can be used to populate zip entry information when writing zip entries. 4 | 5 | |Type|Name|Description|[PKWARE zip app note](zip/appnote.txt) section| 6 | |-|-|-|-| 7 | |uint16_t|version_madeby|Version made by field|4.4.2| 8 | |uint16_t|version_needed|Version needed to extract|4.4.3| 9 | |uint16_t|flag|General purpose bit flag|4.4.4| 10 | |uint16_t|compression_method|Compression method|4.4.5 [MZ_COMPRESS_METHOD](mz_compress_method.md)| 11 | |time_t|modified_date|Last modified unix timestamp|4.4.6, 4.5.5, 4.5.7| 12 | |time_t|accessed_date|Last accessed unix timestamp|4.5.5, 4.5.7| 13 | |time_t|creation_date|Creation date unix timestamp|4.5.5| 14 | |uint32_t|crc|CRC32-B hash of uncompressed data|4.4.7| 15 | |int64_t|compressed_size|Compressed size|4.4.8| 16 | |int64_t|uncompressed_size|Uncompressed size|4.4.9| 17 | |uint16_t|filename_size|Filename length|4.4.10| 18 | |uint16_t|extrafield_size|Extrafield length|4.4.11| 19 | |uint16_t|comment_size|Comment size|4.4.12| 20 | |uint32_t|disk_number|Starting disk number|4.4.13| 21 | |int64_t|disk_offset|Starting disk offset|4.4.16| 22 | |uint16_t|internal_fa|Internal file attributes|4.4.14| 23 | |uint32_t|external_fa|External file attributes|4.4.15| 24 | |const char *|filename|Filename UTF-8 null-terminated string|4.4.17| 25 | |const uint8_t *|extrafield|Extrafield buffer array|4.4.28| 26 | |const char *|comment|Comment UTF-8 null-terminated string|4.4.18| 27 | |uint16_t|zip64|Zip64 extension mode|[MZ_ZIP64](mz_zip64.md)| 28 | |uint16_t|aes_version|WinZip AES version|[WinZip AES App Note](zip/winzip_aes.md)| 29 | |uint8_t|aes_strength|WinZip AES encryption strength|[WinZip AES App Note](zip/winzip_aes.md)| 30 | 31 | For more information about each field please consult the referenced app note section. 32 | 33 | ## Extended Notes 34 | 35 | ### verison_madeby 36 | 37 | > The upper byte indicates the compatibility of the file attribute information... The lower byte indicates the ZIP specification version... supported by the software used to encode the file. 38 | 39 | The preprocessor define `MZ_VERSION_MADEBY` contains the version made by value for the current compiler runtime. To get the file attribute information use the preprocessor define `MZ_HOST_SYSTEM(version_madeby)`. 40 | 41 | ### version_needed 42 | 43 | When writing zip entries, this will automatically be filled in if the value is zero. 44 | 45 | ### flag 46 | 47 | |Flag|Value|Description| 48 | |-|-|-| 49 | | MZ_ZIP_FLAG_ENCRYPTED | 0x1 | Entry is encrypted. If using AES encryption `aes_version` needs to be set to `MZ_AES_VERSION` | 50 | | MZ_ZIP_FLAG_LZMA_EOS_MARKER | 0x2 | Entry contains LZMA end of stream marker | 51 | | MZ_ZIP_FLAG_DEFLATE_MAX | 0x2 | Entry compressed with deflate max algorithm | 52 | | MZ_ZIP_FLAG_DEFLATE_NORMAL | 0 | Entry compressed with deflate normal algorithm | 53 | | MZ_ZIP_FLAG_DEFLATE_FAST | 0x4 | Entry compressed with deflate fast algorithm | 54 | | MZ_ZIP_FLAG_DEFLATE_SUPER_FAST | MAX + FAST | Entry compressed with deflate super fast algorithm | 55 | | MZ_ZIP_FLAG_DATA_DESCRIPTOR | 0x08 | Entry contains data descriptor bytes at the end of the compressed content which contain the compressed and uncompressed size. Local file header contains zeros for these values. | 56 | | MZ_ZIP_FLAG_UTF8 | 0x800 | Entry filename is UTF-8 encoded | 57 | | MZ_ZIP_FLAG_MASK_LOCAL_INFO | 0x2000 | Local file header info is masked | 58 | 59 | ### creation_date 60 | 61 | Creation date is only supported on Windows. 62 | 63 | ### external_fa 64 | 65 | External file attributes. These attributes are native host system attribute values for the entry. To get the host system use `MZ_HOST_SYSTEM(version_madeby)`. It is possible to convert from one host system's attributes to another using `mz_zip_attrib_convert`. 66 | 67 | ### aes_version 68 | 69 | This attribute must be set to `MZ_AES_VERSION` when AES encryption is used. 70 | 71 | ### aes_strength 72 | 73 | AES encryption strength, by default 256-bit encryption is used for compression. 74 | 75 | |Flag|Value|Description| 76 | |-|-|-| 77 | | MZ_AES_STRENGTH_128 | 0x01 | 128-bit AES encryption | 78 | | MZ_AES_STRENGTH_192 | 0x02 | 192-bit AES encryption | 79 | | MZ_AES_STRENGTH_256 | 0x03 | 256-bit AES encryption | -------------------------------------------------------------------------------- /doc/zip/winzip_aes.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlib-ng/minizip-ng/227f2d35bed866de674028a0ac97a50af778bae1/doc/zip/winzip_aes.md -------------------------------------------------------------------------------- /doc/zip/winzip_aes_attack.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlib-ng/minizip-ng/227f2d35bed866de674028a0ac97a50af778bae1/doc/zip/winzip_aes_attack.pdf -------------------------------------------------------------------------------- /minigzip.c: -------------------------------------------------------------------------------- 1 | /* minigzip.c 2 | part of the minizip-ng project 3 | 4 | Copyright (C) Nathan Moinvaziri 5 | https://github.com/zlib-ng/minizip-ng 6 | 7 | This program is distributed under the terms of the same license as zlib. 8 | See the accompanying LICENSE file for the full text of the license. 9 | */ 10 | 11 | #include "mz.h" 12 | #include "mz_os.h" 13 | #include "mz_strm.h" 14 | #include "mz_strm_os.h" 15 | #include "mz_strm_zlib.h" 16 | 17 | #include /* printf */ 18 | 19 | /***************************************************************************/ 20 | 21 | #define MZ_GZIP_COMPRESS (1) 22 | #define MZ_GZIP_DECOMPRESS (2) 23 | 24 | int32_t minigzip_banner(void); 25 | int32_t minigzip_help(void); 26 | 27 | /***************************************************************************/ 28 | 29 | int32_t minigzip_banner(void) { 30 | printf("Minigzip %s - https://github.com/zlib-ng/minizip-ng\n", MZ_VERSION); 31 | printf("---------------------------------------------------\n"); 32 | return MZ_OK; 33 | } 34 | 35 | int32_t minigzip_help(void) { 36 | printf( 37 | "Usage: minigzip [-x] [-d] [-0 to -9] [files]\n\n" 38 | " -x Extract file\n" 39 | " -d Destination directory\n" 40 | " -0 Store only\n" 41 | " -1 Compress faster\n" 42 | " -9 Compress better\n\n"); 43 | return MZ_OK; 44 | } 45 | 46 | /***************************************************************************/ 47 | 48 | int32_t minigzip_copy(const char *path, const char *destination, int16_t operation, int16_t level) { 49 | void *target_stream = NULL; 50 | void *source_stream = NULL; 51 | void *zlib_stream = NULL; 52 | const char *filename = NULL; 53 | char target_path[1024]; 54 | int32_t err = 0; 55 | 56 | memset(target_path, 0, sizeof(target_path)); 57 | 58 | if (destination) { 59 | if (mz_os_file_exists(destination) != MZ_OK) 60 | mz_dir_make(destination); 61 | } 62 | 63 | if (operation == MZ_GZIP_COMPRESS) { 64 | mz_path_combine(target_path, path, sizeof(target_path)); 65 | strncat(target_path, ".gz", sizeof(target_path) - strlen(target_path) - 1); 66 | printf("Compressing to %s\n", target_path); 67 | } else if (operation == MZ_GZIP_DECOMPRESS) { 68 | if (destination) 69 | mz_path_combine(target_path, destination, sizeof(target_path)); 70 | 71 | if (mz_path_get_filename(path, &filename) != MZ_OK) 72 | filename = path; 73 | 74 | mz_path_combine(target_path, filename, sizeof(target_path)); 75 | mz_path_remove_extension(target_path); 76 | printf("Decompressing to %s\n", target_path); 77 | } 78 | 79 | zlib_stream = mz_stream_zlib_create(); 80 | mz_stream_zlib_set_prop_int64(zlib_stream, MZ_STREAM_PROP_COMPRESS_WINDOW, 15 + 16); 81 | 82 | source_stream = mz_stream_os_create(); 83 | err = mz_stream_os_open(source_stream, path, MZ_OPEN_MODE_READ); 84 | 85 | if (err == MZ_OK) { 86 | target_stream = mz_stream_os_create(); 87 | err = mz_stream_os_open(target_stream, target_path, MZ_OPEN_MODE_CREATE | MZ_OPEN_MODE_WRITE); 88 | 89 | if (err == MZ_OK) { 90 | if (operation == MZ_GZIP_COMPRESS) { 91 | mz_stream_zlib_set_prop_int64(zlib_stream, MZ_STREAM_PROP_COMPRESS_LEVEL, level); 92 | mz_stream_zlib_open(zlib_stream, target_path, MZ_OPEN_MODE_WRITE); 93 | mz_stream_set_base(zlib_stream, target_stream); 94 | err = mz_stream_copy_to_end(zlib_stream, source_stream); 95 | } else if (operation == MZ_GZIP_DECOMPRESS) { 96 | mz_stream_zlib_open(zlib_stream, path, MZ_OPEN_MODE_READ); 97 | mz_stream_set_base(zlib_stream, source_stream); 98 | err = mz_stream_copy_to_end(target_stream, zlib_stream); 99 | } 100 | 101 | if (err != MZ_OK) 102 | printf("Error %d in zlib stream (%d)\n", err, mz_stream_zlib_error(zlib_stream)); 103 | else 104 | printf("Operation completed successfully\n"); 105 | 106 | mz_stream_zlib_close(zlib_stream); 107 | } else { 108 | printf("Error %d opening target path %s\n", err, target_path); 109 | } 110 | 111 | mz_stream_os_close(target_stream); 112 | mz_stream_os_delete(&target_stream); 113 | } else { 114 | printf("Error %d opening source path %s\n", err, path); 115 | } 116 | 117 | mz_stream_os_close(source_stream); 118 | mz_stream_os_delete(&source_stream); 119 | 120 | mz_stream_zlib_delete(&zlib_stream); 121 | return err; 122 | } 123 | 124 | /***************************************************************************/ 125 | 126 | #if !defined(MZ_ZIP_NO_MAIN) 127 | int main(int argc, const char *argv[]) { 128 | int16_t operation_level = MZ_COMPRESS_LEVEL_DEFAULT; 129 | int32_t path_arg = 0; 130 | int32_t err = 0; 131 | int32_t i = 0; 132 | uint8_t operation = MZ_GZIP_COMPRESS; 133 | const char *path = NULL; 134 | const char *destination = NULL; 135 | 136 | minigzip_banner(); 137 | if (argc == 1) { 138 | minigzip_help(); 139 | return 0; 140 | } 141 | 142 | /* Parse command line options */ 143 | for (i = 1; i < argc; i += 1) { 144 | printf("%s ", argv[i]); 145 | if (argv[i][0] == '-') { 146 | char c = argv[i][1]; 147 | if ((c == 'x') || (c == 'X')) 148 | operation = MZ_GZIP_DECOMPRESS; 149 | else if ((c >= '0') && (c <= '9')) 150 | operation_level = (c - '0'); 151 | else if (((c == 'd') || (c == 'D')) && (i + 1 < argc)) { 152 | destination = argv[i + 1]; 153 | printf("%s ", argv[i + 1]); 154 | i += 1; 155 | } else { 156 | err = MZ_SUPPORT_ERROR; 157 | } 158 | } else if (path_arg == 0) { 159 | path_arg = i; 160 | break; 161 | } 162 | } 163 | printf("\n"); 164 | 165 | if (err == MZ_SUPPORT_ERROR) { 166 | printf("Feature not supported\n"); 167 | return err; 168 | } 169 | 170 | if (path_arg == 0) { 171 | minigzip_help(); 172 | return 0; 173 | } 174 | 175 | path = argv[path_arg]; 176 | err = minigzip_copy(path, destination, operation, operation_level); 177 | 178 | return err; 179 | } 180 | #endif 181 | -------------------------------------------------------------------------------- /minizip.pc.cmakein: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | exec_prefix=@CMAKE_INSTALL_PREFIX@ 3 | libdir=@CMAKE_INSTALL_FULL_LIBDIR@ 4 | sharedlibdir=@CMAKE_INSTALL_FULL_LIBDIR@ 5 | includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@/@MINIZIP_TARGET@ 6 | 7 | Name: @MINIZIP_TARGET@ 8 | Description: Zip manipulation library 9 | Version: @VERSION@ 10 | 11 | Requires.private: @PC_PRIVATE_DEPS@ 12 | Libs: -L${libdir} -L${sharedlibdir} -l@MINIZIP_TARGET@ 13 | Libs.private:@PC_PRIVATE_LIBS@ 14 | Cflags: -I${includedir} 15 | -------------------------------------------------------------------------------- /mz.h: -------------------------------------------------------------------------------- 1 | /* mz.h -- Errors codes, zip flags and magic 2 | part of the minizip-ng project 3 | 4 | Copyright (C) Nathan Moinvaziri 5 | https://github.com/zlib-ng/minizip-ng 6 | 7 | This program is distributed under the terms of the same license as zlib. 8 | See the accompanying LICENSE file for the full text of the license. 9 | */ 10 | 11 | #ifndef MZ_H 12 | #define MZ_H 13 | 14 | /***************************************************************************/ 15 | 16 | /* MZ_VERSION */ 17 | #define MZ_VERSION ("4.0.10") 18 | #define MZ_VERSION_BUILD (0x04000A) 19 | 20 | /* MZ_ERROR */ 21 | #define MZ_OK (0) /* zlib */ 22 | #define MZ_STREAM_ERROR (-1) /* zlib */ 23 | #define MZ_DATA_ERROR (-3) /* zlib */ 24 | #define MZ_MEM_ERROR (-4) /* zlib */ 25 | #define MZ_BUF_ERROR (-5) /* zlib */ 26 | #define MZ_VERSION_ERROR (-6) /* zlib */ 27 | 28 | #define MZ_END_OF_LIST (-100) 29 | #define MZ_END_OF_STREAM (-101) 30 | 31 | #define MZ_PARAM_ERROR (-102) 32 | #define MZ_FORMAT_ERROR (-103) 33 | #define MZ_INTERNAL_ERROR (-104) 34 | #define MZ_CRC_ERROR (-105) 35 | #define MZ_CRYPT_ERROR (-106) 36 | #define MZ_EXIST_ERROR (-107) 37 | #define MZ_PASSWORD_ERROR (-108) 38 | #define MZ_SUPPORT_ERROR (-109) 39 | #define MZ_HASH_ERROR (-110) 40 | #define MZ_OPEN_ERROR (-111) 41 | #define MZ_CLOSE_ERROR (-112) 42 | #define MZ_SEEK_ERROR (-113) 43 | #define MZ_TELL_ERROR (-114) 44 | #define MZ_READ_ERROR (-115) 45 | #define MZ_WRITE_ERROR (-116) 46 | #define MZ_SIGN_ERROR (-117) 47 | #define MZ_SYMLINK_ERROR (-118) 48 | 49 | /* MZ_OPEN */ 50 | #define MZ_OPEN_MODE_READ (0x01) 51 | #define MZ_OPEN_MODE_WRITE (0x02) 52 | #define MZ_OPEN_MODE_READWRITE (MZ_OPEN_MODE_READ | MZ_OPEN_MODE_WRITE) 53 | #define MZ_OPEN_MODE_APPEND (0x04) 54 | #define MZ_OPEN_MODE_CREATE (0x08) 55 | #define MZ_OPEN_MODE_EXISTING (0x10) 56 | 57 | /* MZ_SEEK */ 58 | #define MZ_SEEK_SET (0) 59 | #define MZ_SEEK_CUR (1) 60 | #define MZ_SEEK_END (2) 61 | 62 | /* MZ_COMPRESS */ 63 | #define MZ_COMPRESS_METHOD_STORE (0) 64 | #define MZ_COMPRESS_METHOD_DEFLATE (8) 65 | #define MZ_COMPRESS_METHOD_BZIP2 (12) 66 | #define MZ_COMPRESS_METHOD_LZMA (14) 67 | #define MZ_COMPRESS_METHOD_ZSTD (93) 68 | #define MZ_COMPRESS_METHOD_XZ (95) 69 | #define MZ_COMPRESS_METHOD_AES (99) 70 | 71 | #define MZ_COMPRESS_LEVEL_DEFAULT (-1) 72 | #define MZ_COMPRESS_LEVEL_FAST (2) 73 | #define MZ_COMPRESS_LEVEL_NORMAL (6) 74 | #define MZ_COMPRESS_LEVEL_BEST (9) 75 | 76 | /* MZ_ZIP_FLAG */ 77 | #define MZ_ZIP_FLAG_ENCRYPTED (1 << 0) 78 | #define MZ_ZIP_FLAG_LZMA_EOS_MARKER (1 << 1) 79 | #define MZ_ZIP_FLAG_DEFLATE_MAX (1 << 1) 80 | #define MZ_ZIP_FLAG_DEFLATE_NORMAL (0) 81 | #define MZ_ZIP_FLAG_DEFLATE_FAST (1 << 2) 82 | #define MZ_ZIP_FLAG_DEFLATE_SUPER_FAST (MZ_ZIP_FLAG_DEFLATE_FAST | MZ_ZIP_FLAG_DEFLATE_MAX) 83 | #define MZ_ZIP_FLAG_DATA_DESCRIPTOR (1 << 3) 84 | #define MZ_ZIP_FLAG_UTF8 (1 << 11) 85 | #define MZ_ZIP_FLAG_MASK_LOCAL_INFO (1 << 13) 86 | 87 | /* MZ_ZIP_EXTENSION */ 88 | #define MZ_ZIP_EXTENSION_ZIP64 (0x0001) 89 | #define MZ_ZIP_EXTENSION_NTFS (0x000a) 90 | #define MZ_ZIP_EXTENSION_AES (0x9901) 91 | #define MZ_ZIP_EXTENSION_UNIX1 (0x000d) 92 | #define MZ_ZIP_EXTENSION_SIGN (0x10c5) 93 | #define MZ_ZIP_EXTENSION_HASH (0x1a51) 94 | #define MZ_ZIP_EXTENSION_CDCD (0xcdcd) 95 | 96 | /* MZ_ZIP64 */ 97 | #define MZ_ZIP64_AUTO (0) 98 | #define MZ_ZIP64_FORCE (1) 99 | #define MZ_ZIP64_DISABLE (2) 100 | 101 | /* MZ_HOST_SYSTEM */ 102 | #define MZ_HOST_SYSTEM(VERSION_MADEBY) ((uint8_t)(VERSION_MADEBY >> 8)) 103 | #define MZ_HOST_SYSTEM_MSDOS (0) 104 | #define MZ_HOST_SYSTEM_UNIX (3) 105 | #define MZ_HOST_SYSTEM_WINDOWS_NTFS (10) 106 | #define MZ_HOST_SYSTEM_RISCOS (13) 107 | #define MZ_HOST_SYSTEM_OSX_DARWIN (19) 108 | 109 | /* MZ_PKCRYPT */ 110 | #define MZ_PKCRYPT_HEADER_SIZE (12) 111 | 112 | /* MZ_AES */ 113 | #define MZ_AES_VERSION (1) 114 | #define MZ_AES_MODE_ECB (0) 115 | #define MZ_AES_MODE_CBC (1) 116 | #define MZ_AES_MODE_GCM (2) 117 | #define MZ_AES_STRENGTH_128 (1) 118 | #define MZ_AES_STRENGTH_192 (2) 119 | #define MZ_AES_STRENGTH_256 (3) 120 | #define MZ_AES_KEY_LENGTH_MAX (32) 121 | #define MZ_AES_BLOCK_SIZE (16) 122 | #define MZ_AES_FOOTER_SIZE (10) 123 | 124 | /* MZ_HASH */ 125 | #define MZ_HASH_MD5 (10) 126 | #define MZ_HASH_MD5_SIZE (16) 127 | #define MZ_HASH_SHA1 (20) 128 | #define MZ_HASH_SHA1_SIZE (20) 129 | #define MZ_HASH_SHA224 (22) 130 | #define MZ_HASH_SHA224_SIZE (28) 131 | #define MZ_HASH_SHA256 (23) 132 | #define MZ_HASH_SHA256_SIZE (32) 133 | #define MZ_HASH_SHA384 (24) 134 | #define MZ_HASH_SHA384_SIZE (48) 135 | #define MZ_HASH_SHA512 (25) 136 | #define MZ_HASH_SHA512_SIZE (64) 137 | #define MZ_HASH_MAX_SIZE (256) 138 | 139 | /* MZ_ENCODING */ 140 | #define MZ_ENCODING_CODEPAGE_437 (437) 141 | #define MZ_ENCODING_CODEPAGE_932 (932) 142 | #define MZ_ENCODING_CODEPAGE_936 (936) 143 | #define MZ_ENCODING_CODEPAGE_950 (950) 144 | #define MZ_ENCODING_UTF8 (65001) 145 | 146 | /* MZ_UTILITY */ 147 | #define MZ_UNUSED(SYMBOL) ((void)SYMBOL) 148 | 149 | #if defined(_WIN32) && defined(MZ_EXPORTS) 150 | # define MZ_EXPORT __declspec(dllexport) 151 | #else 152 | # define MZ_EXPORT 153 | #endif 154 | 155 | /***************************************************************************/ 156 | 157 | #include /* size_t, NULL, malloc */ 158 | #include /* time_t, time() */ 159 | #include /* memset, strncpy, strlen */ 160 | #include 161 | 162 | #if defined(HAVE_STDINT_H) 163 | # include 164 | #elif defined(__has_include) 165 | # if __has_include() 166 | # include 167 | # endif 168 | #endif 169 | 170 | #ifndef INT8_MAX 171 | typedef signed char int8_t; 172 | #endif 173 | #ifndef INT16_MAX 174 | typedef short int16_t; 175 | #endif 176 | #ifndef INT32_MAX 177 | typedef int int32_t; 178 | #endif 179 | #ifndef INT64_MAX 180 | typedef long long int64_t; 181 | #endif 182 | #ifndef UINT8_MAX 183 | typedef unsigned char uint8_t; 184 | #endif 185 | #ifndef UINT16_MAX 186 | typedef unsigned short uint16_t; 187 | #endif 188 | #ifndef UINT32_MAX 189 | typedef unsigned int uint32_t; 190 | #endif 191 | #ifndef UINT64_MAX 192 | typedef unsigned long long uint64_t; 193 | #endif 194 | 195 | #if defined(HAVE_INTTYPES_H) 196 | # include 197 | #elif defined(__has_include) 198 | # if __has_include() 199 | # include 200 | # endif 201 | #endif 202 | 203 | #ifndef PRId8 204 | # define PRId8 "hhd" 205 | #endif 206 | #ifndef PRIu8 207 | # define PRIu8 "hhu" 208 | #endif 209 | #ifndef PRIx8 210 | # define PRIx8 "hhx" 211 | #endif 212 | #ifndef PRId16 213 | # define PRId16 "hd" 214 | #endif 215 | #ifndef PRIu16 216 | # define PRIu16 "hu" 217 | #endif 218 | #ifndef PRIx16 219 | # define PRIx16 "hx" 220 | #endif 221 | #ifndef PRId32 222 | # define PRId32 "d" 223 | #endif 224 | #ifndef PRIu32 225 | # define PRIu32 "u" 226 | #endif 227 | #ifndef PRIx32 228 | # define PRIx32 "x" 229 | #endif 230 | #if ULONG_MAX == 0xfffffffful 231 | # ifndef PRId64 232 | # define PRId64 "ld" 233 | # endif 234 | # ifndef PRIu64 235 | # define PRIu64 "lu" 236 | # endif 237 | # ifndef PRIx64 238 | # define PRIx64 "lx" 239 | # endif 240 | #else 241 | # ifndef PRId64 242 | # define PRId64 "lld" 243 | # endif 244 | # ifndef PRIu64 245 | # define PRIu64 "llu" 246 | # endif 247 | # ifndef PRIx64 248 | # define PRIx64 "llx" 249 | # endif 250 | #endif 251 | 252 | #ifndef INT16_MAX 253 | # define INT16_MAX 32767 254 | #endif 255 | #ifndef INT32_MAX 256 | # define INT32_MAX 2147483647L 257 | #endif 258 | #ifndef INT64_MAX 259 | # define INT64_MAX 9223372036854775807LL 260 | #endif 261 | #ifndef UINT16_MAX 262 | # define UINT16_MAX 65535U 263 | #endif 264 | #ifndef UINT32_MAX 265 | # define UINT32_MAX 4294967295UL 266 | #endif 267 | #ifndef UINT64_MAX 268 | # define UINT64_MAX 18446744073709551615ULL 269 | #endif 270 | 271 | /***************************************************************************/ 272 | 273 | #endif 274 | -------------------------------------------------------------------------------- /mz_crypt.c: -------------------------------------------------------------------------------- 1 | /* mz_crypt.c -- Crypto/hash functions 2 | part of the minizip-ng project 3 | 4 | Copyright (C) Nathan Moinvaziri 5 | https://github.com/zlib-ng/minizip-ng 6 | 7 | This program is distributed under the terms of the same license as zlib. 8 | See the accompanying LICENSE file for the full text of the license. 9 | */ 10 | 11 | #include "mz.h" 12 | #include "mz_os.h" 13 | #include "mz_crypt.h" 14 | 15 | #if defined(HAVE_ZLIB) 16 | # if !defined(ZLIB_COMPAT) 17 | # include "zlib-ng.h" 18 | # define ZLIB_PREFIX(x) zng_##x 19 | # else 20 | # include "zlib.h" 21 | # define ZLIB_PREFIX(x) x 22 | # endif 23 | #elif defined(HAVE_LZMA) 24 | # include "lzma.h" 25 | #endif 26 | 27 | /***************************************************************************/ 28 | 29 | #if defined(MZ_ZIP_NO_CRYPTO) 30 | int32_t mz_crypt_rand(uint8_t *buf, int32_t size) { 31 | return mz_os_rand(buf, size); 32 | } 33 | #endif 34 | 35 | uint32_t mz_crypt_crc32_update(uint32_t value, const uint8_t *buf, int32_t size) { 36 | #if defined(HAVE_ZLIB) 37 | # ifndef ZLIB_VERNUM 38 | /* HAVE_ZLIB but no ZLIB_VERNUM? */ 39 | typedef uint32_t z_crc_t; 40 | # elif (ZLIB_VERNUM & 0xf != 0xf) && (ZLIB_VERNUM < 0x1270) 41 | /* Define z_crc_t in zlib 1.2.6 and less */ 42 | typedef unsigned long z_crc_t; 43 | # elif (ZLIB_VERNUM & 0xf == 0xf) && (ZLIB_VERNUM < 0x12df) 44 | /* Define z_crc_t in zlib-ng 2.0.7 and less */ 45 | typedef unsigned int z_crc_t; 46 | # endif 47 | return (uint32_t)ZLIB_PREFIX(crc32)((z_crc_t)value, buf, (uInt)size); 48 | #elif defined(HAVE_LZMA) 49 | return (uint32_t)lzma_crc32(buf, (size_t)size, (uint32_t)value); 50 | #else 51 | static uint32_t crc32_table[256] = { 52 | 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 53 | 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 54 | 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 55 | 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 56 | 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 57 | 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 58 | 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 59 | 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 60 | 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 61 | 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 62 | 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 63 | 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 64 | 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 65 | 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 66 | 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 67 | 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 68 | 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 69 | 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 70 | 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 71 | 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 72 | 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 73 | 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 74 | 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 75 | 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 76 | 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 77 | 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 78 | 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 79 | 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 80 | 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d}; 81 | value = ~value; 82 | 83 | while (size > 0) { 84 | value = (value >> 8) ^ crc32_table[(value ^ *buf) & 0xFF]; 85 | 86 | buf += 1; 87 | size -= 1; 88 | } 89 | 90 | return ~value; 91 | #endif 92 | } 93 | 94 | #if defined(HAVE_WZAES) 95 | int32_t mz_crypt_pbkdf2(uint8_t *password, int32_t password_length, uint8_t *salt, int32_t salt_length, 96 | uint32_t iteration_count, uint8_t *key, uint16_t key_length) { 97 | void *hmac1 = NULL; 98 | void *hmac2 = NULL; 99 | void *hmac3 = NULL; 100 | int32_t err = MZ_OK; 101 | uint16_t i = 0; 102 | uint32_t j = 0; 103 | uint16_t k = 0; 104 | uint16_t block_count = 0; 105 | uint8_t uu[MZ_HASH_SHA1_SIZE]; 106 | uint8_t ux[MZ_HASH_SHA1_SIZE]; 107 | 108 | if (!password || !salt || !key) 109 | return MZ_PARAM_ERROR; 110 | 111 | memset(key, 0, key_length); 112 | 113 | hmac1 = mz_crypt_hmac_create(); 114 | hmac2 = mz_crypt_hmac_create(); 115 | hmac3 = mz_crypt_hmac_create(); 116 | 117 | if (!hmac1 || !hmac2 || !hmac3) { 118 | err = MZ_MEM_ERROR; 119 | goto pbkdf2_cleanup; 120 | } 121 | 122 | mz_crypt_hmac_set_algorithm(hmac1, MZ_HASH_SHA1); 123 | mz_crypt_hmac_set_algorithm(hmac2, MZ_HASH_SHA1); 124 | mz_crypt_hmac_set_algorithm(hmac3, MZ_HASH_SHA1); 125 | 126 | err = mz_crypt_hmac_init(hmac1, password, password_length); 127 | if (err == MZ_OK) 128 | err = mz_crypt_hmac_init(hmac2, password, password_length); 129 | if (err == MZ_OK) 130 | err = mz_crypt_hmac_update(hmac2, salt, salt_length); 131 | 132 | block_count = 1 + ((uint16_t)key_length - 1) / MZ_HASH_SHA1_SIZE; 133 | 134 | for (i = 0; (err == MZ_OK) && (i < block_count); i += 1) { 135 | memset(ux, 0, sizeof(ux)); 136 | 137 | err = mz_crypt_hmac_copy(hmac2, hmac3); 138 | if (err != MZ_OK) 139 | break; 140 | 141 | uu[0] = (uint8_t)((i + 1) >> 24); 142 | uu[1] = (uint8_t)((i + 1) >> 16); 143 | uu[2] = (uint8_t)((i + 1) >> 8); 144 | uu[3] = (uint8_t)(i + 1); 145 | 146 | for (j = 0, k = 4; j < iteration_count; j += 1) { 147 | err = mz_crypt_hmac_update(hmac3, uu, k); 148 | if (err == MZ_OK) 149 | err = mz_crypt_hmac_end(hmac3, uu, sizeof(uu)); 150 | if (err != MZ_OK) 151 | break; 152 | 153 | for (k = 0; k < MZ_HASH_SHA1_SIZE; k += 1) 154 | ux[k] ^= uu[k]; 155 | 156 | err = mz_crypt_hmac_copy(hmac1, hmac3); 157 | if (err != MZ_OK) 158 | break; 159 | } 160 | 161 | if (err != MZ_OK) 162 | break; 163 | 164 | j = 0; 165 | k = i * MZ_HASH_SHA1_SIZE; 166 | 167 | while (j < MZ_HASH_SHA1_SIZE && k < key_length) 168 | key[k++] = ux[j++]; 169 | } 170 | 171 | pbkdf2_cleanup: 172 | /* hmac3 uses the same provider as hmac2, so it must be deleted 173 | before the context is destroyed. */ 174 | mz_crypt_hmac_delete(&hmac3); 175 | mz_crypt_hmac_delete(&hmac1); 176 | mz_crypt_hmac_delete(&hmac2); 177 | 178 | return err; 179 | } 180 | #endif 181 | 182 | /***************************************************************************/ 183 | -------------------------------------------------------------------------------- /mz_crypt.h: -------------------------------------------------------------------------------- 1 | /* mz_crypt.h -- Crypto/hash functions 2 | part of the minizip-ng project 3 | 4 | Copyright (C) Nathan Moinvaziri 5 | https://github.com/zlib-ng/minizip-ng 6 | 7 | This program is distributed under the terms of the same license as zlib. 8 | See the accompanying LICENSE file for the full text of the license. 9 | */ 10 | 11 | #ifndef MZ_CRYPT_H 12 | #define MZ_CRYPT_H 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | /***************************************************************************/ 19 | 20 | uint32_t mz_crypt_crc32_update(uint32_t value, const uint8_t *buf, int32_t size); 21 | 22 | int32_t mz_crypt_pbkdf2(uint8_t *password, int32_t password_length, uint8_t *salt, int32_t salt_length, 23 | uint32_t iteration_count, uint8_t *key, uint16_t key_length); 24 | 25 | /***************************************************************************/ 26 | 27 | int32_t mz_crypt_rand(uint8_t *buf, int32_t size); 28 | 29 | void mz_crypt_sha_reset(void *handle); 30 | int32_t mz_crypt_sha_begin(void *handle); 31 | int32_t mz_crypt_sha_update(void *handle, const void *buf, int32_t size); 32 | int32_t mz_crypt_sha_end(void *handle, uint8_t *digest, int32_t digest_size); 33 | int32_t mz_crypt_sha_set_algorithm(void *handle, uint16_t algorithm); 34 | void *mz_crypt_sha_create(void); 35 | void mz_crypt_sha_delete(void **handle); 36 | 37 | void mz_crypt_aes_reset(void *handle); 38 | int32_t mz_crypt_aes_encrypt(void *handle, const void *aad, int32_t aad_size, uint8_t *buf, int32_t size); 39 | int32_t mz_crypt_aes_encrypt_final(void *handle, uint8_t *buf, int32_t size, uint8_t *tag, int32_t tag_size); 40 | int32_t mz_crypt_aes_decrypt(void *handle, const void *aad, int32_t aad_size, uint8_t *buf, int32_t size); 41 | int32_t mz_crypt_aes_decrypt_final(void *handle, uint8_t *buf, int32_t size, const uint8_t *tag, int32_t tag_size); 42 | int32_t mz_crypt_aes_set_encrypt_key(void *handle, const void *key, int32_t key_length, const void *iv, 43 | int32_t iv_length); 44 | int32_t mz_crypt_aes_set_decrypt_key(void *handle, const void *key, int32_t key_length, const void *iv, 45 | int32_t iv_length); 46 | void mz_crypt_aes_set_mode(void *handle, int32_t mode); 47 | void *mz_crypt_aes_create(void); 48 | void mz_crypt_aes_delete(void **handle); 49 | 50 | void mz_crypt_hmac_reset(void *handle); 51 | int32_t mz_crypt_hmac_init(void *handle, const void *key, int32_t key_length); 52 | int32_t mz_crypt_hmac_update(void *handle, const void *buf, int32_t size); 53 | int32_t mz_crypt_hmac_end(void *handle, uint8_t *digest, int32_t digest_size); 54 | int32_t mz_crypt_hmac_copy(void *src_handle, void *target_handle); 55 | void mz_crypt_hmac_set_algorithm(void *handle, uint16_t algorithm); 56 | void *mz_crypt_hmac_create(void); 57 | void mz_crypt_hmac_delete(void **handle); 58 | 59 | /***************************************************************************/ 60 | 61 | #ifdef __cplusplus 62 | } 63 | #endif 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /mz_os.c: -------------------------------------------------------------------------------- 1 | /* mz_os.c -- System functions 2 | part of the minizip-ng project 3 | 4 | Copyright (C) Nathan Moinvaziri 5 | https://github.com/zlib-ng/minizip-ng 6 | Copyright (C) 1998-2010 Gilles Vollant 7 | https://www.winimage.com/zLibDll/minizip.html 8 | 9 | This program is distributed under the terms of the same license as zlib. 10 | See the accompanying LICENSE file for the full text of the license. 11 | */ 12 | 13 | #include "mz.h" 14 | #include "mz_crypt.h" 15 | #include "mz_os.h" 16 | #include "mz_strm.h" 17 | #include "mz_strm_os.h" 18 | 19 | #include /* tolower */ 20 | #include 21 | 22 | /***************************************************************************/ 23 | 24 | int32_t mz_path_combine(char *path, const char *join, int32_t max_path) { 25 | int32_t path_len = 0; 26 | 27 | if (!path || !join || !max_path) 28 | return MZ_PARAM_ERROR; 29 | 30 | path_len = (int32_t)strlen(path); 31 | 32 | if (path_len == 0) { 33 | strncpy(path, join, max_path - 1); 34 | path[max_path - 1] = 0; 35 | } else { 36 | mz_path_append_slash(path, max_path, MZ_PATH_SLASH_PLATFORM); 37 | path_len = (int32_t)strlen(path); 38 | if (max_path > path_len) 39 | strncat(path, join, max_path - path_len - 1); 40 | } 41 | 42 | return MZ_OK; 43 | } 44 | 45 | int32_t mz_path_append_slash(char *path, int32_t max_path, char slash) { 46 | int32_t path_len = (int32_t)strlen(path); 47 | if ((path_len + 2) >= max_path) 48 | return MZ_BUF_ERROR; 49 | if (!mz_os_is_dir_separator(path[path_len - 1])) { 50 | path[path_len] = slash; 51 | path[path_len + 1] = 0; 52 | } 53 | return MZ_OK; 54 | } 55 | 56 | int32_t mz_path_remove_slash(char *path) { 57 | int32_t path_len = (int32_t)strlen(path); 58 | while (path_len > 0) { 59 | if (mz_os_is_dir_separator(path[path_len - 1])) 60 | path[path_len - 1] = 0; 61 | else 62 | break; 63 | 64 | path_len -= 1; 65 | } 66 | return MZ_OK; 67 | } 68 | 69 | int32_t mz_path_has_slash(const char *path) { 70 | int32_t path_len = (int32_t)strlen(path); 71 | if (path_len > 0 && !mz_os_is_dir_separator(path[path_len - 1])) 72 | return MZ_EXIST_ERROR; 73 | return MZ_OK; 74 | } 75 | 76 | int32_t mz_path_convert_slashes(char *path, char slash) { 77 | int32_t i = 0; 78 | 79 | for (i = 0; i < (int32_t)strlen(path); i += 1) { 80 | if (mz_os_is_dir_separator(path[i])) 81 | path[i] = slash; 82 | } 83 | return MZ_OK; 84 | } 85 | 86 | int32_t mz_path_compare_wc(const char *path, const char *wildcard, uint8_t ignore_case) { 87 | while (*path != 0) { 88 | switch (*wildcard) { 89 | case '*': 90 | 91 | if (*(wildcard + 1) == 0) 92 | return MZ_OK; 93 | 94 | while (*path != 0) { 95 | if (mz_path_compare_wc(path, (wildcard + 1), ignore_case) == MZ_OK) 96 | return MZ_OK; 97 | 98 | path += 1; 99 | } 100 | 101 | return MZ_EXIST_ERROR; 102 | 103 | default: 104 | /* Ignore differences in path slashes on platforms */ 105 | if ((*path == '\\' && *wildcard == '/') || (*path == '/' && *wildcard == '\\')) 106 | break; 107 | 108 | if (ignore_case) { 109 | if (tolower(*path) != tolower(*wildcard)) 110 | return MZ_EXIST_ERROR; 111 | } else { 112 | if (*path != *wildcard) 113 | return MZ_EXIST_ERROR; 114 | } 115 | 116 | break; 117 | } 118 | 119 | path += 1; 120 | wildcard += 1; 121 | } 122 | 123 | if ((*wildcard != 0) && (*wildcard != '*')) 124 | return MZ_EXIST_ERROR; 125 | 126 | return MZ_OK; 127 | } 128 | 129 | int32_t mz_path_resolve(const char *path, char *output, int32_t max_output) { 130 | const char *source = path; 131 | const char *check = output; 132 | char *target = output; 133 | 134 | if (max_output <= 0) 135 | return MZ_PARAM_ERROR; 136 | 137 | while (*source != 0 && max_output > 1) { 138 | check = source; 139 | if (mz_os_is_dir_separator(*check)) 140 | check += 1; 141 | 142 | if (source == path || target == output || check != source) { 143 | /* Skip double paths */ 144 | if (mz_os_is_dir_separator(*check)) { 145 | source += 1; 146 | continue; 147 | } 148 | if (*check == '.') { 149 | check += 1; 150 | 151 | /* Remove . if at end of string and not at the beginning */ 152 | if (*check == 0 && source != path && target != output) { 153 | /* Copy last slash */ 154 | *target = *source; 155 | target += 1; 156 | max_output -= 1; 157 | source += (check - source); 158 | continue; 159 | } 160 | /* Remove . if not at end of string */ 161 | else if (mz_os_is_dir_separator(*check)) { 162 | source += (check - source); 163 | /* Skip slash if at beginning of string */ 164 | if (target == output && *source != 0) 165 | source += 1; 166 | continue; 167 | } 168 | /* Go to parent directory .. */ 169 | else if (*check == '.') { 170 | check += 1; 171 | if (*check == 0 || mz_os_is_dir_separator(*check)) { 172 | source += (check - source); 173 | 174 | /* Search backwards for previous slash or the start of the output string */ 175 | if (target != output) { 176 | target -= 1; 177 | do { 178 | if (target == output || mz_os_is_dir_separator(*target)) 179 | break; 180 | 181 | target -= 1; 182 | max_output += 1; 183 | } while (target > output); 184 | } 185 | 186 | if ((target == output) && *source != 0) 187 | source += 1; 188 | if (mz_os_is_dir_separator(*target) && *source == 0) 189 | target += 1; 190 | 191 | *target = 0; 192 | continue; 193 | } 194 | } 195 | } 196 | } 197 | 198 | *target = *source; 199 | 200 | source += 1; 201 | target += 1; 202 | max_output -= 1; 203 | } 204 | 205 | *target = 0; 206 | 207 | if (*path == 0) 208 | return MZ_INTERNAL_ERROR; 209 | 210 | return MZ_OK; 211 | } 212 | 213 | int32_t mz_path_remove_filename(char *path) { 214 | char *path_ptr = NULL; 215 | 216 | if (!path) 217 | return MZ_PARAM_ERROR; 218 | 219 | path_ptr = path + strlen(path) - 1; 220 | 221 | while (path_ptr > path) { 222 | if (mz_os_is_dir_separator(*path_ptr)) { 223 | *path_ptr = 0; 224 | break; 225 | } 226 | 227 | path_ptr -= 1; 228 | } 229 | 230 | if (path_ptr == path) 231 | *path_ptr = 0; 232 | 233 | return MZ_OK; 234 | } 235 | 236 | int32_t mz_path_remove_extension(char *path) { 237 | char *path_ptr = NULL; 238 | 239 | if (!path) 240 | return MZ_PARAM_ERROR; 241 | 242 | path_ptr = path + strlen(path) - 1; 243 | 244 | while (path_ptr > path) { 245 | if (mz_os_is_dir_separator(*path_ptr)) 246 | break; 247 | if (*path_ptr == '.') { 248 | *path_ptr = 0; 249 | break; 250 | } 251 | 252 | path_ptr -= 1; 253 | } 254 | 255 | if (path_ptr == path) 256 | *path_ptr = 0; 257 | 258 | return MZ_OK; 259 | } 260 | 261 | int32_t mz_path_get_filename(const char *path, const char **filename) { 262 | const char *match = NULL; 263 | 264 | if (!path || !filename) 265 | return MZ_PARAM_ERROR; 266 | 267 | *filename = NULL; 268 | 269 | for (match = path; *match != 0; match += 1) { 270 | if (mz_os_is_dir_separator(*match)) 271 | *filename = match + 1; 272 | } 273 | 274 | if (!*filename) 275 | return MZ_EXIST_ERROR; 276 | 277 | return MZ_OK; 278 | } 279 | 280 | int32_t mz_dir_make(const char *path) { 281 | int32_t err = MZ_OK; 282 | char *current_dir = NULL; 283 | char *match = NULL; 284 | char hold = 0; 285 | 286 | if (!*path) 287 | return MZ_OK; 288 | 289 | current_dir = strdup(path); 290 | if (!current_dir) 291 | return MZ_MEM_ERROR; 292 | 293 | mz_path_remove_slash(current_dir); 294 | 295 | err = mz_os_make_dir(current_dir); 296 | if (err != MZ_OK) { 297 | match = current_dir + 1; 298 | while (1) { 299 | while (*match != 0 && !mz_os_is_dir_separator(*match)) 300 | match += 1; 301 | hold = *match; 302 | *match = 0; 303 | 304 | err = mz_os_make_dir(current_dir); 305 | if (err != MZ_OK) 306 | break; 307 | if (hold == 0) 308 | break; 309 | 310 | *match = hold; 311 | match += 1; 312 | } 313 | } 314 | 315 | free(current_dir); 316 | return err; 317 | } 318 | 319 | int32_t mz_file_get_crc(const char *path, uint32_t *result_crc) { 320 | void *stream = NULL; 321 | uint32_t crc32 = 0; 322 | int32_t read = 0; 323 | int32_t err = MZ_OK; 324 | uint8_t buf[16384]; 325 | 326 | stream = mz_stream_os_create(); 327 | if (!stream) 328 | return MZ_MEM_ERROR; 329 | 330 | err = mz_stream_os_open(stream, path, MZ_OPEN_MODE_READ); 331 | if (err == MZ_OK) { 332 | do { 333 | read = mz_stream_os_read(stream, buf, sizeof(buf)); 334 | 335 | if (read < 0) { 336 | err = read; 337 | break; 338 | } 339 | 340 | crc32 = mz_crypt_crc32_update(crc32, buf, read); 341 | } while ((err == MZ_OK) && (read > 0)); 342 | 343 | mz_stream_os_close(stream); 344 | } 345 | 346 | *result_crc = crc32; 347 | 348 | mz_stream_os_delete(&stream); 349 | 350 | return err; 351 | } 352 | 353 | /***************************************************************************/ 354 | -------------------------------------------------------------------------------- /mz_os.h: -------------------------------------------------------------------------------- 1 | /* mz_os.h -- System functions 2 | part of the minizip-ng project 3 | 4 | Copyright (C) Nathan Moinvaziri 5 | https://github.com/zlib-ng/minizip-ng 6 | 7 | This program is distributed under the terms of the same license as zlib. 8 | See the accompanying LICENSE file for the full text of the license. 9 | */ 10 | 11 | #ifndef MZ_OS_H 12 | #define MZ_OS_H 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | /***************************************************************************/ 19 | 20 | #if defined(__APPLE__) 21 | # define MZ_VERSION_MADEBY_HOST_SYSTEM (MZ_HOST_SYSTEM_OSX_DARWIN) 22 | #elif defined(__riscos__) 23 | # define MZ_VERSION_MADEBY_HOST_SYSTEM (MZ_HOST_SYSTEM_RISCOS) 24 | #elif defined(_WIN32) 25 | # define MZ_VERSION_MADEBY_HOST_SYSTEM (MZ_HOST_SYSTEM_WINDOWS_NTFS) 26 | #else 27 | # define MZ_VERSION_MADEBY_HOST_SYSTEM (MZ_HOST_SYSTEM_UNIX) 28 | #endif 29 | 30 | #if defined(HAVE_LZMA) || defined(HAVE_LIBCOMP) 31 | # define MZ_VERSION_MADEBY_ZIP_VERSION (63) 32 | #elif defined(HAVE_WZAES) 33 | # define MZ_VERSION_MADEBY_ZIP_VERSION (51) 34 | #elif defined(HAVE_BZIP2) 35 | # define MZ_VERSION_MADEBY_ZIP_VERSION (46) 36 | #else 37 | # define MZ_VERSION_MADEBY_ZIP_VERSION (45) 38 | #endif 39 | 40 | #define MZ_VERSION_MADEBY ((MZ_VERSION_MADEBY_HOST_SYSTEM << 8) | (MZ_VERSION_MADEBY_ZIP_VERSION)) 41 | 42 | #define MZ_PATH_SLASH_UNIX ('/') 43 | #define MZ_PATH_SLASH_WINDOWS ('\\') 44 | #if defined(_WIN32) 45 | # define MZ_PATH_SLASH_PLATFORM (MZ_PATH_SLASH_WINDOWS) 46 | #else 47 | # define MZ_PATH_SLASH_PLATFORM (MZ_PATH_SLASH_UNIX) 48 | #endif 49 | 50 | /***************************************************************************/ 51 | 52 | #if defined(_WIN32) 53 | struct dirent { 54 | char d_name[256]; 55 | }; 56 | typedef void *DIR; 57 | #else 58 | # include 59 | #endif 60 | 61 | /***************************************************************************/ 62 | /* Shared functions */ 63 | 64 | int32_t mz_path_combine(char *path, const char *join, int32_t max_path); 65 | /* Combines two paths */ 66 | 67 | int32_t mz_path_append_slash(char *path, int32_t max_path, char slash); 68 | /* Appends a path slash on to the end of the path */ 69 | 70 | int32_t mz_path_remove_slash(char *path); 71 | /* Removes a path slash from the end of the path */ 72 | 73 | int32_t mz_path_has_slash(const char *path); 74 | /* Returns whether or not the path ends with slash */ 75 | 76 | int32_t mz_path_convert_slashes(char *path, char slash); 77 | /* Converts the slashes in a path */ 78 | 79 | int32_t mz_path_compare_wc(const char *path, const char *wildcard, uint8_t ignore_case); 80 | /* Compare two paths with wildcard */ 81 | 82 | int32_t mz_path_resolve(const char *path, char *target, int32_t max_target); 83 | /* Resolves path */ 84 | 85 | int32_t mz_path_remove_filename(char *path); 86 | /* Remove the filename from a path */ 87 | 88 | int32_t mz_path_remove_extension(char *path); 89 | /* Remove the extension from a path */ 90 | 91 | int32_t mz_path_get_filename(const char *path, const char **filename); 92 | /* Get the filename from a path */ 93 | 94 | int32_t mz_dir_make(const char *path); 95 | /* Creates a directory recursively */ 96 | 97 | int32_t mz_file_get_crc(const char *path, uint32_t *result_crc); 98 | /* Gets the crc32 hash of a file */ 99 | 100 | /***************************************************************************/ 101 | /* Platform specific functions */ 102 | 103 | wchar_t *mz_os_unicode_string_create(const char *string, int32_t encoding); 104 | /* Create unicode string from a utf8 string */ 105 | 106 | void mz_os_unicode_string_delete(wchar_t **string); 107 | /* Delete a unicode string that was created */ 108 | 109 | char *mz_os_utf8_string_create(const char *string, int32_t encoding); 110 | /* Create a utf8 string from a string with another encoding */ 111 | 112 | void mz_os_utf8_string_delete(char **string); 113 | /* Delete a utf8 string that was created */ 114 | 115 | int32_t mz_os_rand(uint8_t *buf, int32_t size); 116 | /* Random number generator (not cryptographically secure) */ 117 | 118 | int32_t mz_os_rename(const char *source_path, const char *target_path); 119 | /* Rename a file */ 120 | 121 | int32_t mz_os_unlink(const char *path); 122 | /* Delete an existing file */ 123 | 124 | int32_t mz_os_file_exists(const char *path); 125 | /* Check to see if a file exists */ 126 | 127 | int64_t mz_os_get_file_size(const char *path); 128 | /* Gets the length of a file */ 129 | 130 | int32_t mz_os_get_file_date(const char *path, time_t *modified_date, time_t *accessed_date, time_t *creation_date); 131 | /* Gets a file's modified, access, and creation dates if supported */ 132 | 133 | int32_t mz_os_set_file_date(const char *path, time_t modified_date, time_t accessed_date, time_t creation_date); 134 | /* Sets a file's modified, access, and creation dates if supported */ 135 | 136 | int32_t mz_os_get_file_attribs(const char *path, uint32_t *attributes); 137 | /* Gets a file's attributes */ 138 | 139 | int32_t mz_os_set_file_attribs(const char *path, uint32_t attributes); 140 | /* Sets a file's attributes */ 141 | 142 | int32_t mz_os_make_dir(const char *path); 143 | /* Recursively creates a directory */ 144 | 145 | DIR *mz_os_open_dir(const char *path); 146 | /* Opens a directory for listing */ 147 | struct dirent *mz_os_read_dir(DIR *dir); 148 | /* Reads a directory listing entry */ 149 | 150 | int32_t mz_os_close_dir(DIR *dir); 151 | /* Closes a directory that has been opened for listing */ 152 | 153 | int32_t mz_os_is_dir_separator(const char c); 154 | /* Checks to see if character is a directory separator */ 155 | 156 | int32_t mz_os_is_dir(const char *path); 157 | /* Checks to see if path is a directory */ 158 | 159 | int32_t mz_os_is_symlink(const char *path); 160 | /* Checks to see if path is a symbolic link */ 161 | 162 | int32_t mz_os_make_symlink(const char *path, const char *target_path); 163 | /* Creates a symbolic link pointing to a target */ 164 | 165 | int32_t mz_os_read_symlink(const char *path, char *target_path, int32_t max_target_path); 166 | /* Gets the target path for a symbolic link */ 167 | 168 | uint64_t mz_os_ms_time(void); 169 | /* Gets the time in milliseconds */ 170 | 171 | /***************************************************************************/ 172 | 173 | #ifdef __cplusplus 174 | } 175 | #endif 176 | 177 | #endif 178 | -------------------------------------------------------------------------------- /mz_os_posix.c: -------------------------------------------------------------------------------- 1 | /* mz_os_posix.c -- System functions for posix 2 | part of the minizip-ng project 3 | 4 | Copyright (C) Nathan Moinvaziri 5 | https://github.com/zlib-ng/minizip-ng 6 | 7 | This program is distributed under the terms of the same license as zlib. 8 | See the accompanying LICENSE file for the full text of the license. 9 | */ 10 | 11 | #include "mz.h" 12 | #include "mz_strm.h" 13 | #include "mz_os.h" 14 | 15 | #include /* rename */ 16 | #include 17 | #if defined(HAVE_ICONV) 18 | # include 19 | #endif 20 | #include 21 | #include 22 | #include 23 | 24 | #ifndef _WIN32 25 | # include 26 | # include 27 | #endif 28 | #if defined(__APPLE__) 29 | # include 30 | # include 31 | #endif 32 | 33 | #if defined(HAVE_GETRANDOM) 34 | # include 35 | #endif 36 | #if defined(HAVE_LIBBSD) 37 | # include /* arc4random_buf */ 38 | #endif 39 | 40 | #ifndef MZ_PRESERVE_NATIVE_STRUCTURE 41 | # define MZ_PRESERVE_NATIVE_STRUCTURE 1 42 | #endif 43 | 44 | /***************************************************************************/ 45 | 46 | #if defined(HAVE_ICONV) 47 | char *mz_os_utf8_string_create(const char *string, int32_t encoding) { 48 | iconv_t cd; 49 | const char *from_encoding = NULL; 50 | size_t result = 0; 51 | size_t string_length = 0; 52 | size_t string_utf8_size = 0; 53 | char *string_utf8 = NULL; 54 | char *string_utf8_ptr = NULL; 55 | 56 | if (!string || encoding <= 0) 57 | return NULL; 58 | 59 | if (encoding == MZ_ENCODING_UTF8) 60 | from_encoding = "UTF-8"; 61 | else { 62 | /// up to CP2147483647 63 | char string_encoding[13]; 64 | snprintf(string_encoding, sizeof(string_encoding), "CP%03" PRId32, encoding); 65 | from_encoding = string_encoding; 66 | } 67 | 68 | cd = iconv_open("UTF-8", from_encoding); 69 | if (cd == (iconv_t)-1) 70 | return NULL; 71 | 72 | string_length = strlen(string); 73 | string_utf8_size = string_length * 2; 74 | string_utf8 = (char *)calloc((int32_t)(string_utf8_size + 1), sizeof(char)); 75 | string_utf8_ptr = string_utf8; 76 | 77 | if (string_utf8) { 78 | result = iconv(cd, (char **)&string, &string_length, (char **)&string_utf8_ptr, &string_utf8_size); 79 | } 80 | 81 | iconv_close(cd); 82 | 83 | if (result == (size_t)-1) { 84 | free(string_utf8); 85 | string_utf8 = NULL; 86 | } 87 | 88 | return string_utf8; 89 | } 90 | #else 91 | char *mz_os_utf8_string_create(const char *string, int32_t encoding) { 92 | return strdup(string); 93 | } 94 | #endif 95 | 96 | void mz_os_utf8_string_delete(char **string) { 97 | if (string) { 98 | free(*string); 99 | *string = NULL; 100 | } 101 | } 102 | 103 | /***************************************************************************/ 104 | 105 | #if defined(HAVE_GETRANDOM) 106 | int32_t mz_os_rand(uint8_t *buf, int32_t size) { 107 | int32_t left = size; 108 | int32_t written = 0; 109 | 110 | while (left > 0) { 111 | written = getrandom(buf, left, 0); 112 | if (written < 0) 113 | return MZ_INTERNAL_ERROR; 114 | 115 | buf += written; 116 | left -= written; 117 | } 118 | return size - left; 119 | } 120 | #elif defined(HAVE_ARC4RANDOM_BUF) 121 | int32_t mz_os_rand(uint8_t *buf, int32_t size) { 122 | if (size < 0) 123 | return 0; 124 | arc4random_buf(buf, (uint32_t)size); 125 | return size; 126 | } 127 | #elif defined(HAVE_ARC4RANDOM) 128 | int32_t mz_os_rand(uint8_t *buf, int32_t size) { 129 | int32_t left = size; 130 | for (; left > 2; left -= 3, buf += 3) { 131 | uint32_t val = arc4random(); 132 | 133 | buf[0] = (val) & 0xFF; 134 | buf[1] = (val >> 8) & 0xFF; 135 | buf[2] = (val >> 16) & 0xFF; 136 | } 137 | for (; left > 0; left--, buf++) { 138 | *buf = arc4random() & 0xFF; 139 | } 140 | return size - left; 141 | } 142 | #else 143 | int32_t mz_os_rand(uint8_t *buf, int32_t size) { 144 | static unsigned calls = 0; 145 | int32_t i = 0; 146 | 147 | /* Ensure different random header each time */ 148 | if (++calls == 1) { 149 | # define PI_SEED 3141592654UL 150 | srand((unsigned)(time(NULL) ^ PI_SEED)); 151 | } 152 | 153 | while (i < size) 154 | buf[i++] = (rand() >> 7) & 0xff; 155 | 156 | return size; 157 | } 158 | #endif 159 | 160 | int32_t mz_os_rename(const char *source_path, const char *target_path) { 161 | if (rename(source_path, target_path) == -1) 162 | return MZ_EXIST_ERROR; 163 | 164 | return MZ_OK; 165 | } 166 | 167 | int32_t mz_os_unlink(const char *path) { 168 | if (unlink(path) == -1) 169 | return MZ_EXIST_ERROR; 170 | 171 | return MZ_OK; 172 | } 173 | 174 | int32_t mz_os_file_exists(const char *path) { 175 | struct stat path_stat; 176 | 177 | memset(&path_stat, 0, sizeof(path_stat)); 178 | if (stat(path, &path_stat) == 0) 179 | return MZ_OK; 180 | return MZ_EXIST_ERROR; 181 | } 182 | 183 | int64_t mz_os_get_file_size(const char *path) { 184 | struct stat path_stat; 185 | 186 | memset(&path_stat, 0, sizeof(path_stat)); 187 | if (stat(path, &path_stat) == 0) { 188 | /* Stat returns size taken up by directory entry, so return 0 */ 189 | if (S_ISDIR(path_stat.st_mode)) 190 | return 0; 191 | 192 | return path_stat.st_size; 193 | } 194 | 195 | return 0; 196 | } 197 | 198 | int32_t mz_os_get_file_date(const char *path, time_t *modified_date, time_t *accessed_date, time_t *creation_date) { 199 | struct stat path_stat; 200 | char *name = NULL; 201 | int32_t err = MZ_INTERNAL_ERROR; 202 | 203 | memset(&path_stat, 0, sizeof(path_stat)); 204 | 205 | if (strcmp(path, "-") != 0) { 206 | /* Not all systems allow stat'ing a file with / appended */ 207 | name = strdup(path); 208 | mz_path_remove_slash(name); 209 | 210 | if (stat(name, &path_stat) == 0) { 211 | if (modified_date) 212 | *modified_date = path_stat.st_mtime; 213 | if (accessed_date) 214 | *accessed_date = path_stat.st_atime; 215 | /* Creation date not supported */ 216 | if (creation_date) 217 | *creation_date = 0; 218 | 219 | err = MZ_OK; 220 | } 221 | 222 | free(name); 223 | } 224 | 225 | return err; 226 | } 227 | 228 | int32_t mz_os_set_file_date(const char *path, time_t modified_date, time_t accessed_date, time_t creation_date) { 229 | struct utimbuf ut; 230 | 231 | ut.actime = accessed_date; 232 | ut.modtime = modified_date; 233 | 234 | /* Creation date not supported */ 235 | MZ_UNUSED(creation_date); 236 | 237 | if (utime(path, &ut) != 0) 238 | return MZ_INTERNAL_ERROR; 239 | 240 | return MZ_OK; 241 | } 242 | 243 | int32_t mz_os_get_file_attribs(const char *path, uint32_t *attributes) { 244 | struct stat path_stat; 245 | int32_t err = MZ_OK; 246 | 247 | memset(&path_stat, 0, sizeof(path_stat)); 248 | if (lstat(path, &path_stat) == -1) 249 | err = MZ_INTERNAL_ERROR; 250 | *attributes = path_stat.st_mode; 251 | return err; 252 | } 253 | 254 | int32_t mz_os_set_file_attribs(const char *path, uint32_t attributes) { 255 | int32_t err = MZ_OK; 256 | 257 | if (chmod(path, (mode_t)attributes) == -1) 258 | err = MZ_INTERNAL_ERROR; 259 | 260 | return err; 261 | } 262 | 263 | int32_t mz_os_make_dir(const char *path) { 264 | int32_t err = 0; 265 | 266 | err = mkdir(path, 0755); 267 | 268 | if (err != 0 && errno != EEXIST) 269 | return MZ_INTERNAL_ERROR; 270 | 271 | return MZ_OK; 272 | } 273 | 274 | DIR *mz_os_open_dir(const char *path) { 275 | return opendir(path); 276 | } 277 | 278 | struct dirent *mz_os_read_dir(DIR *dir) { 279 | if (!dir) 280 | return NULL; 281 | return readdir(dir); 282 | } 283 | 284 | int32_t mz_os_close_dir(DIR *dir) { 285 | if (!dir) 286 | return MZ_PARAM_ERROR; 287 | if (closedir(dir) == -1) 288 | return MZ_INTERNAL_ERROR; 289 | return MZ_OK; 290 | } 291 | 292 | int32_t mz_os_is_dir_separator(const char c) { 293 | #if MZ_PRESERVE_NATIVE_STRUCTURE 294 | // While not strictly adhering to 4.4.17.1, 295 | // this preserves UNIX filesystem structure. 296 | return c == '/'; 297 | #else 298 | // While strictly adhering to 4.4.17.1, 299 | // this corrupts UNIX filesystem structure (a filename with a '\\' will become a folder + a file). 300 | return c == '\\' || c == '/'; 301 | #endif 302 | } 303 | 304 | int32_t mz_os_is_dir(const char *path) { 305 | struct stat path_stat; 306 | 307 | memset(&path_stat, 0, sizeof(path_stat)); 308 | stat(path, &path_stat); 309 | if (S_ISDIR(path_stat.st_mode)) 310 | return MZ_OK; 311 | 312 | return MZ_EXIST_ERROR; 313 | } 314 | 315 | int32_t mz_os_is_symlink(const char *path) { 316 | struct stat path_stat; 317 | 318 | memset(&path_stat, 0, sizeof(path_stat)); 319 | lstat(path, &path_stat); 320 | if (S_ISLNK(path_stat.st_mode)) 321 | return MZ_OK; 322 | 323 | return MZ_EXIST_ERROR; 324 | } 325 | 326 | int32_t mz_os_make_symlink(const char *path, const char *target_path) { 327 | if (symlink(target_path, path) != 0) 328 | return MZ_INTERNAL_ERROR; 329 | return MZ_OK; 330 | } 331 | 332 | int32_t mz_os_read_symlink(const char *path, char *target_path, int32_t max_target_path) { 333 | size_t length = 0; 334 | 335 | length = (size_t)readlink(path, target_path, max_target_path - 1); 336 | if (length == (size_t)-1) 337 | return MZ_EXIST_ERROR; 338 | 339 | target_path[length] = 0; 340 | return MZ_OK; 341 | } 342 | 343 | uint64_t mz_os_ms_time(void) { 344 | struct timespec ts; 345 | 346 | #if defined(__APPLE__) 347 | clock_serv_t cclock; 348 | mach_timespec_t mts; 349 | 350 | host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); 351 | clock_get_time(cclock, &mts); 352 | mach_port_deallocate(mach_task_self(), cclock); 353 | 354 | ts.tv_sec = mts.tv_sec; 355 | ts.tv_nsec = mts.tv_nsec; 356 | #elif !defined(_POSIX_MONOTONIC_CLOCK) || _POSIX_MONOTONIC_CLOCK < 0 357 | clock_gettime(CLOCK_REALTIME, &ts); 358 | #elif _POSIX_MONOTONIC_CLOCK > 0 359 | clock_gettime(CLOCK_MONOTONIC, &ts); 360 | #else 361 | if (sysconf(_SC_MONOTONIC_CLOCK) > 0) 362 | clock_gettime(CLOCK_MONOTONIC, &ts); 363 | else 364 | clock_gettime(CLOCK_REALTIME, &ts); 365 | #endif 366 | 367 | return ((uint64_t)ts.tv_sec * 1000) + ((uint64_t)ts.tv_nsec / 1000000); 368 | } 369 | -------------------------------------------------------------------------------- /mz_strm.h: -------------------------------------------------------------------------------- 1 | /* mz_strm.h -- Stream interface 2 | part of the minizip-ng project 3 | 4 | Copyright (C) Nathan Moinvaziri 5 | https://github.com/zlib-ng/minizip-ng 6 | 7 | This program is distributed under the terms of the same license as zlib. 8 | See the accompanying LICENSE file for the full text of the license. 9 | */ 10 | 11 | #ifndef MZ_STREAM_H 12 | #define MZ_STREAM_H 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | /***************************************************************************/ 19 | 20 | #define MZ_STREAM_PROP_TOTAL_IN (1) 21 | #define MZ_STREAM_PROP_TOTAL_IN_MAX (2) 22 | #define MZ_STREAM_PROP_TOTAL_OUT (3) 23 | #define MZ_STREAM_PROP_TOTAL_OUT_MAX (4) 24 | #define MZ_STREAM_PROP_HEADER_SIZE (5) 25 | #define MZ_STREAM_PROP_FOOTER_SIZE (6) 26 | #define MZ_STREAM_PROP_DISK_SIZE (7) 27 | #define MZ_STREAM_PROP_DISK_NUMBER (8) 28 | #define MZ_STREAM_PROP_COMPRESS_LEVEL (9) 29 | #define MZ_STREAM_PROP_COMPRESS_METHOD (10) 30 | #define MZ_STREAM_PROP_COMPRESS_WINDOW (11) 31 | 32 | /***************************************************************************/ 33 | 34 | typedef int32_t (*mz_stream_open_cb)(void *stream, const char *path, int32_t mode); 35 | typedef int32_t (*mz_stream_is_open_cb)(void *stream); 36 | typedef int32_t (*mz_stream_read_cb)(void *stream, void *buf, int32_t size); 37 | typedef int32_t (*mz_stream_write_cb)(void *stream, const void *buf, int32_t size); 38 | typedef int64_t (*mz_stream_tell_cb)(void *stream); 39 | typedef int32_t (*mz_stream_seek_cb)(void *stream, int64_t offset, int32_t origin); 40 | typedef int32_t (*mz_stream_close_cb)(void *stream); 41 | typedef int32_t (*mz_stream_error_cb)(void *stream); 42 | typedef void *(*mz_stream_create_cb)(void); 43 | typedef void (*mz_stream_destroy_cb)(void **stream); 44 | 45 | typedef int32_t (*mz_stream_get_prop_int64_cb)(void *stream, int32_t prop, int64_t *value); 46 | typedef int32_t (*mz_stream_set_prop_int64_cb)(void *stream, int32_t prop, int64_t value); 47 | 48 | typedef int32_t (*mz_stream_find_cb)(void *stream, const void *find, int32_t find_size, int64_t max_seek, 49 | int64_t *position); 50 | 51 | /***************************************************************************/ 52 | 53 | typedef struct mz_stream_vtbl_s { 54 | mz_stream_open_cb open; 55 | mz_stream_is_open_cb is_open; 56 | mz_stream_read_cb read; 57 | mz_stream_write_cb write; 58 | mz_stream_tell_cb tell; 59 | mz_stream_seek_cb seek; 60 | mz_stream_close_cb close; 61 | mz_stream_error_cb error; 62 | mz_stream_create_cb create; 63 | mz_stream_destroy_cb destroy; 64 | 65 | mz_stream_get_prop_int64_cb get_prop_int64; 66 | mz_stream_set_prop_int64_cb set_prop_int64; 67 | } mz_stream_vtbl; 68 | 69 | typedef struct mz_stream_s { 70 | mz_stream_vtbl *vtbl; 71 | struct mz_stream_s *base; 72 | } mz_stream; 73 | 74 | /***************************************************************************/ 75 | 76 | int32_t mz_stream_open(void *stream, const char *path, int32_t mode); 77 | int32_t mz_stream_is_open(void *stream); 78 | int32_t mz_stream_read(void *stream, void *buf, int32_t size); 79 | int32_t mz_stream_read_uint8(void *stream, uint8_t *value); 80 | int32_t mz_stream_read_uint16(void *stream, uint16_t *value); 81 | int32_t mz_stream_read_uint32(void *stream, uint32_t *value); 82 | int32_t mz_stream_read_int64(void *stream, int64_t *value); 83 | int32_t mz_stream_read_uint64(void *stream, uint64_t *value); 84 | int32_t mz_stream_write(void *stream, const void *buf, int32_t size); 85 | int32_t mz_stream_write_uint8(void *stream, uint8_t value); 86 | int32_t mz_stream_write_uint16(void *stream, uint16_t value); 87 | int32_t mz_stream_write_uint32(void *stream, uint32_t value); 88 | int32_t mz_stream_write_int64(void *stream, int64_t value); 89 | int32_t mz_stream_write_uint64(void *stream, uint64_t value); 90 | int32_t mz_stream_copy(void *target, void *source, int32_t len); 91 | int32_t mz_stream_copy_to_end(void *target, void *source); 92 | int32_t mz_stream_copy_stream(void *target, mz_stream_write_cb write_cb, void *source, mz_stream_read_cb read_cb, 93 | int32_t len); 94 | int32_t mz_stream_copy_stream_to_end(void *target, mz_stream_write_cb write_cb, void *source, 95 | mz_stream_read_cb read_cb); 96 | int64_t mz_stream_tell(void *stream); 97 | int32_t mz_stream_seek(void *stream, int64_t offset, int32_t origin); 98 | int32_t mz_stream_find(void *stream, const void *find, int32_t find_size, int64_t max_seek, int64_t *position); 99 | int32_t mz_stream_find_reverse(void *stream, const void *find, int32_t find_size, int64_t max_seek, int64_t *position); 100 | int32_t mz_stream_close(void *stream); 101 | int32_t mz_stream_error(void *stream); 102 | 103 | int32_t mz_stream_set_base(void *stream, void *base); 104 | void *mz_stream_get_interface(void *stream); 105 | int32_t mz_stream_get_prop_int64(void *stream, int32_t prop, int64_t *value); 106 | int32_t mz_stream_set_prop_int64(void *stream, int32_t prop, int64_t value); 107 | 108 | void *mz_stream_create(mz_stream_vtbl *vtbl); 109 | void mz_stream_delete(void **stream); 110 | 111 | /***************************************************************************/ 112 | 113 | int32_t mz_stream_raw_open(void *stream, const char *filename, int32_t mode); 114 | int32_t mz_stream_raw_is_open(void *stream); 115 | int32_t mz_stream_raw_read(void *stream, void *buf, int32_t size); 116 | int32_t mz_stream_raw_write(void *stream, const void *buf, int32_t size); 117 | int64_t mz_stream_raw_tell(void *stream); 118 | int32_t mz_stream_raw_seek(void *stream, int64_t offset, int32_t origin); 119 | int32_t mz_stream_raw_close(void *stream); 120 | int32_t mz_stream_raw_error(void *stream); 121 | 122 | int32_t mz_stream_raw_get_prop_int64(void *stream, int32_t prop, int64_t *value); 123 | int32_t mz_stream_raw_set_prop_int64(void *stream, int32_t prop, int64_t value); 124 | 125 | void *mz_stream_raw_create(void); 126 | void mz_stream_raw_delete(void **stream); 127 | 128 | /***************************************************************************/ 129 | 130 | #ifdef __cplusplus 131 | } 132 | #endif 133 | 134 | #endif 135 | -------------------------------------------------------------------------------- /mz_strm_buf.h: -------------------------------------------------------------------------------- 1 | /* mz_strm_buf.h -- Stream for buffering reads/writes 2 | part of the minizip-ng project 3 | 4 | This version of ioapi is designed to buffer IO. 5 | 6 | Copyright (C) Nathan Moinvaziri 7 | https://github.com/zlib-ng/minizip-ng 8 | 9 | This program is distributed under the terms of the same license as zlib. 10 | See the accompanying LICENSE file for the full text of the license. 11 | */ 12 | 13 | #ifndef MZ_STREAM_BUFFERED_H 14 | #define MZ_STREAM_BUFFERED_H 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | /***************************************************************************/ 21 | 22 | int32_t mz_stream_buffered_open(void *stream, const char *path, int32_t mode); 23 | int32_t mz_stream_buffered_is_open(void *stream); 24 | int32_t mz_stream_buffered_read(void *stream, void *buf, int32_t size); 25 | int32_t mz_stream_buffered_write(void *stream, const void *buf, int32_t size); 26 | int64_t mz_stream_buffered_tell(void *stream); 27 | int32_t mz_stream_buffered_seek(void *stream, int64_t offset, int32_t origin); 28 | int32_t mz_stream_buffered_close(void *stream); 29 | int32_t mz_stream_buffered_error(void *stream); 30 | 31 | void *mz_stream_buffered_create(void); 32 | void mz_stream_buffered_delete(void **stream); 33 | 34 | void *mz_stream_buffered_get_interface(void); 35 | 36 | /***************************************************************************/ 37 | 38 | #ifdef __cplusplus 39 | } 40 | #endif 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /mz_strm_bzip.h: -------------------------------------------------------------------------------- 1 | /* mz_strm_bzip.h -- Stream for bzip inflate/deflate 2 | part of the minizip-ng project 3 | 4 | Copyright (C) Nathan Moinvaziri 5 | https://github.com/zlib-ng/minizip-ng 6 | 7 | This program is distributed under the terms of the same license as zlib. 8 | See the accompanying LICENSE file for the full text of the license. 9 | */ 10 | 11 | #ifndef MZ_STREAM_BZIP_H 12 | #define MZ_STREAM_BZIP_H 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | /***************************************************************************/ 19 | 20 | int32_t mz_stream_bzip_open(void *stream, const char *filename, int32_t mode); 21 | int32_t mz_stream_bzip_is_open(void *stream); 22 | int32_t mz_stream_bzip_read(void *stream, void *buf, int32_t size); 23 | int32_t mz_stream_bzip_write(void *stream, const void *buf, int32_t size); 24 | int64_t mz_stream_bzip_tell(void *stream); 25 | int32_t mz_stream_bzip_seek(void *stream, int64_t offset, int32_t origin); 26 | int32_t mz_stream_bzip_close(void *stream); 27 | int32_t mz_stream_bzip_error(void *stream); 28 | 29 | int32_t mz_stream_bzip_get_prop_int64(void *stream, int32_t prop, int64_t *value); 30 | int32_t mz_stream_bzip_set_prop_int64(void *stream, int32_t prop, int64_t value); 31 | 32 | void *mz_stream_bzip_create(void); 33 | void mz_stream_bzip_delete(void **stream); 34 | 35 | void *mz_stream_bzip_get_interface(void); 36 | 37 | void bz_internal_error(int errcode); 38 | 39 | /***************************************************************************/ 40 | 41 | #ifdef __cplusplus 42 | } 43 | #endif 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /mz_strm_libcomp.h: -------------------------------------------------------------------------------- 1 | /* mz_strm_libcomp.h -- Stream for apple compression 2 | part of the minizip-ng project 3 | 4 | Copyright (C) Nathan Moinvaziri 5 | https://github.com/zlib-ng/minizip-ng 6 | 7 | This program is distributed under the terms of the same license as zlib. 8 | See the accompanying LICENSE file for the full text of the license. 9 | */ 10 | 11 | #ifndef MZ_STREAM_LIBCOMP_H 12 | #define MZ_STREAM_LIBCOMP_H 13 | 14 | #include 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | /***************************************************************************/ 21 | 22 | int32_t mz_stream_libcomp_open(void *stream, const char *filename, int32_t mode); 23 | int32_t mz_stream_libcomp_is_open(void *stream); 24 | int32_t mz_stream_libcomp_read(void *stream, void *buf, int32_t size); 25 | int32_t mz_stream_libcomp_write(void *stream, const void *buf, int32_t size); 26 | int64_t mz_stream_libcomp_tell(void *stream); 27 | int32_t mz_stream_libcomp_seek(void *stream, int64_t offset, int32_t origin); 28 | int32_t mz_stream_libcomp_close(void *stream); 29 | int32_t mz_stream_libcomp_error(void *stream); 30 | 31 | int32_t mz_stream_libcomp_get_prop_int64(void *stream, int32_t prop, int64_t *value); 32 | int32_t mz_stream_libcomp_set_prop_int64(void *stream, int32_t prop, int64_t value); 33 | 34 | void *mz_stream_libcomp_create(void); 35 | void mz_stream_libcomp_delete(void **stream); 36 | 37 | void *mz_stream_libcomp_get_interface(void); 38 | 39 | /***************************************************************************/ 40 | 41 | #ifdef __cplusplus 42 | } 43 | #endif 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /mz_strm_lzma.h: -------------------------------------------------------------------------------- 1 | /* mz_strm_lzma.h -- Stream for lzma inflate/deflate 2 | part of the minizip-ng project 3 | 4 | Copyright (C) Nathan Moinvaziri 5 | https://github.com/zlib-ng/minizip-ng 6 | 7 | This program is distributed under the terms of the same license as lzma. 8 | See the accompanying LICENSE file for the full text of the license. 9 | */ 10 | 11 | #ifndef MZ_STREAM_LZMA_H 12 | #define MZ_STREAM_LZMA_H 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | /***************************************************************************/ 19 | 20 | int32_t mz_stream_lzma_open(void *stream, const char *filename, int32_t mode); 21 | int32_t mz_stream_lzma_is_open(void *stream); 22 | int32_t mz_stream_lzma_read(void *stream, void *buf, int32_t size); 23 | int32_t mz_stream_lzma_write(void *stream, const void *buf, int32_t size); 24 | int64_t mz_stream_lzma_tell(void *stream); 25 | int32_t mz_stream_lzma_seek(void *stream, int64_t offset, int32_t origin); 26 | int32_t mz_stream_lzma_close(void *stream); 27 | int32_t mz_stream_lzma_error(void *stream); 28 | 29 | int32_t mz_stream_lzma_get_prop_int64(void *stream, int32_t prop, int64_t *value); 30 | int32_t mz_stream_lzma_set_prop_int64(void *stream, int32_t prop, int64_t value); 31 | 32 | void *mz_stream_lzma_create(void); 33 | void mz_stream_lzma_delete(void **stream); 34 | 35 | void *mz_stream_lzma_get_interface(void); 36 | 37 | /***************************************************************************/ 38 | 39 | #ifdef __cplusplus 40 | } 41 | #endif 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /mz_strm_mem.c: -------------------------------------------------------------------------------- 1 | /* mz_strm_mem.c -- Stream for memory access 2 | part of the minizip-ng project 3 | 4 | This interface is designed to access memory rather than files. 5 | We do use a region of memory to put data in to and take it out of. 6 | 7 | Based on Unzip ioapi.c version 0.22, May 19th, 2003 8 | 9 | Copyright (C) Nathan Moinvaziri 10 | https://github.com/zlib-ng/minizip-ng 11 | Copyright (C) 2003 Justin Fletcher 12 | Copyright (C) 1998-2003 Gilles Vollant 13 | https://www.winimage.com/zLibDll/minizip.html 14 | 15 | This program is distributed under the terms of the same license as zlib. 16 | See the accompanying LICENSE file for the full text of the license. 17 | */ 18 | 19 | #include "mz.h" 20 | #include "mz_strm.h" 21 | #include "mz_strm_mem.h" 22 | 23 | /***************************************************************************/ 24 | 25 | static mz_stream_vtbl mz_stream_mem_vtbl = {mz_stream_mem_open, 26 | mz_stream_mem_is_open, 27 | mz_stream_mem_read, 28 | mz_stream_mem_write, 29 | mz_stream_mem_tell, 30 | mz_stream_mem_seek, 31 | mz_stream_mem_close, 32 | mz_stream_mem_error, 33 | mz_stream_mem_create, 34 | mz_stream_mem_delete, 35 | NULL, 36 | NULL}; 37 | 38 | /***************************************************************************/ 39 | 40 | typedef struct mz_stream_mem_s { 41 | mz_stream stream; 42 | int32_t mode; 43 | uint8_t *buffer; /* Memory buffer pointer */ 44 | int32_t size; /* Size of the memory buffer */ 45 | int32_t limit; /* Furthest we've written */ 46 | int32_t position; /* Current position in the memory */ 47 | int32_t grow_size; /* Size to grow when full */ 48 | } mz_stream_mem; 49 | 50 | /***************************************************************************/ 51 | 52 | static int32_t mz_stream_mem_set_size(void *stream, int32_t size) { 53 | mz_stream_mem *mem = (mz_stream_mem *)stream; 54 | int32_t new_size = size; 55 | uint8_t *new_buf = NULL; 56 | 57 | new_buf = (uint8_t *)malloc((uint32_t)new_size); 58 | if (!new_buf) 59 | return MZ_BUF_ERROR; 60 | 61 | if (mem->buffer) { 62 | memcpy(new_buf, mem->buffer, mem->size); 63 | free(mem->buffer); 64 | } 65 | 66 | mem->buffer = new_buf; 67 | mem->size = new_size; 68 | return MZ_OK; 69 | } 70 | 71 | int32_t mz_stream_mem_open(void *stream, const char *path, int32_t mode) { 72 | mz_stream_mem *mem = (mz_stream_mem *)stream; 73 | int32_t err = MZ_OK; 74 | 75 | MZ_UNUSED(path); 76 | 77 | mem->mode = mode; 78 | mem->limit = 0; 79 | mem->position = 0; 80 | 81 | if (mem->mode & MZ_OPEN_MODE_CREATE) 82 | err = mz_stream_mem_set_size(stream, mem->grow_size); 83 | else 84 | mem->limit = mem->size; 85 | 86 | return err; 87 | } 88 | 89 | int32_t mz_stream_mem_is_open(void *stream) { 90 | mz_stream_mem *mem = (mz_stream_mem *)stream; 91 | if (!mem->buffer) 92 | return MZ_OPEN_ERROR; 93 | return MZ_OK; 94 | } 95 | 96 | int32_t mz_stream_mem_read(void *stream, void *buf, int32_t size) { 97 | mz_stream_mem *mem = (mz_stream_mem *)stream; 98 | 99 | if (size > mem->size - mem->position) 100 | size = mem->size - mem->position; 101 | if (mem->position + size > mem->limit) 102 | size = mem->limit - mem->position; 103 | 104 | if (size <= 0) 105 | return 0; 106 | 107 | memcpy(buf, mem->buffer + mem->position, size); 108 | mem->position += size; 109 | 110 | return size; 111 | } 112 | 113 | int32_t mz_stream_mem_write(void *stream, const void *buf, int32_t size) { 114 | mz_stream_mem *mem = (mz_stream_mem *)stream; 115 | int32_t new_size = 0; 116 | int32_t err = MZ_OK; 117 | 118 | if (!size) 119 | return size; 120 | 121 | if (size > mem->size - mem->position) { 122 | if (mem->mode & MZ_OPEN_MODE_CREATE) { 123 | new_size = mem->size; 124 | if (size < mem->grow_size) 125 | new_size += mem->grow_size; 126 | else 127 | new_size += size; 128 | 129 | err = mz_stream_mem_set_size(stream, new_size); 130 | if (err != MZ_OK) 131 | return err; 132 | } else { 133 | size = mem->size - mem->position; 134 | } 135 | } 136 | 137 | memcpy(mem->buffer + mem->position, buf, size); 138 | 139 | mem->position += size; 140 | if (mem->position > mem->limit) 141 | mem->limit = mem->position; 142 | 143 | return size; 144 | } 145 | 146 | int64_t mz_stream_mem_tell(void *stream) { 147 | mz_stream_mem *mem = (mz_stream_mem *)stream; 148 | return mem->position; 149 | } 150 | 151 | int32_t mz_stream_mem_seek(void *stream, int64_t offset, int32_t origin) { 152 | mz_stream_mem *mem = (mz_stream_mem *)stream; 153 | int64_t new_pos = 0; 154 | int32_t err = MZ_OK; 155 | 156 | switch (origin) { 157 | case MZ_SEEK_CUR: 158 | new_pos = mem->position + offset; 159 | break; 160 | case MZ_SEEK_END: 161 | new_pos = mem->limit + offset; 162 | break; 163 | case MZ_SEEK_SET: 164 | new_pos = offset; 165 | break; 166 | default: 167 | return MZ_SEEK_ERROR; 168 | } 169 | 170 | if (new_pos > mem->size) { 171 | if ((mem->mode & MZ_OPEN_MODE_CREATE) == 0) 172 | return MZ_SEEK_ERROR; 173 | 174 | err = mz_stream_mem_set_size(stream, (int32_t)new_pos); 175 | if (err != MZ_OK) 176 | return err; 177 | } else if (new_pos < 0) { 178 | return MZ_SEEK_ERROR; 179 | } 180 | 181 | mem->position = (int32_t)new_pos; 182 | return MZ_OK; 183 | } 184 | 185 | int32_t mz_stream_mem_close(void *stream) { 186 | MZ_UNUSED(stream); 187 | 188 | /* We never return errors */ 189 | return MZ_OK; 190 | } 191 | 192 | int32_t mz_stream_mem_error(void *stream) { 193 | MZ_UNUSED(stream); 194 | 195 | /* We never return errors */ 196 | return MZ_OK; 197 | } 198 | 199 | void mz_stream_mem_set_buffer(void *stream, void *buf, int32_t size) { 200 | mz_stream_mem *mem = (mz_stream_mem *)stream; 201 | mem->buffer = (uint8_t *)buf; 202 | mem->size = size; 203 | mem->limit = size; 204 | } 205 | 206 | int32_t mz_stream_mem_get_buffer(void *stream, const void **buf) { 207 | return mz_stream_mem_get_buffer_at(stream, 0, buf); 208 | } 209 | 210 | int32_t mz_stream_mem_get_buffer_at(void *stream, int64_t position, const void **buf) { 211 | mz_stream_mem *mem = (mz_stream_mem *)stream; 212 | if (!buf || position < 0 || !mem->buffer || mem->size < position) 213 | return MZ_SEEK_ERROR; 214 | *buf = mem->buffer + position; 215 | return MZ_OK; 216 | } 217 | 218 | int32_t mz_stream_mem_get_buffer_at_current(void *stream, const void **buf) { 219 | mz_stream_mem *mem = (mz_stream_mem *)stream; 220 | return mz_stream_mem_get_buffer_at(stream, mem->position, buf); 221 | } 222 | 223 | void mz_stream_mem_get_buffer_length(void *stream, int32_t *length) { 224 | mz_stream_mem *mem = (mz_stream_mem *)stream; 225 | *length = mem->limit; 226 | } 227 | 228 | void mz_stream_mem_set_buffer_limit(void *stream, int32_t limit) { 229 | mz_stream_mem *mem = (mz_stream_mem *)stream; 230 | mem->limit = limit; 231 | } 232 | 233 | void mz_stream_mem_set_grow_size(void *stream, int32_t grow_size) { 234 | mz_stream_mem *mem = (mz_stream_mem *)stream; 235 | mem->grow_size = grow_size; 236 | } 237 | 238 | void *mz_stream_mem_create(void) { 239 | mz_stream_mem *mem = (mz_stream_mem *)calloc(1, sizeof(mz_stream_mem)); 240 | if (mem) { 241 | mem->stream.vtbl = &mz_stream_mem_vtbl; 242 | mem->grow_size = 4096; 243 | } 244 | return mem; 245 | } 246 | 247 | void mz_stream_mem_delete(void **stream) { 248 | mz_stream_mem *mem = NULL; 249 | if (!stream) 250 | return; 251 | mem = (mz_stream_mem *)*stream; 252 | if (mem) { 253 | if ((mem->mode & MZ_OPEN_MODE_CREATE) && (mem->buffer)) 254 | free(mem->buffer); 255 | free(mem); 256 | } 257 | *stream = NULL; 258 | } 259 | 260 | void *mz_stream_mem_get_interface(void) { 261 | return (void *)&mz_stream_mem_vtbl; 262 | } 263 | -------------------------------------------------------------------------------- /mz_strm_mem.h: -------------------------------------------------------------------------------- 1 | /* mz_strm_mem.h -- Stream for memory access 2 | part of the minizip-ng project 3 | 4 | Copyright (C) Nathan Moinvaziri 5 | https://github.com/zlib-ng/minizip-ng 6 | 7 | This program is distributed under the terms of the same license as zlib. 8 | See the accompanying LICENSE file for the full text of the license. 9 | */ 10 | 11 | #ifndef MZ_STREAM_MEM_H 12 | #define MZ_STREAM_MEM_H 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | /***************************************************************************/ 19 | 20 | int32_t mz_stream_mem_open(void *stream, const char *filename, int32_t mode); 21 | int32_t mz_stream_mem_is_open(void *stream); 22 | int32_t mz_stream_mem_read(void *stream, void *buf, int32_t size); 23 | int32_t mz_stream_mem_write(void *stream, const void *buf, int32_t size); 24 | int64_t mz_stream_mem_tell(void *stream); 25 | int32_t mz_stream_mem_seek(void *stream, int64_t offset, int32_t origin); 26 | int32_t mz_stream_mem_close(void *stream); 27 | int32_t mz_stream_mem_error(void *stream); 28 | 29 | void mz_stream_mem_set_buffer(void *stream, void *buf, int32_t size); 30 | int32_t mz_stream_mem_get_buffer(void *stream, const void **buf); 31 | int32_t mz_stream_mem_get_buffer_at(void *stream, int64_t position, const void **buf); 32 | int32_t mz_stream_mem_get_buffer_at_current(void *stream, const void **buf); 33 | void mz_stream_mem_get_buffer_length(void *stream, int32_t *length); 34 | void mz_stream_mem_set_buffer_limit(void *stream, int32_t limit); 35 | void mz_stream_mem_set_grow_size(void *stream, int32_t grow_size); 36 | 37 | void *mz_stream_mem_create(void); 38 | void mz_stream_mem_delete(void **stream); 39 | 40 | void *mz_stream_mem_get_interface(void); 41 | 42 | /***************************************************************************/ 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /mz_strm_os.h: -------------------------------------------------------------------------------- 1 | /* mz_sstrm_os.h -- Stream for filesystem access 2 | part of the minizip-ng project 3 | 4 | Copyright (C) Nathan Moinvaziri 5 | https://github.com/zlib-ng/minizip-ng 6 | 7 | This program is distributed under the terms of the same license as zlib. 8 | See the accompanying LICENSE file for the full text of the license. 9 | */ 10 | 11 | #ifndef MZ_STREAM_OS_H 12 | #define MZ_STREAM_OS_H 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | /***************************************************************************/ 19 | 20 | int32_t mz_stream_os_open(void *stream, const char *path, int32_t mode); 21 | int32_t mz_stream_os_is_open(void *stream); 22 | int32_t mz_stream_os_read(void *stream, void *buf, int32_t size); 23 | int32_t mz_stream_os_write(void *stream, const void *buf, int32_t size); 24 | int64_t mz_stream_os_tell(void *stream); 25 | int32_t mz_stream_os_seek(void *stream, int64_t offset, int32_t origin); 26 | int32_t mz_stream_os_close(void *stream); 27 | int32_t mz_stream_os_error(void *stream); 28 | 29 | void *mz_stream_os_create(void); 30 | void mz_stream_os_delete(void **stream); 31 | 32 | void *mz_stream_os_get_interface(void); 33 | 34 | /***************************************************************************/ 35 | 36 | #ifdef __cplusplus 37 | } 38 | #endif 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /mz_strm_os_posix.c: -------------------------------------------------------------------------------- 1 | /* mz_strm_posix.c -- Stream for filesystem access for posix/linux 2 | part of the minizip-ng project 3 | 4 | Copyright (C) Nathan Moinvaziri 5 | https://github.com/zlib-ng/minizip-ng 6 | Modifications for Zip64 support 7 | Copyright (C) 2009-2010 Mathias Svensson 8 | http://result42.com 9 | Copyright (C) 1998-2010 Gilles Vollant 10 | https://www.winimage.com/zLibDll/minizip.html 11 | 12 | This program is distributed under the terms of the same license as zlib. 13 | See the accompanying LICENSE file for the full text of the license. 14 | */ 15 | 16 | #include "mz.h" 17 | #include "mz_strm.h" 18 | #include "mz_strm_os.h" 19 | 20 | #include /* fopen, fread.. */ 21 | #include 22 | 23 | /***************************************************************************/ 24 | 25 | #define fopen64 fopen 26 | #ifndef MZ_FILE32_API 27 | # ifndef NO_FSEEKO 28 | # define ftello64 ftello 29 | # define fseeko64 fseeko 30 | # elif defined(_MSC_VER) && (_MSC_VER >= 1400) 31 | # define ftello64 _ftelli64 32 | # define fseeko64 _fseeki64 33 | # endif 34 | #endif 35 | #ifndef ftello64 36 | # define ftello64 ftell 37 | #endif 38 | #ifndef fseeko64 39 | # define fseeko64 fseek 40 | #endif 41 | 42 | /***************************************************************************/ 43 | 44 | static mz_stream_vtbl mz_stream_os_vtbl = {mz_stream_os_open, 45 | mz_stream_os_is_open, 46 | mz_stream_os_read, 47 | mz_stream_os_write, 48 | mz_stream_os_tell, 49 | mz_stream_os_seek, 50 | mz_stream_os_close, 51 | mz_stream_os_error, 52 | mz_stream_os_create, 53 | mz_stream_os_delete, 54 | NULL, 55 | NULL}; 56 | 57 | /***************************************************************************/ 58 | 59 | typedef struct mz_stream_posix_s { 60 | mz_stream stream; 61 | int32_t error; 62 | FILE *handle; 63 | } mz_stream_posix; 64 | 65 | /***************************************************************************/ 66 | 67 | int32_t mz_stream_os_open(void *stream, const char *path, int32_t mode) { 68 | mz_stream_posix *posix = (mz_stream_posix *)stream; 69 | const char *mode_fopen = NULL; 70 | 71 | if (!path) 72 | return MZ_PARAM_ERROR; 73 | 74 | if ((mode & MZ_OPEN_MODE_READWRITE) == MZ_OPEN_MODE_READ) 75 | mode_fopen = "rb"; 76 | else if (mode & MZ_OPEN_MODE_APPEND) 77 | mode_fopen = "r+b"; 78 | else if (mode & MZ_OPEN_MODE_CREATE) 79 | mode_fopen = "wb"; 80 | else 81 | return MZ_OPEN_ERROR; 82 | 83 | posix->handle = fopen64(path, mode_fopen); 84 | if (!posix->handle) { 85 | posix->error = errno; 86 | return MZ_OPEN_ERROR; 87 | } 88 | 89 | if (mode & MZ_OPEN_MODE_APPEND) 90 | return mz_stream_os_seek(stream, 0, MZ_SEEK_END); 91 | 92 | return MZ_OK; 93 | } 94 | 95 | int32_t mz_stream_os_is_open(void *stream) { 96 | mz_stream_posix *posix = (mz_stream_posix *)stream; 97 | if (!posix->handle) 98 | return MZ_OPEN_ERROR; 99 | return MZ_OK; 100 | } 101 | 102 | int32_t mz_stream_os_read(void *stream, void *buf, int32_t size) { 103 | mz_stream_posix *posix = (mz_stream_posix *)stream; 104 | int32_t read = (int32_t)fread(buf, 1, (size_t)size, posix->handle); 105 | if (read < size && ferror(posix->handle)) { 106 | posix->error = errno; 107 | return MZ_READ_ERROR; 108 | } 109 | return read; 110 | } 111 | 112 | int32_t mz_stream_os_write(void *stream, const void *buf, int32_t size) { 113 | mz_stream_posix *posix = (mz_stream_posix *)stream; 114 | int32_t written = (int32_t)fwrite(buf, 1, (size_t)size, posix->handle); 115 | if (written < size && ferror(posix->handle)) { 116 | posix->error = errno; 117 | return MZ_WRITE_ERROR; 118 | } 119 | return written; 120 | } 121 | 122 | int64_t mz_stream_os_tell(void *stream) { 123 | mz_stream_posix *posix = (mz_stream_posix *)stream; 124 | int64_t position = ftello64(posix->handle); 125 | if (position == -1) { 126 | posix->error = errno; 127 | return MZ_TELL_ERROR; 128 | } 129 | return position; 130 | } 131 | 132 | int32_t mz_stream_os_seek(void *stream, int64_t offset, int32_t origin) { 133 | mz_stream_posix *posix = (mz_stream_posix *)stream; 134 | int32_t fseek_origin = 0; 135 | 136 | switch (origin) { 137 | case MZ_SEEK_CUR: 138 | fseek_origin = SEEK_CUR; 139 | break; 140 | case MZ_SEEK_END: 141 | fseek_origin = SEEK_END; 142 | break; 143 | case MZ_SEEK_SET: 144 | fseek_origin = SEEK_SET; 145 | break; 146 | default: 147 | return MZ_SEEK_ERROR; 148 | } 149 | 150 | if (fseeko64(posix->handle, offset, fseek_origin) != 0) { 151 | posix->error = errno; 152 | return MZ_SEEK_ERROR; 153 | } 154 | 155 | return MZ_OK; 156 | } 157 | 158 | int32_t mz_stream_os_close(void *stream) { 159 | mz_stream_posix *posix = (mz_stream_posix *)stream; 160 | int32_t closed = 0; 161 | if (posix->handle) { 162 | closed = fclose(posix->handle); 163 | posix->handle = NULL; 164 | } 165 | if (closed != 0) { 166 | posix->error = errno; 167 | return MZ_CLOSE_ERROR; 168 | } 169 | return MZ_OK; 170 | } 171 | 172 | int32_t mz_stream_os_error(void *stream) { 173 | mz_stream_posix *posix = (mz_stream_posix *)stream; 174 | return posix->error; 175 | } 176 | 177 | void *mz_stream_os_create(void) { 178 | mz_stream_posix *posix = (mz_stream_posix *)calloc(1, sizeof(mz_stream_posix)); 179 | if (posix) 180 | posix->stream.vtbl = &mz_stream_os_vtbl; 181 | return posix; 182 | } 183 | 184 | void mz_stream_os_delete(void **stream) { 185 | mz_stream_posix *posix = NULL; 186 | if (!stream) 187 | return; 188 | posix = (mz_stream_posix *)*stream; 189 | free(posix); 190 | *stream = NULL; 191 | } 192 | 193 | void *mz_stream_os_get_interface(void) { 194 | return (void *)&mz_stream_os_vtbl; 195 | } 196 | -------------------------------------------------------------------------------- /mz_strm_os_win32.c: -------------------------------------------------------------------------------- 1 | /* mz_strm_win32.c -- Stream for filesystem access for windows 2 | part of the minizip-ng project 3 | 4 | Copyright (C) Nathan Moinvaziri 5 | https://github.com/zlib-ng/minizip-ng 6 | Copyright (C) 2009-2010 Mathias Svensson 7 | Modifications for Zip64 support 8 | http://result42.com 9 | Copyright (C) 1998-2010 Gilles Vollant 10 | https://www.winimage.com/zLibDll/minizip.html 11 | 12 | This program is distributed under the terms of the same license as zlib. 13 | See the accompanying LICENSE file for the full text of the license. 14 | */ 15 | 16 | #include "mz.h" 17 | #include "mz_os.h" 18 | #include "mz_strm.h" 19 | #include "mz_strm_os.h" 20 | 21 | #include 22 | 23 | /***************************************************************************/ 24 | 25 | #ifndef INVALID_HANDLE_VALUE 26 | # define INVALID_HANDLE_VALUE 0xFFFFFFFF 27 | #endif 28 | 29 | #ifndef INVALID_SET_FILE_POINTER 30 | # define INVALID_SET_FILE_POINTER (DWORD)(-1) 31 | #endif 32 | 33 | #ifndef _WIN32_WINNT_WIN8 34 | # define _WIN32_WINNT_WIN8 0x0602 35 | #endif 36 | 37 | /***************************************************************************/ 38 | 39 | static mz_stream_vtbl mz_stream_os_vtbl = {mz_stream_os_open, 40 | mz_stream_os_is_open, 41 | mz_stream_os_read, 42 | mz_stream_os_write, 43 | mz_stream_os_tell, 44 | mz_stream_os_seek, 45 | mz_stream_os_close, 46 | mz_stream_os_error, 47 | mz_stream_os_create, 48 | mz_stream_os_delete, 49 | NULL, 50 | NULL}; 51 | 52 | /***************************************************************************/ 53 | 54 | typedef struct mz_stream_win32_s { 55 | mz_stream stream; 56 | HANDLE handle; 57 | int32_t error; 58 | } mz_stream_win32; 59 | 60 | /***************************************************************************/ 61 | 62 | #if 0 63 | # define mz_stream_os_print printf 64 | #else 65 | # define mz_stream_os_print(fmt, ...) 66 | #endif 67 | 68 | /***************************************************************************/ 69 | 70 | int32_t mz_stream_os_open(void *stream, const char *path, int32_t mode) { 71 | mz_stream_win32 *win32 = (mz_stream_win32 *)stream; 72 | uint32_t desired_access = 0; 73 | uint32_t creation_disposition = 0; 74 | uint32_t share_mode = FILE_SHARE_READ; 75 | uint32_t flags_attribs = FILE_ATTRIBUTE_NORMAL; 76 | wchar_t *path_wide = NULL; 77 | 78 | if (!path) 79 | return MZ_PARAM_ERROR; 80 | 81 | /* Some use cases require write sharing as well */ 82 | share_mode |= FILE_SHARE_WRITE; 83 | 84 | if ((mode & MZ_OPEN_MODE_READWRITE) == MZ_OPEN_MODE_READ) { 85 | desired_access = GENERIC_READ; 86 | creation_disposition = OPEN_EXISTING; 87 | } else if (mode & MZ_OPEN_MODE_APPEND) { 88 | desired_access = GENERIC_WRITE | GENERIC_READ; 89 | creation_disposition = OPEN_EXISTING; 90 | } else if (mode & MZ_OPEN_MODE_CREATE) { 91 | desired_access = GENERIC_WRITE | GENERIC_READ; 92 | creation_disposition = CREATE_ALWAYS; 93 | } else { 94 | return MZ_PARAM_ERROR; 95 | } 96 | 97 | mz_stream_os_print("Win32 - Open - %s (mode %" PRId32 ")\n", path); 98 | 99 | path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8); 100 | if (!path_wide) 101 | return MZ_PARAM_ERROR; 102 | 103 | #if _WIN32_WINNT >= _WIN32_WINNT_WIN8 104 | win32->handle = CreateFile2(path_wide, desired_access, share_mode, creation_disposition, NULL); 105 | #else 106 | win32->handle = CreateFileW(path_wide, desired_access, share_mode, NULL, creation_disposition, flags_attribs, NULL); 107 | #endif 108 | 109 | mz_os_unicode_string_delete(&path_wide); 110 | 111 | if (mz_stream_os_is_open(stream) != MZ_OK) { 112 | win32->error = GetLastError(); 113 | return MZ_OPEN_ERROR; 114 | } 115 | 116 | if (mode & MZ_OPEN_MODE_APPEND) 117 | return mz_stream_os_seek(stream, 0, MZ_SEEK_END); 118 | 119 | return MZ_OK; 120 | } 121 | 122 | int32_t mz_stream_os_is_open(void *stream) { 123 | mz_stream_win32 *win32 = (mz_stream_win32 *)stream; 124 | if (!win32->handle || win32->handle == INVALID_HANDLE_VALUE) 125 | return MZ_OPEN_ERROR; 126 | return MZ_OK; 127 | } 128 | 129 | int32_t mz_stream_os_read(void *stream, void *buf, int32_t size) { 130 | mz_stream_win32 *win32 = (mz_stream_win32 *)stream; 131 | uint32_t read = 0; 132 | 133 | if (mz_stream_os_is_open(stream) != MZ_OK) 134 | return MZ_OPEN_ERROR; 135 | 136 | if (!ReadFile(win32->handle, buf, size, (DWORD *)&read, NULL)) { 137 | win32->error = GetLastError(); 138 | if (win32->error == ERROR_HANDLE_EOF) 139 | win32->error = 0; 140 | } 141 | 142 | mz_stream_os_print("Win32 - Read - %" PRId32 "\n", read); 143 | 144 | return read; 145 | } 146 | 147 | int32_t mz_stream_os_write(void *stream, const void *buf, int32_t size) { 148 | mz_stream_win32 *win32 = (mz_stream_win32 *)stream; 149 | int32_t written = 0; 150 | 151 | if (mz_stream_os_is_open(stream) != MZ_OK) 152 | return MZ_OPEN_ERROR; 153 | 154 | if (!WriteFile(win32->handle, buf, size, (DWORD *)&written, NULL)) { 155 | win32->error = GetLastError(); 156 | if (win32->error == ERROR_HANDLE_EOF) 157 | win32->error = 0; 158 | } 159 | 160 | mz_stream_os_print("Win32 - Write - %" PRId32 "\n", written); 161 | 162 | return written; 163 | } 164 | 165 | static int32_t mz_stream_os_seekinternal(HANDLE handle, LARGE_INTEGER large_pos, LARGE_INTEGER *new_pos, 166 | uint32_t move_method) { 167 | #if _WIN32_WINNT >= _WIN32_WINNT_WINXP 168 | BOOL success = FALSE; 169 | success = SetFilePointerEx(handle, large_pos, new_pos, move_method); 170 | if ((success == FALSE) && (GetLastError() != NO_ERROR)) 171 | return MZ_SEEK_ERROR; 172 | 173 | return MZ_OK; 174 | #else 175 | LONG high_part = 0; 176 | uint32_t pos = 0; 177 | 178 | high_part = large_pos.HighPart; 179 | pos = SetFilePointer(handle, large_pos.LowPart, &high_part, move_method); 180 | 181 | if ((pos == INVALID_SET_FILE_POINTER) && (GetLastError() != NO_ERROR)) 182 | return MZ_SEEK_ERROR; 183 | 184 | if (new_pos) { 185 | new_pos->LowPart = pos; 186 | new_pos->HighPart = high_part; 187 | } 188 | 189 | return MZ_OK; 190 | #endif 191 | } 192 | 193 | int64_t mz_stream_os_tell(void *stream) { 194 | mz_stream_win32 *win32 = (mz_stream_win32 *)stream; 195 | LARGE_INTEGER large_pos; 196 | 197 | if (mz_stream_os_is_open(stream) != MZ_OK) 198 | return MZ_OPEN_ERROR; 199 | 200 | large_pos.QuadPart = 0; 201 | 202 | if (mz_stream_os_seekinternal(win32->handle, large_pos, &large_pos, FILE_CURRENT) != MZ_OK) 203 | win32->error = GetLastError(); 204 | 205 | mz_stream_os_print("Win32 - Tell - %" PRId64 "\n", large_pos.QuadPart); 206 | 207 | return large_pos.QuadPart; 208 | } 209 | 210 | int32_t mz_stream_os_seek(void *stream, int64_t offset, int32_t origin) { 211 | mz_stream_win32 *win32 = (mz_stream_win32 *)stream; 212 | uint32_t move_method = 0xFFFFFFFF; 213 | int32_t err = MZ_OK; 214 | LARGE_INTEGER large_pos; 215 | 216 | if (mz_stream_os_is_open(stream) != MZ_OK) 217 | return MZ_OPEN_ERROR; 218 | 219 | switch (origin) { 220 | case MZ_SEEK_CUR: 221 | move_method = FILE_CURRENT; 222 | break; 223 | case MZ_SEEK_END: 224 | move_method = FILE_END; 225 | break; 226 | case MZ_SEEK_SET: 227 | move_method = FILE_BEGIN; 228 | break; 229 | default: 230 | return MZ_SEEK_ERROR; 231 | } 232 | 233 | mz_stream_os_print("Win32 - Seek - %" PRId64 " (origin %" PRId32 ")\n", offset, origin); 234 | 235 | large_pos.QuadPart = offset; 236 | 237 | err = mz_stream_os_seekinternal(win32->handle, large_pos, NULL, move_method); 238 | if (err != MZ_OK) { 239 | win32->error = GetLastError(); 240 | return err; 241 | } 242 | 243 | return MZ_OK; 244 | } 245 | 246 | int32_t mz_stream_os_close(void *stream) { 247 | mz_stream_win32 *win32 = (mz_stream_win32 *)stream; 248 | 249 | if (win32->handle) 250 | CloseHandle(win32->handle); 251 | mz_stream_os_print("Win32 - Close\n"); 252 | win32->handle = NULL; 253 | return MZ_OK; 254 | } 255 | 256 | int32_t mz_stream_os_error(void *stream) { 257 | mz_stream_win32 *win32 = (mz_stream_win32 *)stream; 258 | return win32->error; 259 | } 260 | 261 | void *mz_stream_os_create(void) { 262 | mz_stream_win32 *win32 = (mz_stream_win32 *)calloc(1, sizeof(mz_stream_win32)); 263 | if (win32) 264 | win32->stream.vtbl = &mz_stream_os_vtbl; 265 | return win32; 266 | } 267 | 268 | void mz_stream_os_delete(void **stream) { 269 | mz_stream_win32 *win32 = NULL; 270 | if (!stream) 271 | return; 272 | win32 = (mz_stream_win32 *)*stream; 273 | if (win32) 274 | free(win32); 275 | *stream = NULL; 276 | } 277 | 278 | void *mz_stream_os_get_interface(void) { 279 | return (void *)&mz_stream_os_vtbl; 280 | } 281 | -------------------------------------------------------------------------------- /mz_strm_pkcrypt.h: -------------------------------------------------------------------------------- 1 | /* mz_strm_pkcrypt.h -- Code for traditional PKWARE encryption 2 | part of the minizip-ng project 3 | 4 | Copyright (C) Nathan Moinvaziri 5 | https://github.com/zlib-ng/minizip-ng 6 | 7 | This program is distributed under the terms of the same license as zlib. 8 | See the accompanying LICENSE file for the full text of the license. 9 | */ 10 | 11 | #ifndef MZ_STREAM_PKCRYPT_H 12 | #define MZ_STREAM_PKCRYPT_H 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | /***************************************************************************/ 19 | 20 | int32_t mz_stream_pkcrypt_open(void *stream, const char *filename, int32_t mode); 21 | int32_t mz_stream_pkcrypt_is_open(void *stream); 22 | int32_t mz_stream_pkcrypt_read(void *stream, void *buf, int32_t size); 23 | int32_t mz_stream_pkcrypt_write(void *stream, const void *buf, int32_t size); 24 | int64_t mz_stream_pkcrypt_tell(void *stream); 25 | int32_t mz_stream_pkcrypt_seek(void *stream, int64_t offset, int32_t origin); 26 | int32_t mz_stream_pkcrypt_close(void *stream); 27 | int32_t mz_stream_pkcrypt_error(void *stream); 28 | 29 | void mz_stream_pkcrypt_set_password(void *stream, const char *password); 30 | void mz_stream_pkcrypt_set_verify(void *stream, uint8_t verify1, uint8_t verify2, uint16_t version); 31 | void mz_stream_pkcrypt_get_verify(void *stream, uint8_t *verify1, uint8_t *verify2, uint16_t *version); 32 | int32_t mz_stream_pkcrypt_get_prop_int64(void *stream, int32_t prop, int64_t *value); 33 | int32_t mz_stream_pkcrypt_set_prop_int64(void *stream, int32_t prop, int64_t value); 34 | 35 | void *mz_stream_pkcrypt_create(void); 36 | void mz_stream_pkcrypt_delete(void **stream); 37 | 38 | void *mz_stream_pkcrypt_get_interface(void); 39 | 40 | /***************************************************************************/ 41 | 42 | #ifdef __cplusplus 43 | } 44 | #endif 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /mz_strm_split.h: -------------------------------------------------------------------------------- 1 | /* mz_strm_split.h -- Stream for split files 2 | part of the minizip-ng project 3 | 4 | Copyright (C) Nathan Moinvaziri 5 | https://github.com/zlib-ng/minizip-ng 6 | 7 | This program is distributed under the terms of the same license as zlib. 8 | See the accompanying LICENSE file for the full text of the license. 9 | */ 10 | 11 | #ifndef MZ_STREAM_SPLIT_H 12 | #define MZ_STREAM_SPLIT_H 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | /***************************************************************************/ 19 | 20 | int32_t mz_stream_split_open(void *stream, const char *filename, int32_t mode); 21 | int32_t mz_stream_split_is_open(void *stream); 22 | int32_t mz_stream_split_read(void *stream, void *buf, int32_t size); 23 | int32_t mz_stream_split_write(void *stream, const void *buf, int32_t size); 24 | int64_t mz_stream_split_tell(void *stream); 25 | int32_t mz_stream_split_seek(void *stream, int64_t offset, int32_t origin); 26 | int32_t mz_stream_split_close(void *stream); 27 | int32_t mz_stream_split_error(void *stream); 28 | 29 | int32_t mz_stream_split_get_prop_int64(void *stream, int32_t prop, int64_t *value); 30 | int32_t mz_stream_split_set_prop_int64(void *stream, int32_t prop, int64_t value); 31 | 32 | void *mz_stream_split_create(void); 33 | void mz_stream_split_delete(void **stream); 34 | 35 | void *mz_stream_split_get_interface(void); 36 | 37 | /***************************************************************************/ 38 | 39 | #ifdef __cplusplus 40 | } 41 | #endif 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /mz_strm_wzaes.h: -------------------------------------------------------------------------------- 1 | /* mz_strm_wzaes.h -- Stream for WinZIP AES encryption 2 | part of the minizip-ng project 3 | 4 | Copyright (C) Nathan Moinvaziri 5 | https://github.com/zlib-ng/minizip-ng 6 | 7 | This program is distributed under the terms of the same license as zlib. 8 | See the accompanying LICENSE file for the full text of the license. 9 | */ 10 | 11 | #ifndef MZ_STREAM_WZAES_SHA1_H 12 | #define MZ_STREAM_WZAES_SHA1_H 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | /***************************************************************************/ 19 | 20 | int32_t mz_stream_wzaes_open(void *stream, const char *filename, int32_t mode); 21 | int32_t mz_stream_wzaes_is_open(void *stream); 22 | int32_t mz_stream_wzaes_read(void *stream, void *buf, int32_t size); 23 | int32_t mz_stream_wzaes_write(void *stream, const void *buf, int32_t size); 24 | int64_t mz_stream_wzaes_tell(void *stream); 25 | int32_t mz_stream_wzaes_seek(void *stream, int64_t offset, int32_t origin); 26 | int32_t mz_stream_wzaes_close(void *stream); 27 | int32_t mz_stream_wzaes_error(void *stream); 28 | 29 | void mz_stream_wzaes_set_password(void *stream, const char *password); 30 | void mz_stream_wzaes_set_strength(void *stream, uint8_t strength); 31 | 32 | int32_t mz_stream_wzaes_get_prop_int64(void *stream, int32_t prop, int64_t *value); 33 | int32_t mz_stream_wzaes_set_prop_int64(void *stream, int32_t prop, int64_t value); 34 | 35 | void *mz_stream_wzaes_create(void); 36 | void mz_stream_wzaes_delete(void **stream); 37 | 38 | void *mz_stream_wzaes_get_interface(void); 39 | 40 | /***************************************************************************/ 41 | 42 | #ifdef __cplusplus 43 | } 44 | #endif 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /mz_strm_zlib.h: -------------------------------------------------------------------------------- 1 | /* mz_strm_zlib.h -- Stream for zlib inflate/deflate 2 | part of the minizip-ng project 3 | 4 | Copyright (C) Nathan Moinvaziri 5 | https://github.com/zlib-ng/minizip-ng 6 | 7 | This program is distributed under the terms of the same license as zlib. 8 | See the accompanying LICENSE file for the full text of the license. 9 | */ 10 | 11 | #ifndef MZ_STREAM_ZLIB_H 12 | #define MZ_STREAM_ZLIB_H 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | /***************************************************************************/ 19 | 20 | int32_t mz_stream_zlib_open(void *stream, const char *filename, int32_t mode); 21 | int32_t mz_stream_zlib_is_open(void *stream); 22 | int32_t mz_stream_zlib_read(void *stream, void *buf, int32_t size); 23 | int32_t mz_stream_zlib_write(void *stream, const void *buf, int32_t size); 24 | int64_t mz_stream_zlib_tell(void *stream); 25 | int32_t mz_stream_zlib_seek(void *stream, int64_t offset, int32_t origin); 26 | int32_t mz_stream_zlib_close(void *stream); 27 | int32_t mz_stream_zlib_error(void *stream); 28 | 29 | int32_t mz_stream_zlib_get_prop_int64(void *stream, int32_t prop, int64_t *value); 30 | int32_t mz_stream_zlib_set_prop_int64(void *stream, int32_t prop, int64_t value); 31 | 32 | void *mz_stream_zlib_create(void); 33 | void mz_stream_zlib_delete(void **stream); 34 | 35 | void *mz_stream_zlib_get_interface(void); 36 | 37 | /***************************************************************************/ 38 | 39 | #ifdef __cplusplus 40 | } 41 | #endif 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /mz_strm_zstd.h: -------------------------------------------------------------------------------- 1 | /* mz_strm_zlib.h -- Stream for zlib inflate/deflate 2 | Version 2.9.2, February 12, 2020 3 | part of the minizip-ng project 4 | 5 | Copyright (C) Nathan Moinvaziri 6 | https://github.com/zlib-ng/minizip-ng 7 | 8 | This program is distributed under the terms of the same license as zlib. 9 | See the accompanying LICENSE file for the full text of the license. 10 | */ 11 | 12 | #ifndef MZ_STREAM_ZSTD_H 13 | #define MZ_STREAM_ZSTD_H 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | /***************************************************************************/ 20 | 21 | int32_t mz_stream_zstd_open(void *stream, const char *filename, int32_t mode); 22 | int32_t mz_stream_zstd_is_open(void *stream); 23 | int32_t mz_stream_zstd_read(void *stream, void *buf, int32_t size); 24 | int32_t mz_stream_zstd_write(void *stream, const void *buf, int32_t size); 25 | int64_t mz_stream_zstd_tell(void *stream); 26 | int32_t mz_stream_zstd_seek(void *stream, int64_t offset, int32_t origin); 27 | int32_t mz_stream_zstd_close(void *stream); 28 | int32_t mz_stream_zstd_error(void *stream); 29 | 30 | int32_t mz_stream_zstd_get_prop_int64(void *stream, int32_t prop, int64_t *value); 31 | int32_t mz_stream_zstd_set_prop_int64(void *stream, int32_t prop, int64_t value); 32 | 33 | void *mz_stream_zstd_create(void); 34 | void mz_stream_zstd_delete(void **stream); 35 | 36 | void *mz_stream_zstd_get_interface(void); 37 | 38 | /***************************************************************************/ 39 | 40 | #ifdef __cplusplus 41 | } 42 | #endif 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.12) 2 | 3 | include(FetchContent) 4 | 5 | enable_language(CXX) 6 | 7 | if(NOT TARGET GTest::GTest) 8 | find_package(GTest QUIET) 9 | endif() 10 | 11 | if(NOT TARGET GTest::GTest) 12 | if (WIN32) 13 | # Prevent overriding the parent project's compiler/linker settings for Windows 14 | set(gtest_force_shared_crt ON CACHE BOOL 15 | "Use shared (DLL) run-time lib even when Google Test is built as static lib." FORCE) 16 | 17 | set(gtest_disable_pthreads ON CACHE BOOL "Disable pthreads" FORCE) 18 | endif() 19 | 20 | # Allow specifying alternative Google test repository 21 | if(NOT DEFINED GTEST_REPOSITORY) 22 | set(GTEST_REPOSITORY https://github.com/google/googletest.git) 23 | endif() 24 | if(NOT DEFINED GTEST_TAG) 25 | # Use older version of Google test to support older versions of GCC 26 | if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS_EQUAL 5.3) 27 | set(GTEST_TAG release-1.10.0) 28 | else() 29 | set(GTEST_TAG v1.13.0) 30 | endif() 31 | endif() 32 | 33 | # Fetch Google test source code from official repository 34 | FetchContent_Declare(googletest 35 | GIT_REPOSITORY ${GTEST_REPOSITORY} 36 | GIT_TAG ${GTEST_TAG}) 37 | 38 | FetchContent_GetProperties(googletest) 39 | if(NOT googletest_POPULATED) 40 | FetchContent_Populate(googletest) 41 | add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR} EXCLUDE_FROM_ALL) 42 | endif() 43 | add_library(GTest::GTest ALIAS gtest) 44 | endif() 45 | 46 | set(TEST_SRCS 47 | test_crypt.cc 48 | test_encoding.cc 49 | test_path.cc 50 | test_stream.cc 51 | test_stream_crypt.cc 52 | ) 53 | 54 | if(NOT MZ_COMPRESS_ONLY AND NOT MZ_DECOMPRESS_ONLY) 55 | if(MZ_COMPAT) 56 | list(APPEND TEST_SRCS test_compat.cc) 57 | endif() 58 | list(APPEND TEST_SRCS test_stream_compress.cc) 59 | endif() 60 | 61 | if(MSVC) 62 | list(APPEND TEST_SRCS test_file.cc) 63 | endif() 64 | 65 | add_executable(gtest_minizip test_main.cc ${TEST_SRCS}) 66 | target_compile_definitions(gtest_minizip PRIVATE ${STDLIB_DEF} ${MINIZIP_DEF}) 67 | target_include_directories(gtest_minizip PRIVATE 68 | ${CMAKE_SOURCE_DIR} 69 | ${CMAKE_BINARY_DIR}) 70 | 71 | target_link_libraries(gtest_minizip MINIZIP::minizip GTest::GTest) 72 | 73 | if(MSVC) 74 | set_target_properties(gtest_minizip PROPERTIES 75 | VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) 76 | endif() 77 | 78 | add_test(NAME gtest_minizip 79 | COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $ 80 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) 81 | -------------------------------------------------------------------------------- /test/empty.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlib-ng/minizip-ng/227f2d35bed866de674028a0ac97a50af778bae1/test/empty.txt -------------------------------------------------------------------------------- /test/fuzz/standalone.c: -------------------------------------------------------------------------------- 1 | /* standalone.c - Standalone fuzzer tester 2 | part of the minizip-ng project 3 | 4 | Copyright (C) Nathan Moinvaziri 5 | https://github.com/zlib-ng/minizip-ng 6 | Copyright (C) 2018 sebpop 7 | https://github.com/sebpop 8 | 9 | This program is distributed under the terms of the same license as zlib. 10 | See the accompanying LICENSE file for the full text of the license. 11 | */ 12 | 13 | #include "mz.h" 14 | #include "mz_strm.h" 15 | #include "mz_strm_os.h" 16 | 17 | #include /* printf */ 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /***************************************************************************/ 24 | 25 | extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size); 26 | 27 | /***************************************************************************/ 28 | 29 | int main(int argc, char **argv) { 30 | void *stream = NULL; 31 | int64_t file_size = 0; 32 | uint8_t *buf = NULL; 33 | int32_t buf_length = 0; 34 | int32_t err = MZ_OK; 35 | int32_t read = 0; 36 | int32_t i = 0; 37 | 38 | if (argc < 1) { 39 | printf("Must specify an input file\n"); 40 | return 1; 41 | } 42 | 43 | printf("Running %" PRId32 " inputs\n", argc - 1); 44 | 45 | for (i = 1; (i < argc) && (err == MZ_OK); i++) { 46 | read = 0; 47 | 48 | stream = mz_stream_os_create(); 49 | err = mz_stream_os_open(stream, argv[i], MZ_OPEN_MODE_READ); 50 | 51 | if (err != MZ_OK) { 52 | printf("Skipping %s (%" PRId32 ")\n", argv[i], err); 53 | } else { 54 | mz_stream_os_seek(stream, 0, MZ_SEEK_END); 55 | file_size = mz_stream_os_tell(stream); 56 | if (file_size > INT32_MAX) 57 | printf("File size is too large (%" PRId64 ")\n", file_size); 58 | else 59 | buf_length = (int32_t)file_size; 60 | mz_stream_os_seek(stream, 0, MZ_SEEK_SET); 61 | 62 | buf = NULL; 63 | if (buf_length > 0) 64 | buf = malloc(buf_length); 65 | 66 | if (buf) { 67 | printf("Running %s %" PRId32 "\n", argv[i], buf_length); 68 | read = mz_stream_os_read(stream, buf, buf_length); 69 | if (read == buf_length) 70 | LLVMFuzzerTestOneInput(buf, buf_length); 71 | else 72 | err = MZ_BUF_ERROR; 73 | 74 | free(buf); 75 | } 76 | 77 | mz_stream_os_close(stream); 78 | } 79 | 80 | mz_stream_os_delete(&stream); 81 | printf("Done %s (%" PRId32 ")\n", argv[i], err); 82 | } 83 | 84 | return 0; 85 | } 86 | 87 | /***************************************************************************/ 88 | 89 | #ifdef __cplusplus 90 | } 91 | #endif 92 | -------------------------------------------------------------------------------- /test/fuzz/unzip_fuzzer.c: -------------------------------------------------------------------------------- 1 | /* unzip_fuzzer.c - Unzip fuzzer for libFuzzer 2 | part of the minizip-ng project 3 | 4 | Copyright (C) 2018 The Chromium Authors 5 | Copyright (C) 2018 Anand K. Mistry 6 | Copyright (C) Nathan Moinvaziri 7 | https://github.com/zlib-ng/minizip-ng 8 | 9 | This program is distributed under the terms of the same license as zlib. 10 | See the accompanying LICENSE file for the full text of the license. 11 | */ 12 | 13 | #include "mz.h" 14 | #include "mz_strm.h" 15 | #include "mz_strm_mem.h" 16 | #include "mz_zip.h" 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | /***************************************************************************/ 23 | 24 | #define MZ_FUZZ_TEST_PWD "test123" 25 | #define MZ_FUZZ_TEST_FILENAME "foo" 26 | #define MZ_FUZZ_TEST_FILENAMEUC "FOO" 27 | 28 | /***************************************************************************/ 29 | 30 | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 31 | mz_zip_file *file_info = NULL; 32 | void *stream = NULL; 33 | void *handle = NULL; 34 | const char *archive_comment = NULL; 35 | char buffer[1024]; 36 | uint16_t version_madeby = 0; 37 | uint64_t num_entries = 0; 38 | int64_t entry_pos = 0; 39 | int32_t err = MZ_OK; 40 | uint8_t encrypted = 0; 41 | 42 | stream = mz_stream_mem_create(); 43 | if (!stream) 44 | return 1; 45 | 46 | mz_stream_mem_set_buffer(stream, (void *)data, (int32_t)size); 47 | 48 | handle = mz_zip_create(); 49 | if (!handle) 50 | return 1; 51 | 52 | mz_zip_set_recover(handle, (size & 0xE0) == 0xE0); 53 | err = mz_zip_open(handle, stream, MZ_OPEN_MODE_READ); 54 | 55 | if (err == MZ_OK) { 56 | /* Some archive properties that are non-fatal for reading the archive. */ 57 | mz_zip_get_comment(handle, &archive_comment); 58 | mz_zip_get_version_madeby(handle, &version_madeby); 59 | mz_zip_get_number_entry(handle, &num_entries); 60 | 61 | err = mz_zip_goto_first_entry(handle); 62 | while (err == MZ_OK) { 63 | err = mz_zip_entry_get_info(handle, &file_info); 64 | if (err != MZ_OK) 65 | break; 66 | 67 | encrypted = (file_info->flag & MZ_ZIP_FLAG_ENCRYPTED); 68 | 69 | err = mz_zip_entry_read_open(handle, 0, encrypted ? MZ_FUZZ_TEST_PWD : NULL); 70 | if (err != MZ_OK) 71 | break; 72 | 73 | err = mz_zip_entry_is_open(handle); 74 | if (err != MZ_OK) 75 | break; 76 | 77 | /* Return value isn't checked here because we can't predict 78 | what the value will be. */ 79 | 80 | mz_zip_entry_is_dir(handle); 81 | entry_pos = mz_zip_get_entry(handle); 82 | if (entry_pos < 0) 83 | break; 84 | 85 | err = mz_zip_entry_read(handle, buffer, sizeof(buffer)); 86 | if (err < 0) 87 | break; 88 | 89 | err = mz_zip_entry_close(handle); 90 | if (err != MZ_OK) 91 | break; 92 | 93 | err = mz_zip_goto_next_entry(handle); 94 | } 95 | 96 | mz_zip_entry_close(handle); 97 | 98 | /* Return value isn't checked here because we can't predict what the value 99 | will be. */ 100 | 101 | mz_zip_locate_entry(handle, MZ_FUZZ_TEST_FILENAME, 0); 102 | mz_zip_locate_entry(handle, MZ_FUZZ_TEST_FILENAMEUC, 0); 103 | mz_zip_locate_entry(handle, MZ_FUZZ_TEST_FILENAME, 1); 104 | mz_zip_locate_entry(handle, MZ_FUZZ_TEST_FILENAMEUC, 1); 105 | 106 | mz_zip_close(handle); 107 | } 108 | 109 | mz_zip_delete(&handle); 110 | mz_stream_mem_delete(&stream); 111 | 112 | return 0; 113 | } 114 | 115 | /***************************************************************************/ 116 | 117 | #ifdef __cplusplus 118 | } 119 | #endif 120 | -------------------------------------------------------------------------------- /test/fuzz/unzip_fuzzer.dict: -------------------------------------------------------------------------------- 1 | # A dictionary for more efficient fuzzing of DoStuff(). 2 | # If the inputs contain multi-byte tokens, list them here. 3 | # See https://llvm.org/docs/LibFuzzer.html#dictionaries 4 | "\x50\x4b\x03\x04" 5 | "\x50\x4b\x01\x02" 6 | "\x50\x4b\x05\x06" 7 | "\x50\x4b\x06\x06" 8 | "\x50\x4b\x06\x07" 9 | "\x50\x4b\x07\x08" 10 | -------------------------------------------------------------------------------- /test/fuzz/unzip_fuzzer_seed_corpus/as.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlib-ng/minizip-ng/227f2d35bed866de674028a0ac97a50af778bae1/test/fuzz/unzip_fuzzer_seed_corpus/as.zip -------------------------------------------------------------------------------- /test/fuzz/unzip_fuzzer_seed_corpus/bzip2.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlib-ng/minizip-ng/227f2d35bed866de674028a0ac97a50af778bae1/test/fuzz/unzip_fuzzer_seed_corpus/bzip2.zip -------------------------------------------------------------------------------- /test/fuzz/unzip_fuzzer_seed_corpus/comments.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlib-ng/minizip-ng/227f2d35bed866de674028a0ac97a50af778bae1/test/fuzz/unzip_fuzzer_seed_corpus/comments.zip -------------------------------------------------------------------------------- /test/fuzz/unzip_fuzzer_seed_corpus/corpus.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlib-ng/minizip-ng/227f2d35bed866de674028a0ac97a50af778bae1/test/fuzz/unzip_fuzzer_seed_corpus/corpus.zip -------------------------------------------------------------------------------- /test/fuzz/unzip_fuzzer_seed_corpus/dot_dot_backslash_name.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlib-ng/minizip-ng/227f2d35bed866de674028a0ac97a50af778bae1/test/fuzz/unzip_fuzzer_seed_corpus/dot_dot_backslash_name.zip -------------------------------------------------------------------------------- /test/fuzz/unzip_fuzzer_seed_corpus/encrypted_pkcrypt.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlib-ng/minizip-ng/227f2d35bed866de674028a0ac97a50af778bae1/test/fuzz/unzip_fuzzer_seed_corpus/encrypted_pkcrypt.zip -------------------------------------------------------------------------------- /test/fuzz/unzip_fuzzer_seed_corpus/encrypted_wzaes.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlib-ng/minizip-ng/227f2d35bed866de674028a0ac97a50af778bae1/test/fuzz/unzip_fuzzer_seed_corpus/encrypted_wzaes.zip -------------------------------------------------------------------------------- /test/fuzz/unzip_fuzzer_seed_corpus/gh.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlib-ng/minizip-ng/227f2d35bed866de674028a0ac97a50af778bae1/test/fuzz/unzip_fuzzer_seed_corpus/gh.zip -------------------------------------------------------------------------------- /test/fuzz/unzip_fuzzer_seed_corpus/gh_739.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlib-ng/minizip-ng/227f2d35bed866de674028a0ac97a50af778bae1/test/fuzz/unzip_fuzzer_seed_corpus/gh_739.zip -------------------------------------------------------------------------------- /test/fuzz/unzip_fuzzer_seed_corpus/gh_740.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlib-ng/minizip-ng/227f2d35bed866de674028a0ac97a50af778bae1/test/fuzz/unzip_fuzzer_seed_corpus/gh_740.zip -------------------------------------------------------------------------------- /test/fuzz/unzip_fuzzer_seed_corpus/incorrect_number_entries.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlib-ng/minizip-ng/227f2d35bed866de674028a0ac97a50af778bae1/test/fuzz/unzip_fuzzer_seed_corpus/incorrect_number_entries.zip -------------------------------------------------------------------------------- /test/fuzz/unzip_fuzzer_seed_corpus/infozip_symlinks.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlib-ng/minizip-ng/227f2d35bed866de674028a0ac97a50af778bae1/test/fuzz/unzip_fuzzer_seed_corpus/infozip_symlinks.zip -------------------------------------------------------------------------------- /test/fuzz/unzip_fuzzer_seed_corpus/large_cd_comment.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlib-ng/minizip-ng/227f2d35bed866de674028a0ac97a50af778bae1/test/fuzz/unzip_fuzzer_seed_corpus/large_cd_comment.zip -------------------------------------------------------------------------------- /test/fuzz/unzip_fuzzer_seed_corpus/license_zstd.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlib-ng/minizip-ng/227f2d35bed866de674028a0ac97a50af778bae1/test/fuzz/unzip_fuzzer_seed_corpus/license_zstd.zip -------------------------------------------------------------------------------- /test/fuzz/unzip_fuzzer_seed_corpus/lzma.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlib-ng/minizip-ng/227f2d35bed866de674028a0ac97a50af778bae1/test/fuzz/unzip_fuzzer_seed_corpus/lzma.zip -------------------------------------------------------------------------------- /test/fuzz/unzip_fuzzer_seed_corpus/permissions.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlib-ng/minizip-ng/227f2d35bed866de674028a0ac97a50af778bae1/test/fuzz/unzip_fuzzer_seed_corpus/permissions.zip -------------------------------------------------------------------------------- /test/fuzz/unzip_fuzzer_seed_corpus/signed.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlib-ng/minizip-ng/227f2d35bed866de674028a0ac97a50af778bae1/test/fuzz/unzip_fuzzer_seed_corpus/signed.zip -------------------------------------------------------------------------------- /test/fuzz/unzip_fuzzer_seed_corpus/storeonly.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlib-ng/minizip-ng/227f2d35bed866de674028a0ac97a50af778bae1/test/fuzz/unzip_fuzzer_seed_corpus/storeonly.zip -------------------------------------------------------------------------------- /test/fuzz/unzip_fuzzer_seed_corpus/tiny.zip: -------------------------------------------------------------------------------- 1 | PK -------------------------------------------------------------------------------- /test/fuzz/unzip_fuzzer_seed_corpus/unsupported_permissions.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlib-ng/minizip-ng/227f2d35bed866de674028a0ac97a50af778bae1/test/fuzz/unzip_fuzzer_seed_corpus/unsupported_permissions.zip -------------------------------------------------------------------------------- /test/fuzz/unzip_fuzzer_seed_corpus/xz.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlib-ng/minizip-ng/227f2d35bed866de674028a0ac97a50af778bae1/test/fuzz/unzip_fuzzer_seed_corpus/xz.zip -------------------------------------------------------------------------------- /test/fuzz/unzip_fuzzer_seed_corpus/zip64.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlib-ng/minizip-ng/227f2d35bed866de674028a0ac97a50af778bae1/test/fuzz/unzip_fuzzer_seed_corpus/zip64.zip -------------------------------------------------------------------------------- /test/fuzz/zip_fuzzer.c: -------------------------------------------------------------------------------- 1 | /* zip_fuzzer.c - Zip fuzzer for libFuzzer 2 | part of the minizip-ng project 3 | 4 | Copyright (C) 2018 The Chromium Authors 5 | Copyright (C) 2018 Anand K. Mistry 6 | Copyright (C) Nathan Moinvaziri 7 | https://github.com/zlib-ng/minizip-ng 8 | 9 | This program is distributed under the terms of the same license as zlib. 10 | See the accompanying LICENSE file for the full text of the license. 11 | */ 12 | 13 | #include "mz.h" 14 | #include "mz_strm.h" 15 | #include "mz_strm_mem.h" 16 | #include "mz_zip.h" 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | /***************************************************************************/ 23 | 24 | #define MZ_FUZZ_TEST_FILENAME "foo" 25 | #define MZ_FUZZ_TEST_PWD "test123" 26 | 27 | /***************************************************************************/ 28 | 29 | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 30 | mz_zip_file file_info; 31 | void *fuzz_stream = NULL; 32 | void *stream = NULL; 33 | void *handle = NULL; 34 | int32_t err = MZ_OK; 35 | uint16_t value16 = 0; 36 | uint8_t value8 = 0; 37 | int16_t compress_level = 0; 38 | int64_t fuzz_pos = 0; 39 | int32_t fuzz_length = 0; 40 | uint8_t *fuzz_buf = NULL; 41 | const char *password = NULL; 42 | 43 | fuzz_stream = mz_stream_mem_create(); 44 | if (!fuzz_stream) 45 | return 1; 46 | mz_stream_mem_set_buffer(fuzz_stream, (void *)data, (int32_t)size); 47 | 48 | memset(&file_info, 0, sizeof(file_info)); 49 | 50 | file_info.flag = MZ_ZIP_FLAG_UTF8; 51 | if ((mz_stream_read_uint8(fuzz_stream, &value8) == MZ_OK) && (value8 < 0x08)) { 52 | if (mz_stream_read_uint16(fuzz_stream, &value16) == MZ_OK) 53 | file_info.flag = value16; 54 | } 55 | file_info.compression_method = MZ_COMPRESS_METHOD_DEFLATE; 56 | if ((mz_stream_read_uint8(fuzz_stream, &value8) == MZ_OK) && (value8 < 0x08)) { 57 | file_info.compression_method = MZ_COMPRESS_METHOD_STORE; 58 | } else if ((mz_stream_read_uint8(fuzz_stream, &value8) == MZ_OK) && (value8 < 0x08)) { 59 | if (mz_stream_read_uint16(fuzz_stream, &value16) == MZ_OK) 60 | file_info.compression_method = value16; 61 | } 62 | 63 | if ((mz_stream_read_uint8(fuzz_stream, &value8) == MZ_OK) && (value8 < 0x08)) { 64 | if (mz_stream_read_uint16(fuzz_stream, &value16) == MZ_OK) 65 | file_info.zip64 = value16; 66 | } 67 | 68 | file_info.filename = MZ_FUZZ_TEST_FILENAME; 69 | file_info.filename_size = (uint16_t)strlen(MZ_FUZZ_TEST_FILENAME); 70 | 71 | compress_level = MZ_COMPRESS_LEVEL_DEFAULT; 72 | if ((mz_stream_read_uint8(fuzz_stream, &value8) == MZ_OK) && (value8 < 0x08)) { 73 | if (mz_stream_read_uint16(fuzz_stream, &value16) == MZ_OK) 74 | compress_level = value16; 75 | } 76 | 77 | stream = mz_stream_mem_create(); 78 | if (!stream) { 79 | mz_stream_mem_delete(&fuzz_stream); 80 | return 1; 81 | } 82 | 83 | err = mz_stream_mem_open(stream, MZ_FUZZ_TEST_FILENAME, MZ_OPEN_MODE_CREATE | MZ_OPEN_MODE_WRITE); 84 | if (err != MZ_OK) { 85 | mz_stream_mem_delete(&stream); 86 | mz_stream_mem_delete(&fuzz_stream); 87 | return 1; 88 | } 89 | 90 | handle = mz_zip_create(); 91 | if (!handle) { 92 | mz_stream_mem_delete(&stream); 93 | mz_stream_mem_delete(&fuzz_stream); 94 | return 1; 95 | } 96 | 97 | err = mz_zip_open(handle, stream, MZ_OPEN_MODE_CREATE | MZ_OPEN_MODE_WRITE); 98 | if (err == MZ_OK) { 99 | password = file_info.flag & MZ_ZIP_FLAG_ENCRYPTED ? MZ_FUZZ_TEST_PWD : NULL; 100 | err = mz_zip_entry_write_open(handle, &file_info, compress_level, 0, password); 101 | if (err == MZ_OK) { 102 | mz_stream_mem_get_buffer_at_current(fuzz_stream, (const void **)&fuzz_buf); 103 | fuzz_pos = mz_stream_tell(fuzz_stream); 104 | mz_stream_mem_get_buffer_length(fuzz_stream, &fuzz_length); 105 | 106 | err = mz_zip_entry_write(handle, fuzz_buf, (fuzz_length - (int32_t)fuzz_pos)); 107 | 108 | mz_zip_entry_close(handle); 109 | } 110 | 111 | mz_zip_close(handle); 112 | } 113 | 114 | mz_zip_delete(&handle); 115 | mz_stream_mem_delete(&stream); 116 | 117 | mz_stream_mem_delete(&fuzz_stream); 118 | 119 | return 0; 120 | } 121 | 122 | /***************************************************************************/ 123 | 124 | #ifdef __cplusplus 125 | } 126 | #endif 127 | -------------------------------------------------------------------------------- /test/random.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlib-ng/minizip-ng/227f2d35bed866de674028a0ac97a50af778bae1/test/random.bin -------------------------------------------------------------------------------- /test/single.txt: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /test/test.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlib-ng/minizip-ng/227f2d35bed866de674028a0ac97a50af778bae1/test/test.p12 -------------------------------------------------------------------------------- /test/test.pem: -------------------------------------------------------------------------------- 1 | Bag Attributes 2 | friendlyName: Minizip 3 | localKeyID: 58 47 0B C9 69 23 3A 00 CD 7E 00 94 80 25 34 19 43 A8 C9 6C 4 | subject=CN = Minizip, O = Minizip, OU = MZ, ST = AZ, C = US, L = Phoenix, emailAddress = nathan@nathanm.com 5 | issuer=CN = Minizip, O = Minizip, OU = MZ, ST = AZ, C = US, L = Phoenix, emailAddress = nathan@nathanm.com 6 | -----BEGIN CERTIFICATE----- 7 | MIIDpzCCAo+gAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgDEQMA4GA1UEAwwHTWlu 8 | aXppcDEQMA4GA1UECgwHTWluaXppcDELMAkGA1UECwwCTVoxCzAJBgNVBAgMAkFa 9 | MQswCQYDVQQGEwJVUzEQMA4GA1UEBwwHUGhvZW5peDEhMB8GCSqGSIb3DQEJARYS 10 | bmF0aGFuQG5hdGhhbm0uY29tMB4XDTE5MTExMTAyMjYwMVoXDTM4MDIxMDAyMjYw 11 | MVowgYAxEDAOBgNVBAMMB01pbml6aXAxEDAOBgNVBAoMB01pbml6aXAxCzAJBgNV 12 | BAsMAk1aMQswCQYDVQQIDAJBWjELMAkGA1UEBhMCVVMxEDAOBgNVBAcMB1Bob2Vu 13 | aXgxITAfBgkqhkiG9w0BCQEWEm5hdGhhbkBuYXRoYW5tLmNvbTCCASIwDQYJKoZI 14 | hvcNAQEBBQADggEPADCCAQoCggEBAORnHpfjKNyRKiVoziTDXQAr5Bbaju33vhW6 15 | RVK1mBbDWmDQUgRa/iHlpJMxeHOmAZOezeu+h9VWJ9Co1zMO7aoJfbvHk7iYTFBY 16 | 7lFpXi5xdMvSngmNq2+DGnAylwuPjmwFmbFftML/Fk/u5P/0KB4lxLY0n5pUppO6 17 | sU4J6S1NjlNc19zW1fy2BXMibTxEFz9SMWCpKPy22JbBhzIWhzfQQlVHsQmx8yaR 18 | LMLYGNurjZ8gJcObMQo7atN6IJb7rUSgTt2xLceL+aFGjb8dNap2fb/KsWNUR+OM 19 | s8GVEjHoOrgu5xqGN2GVAeoccPyDySVk0B0nqJ1byDBoHli+fwMCAwEAAaMqMCgw 20 | DgYDVR0PAQH/BAQDAgKEMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3 21 | DQEBCwUAA4IBAQBWcLT4hkSE1csTj2IhRvRoKX5eOz4g/GL4BbMsBmIYdTNcAT/M 22 | NF5gIgeZRHJUiaaprTAawG6Kmbf9cUUSz04bWMitErJmYAPC9PmZhN501YzIsr8c 23 | hks5+MCE0Z0P6STgor3hxGZ5RSuh6vCzKjgIONMXOevuBPCItJZmKIrOowHH/VvT 24 | YUVcn3ZqBRPVOHeFuBugRyw8/RqpU/SpPb1Pupo9M7KVVNztpXMzfVV2tw2yNQiZ 25 | 7GSXKF65ukDfQ8t7+4cWbINmKpkDyA5Bg5lcQT3DpjKmiUTYGtqKU13m/OgbES9g 26 | yampfcsNiorTiKw6JnSuwjv6VAZC+FZlz03b 27 | -----END CERTIFICATE----- 28 | Bag Attributes 29 | friendlyName: Minizip 30 | localKeyID: 58 47 0B C9 69 23 3A 00 CD 7E 00 94 80 25 34 19 43 A8 C9 6C 31 | Key Attributes: 32 | -----BEGIN ENCRYPTED PRIVATE KEY----- 33 | MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIdEObza0X7HkCAggA 34 | MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECFaNr4AhZbmfBIIEyLxrF5LWO64O 35 | iuhuUbPy7I7eXU3efFoWN5rUA++Ul+e8nSAbonTWTh1tedaKJCZAnG0AmJUR0c8A 36 | f/88YsEETLAH9DhakmrRwfwbPugXXI030q9enAKswILwS856hu9RVEmAwwA4pnma 37 | cWFWWdbk7urPFBwc9xMN0nP0bsGVT8QL5WqEDG1nxE3iHYppVjKbLNE6LoAgABUR 38 | Oexdf4L8wRSn8H7RjjubXKgfalXnjPPcezAl4qtNoewUdLXEsJQbAgT9/Rde1q6U 39 | 2XL01trTcDkRHIeT8jZc9F7s43Ec/KToLdZrYJRd/kJMuBUyAyLV+YgGfe0dmSlb 40 | e0AIEny52Ci/z+gg+dfKGV9baahqevi8/Sk6zblDsxzZfroUN1eUt/ZCT5LZv7U2 41 | NkXHB96TdSnM3IHZfKz2YjVMq2d69NTK4qOrX7Civhq+KFHauROBIdUg5wi8Qraq 42 | htF+R9d218s9ZWgzwDX6TW7gA47qDK20vDQTNFMuhnTiaIY5loGAj5cwsuzpSX0s 43 | +WmzFgclNHJSeYx2VA4vnLkyEkhnYI4P6QHb43p9qbvWTUGbWPTnv2ZZf6H0Wkzk 44 | z3Hwpgdauklck4rdZt00OTp8O/WYPDcb66YbrPW648wPHJQ+i+lBKlGt20GPfXvf 45 | Xjy4LiRzQHUauvio29MB3Am4T/y3q5qKD3bKtgaIfjD6KYCCrq7VGs+GrjsN365v 46 | LsKjzr/CrlAzDCD7UJ7K1+BvADrqZ+uWBzH9exWBfMWRLdqgFHGAubIDrw55JB4s 47 | KDr545r1GVGn0hmRWJuDfHrikQgFr9UlR3NguLR/rBbmzEuZcljzQdu6gL9CGGpR 48 | ZgW0WbLulXeN9S5z1KK22Jrq2bdteCvPSQbZrtkbqfWLbBUbWC5TJbmWKF91B+ZY 49 | b4qdBhM4d4MF9YA7+TXfOMSIesJJMt65ekEyvyn+lDvJCrbQM+YdUgl41Gglcgx7 50 | dQQZpT0fN2TkfAHhjU3VLxbmjIPOukVhcV4D7RyBVjyOYuQAUZCe8HZ61YYYPaQg 51 | z+cFOYkBO1tf7OdvRAnZzkADp9bPtRtoDXKuRr+4CjukPr4mCByQb1t5zk3o/24W 52 | dvghXFXmALHLumvTaGHSZabLmm7Qoqif2woxOTaIacxxso2zLESblkjnT5gR3aKp 53 | UfDo8Bqt2NjnpqqlhlQo8Hw2lqEcdz5OxQ88sbOUDlkYCHV3m5tySopF90EIcn/V 54 | YTwkNGBMTuYvqIr/bLtBlkKYuoChCFOGO3bCIoe9PTfSk8ctGAxZDGhoYt0zK4uf 55 | iLbMNms15IprTXBixXIR1srht/jxPvA8uwB6YvAxAK1vwKVOjpKCFfokIWmR6WHB 56 | 0zMB0dhaNgKfVSjArcaqEJdMshg2vtFWCVsn9x/DTkqEgpkRWZ/e67+7udBM3F+6 57 | klIrszel8URcu3M7VZ7goP4d4vC6ukQTy/Dzhi/Sx+Fesb17woFJtbWfejObFjHV 58 | LGUTuVERdUIUc3V91IG6jyAUBtwdKrZy73LSOJyUsxZUA1mWL3YQn2Cq84ylWxHs 59 | Sc0gp51PEjqcjNTO7q5LzrloX4XDbmGnt8uWkZTvmY/wHEI/YKUR6IMCFpbjFlZo 60 | bp5Sjaq/lk0VkASjl+s4cw== 61 | -----END ENCRYPTED PRIVATE KEY----- 62 | -------------------------------------------------------------------------------- /test/test_encoding.cc: -------------------------------------------------------------------------------- 1 | /* test_encoding.cc - Test string encoding 2 | part of the minizip-ng project 3 | 4 | Copyright (C) Nathan Moinvaziri 5 | https://github.com/zlib-ng/minizip-ng 6 | 7 | This program is distributed under the terms of the same license as zlib. 8 | See the accompanying LICENSE file for the full text of the license. 9 | */ 10 | 11 | #include "mz.h" 12 | #include "mz_os.h" 13 | 14 | #include 15 | 16 | TEST(os, utf8_unicode_string) { 17 | const char *test_string = "Heiz�lr�cksto�abd�mpfung"; 18 | char *utf8_string = mz_os_utf8_string_create(test_string, MZ_ENCODING_CODEPAGE_950); 19 | ASSERT_NE(utf8_string, nullptr); 20 | #if defined(_WIN32) 21 | wchar_t *unicode_string = mz_os_unicode_string_create(utf8_string, MZ_ENCODING_UTF8); 22 | ASSERT_NE(unicode_string, nullptr); 23 | mz_os_unicode_string_delete(&unicode_string); 24 | #endif 25 | mz_os_utf8_string_delete(&utf8_string); 26 | } 27 | -------------------------------------------------------------------------------- /test/test_file.cc: -------------------------------------------------------------------------------- 1 | /* test_file.cc - Test file functionality 2 | part of the minizip-ng project 3 | 4 | Copyright (C) Nathan Moinvaziri 5 | https://github.com/zlib-ng/minizip-ng 6 | 7 | This program is distributed under the terms of the same license as zlib. 8 | See the accompanying LICENSE file for the full text of the license. 9 | */ 10 | 11 | #include "mz.h" 12 | #include "mz_os.h" 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | TEST(os, get_file_date_ads) { 19 | const std::string main_stream_name = "minizip_ads_test"; 20 | const std::string ads_name = main_stream_name + ":ads"; 21 | const std::string ads_contents = "Alternate Data Stream"; 22 | 23 | // Create main stream 24 | std::ofstream main_stream(main_stream_name); 25 | main_stream.close(); 26 | 27 | // Attach ADS 28 | std::ofstream ads(ads_name); 29 | ads << ads_contents; 30 | ads.close(); 31 | 32 | // Get file date 33 | time_t modified_date = 0; 34 | time_t accessed_date = 0; 35 | time_t creation_date = 0; 36 | 37 | EXPECT_EQ(MZ_OK, mz_os_get_file_date(ads_name.c_str(), &modified_date, &accessed_date, &creation_date)); 38 | 39 | std::remove(main_stream_name.c_str()); 40 | 41 | ASSERT_GT(modified_date, 0); 42 | ASSERT_GT(accessed_date, 0); 43 | ASSERT_GT(creation_date, 0); 44 | } 45 | -------------------------------------------------------------------------------- /test/test_main.cc: -------------------------------------------------------------------------------- 1 | /* test_main.cc - Main entry point for test framework */ 2 | 3 | #include 4 | 5 | #include "gtest/gtest.h" 6 | 7 | GTEST_API_ int main(int argc, char **argv) { 8 | printf("Running main() from %s\n", __FILE__); 9 | testing::InitGoogleTest(&argc, argv); 10 | return RUN_ALL_TESTS(); 11 | } 12 | -------------------------------------------------------------------------------- /test/test_path.cc: -------------------------------------------------------------------------------- 1 | /* test_path.cc - Test path functionality 2 | part of the minizip-ng project 3 | 4 | Copyright (C) Nathan Moinvaziri 5 | https://github.com/zlib-ng/minizip-ng 6 | 7 | This program is distributed under the terms of the same license as zlib. 8 | See the accompanying LICENSE file for the full text of the license. 9 | */ 10 | 11 | #include "mz.h" 12 | #include "mz_os.h" 13 | 14 | #include 15 | #include 16 | 17 | struct resolve_path_param { 18 | const char *path; 19 | const char *expected_path; 20 | 21 | friend std::ostream &operator<<(std::ostream &os, const resolve_path_param ¶m) { 22 | return os << "path: " << param.path; 23 | } 24 | }; 25 | 26 | constexpr resolve_path_param resolve_path_tests[] = { 27 | { "c:\\test\\.", "c:\\test\\"}, 28 | { "c:\\test\\.\\", "c:\\test\\"}, 29 | { "c:\\test\\.\\.", "c:\\test\\"}, 30 | { "c:\\test\\..", "c:\\"}, 31 | { "c:\\test\\..\\", "c:\\"}, 32 | { "c:\\test\\.\\..", "c:\\"}, 33 | { "c:\\test\\.\\\\..", "c:\\"}, 34 | { ".", "."}, 35 | { ".\\", ""}, 36 | { "..", ""}, 37 | { "..\\", ""}, 38 | { ".\\test\\123", "test\\123"}, 39 | { ".\\..\\test\\123", "test\\123"}, 40 | { "..\\..\\test\\123", "test\\123"}, 41 | { "test\\.abc.txt", "test\\.abc.txt"}, 42 | { "c:\\test\\123\\.\\abc.txt", "c:\\test\\123\\abc.txt"}, 43 | { "c:\\test\\123\\..\\abc.txt", "c:\\test\\abc.txt"}, 44 | { "c:\\test\\123\\..\\..\\abc.txt", "c:\\abc.txt"}, 45 | {"c:\\test\\123\\..\\..\\..\\abc.txt", "abc.txt"}, 46 | { "c:\\test\\123\\..\\.\\..\\abc.txt", "c:\\abc.txt"}, 47 | }; 48 | 49 | class path_resolve : public ::testing::TestWithParam {}; 50 | 51 | INSTANTIATE_TEST_SUITE_P(os, path_resolve, testing::ValuesIn(resolve_path_tests)); 52 | 53 | TEST_P(path_resolve, os) { 54 | const auto ¶m = GetParam(); 55 | std::string path = param.path; 56 | std::string expected_path = param.expected_path; 57 | char output[256]; 58 | 59 | memset(output, 'z', sizeof(output)); 60 | // archiving and unarchiving data on a system should preserve its structure 61 | if (!mz_os_is_dir_separator('\\')) { 62 | std::replace(path.begin(), path.end(), '\\', '/'); 63 | std::replace(expected_path.begin(), expected_path.end(), '\\', '/'); 64 | } 65 | mz_path_resolve(path.c_str(), output, sizeof(output)); 66 | EXPECT_STREQ(output, expected_path.c_str()); 67 | } 68 | -------------------------------------------------------------------------------- /test/test_stream.cc: -------------------------------------------------------------------------------- 1 | /* test_stream.cc - Test basic streaming functionality 2 | part of the minizip-ng project 3 | 4 | Copyright (C) Nathan Moinvaziri 5 | https://github.com/zlib-ng/minizip-ng 6 | 7 | This program is distributed under the terms of the same license as zlib. 8 | See the accompanying LICENSE file for the full text of the license. 9 | */ 10 | 11 | #include "mz.h" 12 | #include "mz_strm.h" 13 | #include "mz_strm_mem.h" 14 | 15 | #include 16 | 17 | typedef void (*stream_test_cb)(const char *name, int32_t count, const uint8_t *find, int32_t find_size, 18 | mz_stream_find_cb find_cb); 19 | 20 | static void test_stream_find_begin(const char *name, int32_t count, const uint8_t *find, int32_t find_size, 21 | mz_stream_find_cb find_cb) { 22 | void *mem_stream = NULL; 23 | int32_t i = 0; 24 | int32_t x = 0; 25 | int64_t last_pos = 0; 26 | int64_t position = 0; 27 | 28 | MZ_UNUSED(name); 29 | 30 | ASSERT_GT(find_size, 0); 31 | ASSERT_NE(find, nullptr); 32 | ASSERT_NE(find_cb, nullptr); 33 | 34 | for (i = 0; i < count; i++) { 35 | mem_stream = mz_stream_mem_create(); 36 | ASSERT_NE(mem_stream, nullptr); 37 | mz_stream_mem_open(mem_stream, NULL, MZ_OPEN_MODE_CREATE); 38 | 39 | /* Find when the needle is at the beginning of the stream */ 40 | for (x = 0; x < i && x < find_size; x++) 41 | mz_stream_write_uint8(mem_stream, find[x]); 42 | while (x++ < i) 43 | mz_stream_write_uint8(mem_stream, 0); 44 | 45 | if (find_cb == mz_stream_find) 46 | mz_stream_seek(mem_stream, 0, MZ_SEEK_SET); 47 | 48 | find_cb(mem_stream, (const void *)find, find_size, i, &position); 49 | 50 | /* Should always find at the start of the stream if entire needle 51 | was written to stream */ 52 | EXPECT_EQ(position, (i < find_size) ? -1 : 0) << "name: " << name << std::endl 53 | << "find_size: " << find_size << std::endl 54 | << "index: " << i << std::endl; 55 | 56 | mz_stream_seek(mem_stream, 0, MZ_SEEK_END); 57 | last_pos = mz_stream_tell(mem_stream); 58 | mz_stream_mem_delete(&mem_stream); 59 | 60 | /* Shouldn't be at the end of the stream */ 61 | EXPECT_NE(position, last_pos); 62 | } 63 | } 64 | 65 | static void test_stream_find_end(const char *name, int32_t count, const uint8_t *find, int32_t find_size, 66 | mz_stream_find_cb find_cb) { 67 | void *mem_stream = NULL; 68 | int32_t i = 0; 69 | int32_t x = 0; 70 | int32_t y = 0; 71 | int64_t last_pos = 0; 72 | int64_t position = 0; 73 | 74 | MZ_UNUSED(name); 75 | 76 | ASSERT_GT(find_size, 0); 77 | ASSERT_NE(find, nullptr); 78 | ASSERT_NE(find_cb, nullptr); 79 | 80 | for (i = 0; i < count; i++) { 81 | mem_stream = mz_stream_mem_create(); 82 | ASSERT_NE(mem_stream, nullptr); 83 | mz_stream_mem_open(mem_stream, NULL, MZ_OPEN_MODE_CREATE); 84 | 85 | /* Find when the needle is at the end of the stream */ 86 | for (x = 0; x < i - find_size; x++) 87 | mz_stream_write_uint8(mem_stream, 0); 88 | for (y = 0; x + y < i && y < find_size; y++) 89 | mz_stream_write_uint8(mem_stream, find[y]); 90 | 91 | if (find_cb == mz_stream_find) 92 | mz_stream_seek(mem_stream, 0, MZ_SEEK_SET); 93 | 94 | find_cb(mem_stream, (const void *)find, find_size, i, &position); 95 | 96 | /* Should always find after zeros if entire needle 97 | was written to stream */ 98 | EXPECT_EQ(position, (i < find_size) ? -1 : (i - find_size)) << "name: " << name << std::endl 99 | << "find_size: " << find_size << std::endl 100 | << "index: " << i << std::endl; 101 | 102 | mz_stream_seek(mem_stream, 0, MZ_SEEK_END); 103 | last_pos = mz_stream_tell(mem_stream); 104 | mz_stream_mem_delete(&mem_stream); 105 | 106 | /* Shouldn't be at the end of the stream */ 107 | EXPECT_NE(position, last_pos); 108 | } 109 | } 110 | 111 | static void test_stream_find_middle(const char *name, int32_t count, const uint8_t *find, int32_t find_size, 112 | mz_stream_find_cb find_cb) { 113 | void *mem_stream = NULL; 114 | int32_t i = 0; 115 | int32_t x = 0; 116 | int64_t last_pos = 0; 117 | int64_t position = 0; 118 | 119 | MZ_UNUSED(name); 120 | 121 | ASSERT_GT(find_size, 0); 122 | ASSERT_NE(find, nullptr); 123 | ASSERT_NE(find_cb, nullptr); 124 | 125 | for (i = 0; i < count; i++) { 126 | mem_stream = mz_stream_mem_create(); 127 | ASSERT_NE(mem_stream, nullptr); 128 | mz_stream_mem_open(mem_stream, NULL, MZ_OPEN_MODE_CREATE); 129 | 130 | /* Find when the neddle is in the middle of the stream */ 131 | for (x = 0; x < i; x++) 132 | mz_stream_write_uint8(mem_stream, 0); 133 | mz_stream_write(mem_stream, find, find_size); 134 | for (x = 0; x < i; x++) 135 | mz_stream_write_uint8(mem_stream, 0); 136 | 137 | if (find_cb == mz_stream_find) 138 | mz_stream_seek(mem_stream, 0, MZ_SEEK_SET); 139 | 140 | find_cb(mem_stream, (const void *)find, find_size, i + find_size + i, &position); 141 | 142 | /* Should always find after initial set of zeros */ 143 | EXPECT_EQ(position, i) << "name: " << name << std::endl 144 | << "find_size: " << find_size << std::endl 145 | << "index: " << i << std::endl; 146 | 147 | mz_stream_seek(mem_stream, 0, MZ_SEEK_END); 148 | last_pos = mz_stream_tell(mem_stream); 149 | mz_stream_mem_delete(&mem_stream); 150 | 151 | /* Shouldn't be at the end of the stream */ 152 | EXPECT_NE(position, last_pos); 153 | } 154 | } 155 | 156 | static void test_stream_find_middle_odd(const char *name, int32_t count, const uint8_t *find, int32_t find_size, 157 | mz_stream_find_cb find_cb) { 158 | void *mem_stream = NULL; 159 | int32_t i = 0; 160 | int32_t x = 0; 161 | int64_t last_pos = 0; 162 | int64_t position = 0; 163 | 164 | MZ_UNUSED(name); 165 | 166 | ASSERT_GT(find_size, 0); 167 | ASSERT_NE(find, nullptr); 168 | ASSERT_NE(find_cb, nullptr); 169 | 170 | for (i = 0; i < count; i++) { 171 | mem_stream = mz_stream_mem_create(); 172 | ASSERT_NE(mem_stream, nullptr); 173 | mz_stream_mem_open(mem_stream, NULL, MZ_OPEN_MODE_CREATE); 174 | 175 | /* Find when the needle is in the middle of the stream */ 176 | for (x = 0; x < i; x++) 177 | mz_stream_write_uint8(mem_stream, 0); 178 | mz_stream_write(mem_stream, find, find_size); 179 | for (x = 0; x < i + 1; x++) 180 | mz_stream_write_uint8(mem_stream, 0); 181 | 182 | if (find_cb == mz_stream_find) 183 | mz_stream_seek(mem_stream, 0, MZ_SEEK_SET); 184 | 185 | find_cb(mem_stream, (const void *)find, find_size, i + find_size + i + 1, &position); 186 | 187 | /* Should always find after initial set of zeros */ 188 | EXPECT_EQ(position, i) << "name: " << name << std::endl 189 | << "find_size: " << find_size << std::endl 190 | << "index: " << i << std::endl; 191 | 192 | mz_stream_seek(mem_stream, 0, MZ_SEEK_END); 193 | last_pos = mz_stream_tell(mem_stream); 194 | mz_stream_mem_delete(&mem_stream); 195 | 196 | /* Shouldn't be at the end of the stream */ 197 | EXPECT_NE(position, last_pos); 198 | } 199 | } 200 | 201 | struct stream_find_param { 202 | const char *name; 203 | stream_test_cb test_cb; 204 | mz_stream_find_cb find_cb; 205 | 206 | friend std::ostream &operator<<(std::ostream &os, const stream_find_param ¶m) { 207 | return os << "name: " << param.name; 208 | } 209 | }; 210 | 211 | constexpr stream_find_param find_tests[] = { 212 | { "begin", test_stream_find_begin, mz_stream_find}, 213 | { "begin reverse", test_stream_find_begin, mz_stream_find_reverse}, 214 | { "end", test_stream_find_end, mz_stream_find}, 215 | { "end reverse", test_stream_find_end, mz_stream_find_reverse}, 216 | { "middle", test_stream_find_middle, mz_stream_find}, 217 | { "middle reverse", test_stream_find_middle, mz_stream_find_reverse}, 218 | { "middle odd", test_stream_find_middle_odd, mz_stream_find}, 219 | {"middle odd reverse", test_stream_find_middle_odd, mz_stream_find_reverse} 220 | }; 221 | 222 | class stream_find : public ::testing::TestWithParam {}; 223 | 224 | INSTANTIATE_TEST_SUITE_P(stream, stream_find, testing::ValuesIn(find_tests)); 225 | 226 | TEST_P(stream_find, find) { 227 | const auto ¶m = GetParam(); 228 | const char *find = "0123456789"; 229 | int32_t c = 1; 230 | 231 | for (c = 1; c < (int32_t)strlen(find); c += 1) 232 | param.test_cb(param.name, 2096, (const uint8_t *)find, c, param.find_cb); 233 | } 234 | -------------------------------------------------------------------------------- /test/test_stream_compress.cc: -------------------------------------------------------------------------------- 1 | /* test_stream_compress.cc - Test basic compression 2 | part of the minizip-ng project 3 | 4 | Copyright (C) Nathan Moinvaziri 5 | https://github.com/zlib-ng/minizip-ng 6 | 7 | This program is distributed under the terms of the same license as zlib. 8 | See the accompanying LICENSE file for the full text of the license. 9 | */ 10 | 11 | #include "mz.h" 12 | #include "mz_os.h" 13 | #include "mz_strm.h" 14 | #include "mz_strm_mem.h" 15 | #include "mz_strm_os.h" 16 | 17 | #ifdef HAVE_BZIP2 18 | # include "mz_strm_bzip.h" 19 | #endif 20 | #ifdef HAVE_LZMA 21 | # include "mz_strm_lzma.h" 22 | #endif 23 | #ifdef HAVE_ZLIB 24 | # include "mz_strm_zlib.h" 25 | #endif 26 | #ifdef HAVE_ZSTD 27 | # include "mz_strm_zstd.h" 28 | #endif 29 | 30 | #include 31 | 32 | static void test_compare_stream_to_end(void *source1, void *source2) { 33 | uint8_t source1_buf[4096]; 34 | uint8_t source2_buf[4096]; 35 | int32_t source1_read = 0; 36 | int32_t source2_read = 0; 37 | 38 | do { 39 | source1_read = mz_stream_read(source1, source1_buf, sizeof(source1_buf)); 40 | source2_read = mz_stream_read(source2, source2_buf, sizeof(source2_buf)); 41 | 42 | EXPECT_EQ(source1_read, source2_read); 43 | if (source1_read <= 0) 44 | break; 45 | 46 | EXPECT_EQ(memcmp(source1_buf, source2_buf, source1_read), 0); 47 | } while (1); 48 | } 49 | 50 | static void test_compress(const char *method, mz_stream_create_cb create_compress) { 51 | int64_t total_in = 0; 52 | int64_t total_out = 0; 53 | void *org_stream = NULL; 54 | void *compress_stream = NULL; 55 | void *uncompress_stream = NULL; 56 | void *deflate_stream = NULL; 57 | void *inflate_stream = NULL; 58 | 59 | /* Open file to be compressed */ 60 | org_stream = mz_stream_os_create(); 61 | ASSERT_NE(org_stream, nullptr); 62 | ASSERT_EQ(mz_stream_os_open(org_stream, "LICENSE", MZ_OPEN_MODE_READ), MZ_OK); 63 | 64 | /* Compress data into memory stream */ 65 | compress_stream = mz_stream_mem_create(); 66 | ASSERT_NE(compress_stream, nullptr); 67 | ASSERT_EQ(mz_stream_mem_open(compress_stream, NULL, MZ_OPEN_MODE_CREATE), MZ_OK); 68 | 69 | deflate_stream = create_compress(); 70 | ASSERT_NE(deflate_stream, nullptr); 71 | mz_stream_set_base(deflate_stream, compress_stream); 72 | 73 | /* Copy data from file stream and write to compression stream */ 74 | mz_stream_open(deflate_stream, NULL, MZ_OPEN_MODE_WRITE); 75 | mz_stream_copy_stream_to_end(deflate_stream, NULL, org_stream, NULL); 76 | mz_stream_close(deflate_stream); 77 | 78 | mz_stream_get_prop_int64(deflate_stream, MZ_STREAM_PROP_TOTAL_IN, &total_in); 79 | EXPECT_EQ(total_in, mz_stream_tell(org_stream)); 80 | 81 | mz_stream_get_prop_int64(deflate_stream, MZ_STREAM_PROP_TOTAL_OUT, &total_out); 82 | EXPECT_EQ(total_out, mz_stream_tell(compress_stream)); 83 | 84 | mz_stream_delete(&deflate_stream); 85 | 86 | printf("%s compressed from %u to %u\n", method, (uint32_t)total_in, (uint32_t)total_out); 87 | 88 | /* Decompress data into memory stream */ 89 | uncompress_stream = mz_stream_mem_create(); 90 | ASSERT_NE(uncompress_stream, nullptr); 91 | ASSERT_EQ(mz_stream_mem_open(uncompress_stream, NULL, MZ_OPEN_MODE_CREATE), MZ_OK); 92 | 93 | mz_stream_seek(compress_stream, 0, MZ_SEEK_SET); 94 | 95 | inflate_stream = create_compress(); 96 | ASSERT_NE(inflate_stream, nullptr); 97 | mz_stream_set_base(inflate_stream, compress_stream); 98 | 99 | mz_stream_open(inflate_stream, NULL, MZ_OPEN_MODE_READ); 100 | mz_stream_copy_stream_to_end(uncompress_stream, NULL, inflate_stream, NULL); 101 | mz_stream_close(inflate_stream); 102 | 103 | mz_stream_get_prop_int64(inflate_stream, MZ_STREAM_PROP_TOTAL_IN, &total_in); 104 | EXPECT_EQ(total_in, mz_stream_tell(compress_stream)); 105 | 106 | mz_stream_get_prop_int64(inflate_stream, MZ_STREAM_PROP_TOTAL_OUT, &total_out); 107 | EXPECT_EQ(total_out, mz_stream_tell(uncompress_stream)); 108 | 109 | mz_stream_delete(&inflate_stream); 110 | 111 | printf("%s uncompressed from %u to %u\n", method, (uint32_t)total_in, (uint32_t)total_out); 112 | 113 | /* Compare uncompress stream to original file stream */ 114 | mz_stream_seek(org_stream, 0, MZ_SEEK_SET); 115 | mz_stream_seek(uncompress_stream, 0, MZ_SEEK_SET); 116 | 117 | test_compare_stream_to_end(org_stream, uncompress_stream); 118 | 119 | mz_stream_mem_close(uncompress_stream); 120 | mz_stream_mem_delete(&uncompress_stream); 121 | 122 | mz_stream_mem_close(compress_stream); 123 | mz_stream_mem_delete(&compress_stream); 124 | 125 | mz_stream_os_close(org_stream); 126 | mz_stream_os_delete(&org_stream); 127 | } 128 | 129 | #ifdef HAVE_BZIP2 130 | TEST(stream, bzip) { 131 | return test_compress("bzip", mz_stream_bzip_create); 132 | } 133 | #endif 134 | #ifdef HAVE_LZMA 135 | TEST(stream, lzma) { 136 | return test_compress("lzma", mz_stream_lzma_create); 137 | } 138 | #endif 139 | #ifdef HAVE_ZLIB 140 | TEST(stream, zlib) { 141 | return test_compress("zlib", mz_stream_zlib_create); 142 | } 143 | #endif 144 | #ifdef HAVE_ZSTD 145 | TEST(stream, zstd) { 146 | return test_compress("zstd", mz_stream_zstd_create); 147 | } 148 | #endif 149 | -------------------------------------------------------------------------------- /test/test_stream_crypt.cc: -------------------------------------------------------------------------------- 1 | /* test_stream_crypt.cc - Test encryption stream functionality 2 | part of the minizip-ng project 3 | 4 | Copyright (C) Nathan Moinvaziri 5 | https://github.com/zlib-ng/minizip-ng 6 | 7 | This program is distributed under the terms of the same license as zlib. 8 | See the accompanying LICENSE file for the full text of the license. 9 | */ 10 | 11 | #include "mz.h" 12 | #include "mz_strm.h" 13 | #include "mz_strm_os.h" 14 | #include "mz_strm_pkcrypt.h" 15 | #include "mz_strm_wzaes.h" 16 | 17 | #include 18 | 19 | #include /* printf, snprintf */ 20 | 21 | #if defined(_MSC_VER) && (_MSC_VER < 1900) 22 | # define snprintf _snprintf 23 | #endif 24 | 25 | static void test_encrypt(const char *path, const char *method, mz_stream_create_cb crypt_create, const char *password) { 26 | char org_buf[4096]; 27 | char mod_buf[4096]; 28 | int32_t read = 0; 29 | int32_t written = 0; 30 | int64_t total_written = 0; 31 | void *out_stream = NULL; 32 | void *in_stream = NULL; 33 | void *crypt_out_stream = NULL; 34 | char encrypt_path[256]; 35 | char decrypt_path[256]; 36 | 37 | snprintf(encrypt_path, sizeof(encrypt_path), "%s.enc.%s", path, method); 38 | snprintf(decrypt_path, sizeof(decrypt_path), "%s.dec.%s", path, method); 39 | 40 | /* Read file to encrypt into memory buffer */ 41 | in_stream = mz_stream_os_create(); 42 | ASSERT_NE(in_stream, nullptr); 43 | EXPECT_EQ(mz_stream_os_open(in_stream, path, MZ_OPEN_MODE_READ), MZ_OK); 44 | { 45 | read = mz_stream_os_read(in_stream, org_buf, sizeof(org_buf)); 46 | mz_stream_os_close(in_stream); 47 | } 48 | mz_stream_os_delete(&in_stream); 49 | EXPECT_GT(read, 0); 50 | 51 | /* Encrypt data to disk */ 52 | out_stream = mz_stream_os_create(); 53 | ASSERT_NE(out_stream, nullptr); 54 | EXPECT_EQ(mz_stream_os_open(out_stream, encrypt_path, MZ_OPEN_MODE_CREATE | MZ_OPEN_MODE_WRITE), MZ_OK); 55 | { 56 | crypt_out_stream = crypt_create(); 57 | ASSERT_NE(crypt_out_stream, nullptr); 58 | 59 | mz_stream_set_base(crypt_out_stream, out_stream); 60 | 61 | EXPECT_EQ(mz_stream_open(crypt_out_stream, password, MZ_OPEN_MODE_WRITE), MZ_OK); 62 | { 63 | written = mz_stream_write(crypt_out_stream, org_buf, read); 64 | mz_stream_close(crypt_out_stream); 65 | mz_stream_get_prop_int64(crypt_out_stream, MZ_STREAM_PROP_TOTAL_OUT, &total_written); 66 | } 67 | 68 | mz_stream_delete(&crypt_out_stream); 69 | mz_stream_os_close(out_stream); 70 | } 71 | mz_stream_os_delete(&out_stream); 72 | EXPECT_GT(written, 0); 73 | 74 | /* Decrypt data from disk */ 75 | in_stream = mz_stream_os_create(); 76 | ASSERT_NE(in_stream, nullptr); 77 | EXPECT_EQ(mz_stream_os_open(in_stream, encrypt_path, MZ_OPEN_MODE_READ), MZ_OK); 78 | { 79 | crypt_out_stream = crypt_create(); 80 | ASSERT_NE(crypt_out_stream, nullptr); 81 | 82 | mz_stream_set_base(crypt_out_stream, in_stream); 83 | mz_stream_set_prop_int64(crypt_out_stream, MZ_STREAM_PROP_TOTAL_IN_MAX, total_written); 84 | 85 | EXPECT_EQ(mz_stream_open(crypt_out_stream, password, MZ_OPEN_MODE_READ), MZ_OK); 86 | { 87 | ASSERT_LE(read, sizeof(mod_buf)); 88 | read = mz_stream_read(crypt_out_stream, mod_buf, read); 89 | mz_stream_close(crypt_out_stream); 90 | } 91 | 92 | mz_stream_delete(&crypt_out_stream); 93 | mz_stream_os_close(in_stream); 94 | } 95 | mz_stream_os_delete(&in_stream); 96 | EXPECT_GT(read, 0); 97 | 98 | /* Write out decrypted contents to disk for debugging */ 99 | out_stream = mz_stream_os_create(); 100 | ASSERT_NE(out_stream, nullptr); 101 | EXPECT_EQ(mz_stream_os_open(out_stream, decrypt_path, MZ_OPEN_MODE_CREATE | MZ_OPEN_MODE_WRITE), MZ_OK); 102 | { 103 | mz_stream_os_write(out_stream, mod_buf, read); 104 | mz_stream_os_close(out_stream); 105 | } 106 | mz_stream_os_delete(&out_stream); 107 | 108 | /* Compare original and modified buffers */ 109 | EXPECT_EQ(memcmp(org_buf, mod_buf, read), 0); 110 | } 111 | 112 | #ifdef HAVE_PKCRYPT 113 | TEST(encrypt, pkcrypt) { 114 | test_encrypt("LICENSE", "pkcrypt", mz_stream_pkcrypt_create, "hello"); 115 | } 116 | #endif 117 | 118 | #ifdef HAVE_WZAES 119 | TEST(encrypt, aes) { 120 | test_encrypt("LICENSE", "aes", mz_stream_wzaes_create, "hello"); 121 | } 122 | #endif 123 | --------------------------------------------------------------------------------