Imported Upstream version 1.8.0 upstream/1.8.0
authorJinWang An <jinwang.an@samsung.com>
Fri, 24 Dec 2021 08:29:39 +0000 (17:29 +0900)
committerJinWang An <jinwang.an@samsung.com>
Fri, 24 Dec 2021 08:29:39 +0000 (17:29 +0900)
327 files changed:
.clang-format
.github/workflows/build.yml [new file with mode: 0644]
.github/workflows/codeql-analysis.yml [new file with mode: 0644]
CMakeLists.txt
INSTALL.md
NEWS.md
README.md
THANKS
TODO.md
appveyor.yml
cmake-compat/FindGnuTLS.cmake [new file with mode: 0644]
cmake-config.h.in
cmake/FindZstd.cmake [new file with mode: 0644]
examples/in-memory.c
examples/windows-open.c
lib/CMakeLists.txt
lib/compat.h
lib/zip.h
lib/zip_add.c
lib/zip_add_dir.c
lib/zip_add_entry.c
lib/zip_algorithm_bzip2.c
lib/zip_algorithm_deflate.c
lib/zip_algorithm_xz.c
lib/zip_algorithm_zstd.c [new file with mode: 0644]
lib/zip_buffer.c
lib/zip_close.c
lib/zip_crypto.h
lib/zip_crypto_commoncrypto.c
lib/zip_crypto_gnutls.c
lib/zip_crypto_gnutls.h
lib/zip_crypto_mbedtls.c
lib/zip_crypto_mbedtls.h
lib/zip_crypto_openssl.c
lib/zip_crypto_openssl.h
lib/zip_crypto_win.c
lib/zip_crypto_win.h
lib/zip_delete.c
lib/zip_dir_add.c
lib/zip_dirent.c
lib/zip_discard.c
lib/zip_entry.c
lib/zip_error.c
lib/zip_error_clear.c
lib/zip_error_get.c
lib/zip_error_get_sys_type.c
lib/zip_error_strerror.c
lib/zip_error_to_str.c
lib/zip_extra_field.c
lib/zip_extra_field_api.c
lib/zip_fclose.c
lib/zip_fdopen.c
lib/zip_file_add.c
lib/zip_file_error_clear.c
lib/zip_file_error_get.c
lib/zip_file_get_comment.c
lib/zip_file_get_external_attributes.c
lib/zip_file_get_offset.c
lib/zip_file_rename.c
lib/zip_file_replace.c
lib/zip_file_set_comment.c
lib/zip_file_set_encryption.c
lib/zip_file_set_external_attributes.c
lib/zip_file_set_mtime.c
lib/zip_file_strerror.c
lib/zip_fopen.c
lib/zip_fopen_encrypted.c
lib/zip_fopen_index.c
lib/zip_fopen_index_encrypted.c
lib/zip_fread.c
lib/zip_fseek.c
lib/zip_ftell.c
lib/zip_get_archive_comment.c
lib/zip_get_archive_flag.c
lib/zip_get_encryption_implementation.c
lib/zip_get_file_comment.c
lib/zip_get_name.c
lib/zip_get_num_entries.c
lib/zip_get_num_files.c
lib/zip_hash.c
lib/zip_io_util.c
lib/zip_libzip_version.c
lib/zip_memdup.c
lib/zip_mkstempm.c
lib/zip_name_locate.c
lib/zip_new.c
lib/zip_open.c
lib/zip_pkware.c
lib/zip_progress.c
lib/zip_random_unix.c
lib/zip_random_uwp.c
lib/zip_random_win32.c
lib/zip_rename.c
lib/zip_replace.c
lib/zip_set_archive_comment.c
lib/zip_set_archive_flag.c
lib/zip_set_default_password.c
lib/zip_set_file_comment.c
lib/zip_set_file_compression.c
lib/zip_set_name.c
lib/zip_source_accept_empty.c
lib/zip_source_begin_write.c
lib/zip_source_begin_write_cloning.c
lib/zip_source_buffer.c
lib/zip_source_call.c
lib/zip_source_close.c
lib/zip_source_commit_write.c
lib/zip_source_compress.c
lib/zip_source_crc.c
lib/zip_source_error.c
lib/zip_source_file_common.c
lib/zip_source_file_stdio.c
lib/zip_source_file_stdio_named.c
lib/zip_source_file_win32.c
lib/zip_source_file_win32.h
lib/zip_source_file_win32_ansi.c
lib/zip_source_file_win32_named.c
lib/zip_source_file_win32_utf16.c
lib/zip_source_file_win32_utf8.c
lib/zip_source_free.c
lib/zip_source_function.c
lib/zip_source_get_file_attributes.c
lib/zip_source_is_deleted.c
lib/zip_source_layered.c
lib/zip_source_open.c
lib/zip_source_pkware_decode.c
lib/zip_source_pkware_encode.c
lib/zip_source_read.c
lib/zip_source_remove.c
lib/zip_source_rollback_write.c
lib/zip_source_seek.c
lib/zip_source_seek_write.c
lib/zip_source_stat.c
lib/zip_source_supports.c
lib/zip_source_tell.c
lib/zip_source_tell_write.c
lib/zip_source_window.c
lib/zip_source_winzip_aes_decode.c
lib/zip_source_winzip_aes_encode.c
lib/zip_source_write.c
lib/zip_source_zip.c
lib/zip_source_zip_new.c
lib/zip_stat.c
lib/zip_stat_index.c
lib/zip_stat_init.c
lib/zip_strerror.c
lib/zip_string.c
lib/zip_unchange.c
lib/zip_unchange_all.c
lib/zip_unchange_archive.c
lib/zip_unchange_data.c
lib/zip_utf-8.c
lib/zip_winzip_aes.c
lib/zipint.h
man/CMakeLists.txt
man/libzip.html
man/libzip.man
man/libzip.mdoc
man/update-html.cmake
man/update-man.cmake
man/zip_close.html
man/zip_close.man
man/zip_close.mdoc
man/zip_dir_add.html
man/zip_dir_add.man
man/zip_dir_add.mdoc
man/zip_error_clear.html
man/zip_error_clear.man
man/zip_error_clear.mdoc
man/zip_error_set.html
man/zip_error_set.man
man/zip_error_set.mdoc
man/zip_errors.html
man/zip_errors.man
man/zip_errors.mdoc
man/zip_fdopen.html
man/zip_fdopen.man
man/zip_fdopen.mdoc
man/zip_file_add.html
man/zip_file_add.man
man/zip_file_add.mdoc
man/zip_file_get_comment.html
man/zip_file_get_comment.man
man/zip_file_get_comment.mdoc
man/zip_file_rename.html
man/zip_file_rename.man
man/zip_file_rename.mdoc
man/zip_file_set_comment.html
man/zip_file_set_comment.man
man/zip_file_set_comment.mdoc
man/zip_file_set_encryption.html
man/zip_file_set_encryption.man
man/zip_file_set_encryption.mdoc
man/zip_file_set_mtime.html
man/zip_file_set_mtime.man
man/zip_file_set_mtime.mdoc
man/zip_file_strerror.html
man/zip_file_strerror.man
man/zip_file_strerror.mdoc
man/zip_fopen_encrypted.html
man/zip_fopen_encrypted.man
man/zip_fopen_encrypted.mdoc
man/zip_ftell.html
man/zip_ftell.man
man/zip_ftell.mdoc
man/zip_get_archive_comment.html
man/zip_get_archive_comment.man
man/zip_get_archive_comment.mdoc
man/zip_get_name.html
man/zip_get_name.man
man/zip_get_name.mdoc
man/zip_name_locate.html
man/zip_name_locate.man
man/zip_name_locate.mdoc
man/zip_open.html
man/zip_open.man
man/zip_open.mdoc
man/zip_register_cancel_callback_with_state.html [new file with mode: 0644]
man/zip_register_cancel_callback_with_state.man [new file with mode: 0644]
man/zip_register_cancel_callback_with_state.mdoc [new file with mode: 0644]
man/zip_register_progress_callback_with_state.html
man/zip_register_progress_callback_with_state.man
man/zip_register_progress_callback_with_state.mdoc
man/zip_set_archive_comment.html
man/zip_set_archive_comment.man
man/zip_set_archive_comment.mdoc
man/zip_set_default_password.html
man/zip_set_default_password.man
man/zip_set_default_password.mdoc
man/zip_set_file_compression.html
man/zip_set_file_compression.man
man/zip_set_file_compression.mdoc
man/zip_source.html
man/zip_source.man
man/zip_source.mdoc
man/zip_source_buffer.html
man/zip_source_buffer.man
man/zip_source_buffer.mdoc
man/zip_source_buffer_fragment.html
man/zip_source_buffer_fragment.man
man/zip_source_buffer_fragment.mdoc
man/zip_source_close.html
man/zip_source_close.man
man/zip_source_close.mdoc
man/zip_source_file.html
man/zip_source_file.man
man/zip_source_file.mdoc
man/zip_source_filep.html
man/zip_source_filep.man
man/zip_source_filep.mdoc
man/zip_source_function.html
man/zip_source_function.man
man/zip_source_function.mdoc
man/zip_source_stat.html
man/zip_source_stat.man
man/zip_source_stat.mdoc
man/zip_source_win32a.html
man/zip_source_win32a.man
man/zip_source_win32a.mdoc
man/zip_source_win32handle.html
man/zip_source_win32handle.man
man/zip_source_win32handle.mdoc
man/zip_source_win32w.html
man/zip_source_win32w.man
man/zip_source_win32w.mdoc
man/zip_source_window.html [new file with mode: 0644]
man/zip_source_window.man [new file with mode: 0644]
man/zip_source_window.mdoc [new file with mode: 0644]
man/zip_source_zip.html
man/zip_source_zip.man
man/zip_source_zip.mdoc
man/zipcmp.html
man/zipcmp.man
man/zipcmp.mdoc
man/zipmerge.html
man/zipmerge.man
man/zipmerge.mdoc
regress/CMakeLists.txt
regress/add_from_file_unchange.test [new file with mode: 0644]
regress/add_from_filep.c
regress/can_clone_file.c
regress/decrypt-correct-password-pkware-2.test [new file with mode: 0644]
regress/decrypt-wrong-password-pkware-2.test [new file with mode: 0644]
regress/encrypt-1234.zip [new file with mode: 0644]
regress/encryption-nonrandom-aes128.test
regress/encryption-nonrandom-aes192.test
regress/encryption-nonrandom-aes256.test
regress/encryption-nonrandom-pkware.test
regress/encryption-stat.test [new file with mode: 0644]
regress/extra_field_align.test
regress/fopen_unchanged.c
regress/fread.c
regress/fseek.c
regress/fuzz_main.c
regress/hole.c
regress/liboverride-test.c [new file with mode: 0644]
regress/liboverride.c [new file with mode: 0644]
regress/lzma-no-eos.zip [new file with mode: 0644]
regress/malloc.c
regress/nonrandomopen.c
regress/nonrandomopentest.c
regress/open_cons_extrabytes.test
regress/open_file_count.test
regress/open_incons.test
regress/open_many_fail.test
regress/set_compression_lzma_no_eos_to_store.test [new file with mode: 0644]
regress/set_compression_lzma_to_store.test [new file with mode: 0644]
regress/set_compression_store_to_lzma.test [new file with mode: 0644]
regress/set_compression_store_to_zstd.test [new file with mode: 0644]
regress/set_compression_zstd_to_store.test [new file with mode: 0644]
regress/source_hole.c
regress/stored-no-eos.zip [new file with mode: 0644]
regress/testfile-lzma.zip
regress/testfile-stored-dos.zip
regress/testfile-zstd.zip [new file with mode: 0755]
regress/tryopen.c
regress/zipcmp_zip_dir.test [new file with mode: 0644]
regress/zipcmp_zip_dir.zip [new file with mode: 0644]
regress/ziptool_regress.c
src/CMakeLists.txt
src/diff_output.c [new file with mode: 0644]
src/diff_output.h [new file with mode: 0644]
src/getopt.c
src/getopt.h
src/zipcmp.c
src/zipmerge.c
src/ziptool.c

index 55909c0..8bb62b8 100644 (file)
@@ -8,5 +8,5 @@ BreakBeforeBraces: Custom
 BraceWrapping:
   BeforeElse: true
 AlignEscapedNewlines: Left
-UseTab: ForContinuationAndIndentation
+UseTab: Never
 #PPDirectiveIndentStyle: AfterHash
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644 (file)
index 0000000..d01b75d
--- /dev/null
@@ -0,0 +1,46 @@
+name: build
+on: [push]
+
+jobs:
+  all:
+    runs-on: ${{ matrix.os }}
+    strategy:
+      matrix:
+        os: [macos-latest, ubuntu-latest, windows-latest]
+#        os: [macos-latest, ubuntu-latest]
+    steps:
+      - name: checkout
+        uses: actions/checkout@v2
+      - name: install dependencies (Linux)
+        if: ${{ runner.os == 'Linux' }}
+        run: |
+          sudo apt-get install libzstd-dev
+      - name: install dependencies (Windows)
+        if: ${{ runner.os == 'Windows' }}
+        uses: lukka/run-vcpkg@v6
+        id: runvcpkg
+        with:
+          vcpkgGitCommitId: 0bf3923f9fab4001c00f0f429682a0853b5749e0
+          vcpkgTriplet: x64-windows
+          vcpkgArguments: zlib bzip2 liblzma zstd
+      - name: prepare build directory
+        run: |
+          cmake -E make_directory ${{runner.workspace}}/build
+      - name: configure (Unix)
+        if: ${{ runner.os != 'Windows' }}
+        working-directory: ${{runner.workspace}}/build
+        run: |
+          cmake ${{github.workspace}}
+      - name: configure (Windows)
+        if: ${{ runner.os == 'Windows' }}
+        working-directory: ${{runner.workspace}}/build
+        run: |
+          cmake -DCMAKE_TOOLCHAIN_FILE=${{env.VCPKG_ROOT}}/scripts/buildsystems/vcpkg.cmake ${{github.workspace}}
+      - name: build
+        working-directory: ${{runner.workspace}}/build
+        run: |
+          cmake --build . --config Release
+      - name: test
+        working-directory: ${{runner.workspace}}/build
+        run: |
+          ctest -v -C Release
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
new file mode 100644 (file)
index 0000000..696b1fa
--- /dev/null
@@ -0,0 +1,66 @@
+# For most projects, this workflow file will not need changing; you simply need
+# to commit it to your repository.
+#
+# You may wish to alter this file to override the set of languages analyzed,
+# or to provide custom queries or build logic.
+name: "CodeQL"
+
+on:
+  push:
+    branches: [master]
+  pull_request:
+    # The branches below must be a subset of the branches above
+    branches: [master]
+  schedule:
+    - cron: '0 10 * * 4'
+
+jobs:
+  analyze:
+    name: Analyze
+    runs-on: ubuntu-latest
+
+    strategy:
+      fail-fast: false
+      matrix:
+        # Override automatic language detection by changing the below list
+        # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
+        language: ['cpp']
+        # Learn more...
+        # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
+
+    steps:
+    - name: Checkout repository
+      uses: actions/checkout@v2
+      with:
+        # We must fetch at least the immediate parents so that if this is
+        # a pull request then we can checkout the head.
+        fetch-depth: 2
+
+    # Initializes the CodeQL tools for scanning.
+    - name: Initialize CodeQL
+      uses: github/codeql-action/init@v1
+      with:
+        languages: ${{ matrix.language }}
+        # If you wish to specify custom queries, you can do so here or in a config file.
+        # By default, queries listed here will override any specified in a config file. 
+        # Prefix the list here with "+" to use these queries and those in the config file.
+        # queries: ./path/to/local/query, your-org/your-repo/queries@main
+
+    # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).
+    # If this step fails, then you should remove it and run the build manually (see below)
+    - name: Autobuild
+      uses: github/codeql-action/autobuild@v1
+
+    # ℹ️ Command-line programs to run using the OS shell.
+    # 📚 https://git.io/JvXDl
+
+    # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
+    #    and modify them (or add more) to build your code if your project
+    #    uses a compiled language
+
+    #- run: |
+    #   make bootstrap
+    #   make release
+
+    - name: Perform CodeQL Analysis
+      uses: github/codeql-action/analyze@v1
index 017f7cf..93b46a6 100644 (file)
@@ -6,7 +6,7 @@ if (${CMAKE_VERSION} VERSION_LESS "3.17.0")
 endif()
 
 project(libzip
-  VERSION 1.7.3
+  VERSION 1.8.0
   LANGUAGES C)
 
 option(ENABLE_COMMONCRYPTO "Enable use of CommonCrypto" ON)
@@ -17,6 +17,7 @@ option(ENABLE_WINDOWS_CRYPTO "Enable use of Windows cryptography libraries" ON)
 
 option(ENABLE_BZIP2 "Enable use of BZip2" ON)
 option(ENABLE_LZMA "Enable use of LZMA" ON)
+option(ENABLE_ZSTD "Enable use of Zstandard" ON)
 
 option(BUILD_TOOLS "Build tools in the src directory (zipcmp, zipmerge, ziptool)" ON)
 option(BUILD_REGRESS "Build regression tests" ON)
@@ -33,33 +34,24 @@ include(CheckCSourceCompiles)
 include(CheckStructHasMember)
 include(TestBigEndian)
 include(GNUInstallDirs)
+
 if(ENABLE_COMMONCRYPTO)
   check_include_files(CommonCrypto/CommonCrypto.h COMMONCRYPTO_FOUND)
-else()
-  set(COMMONCRYPTO_FOUND FALSE)
 endif()
 if(ENABLE_GNUTLS)
   find_package(Nettle 3.0)
   find_package(GnuTLS)
-else()
-  set(GNUTLS_FOUND FALSE)
 endif()
 if(ENABLE_MBEDTLS)
   find_package(MbedTLS 1.0)
-else()
-  set(MBEDTLS_LIBRARIES FALSE)
 endif()
 if(ENABLE_OPENSSL)
   find_package(OpenSSL)
-else()
-  set(OPENSSL_FOUND FALSE)
 endif()
 if(WIN32)
   if(ENABLE_WINDOWS_CRYPTO)
     set(WINDOWS_CRYPTO_FOUND TRUE)
   endif()
-else()
-  set(WINDOWS_CRYPTO_FOUND FALSE)
 endif()
 
 option(BUILD_SHARED_LIBS "Build shared libraries" ON)
@@ -100,9 +92,9 @@ check_function_exists(_dup HAVE__DUP)
 check_function_exists(_fdopen HAVE__FDOPEN)
 check_function_exists(_fileno HAVE__FILENO)
 check_function_exists(_setmode HAVE__SETMODE)
-check_function_exists(_snprintf HAVE__SNPRINTF)
+check_symbol_exists(_snprintf stdio.h HAVE__SNPRINTF)
 check_function_exists(_strdup HAVE__STRDUP)
-check_function_exists(_stricmp HAVE__STRICMP)
+check_symbol_exists(_stricmp string.h HAVE__STRICMP)
 check_function_exists(_strtoi64 HAVE__STRTOI64)
 check_function_exists(_strtoui64 HAVE__STRTOUI64)
 check_function_exists(_unlink HAVE__UNLINK)
@@ -116,8 +108,8 @@ check_function_exists(ftello HAVE_FTELLO)
 check_function_exists(getprogname HAVE_GETPROGNAME)
 check_function_exists(localtime_r HAVE_LOCALTIME_R)
 check_function_exists(setmode HAVE_SETMODE)
-check_function_exists(snprintf HAVE_SNPRINTF)
-check_function_exists(strcasecmp HAVE_STRCASECMP)
+check_symbol_exists(snprintf stdio.h HAVE_SNPRINTF)
+check_symbol_exists(strcasecmp strings.h HAVE_STRCASECMP)
 check_function_exists(strdup HAVE_STRDUP)
 check_function_exists(stricmp HAVE_STRICMP)
 check_function_exists(strtoll HAVE_STRTOLL)
@@ -199,10 +191,18 @@ if(ENABLE_LZMA)
   if(LIBLZMA_FOUND)
     set(HAVE_LIBLZMA 1)
   else()
-    message(WARNING "-- lzma library not found; lzma support disabled")
+    message(WARNING "-- lzma library not found; lzma/xz support disabled")
   endif(LIBLZMA_FOUND)
 endif(ENABLE_LZMA)
 
+if(ENABLE_ZSTD)
+  find_package(Zstd)
+  if(Zstd_FOUND)
+    set(HAVE_LIBZSTD 1)
+  else()
+    message(WARNING "-- zstd library not found; zstandard support disabled")
+  endif(Zstd_FOUND)
+endif(ENABLE_ZSTD)
 
 if (COMMONCRYPTO_FOUND)
   set(HAVE_CRYPTO 1)
@@ -283,9 +283,9 @@ endif()
 # pkgconfig file
 set(prefix ${CMAKE_INSTALL_PREFIX})
 set(exec_prefix \${prefix})
-SET(bindir \${exec_prefix}/${CMAKE_INSTALL_BINDIR})
-SET(libdir \${exec_prefix}/${CMAKE_INSTALL_LIBDIR})
-SET(includedir \${prefix}/${CMAKE_INSTALL_INCLUDEDIR})
+SET(bindir ${CMAKE_INSTALL_FULL_BINDIR})
+SET(libdir ${CMAKE_INSTALL_FULL_LIBDIR})
+SET(includedir ${CMAKE_INSTALL_FULL_INCLUDEDIR})
 if(CMAKE_SYSTEM_NAME MATCHES BSD)
   set(PKG_CONFIG_RPATH "-Wl,-R\${libdir}")
 endif(CMAKE_SYSTEM_NAME MATCHES BSD)
@@ -429,12 +429,12 @@ write_basic_package_version_file("${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config-v
 configure_package_config_file("${PROJECT_NAME}-config.cmake.in" "${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake"
   INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libzip)
 
-# Add targets to the build-tree export set
-export(TARGETS zip
-  FILE "${PROJECT_BINARY_DIR}/${PROJECT_NAME}-targets.cmake")
-
-# installation
 if(LIBZIP_DO_INSTALL)
+  # Add targets to the build-tree export set
+  export(TARGETS zip
+    FILE "${PROJECT_BINARY_DIR}/${PROJECT_NAME}-targets.cmake")
+
+  # installation
   install(FILES ${PROJECT_BINARY_DIR}/zipconf.h DESTINATION include)
   install(FILES ${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake ${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake
     DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
index 84ab741..5112182 100644 (file)
@@ -8,9 +8,12 @@ comes with most operating systems.
 For supporting bzip2-compressed zip archives, you need
 [bzip2](http://bzip.org/).
 
-For supporting xz-compressed zip archives, you need
+For supporting lzma- and xz-compressed zip archives, you need
 [liblzma](https://tukaani.org/xz/) which is part of xz, at least version 5.2.
 
+For supporting zstd-compressed zip archives, you need
+[zstd](https://github.com/facebook/zstd/).
+
 For AES (encryption) support, you need one of these cryptographic libraries,
 listed in order of preference:
 
@@ -63,4 +66,4 @@ will break in `zipcmp`.
 You can get verbose build output with by passing `VERBOSE=1` to
 `make`.
 
-You can also check the [cmake FAQ](https://cmake.org/Wiki/CMake_FAQ).
+You can also check the [cmake FAQ](https://gitlab.kitware.com/cmake/community/-/wikis/FAQ).
diff --git a/NEWS.md b/NEWS.md
index d48b59a..c6a4181 100644 (file)
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,3 +1,17 @@
+1.8.0 [2021-06-18]
+==================
+
+* Add support for zstd (Zstandard) compression.
+* Add support for lzma (ID 14) compression.
+* Add `zip_source_window_create()`.
+* Add `zip_source_zip_create()` variant to `zip_source_zip()`.
+* Allow method specific `comp_flags` in `zip_set_file_compression()`.
+* Allow `zip_source_tell()` on sources that don't support seeking and `zip_ftell()` on compressed data.
+* Provide more details for consistency check errors.
+* Improve output of `zipcmp`.
+* In `zipcmp`, don’t ignore empty directories when comparing directory listing.
+* Treat empty string as no password given in `zip_file_set_encryption()`, `zip_fopen_encrypted()`, and `zip_set_default_password()`.
+
 1.7.3 [2020-07-15]
 ==================
 
index 9262c3d..c8cffd5 100644 (file)
--- a/README.md
+++ b/README.md
@@ -34,6 +34,6 @@ to libzip-discuss at nih.at. Use this for bug reports or questions.
 
 If you want to reach the authors in private, use <libzip@nih.at>.
 
-[![Travis Build Status](https://api.travis-ci.org/nih-at/libzip.svg?branch=master)](https://travis-ci.org/nih-at/libzip)
+[![Github Actions Build Status](https://github.com/nih-at/libzip/workflows/build/badge.svg)](https://github.com/nih-at/libzip/actions?query=workflow%3Abuild)
 [![Appveyor Build status](https://ci.appveyor.com/api/projects/status/f1bqqt9djvf22f5g?svg=true)](https://ci.appveyor.com/project/nih-at/libzip)
 [![Coverity Status](https://scan.coverity.com/projects/127/badge.svg)](https://scan.coverity.com/projects/libzip)
diff --git a/THANKS b/THANKS
index 7a16c62..843349e 100644 (file)
--- a/THANKS
+++ b/THANKS
@@ -7,11 +7,13 @@ Agostino Sarubbo
 Alexander Galanin <al@galanin.nnov.ru>
 Alexandr Shadchin <alexandr.shadchin@gmail.com>
 Alexey Bykov <gnfalex@rambler.ru>
+Andreas Deininger <andreas@deininger.net>
 Andreas Falkenhahn <andreas@falkenhahn.com>
 Andrew Brampton <brampton@gmail.com>
 Andrew Molyneux <andrew@molyneuxfamily.co.uk>
 Ankur Kothari <ankz.kothari@gmail.com>
 Antonin Décimo <antonin.decimo@gmail.com>
+Arseniy Terekhin <senyai@gmail.com>
 BALATON Zoltan <balaton@eik.bme.hu>
 Benjamin Gilbert <bgilbert@backtick.net>
 Beuc <beuc@beuc.net>
@@ -21,20 +23,29 @@ Brian 'geeknik' Carpenter <geeknik@protonmail.ch>
 Carl Mastrangelo <notcarl@google.com>
 Cédric Tabin
 celan69
+Charlie Li <git@vishwin.info>
 Chris Nehren <cnehren+libzip@pobox.com>
+Christoph Cullmann <cullmann@kde.org>
+Christoph M. Becker <cmbecker69@gmx.de>
 Coverity <info@coverity.com>
 Dane Springmeyer <dane.springmeyer@gmail.com>
+Ларионов Даниил <scumcoder@yandex.ru>
 David Demelier <demelier.david@gmail.com>
+Dean Ellis <dellis1972@googlemail.com>
 Declan Moran
 Del Merritt <del@alum.mit.edu>
+Devin Davila <daviladsoftware@gmail.com>
 Dmytro Rybachenko <atmoliton@gmail.com>
 Elvis Angelaccio
 Erwin Haid <erwin.haid@gmx.de>
 Eun-cheol Joo
+Fabrice Fontaine
 Florian Delizy <florian.delizy@gmail.com>
+Force Charlie <charlieio@outlook.com>
 François Simon <AT.GFI.Francois.SIMON@sesam-vitale.fr>
 Frederik Ramm <frederik@remote.org>
 gk7huki <gk7huki@gmail.com>
+Gerard ODonnell
 Hanno Böck <hanno@hboeck.de>
 HeeMyung
 Heiko Becker
@@ -43,6 +54,7 @@ Ilya Voronin
 Info-ZIP group
 Jan Weiß <jan@geheimwerk.de>
 Jay Freeman (saurik) <saurik@saurik.com>
+jloqfjgk@github
 Joachim Reichel <joachim.reichel@gmx.de>
 João Custódio <joao_custodio@symantec.com>
 Joel Ebrahimi <joel.ebrahimi@gmail.com>
@@ -50,6 +62,7 @@ Jono Spiro <jono.spiro@gmail.com>
 Julien Schueller <schueller@phimeca.com>
 kensington <kensington@gentoo.org>
 Keith Jones <keith@keithjjones.com>
+Khaled Mardam-Bey
 Kohei Yoshida <kohei.yoshida@gmail.com>
 Leith Bade <leith@mapbox.com>
 Lubomir I. Ivanov <neolit123@gmail.com>
@@ -67,6 +80,7 @@ Morris Hafner
 Oliver Kaiser <under.northern.sky@googlemail.com>
 Oliver Kuckertz <oliver.kuckertz@mologie.de>
 OSS-Fuzz Team
+Ørjan Malde <red@foxi.me>
 Pascal Terjan <pterjan@gmail.com>
 Patrick Spendrin <ps_ml@gmx.de>
 Paul Harris <harris.pc@gmail.com>
@@ -83,6 +97,7 @@ Robert Norris <rw_norris@hotmail.com>
 Roberto Tirabassi <rtirabassi@3di.it>
 Roland Ortloff <Ortloff.R@gmx.de>
 Rosen Penev <rosenp@gmail.com>
+Ryan Burns <rtburns@protonmail.com>
 Sebastian Kemper <sebastian_ml@gmx.net>
 Sebastian Schmitt <sebastian.schmitt@auvesy.de>
 Sergei Ozerov <ru.programmist@gmail.com>
@@ -90,6 +105,7 @@ Simon Talbot <simont@nse.co.uk>
 Stephen Bryant <steve@bawue.de>
 Tabata Shintaro <tabata.shintaro@gmail.com>
 Tarmo Pikaro <tapika@yahoo.com>
+Taylor C. Richberger
 TC
 Tim Lunn <Tim@feathertop.org>
 Timo Warns <warns@pre-sense.de>
diff --git a/TODO.md b/TODO.md
index 7f3a275..a7305aa 100644 (file)
--- a/TODO.md
+++ b/TODO.md
@@ -1,3 +1,7 @@
+## Before next release
+
+reconsider zip_source_zip (uncompressed data for whole file not easy to get)
+
 ## Prefixes
 
 For example for adding extractors for self-extracting zip archives.
@@ -8,7 +12,7 @@ const zip_uint8_t *zip_get_archive_prefix(struct zip *za, zip_uint64_t *lengthp)
 
 ## Compression
 
-* add lzma support
+* add lzma2 support
 * add deflate64 support (https://github.com/madler/zlib/blob/master/contrib/infback9/infback9.h)
 
 ## API Issues
@@ -21,6 +25,7 @@ const zip_uint8_t *zip_get_archive_prefix(struct zip *za, zip_uint64_t *lengthp)
 
 ## Features
 
+* add flag `ZIP_FL_SUPPORT_MULTIPLE_OPENS` and allow zip_fopen (perhaps other functions) on added/replaced files with such sources
 * add seek support for AES-encrypted files
 * consistently use `_zip_crypto_clear()` for passwords
 * support setting extra fields from `zip_source`
@@ -97,6 +102,8 @@ const zip_uint8_t *zip_get_archive_prefix(struct zip *za, zip_uint64_t *lengthp)
 
 ## Test Case Issues
 
+* add test cases for all ZIP_INCONS detail errors
+* `incons-local-filename-short.zzip` doesn't test short filename, since extra fields fail to parse.
 * test error cases with special source
   - tell it which command should fail
   - use it both as source for `zip_add` and `zip_open_from_source`
@@ -120,8 +127,7 @@ const zip_uint8_t *zip_get_archive_prefix(struct zip *za, zip_uint64_t *lengthp)
   * support testing on macOS
 * add test cases for lots of files (including too many)
 * add test cases for holes (between files, between files and cdir, between cdir and eocd, + zip64 where appropriate)
-* unchange on added file
-* test seek in `zip_source_crc()`
+* test seek in `zip_source_crc_create()`
 * test cases for `set_extra*`, `delete_extra*`, `*extra_field*`
 * test cases for in memory archives
   * add
index 290a0af..21d6456 100644 (file)
@@ -56,7 +56,7 @@ environment:
 
 before_build:
   cmd: >-
-    vcpkg install zlib:%TRIPLET% bzip2:%TRIPLET% liblzma:%TRIPLET%
+    vcpkg install zlib:%TRIPLET% bzip2:%TRIPLET% liblzma:%TRIPLET% zstd:%TRIPLET%
 
     mkdir build
 
diff --git a/cmake-compat/FindGnuTLS.cmake b/cmake-compat/FindGnuTLS.cmake
new file mode 100644 (file)
index 0000000..819f000
--- /dev/null
@@ -0,0 +1,82 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+FindGnuTLS
+----------
+
+Find the GNU Transport Layer Security library (gnutls)
+
+IMPORTED Targets
+^^^^^^^^^^^^^^^^
+
+This module defines :prop_tgt:`IMPORTED` target ``GnuTLS::GnuTLS``, if
+gnutls has been found.
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+``GNUTLS_FOUND``
+  System has gnutls
+``GNUTLS_INCLUDE_DIR``
+  The gnutls include directory
+``GNUTLS_LIBRARIES``
+  The libraries needed to use gnutls
+``GNUTLS_DEFINITIONS``
+  Compiler switches required for using gnutls
+``GNUTLS_VERSION``
+  version of gnutls.
+#]=======================================================================]
+
+# Note that this doesn't try to find the gnutls-extra package.
+
+
+if (GNUTLS_INCLUDE_DIR AND GNUTLS_LIBRARY)
+  # in cache already
+  set(gnutls_FIND_QUIETLY TRUE)
+endif ()
+
+if (NOT WIN32)
+  # try using pkg-config to get the directories and then use these values
+  # in the find_path() and find_library() calls
+  # also fills in GNUTLS_DEFINITIONS, although that isn't normally useful
+  find_package(PkgConfig QUIET)
+  PKG_CHECK_MODULES(PC_GNUTLS QUIET gnutls)
+  set(GNUTLS_DEFINITIONS ${PC_GNUTLS_CFLAGS_OTHER})
+  set(GNUTLS_VERSION ${PC_GNUTLS_VERSION})
+  # keep for backward compatibility
+  set(GNUTLS_VERSION_STRING ${PC_GNUTLS_VERSION})
+endif ()
+
+find_path(GNUTLS_INCLUDE_DIR gnutls/gnutls.h
+  HINTS
+    ${PC_GNUTLS_INCLUDEDIR}
+    ${PC_GNUTLS_INCLUDE_DIRS}
+  )
+
+find_library(GNUTLS_LIBRARY NAMES gnutls libgnutls
+  HINTS
+    ${PC_GNUTLS_LIBDIR}
+    ${PC_GNUTLS_LIBRARY_DIRS}
+  )
+
+mark_as_advanced(GNUTLS_INCLUDE_DIR GNUTLS_LIBRARY)
+
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(GnuTLS
+                                  REQUIRED_VARS GNUTLS_LIBRARY GNUTLS_INCLUDE_DIR
+                                  VERSION_VAR GNUTLS_VERSION_STRING)
+
+if(GNUTLS_FOUND)
+  set(GNUTLS_LIBRARIES    ${GNUTLS_LIBRARY})
+  set(GNUTLS_INCLUDE_DIRS ${GNUTLS_INCLUDE_DIR})
+
+  if(NOT TARGET GnuTLS::GnuTLS)
+    add_library(GnuTLS::GnuTLS UNKNOWN IMPORTED)
+    set_target_properties(GnuTLS::GnuTLS PROPERTIES
+      INTERFACE_INCLUDE_DIRECTORIES "${GNUTLS_INCLUDE_DIRS}"
+      INTERFACE_COMPILE_DEFINITIONS "${GNUTLS_DEFINITIONS}"
+      IMPORTED_LINK_INTERFACE_LANGUAGES "C"
+      IMPORTED_LOCATION "${GNUTLS_LIBRARIES}")
+  endif()
+endif()
index 2df6f82..544adbd 100644 (file)
@@ -29,6 +29,7 @@
 #cmakedefine HAVE_GNUTLS
 #cmakedefine HAVE_LIBBZ2
 #cmakedefine HAVE_LIBLZMA
+#cmakedefine HAVE_LIBZSTD
 #cmakedefine HAVE_LOCALTIME_R
 #cmakedefine HAVE_MBEDTLS
 #cmakedefine HAVE_MKSTEMP
diff --git a/cmake/FindZstd.cmake b/cmake/FindZstd.cmake
new file mode 100644 (file)
index 0000000..a0da503
--- /dev/null
@@ -0,0 +1,135 @@
+# Copyright (C) 2020 Dieter Baron and Thomas Klausner
+#
+# The authors can be contacted at <libzip@nih.at>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in
+#   the documentation and/or other materials provided with the
+#   distribution.
+#
+# 3. The names of the authors may not be used to endorse or promote
+#   products derived from this software without specific prior
+#   written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#[=======================================================================[.rst:
+FindZstd
+-------
+
+Finds the Zstandard (zstd) library.
+
+Imported Targets
+^^^^^^^^^^^^^^^^
+
+This module provides the following imported targets, if found:
+
+``Zstd::Zstd``
+  The Zstandard library
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+This will define the following variables:
+
+``Zstd_FOUND``
+  True if the system has the Zstandard library.
+``Zstd_VERSION``
+  The version of the Zstandard library which was found.
+``Zstd_INCLUDE_DIRS``
+  Include directories needed to use Zstandard.
+``Zstd_LIBRARIES``
+  Libraries needed to link to Zstandard.
+
+Cache Variables
+^^^^^^^^^^^^^^^
+
+The following cache variables may also be set:
+
+``Zstd_INCLUDE_DIR``
+  The directory containing ``zstd.h``.
+``Zstd_LIBRARY``
+  The path to the Zstandard library.
+
+#]=======================================================================]
+
+find_package(PkgConfig)
+pkg_check_modules(PC_Zstd QUIET zstd)
+
+find_path(Zstd_INCLUDE_DIR
+  NAMES zstd.h
+  PATHS ${PC_Zstd_INCLUDE_DIRS}
+)
+find_library(Zstd_LIBRARY
+  NAMES zstd
+  PATHS ${PC_Zstd_LIBRARY_DIRS}
+)
+
+# Extract version information from the header file
+if(Zstd_INCLUDE_DIR)
+  file(STRINGS ${Zstd_INCLUDE_DIR}/zstd.h _ver_major_line
+    REGEX "^#define ZSTD_VERSION_MAJOR  *[0-9]+"
+    LIMIT_COUNT 1)
+  string(REGEX MATCH "[0-9]+"
+    Zstd_MAJOR_VERSION "${_ver_major_line}")
+  file(STRINGS ${Zstd_INCLUDE_DIR}/zstd.h _ver_minor_line
+    REGEX "^#define ZSTD_VERSION_MINOR  *[0-9]+"
+    LIMIT_COUNT 1)
+  string(REGEX MATCH "[0-9]+"
+    Zstd_MINOR_VERSION "${_ver_minor_line}")
+  file(STRINGS ${Zstd_INCLUDE_DIR}/zstd.h _ver_release_line
+    REGEX "^#define ZSTD_VERSION_RELEASE  *[0-9]+"
+    LIMIT_COUNT 1)
+  string(REGEX MATCH "[0-9]+"
+    Zstd_RELEASE_VERSION "${_ver_release_line}")
+  set(Zstd_VERSION "${Zstd_MAJOR_VERSION}.${Zstd_MINOR_VERSION}.${Zstd_RELEASE_VERSION}")
+  unset(_ver_major_line)
+  unset(_ver_minor_line)
+  unset(_ver_release_line)
+endif()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(Zstd
+  FOUND_VAR Zstd_FOUND
+  REQUIRED_VARS
+    Zstd_LIBRARY
+    Zstd_INCLUDE_DIR
+  VERSION_VAR Zstd_VERSION
+)
+
+if(Zstd_FOUND)
+  set(Zstd_LIBRARIES ${Zstd_LIBRARY})
+  set(Zstd_INCLUDE_DIRS ${Zstd_INCLUDE_DIR})
+  set(Zstd_DEFINITIONS ${PC_Zstd_CFLAGS_OTHER})
+endif()
+
+if(Zstd_FOUND AND NOT TARGET Zstd::Zstd)
+  add_library(Zstd::Zstd UNKNOWN IMPORTED)
+  set_target_properties(Zstd::Zstd PROPERTIES
+    IMPORTED_LOCATION "${Zstd_LIBRARY}"
+    INTERFACE_COMPILE_OPTIONS "${PC_Zstd_CFLAGS_OTHER}"
+    INTERFACE_INCLUDE_DIRECTORIES "${Zstd_INCLUDE_DIR}"
+  )
+endif()
+
+mark_as_advanced(
+  Zstd_INCLUDE_DIR
+  Zstd_LIBRARY
+)
index b86089a..19f60ee 100644 (file)
@@ -1,6 +1,6 @@
 /*
   in-memory.c -- modify zip file in memory
-  Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2014-2020 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -46,34 +46,34 @@ get_data(void **datap, size_t *sizep, const char *archive) {
     FILE *fp;
 
     if ((fp = fopen(archive, "rb")) == NULL) {
-       if (errno != ENOENT) {
-           fprintf(stderr, "can't open %s: %s\n", archive, strerror(errno));
-           return -1;
-       }
+        if (errno != ENOENT) {
+            fprintf(stderr, "can't open %s: %s\n", archive, strerror(errno));
+            return -1;
+        }
 
-       *datap = NULL;
-       *sizep = 0;
+        *datap = NULL;
+        *sizep = 0;
 
-       return 0;
+        return 0;
     }
 
     if (fstat(fileno(fp), &st) < 0) {
-       fprintf(stderr, "can't stat %s: %s\n", archive, strerror(errno));
-       fclose(fp);
-       return -1;
+        fprintf(stderr, "can't stat %s: %s\n", archive, strerror(errno));
+        fclose(fp);
+        return -1;
     }
 
     if ((*datap = malloc((size_t)st.st_size)) == NULL) {
-       fprintf(stderr, "can't allocate buffer\n");
-       fclose(fp);
-       return -1;
+        fprintf(stderr, "can't allocate buffer\n");
+        fclose(fp);
+        return -1;
     }
 
     if (fread(*datap, 1, (size_t)st.st_size, fp) < (size_t)st.st_size) {
-       fprintf(stderr, "can't read %s: %s\n", archive, strerror(errno));
-       free(*datap);
-       fclose(fp);
-       return -1;
+        fprintf(stderr, "can't read %s: %s\n", archive, strerror(errno));
+        free(*datap);
+        fclose(fp);
+        return -1;
     }
 
     fclose(fp);
@@ -95,25 +95,25 @@ use_data(void *data, size_t size, const char *archive) {
     FILE *fp;
 
     if (data == NULL) {
-       if (remove(archive) < 0 && errno != ENOENT) {
-           fprintf(stderr, "can't remove %s: %s\n", archive, strerror(errno));
-           return -1;
-       }
-       return 0;
+        if (remove(archive) < 0 && errno != ENOENT) {
+            fprintf(stderr, "can't remove %s: %s\n", archive, strerror(errno));
+            return -1;
+        }
+        return 0;
     }
 
     if ((fp = fopen(archive, "wb")) == NULL) {
-       fprintf(stderr, "can't open %s: %s\n", archive, strerror(errno));
-       return -1;
+        fprintf(stderr, "can't open %s: %s\n", archive, strerror(errno));
+        return -1;
     }
     if (fwrite(data, 1, size, fp) < size) {
-       fprintf(stderr, "can't write %s: %s\n", archive, strerror(errno));
-       fclose(fp);
-       return -1;
+        fprintf(stderr, "can't write %s: %s\n", archive, strerror(errno));
+        fclose(fp);
+        return -1;
     }
     if (fclose(fp) < 0) {
-       fprintf(stderr, "can't write %s: %s\n", archive, strerror(errno));
-       return -1;
+        fprintf(stderr, "can't write %s: %s\n", archive, strerror(errno));
+        return -1;
     }
 
     return 0;
@@ -130,31 +130,31 @@ main(int argc, char *argv[]) {
     size_t size;
 
     if (argc < 2) {
-       fprintf(stderr, "usage: %s archive\n", argv[0]);
-       return 1;
+        fprintf(stderr, "usage: %s archive\n", argv[0]);
+        return 1;
     }
     archive = argv[1];
 
     /* get buffer with zip archive inside */
     if (get_data(&data, &size, archive) < 0) {
-       return 1;
+        return 1;
     }
 
     zip_error_init(&error);
     /* create source from buffer */
     if ((src = zip_source_buffer_create(data, size, 1, &error)) == NULL) {
-       fprintf(stderr, "can't create source: %s\n", zip_error_strerror(&error));
-       free(data);
-       zip_error_fini(&error);
-       return 1;
+        fprintf(stderr, "can't create source: %s\n", zip_error_strerror(&error));
+        free(data);
+        zip_error_fini(&error);
+        return 1;
     }
 
     /* open zip archive from source */
     if ((za = zip_open_from_source(src, 0, &error)) == NULL) {
-       fprintf(stderr, "can't open zip from source: %s\n", zip_error_strerror(&error));
-       zip_source_free(src);
-       zip_error_fini(&error);
-       return 1;
+        fprintf(stderr, "can't open zip from source: %s\n", zip_error_strerror(&error));
+        zip_source_free(src);
+        zip_error_fini(&error);
+        return 1;
     }
     zip_error_fini(&error);
 
@@ -166,43 +166,43 @@ main(int argc, char *argv[]) {
 
     /* close archive */
     if (zip_close(za) < 0) {
-       fprintf(stderr, "can't close zip archive '%s': %s\n", archive, zip_strerror(za));
-       return 1;
+        fprintf(stderr, "can't close zip archive '%s': %s\n", archive, zip_strerror(za));
+        return 1;
     }
 
 
     /* copy new archive to buffer */
 
     if (zip_source_is_deleted(src)) {
-       /* new archive is empty, thus no data */
-       data = NULL;
+        /* new archive is empty, thus no data */
+        data = NULL;
     }
     else {
-       zip_stat_t zst;
-
-       if (zip_source_stat(src, &zst) < 0) {
-           fprintf(stderr, "can't stat source: %s\n", zip_error_strerror(zip_source_error(src)));
-           return 1;
-       }
-
-       size = zst.size;
-
-       if (zip_source_open(src) < 0) {
-           fprintf(stderr, "can't open source: %s\n", zip_error_strerror(zip_source_error(src)));
-           return 1;
-       }
-       if ((data = malloc(size)) == NULL) {
-           fprintf(stderr, "malloc failed: %s\n", strerror(errno));
-           zip_source_close(src);
-           return 1;
-       }
-       if ((zip_uint64_t)zip_source_read(src, data, size) < size) {
-           fprintf(stderr, "can't read data from source: %s\n", zip_error_strerror(zip_source_error(src)));
-           zip_source_close(src);
-           free(data);
-           return 1;
-       }
-       zip_source_close(src);
+        zip_stat_t zst;
+
+        if (zip_source_stat(src, &zst) < 0) {
+            fprintf(stderr, "can't stat source: %s\n", zip_error_strerror(zip_source_error(src)));
+            return 1;
+        }
+
+        size = zst.size;
+
+        if (zip_source_open(src) < 0) {
+            fprintf(stderr, "can't open source: %s\n", zip_error_strerror(zip_source_error(src)));
+            return 1;
+        }
+        if ((data = malloc(size)) == NULL) {
+            fprintf(stderr, "malloc failed: %s\n", strerror(errno));
+            zip_source_close(src);
+            return 1;
+        }
+        if ((zip_uint64_t)zip_source_read(src, data, size) < size) {
+            fprintf(stderr, "can't read data from source: %s\n", zip_error_strerror(zip_source_error(src)));
+            zip_source_close(src);
+            free(data);
+            return 1;
+        }
+        zip_source_close(src);
     }
 
     /* we're done with src */
index bc8660d..d01ea06 100644 (file)
@@ -1,6 +1,6 @@
 /*
   windows-open.c -- open zip archive using Windows UTF-16/Unicode file name
-  Copyright (C) 2015-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2015-2020 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -42,17 +42,17 @@ windows_open(const wchar_t *name, int flags) {
     zip_error_init(&error);
     /* create source from buffer */
     if ((src = zip_source_win32w_create(name, 0, -1, &error)) == NULL) {
-       fprintf(stderr, "can't create source: %s\n", zip_error_strerror(&error));
-       zip_error_fini(&error);
-       return NULL;
+        fprintf(stderr, "can't create source: %s\n", zip_error_strerror(&error));
+        zip_error_fini(&error);
+        return NULL;
     }
 
     /* open zip archive from source */
     if ((za = zip_open_from_source(src, flags, &error)) == NULL) {
-       fprintf(stderr, "can't open zip from source: %s\n", zip_error_strerror(&error));
-       zip_source_free(src);
-       zip_error_fini(&error);
-       return NULL;
+        fprintf(stderr, "can't open zip from source: %s\n", zip_error_strerror(&error));
+        zip_source_free(src);
+        zip_error_fini(&error);
+        return NULL;
     }
     zip_error_fini(&error);
 
index 082203d..1069cec 100644 (file)
@@ -111,7 +111,7 @@ add_library(zip
   zip_unchange_archive.c
   zip_unchange_data.c
   zip_utf-8.c
-  ${CMAKE_BINARY_DIR}/zip_err_str.c
+  ${CMAKE_CURRENT_BINARY_DIR}/zip_err_str.c
   )
 add_library(libzip::zip ALIAS zip)
 
@@ -146,6 +146,11 @@ if(HAVE_LIBLZMA)
   target_link_libraries(zip PRIVATE LibLZMA::LibLZMA)
 endif()
 
+if(HAVE_LIBZSTD)
+  target_sources(zip PRIVATE zip_algorithm_zstd.c)
+  target_link_libraries(zip PRIVATE Zstd::Zstd)
+endif()
+
 if(HAVE_COMMONCRYPTO)
   target_sources(zip PRIVATE zip_crypto_commoncrypto.c)
 elseif(HAVE_WINDOWS_CRYPTO)
@@ -167,7 +172,7 @@ if(HAVE_CRYPTO)
 endif()
 
 if(SHARED_LIB_VERSIONNING)
-  set_target_properties(zip PROPERTIES VERSION 5.3 SOVERSION 5)
+  set_target_properties(zip PROPERTIES VERSION 5.4 SOVERSION 5)
 endif()
 
 target_link_libraries(zip PRIVATE ZLIB::ZLIB)
@@ -175,7 +180,7 @@ target_include_directories(zip
   PUBLIC
   $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/lib>
   $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>
-  $<INSTALL_INTERFACE:include>
+  $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
   )
 
 if(LIBZIP_DO_INSTALL)
@@ -190,34 +195,48 @@ endif()
 
 # create zip_err_str.h from zip.h
 file(READ ${PROJECT_SOURCE_DIR}/lib/zip.h zip_h)
-string(REGEX MATCHALL "#define ZIP_ER_([A-Z_]+) ([0-9]+)[ \t]+/([-*0-9a-zA-Z ']*)/" zip_h_err ${zip_h})
+string(REGEX MATCHALL "#define ZIP_ER_([A-Z0-9_]+) ([0-9]+)[ \t]+/([-*0-9a-zA-Z, ']*)/" zip_h_err ${zip_h})
+file(READ ${PROJECT_SOURCE_DIR}/lib/zipint.h zipint_h)
+string(REGEX MATCHALL "#define ZIP_ER_DETAIL_([A-Z0-9_]+) ([0-9]+)[ \t]+/([-*0-9a-zA-Z, ']*)/" zipint_h_err ${zipint_h})
 set(zip_err_str [=[
 /*
   This file was generated automatically by CMake
-  from zip.h\; make changes there.
+  from zip.h and zipint.h\; make changes there.
 */
 
 #include "zipint.h"
 
-const char * const _zip_err_str[] = {
+#define L ZIP_ET_LIBZIP
+#define N ZIP_ET_NONE
+#define S ZIP_ET_SYS
+#define Z ZIP_ET_ZLIB
+
+#define E ZIP_DETAIL_ET_ENTRY
+#define G ZIP_DETAIL_ET_GLOBAL
+
+const struct _zip_err_info _zip_err_str[] = {
 ]=])
 set(zip_err_type)
 foreach(errln ${zip_h_err})
-  string(REGEX MATCH "#define ZIP_ER_([A-Z_]+) ([0-9]+)[ \t]+/([-*0-9a-zA-Z ']*)/" err_t_tt ${errln})
-  string(REGEX MATCH "([N|S|Z]+) ([-0-9a-zA-Z ']*)" err_t_tt "${CMAKE_MATCH_3}")
-  string(APPEND zip_err_type "    ${CMAKE_MATCH_1},\n")
+  string(REGEX MATCH "#define ZIP_ER_([A-Z0-9_]+) ([0-9]+)[ \t]+/([-*0-9a-zA-Z, ']*)/" err_t_tt ${errln})
+  string(REGEX MATCH "([L|N|S|Z]+) ([-0-9a-zA-Z,, ']*)" err_t_tt "${CMAKE_MATCH_3}")
   string(STRIP "${CMAKE_MATCH_2}" err_t_tt)
-  string(APPEND zip_err_str "    \"${err_t_tt}\",\n")
+  string(APPEND zip_err_str "    { ${CMAKE_MATCH_1}, \"${err_t_tt}\" },\n")
 endforeach()
 string(APPEND zip_err_str [=[}\;
 
-const int _zip_nerr_str = sizeof(_zip_err_str)/sizeof(_zip_err_str[0])\;
+const int _zip_err_str_count = sizeof(_zip_err_str)/sizeof(_zip_err_str[0])\;
 
-#define N ZIP_ET_NONE
-#define S ZIP_ET_SYS
-#define Z ZIP_ET_ZLIB
+const struct _zip_err_info _zip_err_details[] = {
+]=])
+foreach(errln ${zipint_h_err})
+  string(REGEX MATCH "#define ZIP_ER_DETAIL_([A-Z0-9_]+) ([0-9]+)[ \t]+/([-*0-9a-zA-Z, ']*)/" err_t_tt ${errln})
+  string(REGEX MATCH "([E|G]+) ([-0-9a-zA-Z, ']*)" err_t_tt "${CMAKE_MATCH_3}")
+  string(STRIP "${CMAKE_MATCH_2}" err_t_tt)
+  string(APPEND zip_err_str "    { ${CMAKE_MATCH_1}, \"${err_t_tt}\" },\n")
+endforeach()
+string(APPEND zip_err_str [=[}\;
 
-const int _zip_err_type[] = {
+const int _zip_err_details_count = sizeof(_zip_err_details)/sizeof(_zip_err_details[0])\;
 ]=])
-string(APPEND zip_err_str "${zip_err_type}}\;\n")
-file(WRITE ${CMAKE_BINARY_DIR}/zip_err_str.c ${zip_err_str})
+file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/zip_err_str.c ${zip_err_str})
index a5cf728..47c28fd 100644 (file)
@@ -3,7 +3,7 @@
 
 /*
   compat.h -- compatibility defines.
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -94,7 +94,7 @@ typedef char bool;
 #if !defined(HAVE_FILENO) && defined(HAVE__FILENO)
 #define fileno _fileno
 #endif
-#if defined(HAVE__SNPRINTF)
+#if !defined(HAVE_SNPRINTF) && defined(HAVE__SNPRINTF)
 #define snprintf _snprintf
 #endif
 #if defined(HAVE__STRDUP)
index a90776d..4b9b9e9 100644 (file)
--- a/lib/zip.h
+++ b/lib/zip.h
@@ -3,7 +3,7 @@
 
 /*
   zip.h -- exported declarations.
-  Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -123,7 +123,7 @@ extern "C" {
 #define ZIP_ER_INVAL 18           /* N Invalid argument */
 #define ZIP_ER_NOZIP 19           /* N Not a zip archive */
 #define ZIP_ER_INTERNAL 20        /* N Internal error */
-#define ZIP_ER_INCONS 21          /* N Zip archive inconsistent */
+#define ZIP_ER_INCONS 21          /* L Zip archive inconsistent */
 #define ZIP_ER_REMOVE 22          /* S Can't remove file */
 #define ZIP_ER_DELETED 23         /* N Entry has been deleted */
 #define ZIP_ER_ENCRNOTSUPP 24     /* N Encryption method not supported */
@@ -138,9 +138,10 @@ extern "C" {
 
 /* type of system error value */
 
-#define ZIP_ET_NONE 0 /* sys_err unused */
-#define ZIP_ET_SYS 1  /* sys_err is errno */
-#define ZIP_ET_ZLIB 2 /* sys_err is zlib error code */
+#define ZIP_ET_NONE 0   /* sys_err unused */
+#define ZIP_ET_SYS 1    /* sys_err is errno */
+#define ZIP_ET_ZLIB 2   /* sys_err is zlib error code */
+#define ZIP_ET_LIBZIP 3 /* sys_err is libzip error code */
 
 /* compression methods */
 
@@ -163,7 +164,9 @@ extern "C" {
 /* 15-17 - Reserved by PKWARE */
 #define ZIP_CM_TERSE 18 /* compressed using IBM TERSE (new) */
 #define ZIP_CM_LZ77 19  /* IBM LZ77 z Architecture (PFS) */
+/* 20 - old value for Zstandard */
 #define ZIP_CM_LZMA2 33
+#define ZIP_CM_ZSTD 93    /* Zstandard compressed data */
 #define ZIP_CM_XZ 95      /* XZ compressed data */
 #define ZIP_CM_JPEG 96    /* Compressed Jpeg data */
 #define ZIP_CM_WAVPACK 97 /* WavPack compressed data */
@@ -460,8 +463,10 @@ ZIP_EXTERN zip_source_t *zip_source_win32handle_create(void *, zip_uint64_t, zip
 ZIP_EXTERN zip_source_t *zip_source_win32w(zip_t *, const wchar_t *, zip_uint64_t, zip_int64_t);
 ZIP_EXTERN zip_source_t *zip_source_win32w_create(const wchar_t *, zip_uint64_t, zip_int64_t, zip_error_t *);
 #endif
+ZIP_EXTERN zip_source_t *_Nullable zip_source_window_create(zip_source_t *_Nonnull, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable);
 ZIP_EXTERN zip_int64_t zip_source_write(zip_source_t *_Nonnull, const void *_Nullable, zip_uint64_t);
 ZIP_EXTERN zip_source_t *_Nullable zip_source_zip(zip_t *_Nonnull, zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t);
+ZIP_EXTERN zip_source_t *_Nullable zip_source_zip_create(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable);
 ZIP_EXTERN int zip_stat(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t, zip_stat_t *_Nonnull);
 ZIP_EXTERN int zip_stat_index(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_stat_t *_Nonnull);
 ZIP_EXTERN void zip_stat_init(zip_stat_t *_Nonnull);
index 1954235..dd6dcbc 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_add.c -- add file via callback function
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -38,9 +38,9 @@
 
 /*
   NOTE: Return type is signed so we can return -1 on error.
-       The index can not be larger than ZIP_INT64_MAX since the size
-       of the central directory cannot be larger than
-       ZIP_UINT64_MAX, and each entry is larger than 2 bytes.
+        The index can not be larger than ZIP_INT64_MAX since the size
+        of the central directory cannot be larger than
+        ZIP_UINT64_MAX, and each entry is larger than 2 bytes.
 */
 
 ZIP_EXTERN zip_int64_t
index 88fcf53..41de94b 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_add_dir.c -- add directory
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
index f52e0b5..6f3c162 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_add_entry.c -- create and init struct zip_entry
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -44,32 +44,32 @@ _zip_add_entry(zip_t *za) {
     zip_uint64_t idx;
 
     if (za->nentry + 1 >= za->nentry_alloc) {
-       zip_entry_t *rentries;
-       zip_uint64_t nalloc = za->nentry_alloc;
-       zip_uint64_t additional_entries = 2 * nalloc;
-       zip_uint64_t realloc_size;
+        zip_entry_t *rentries;
+        zip_uint64_t nalloc = za->nentry_alloc;
+        zip_uint64_t additional_entries = 2 * nalloc;
+        zip_uint64_t realloc_size;
 
-       if (additional_entries < 16) {
-           additional_entries = 16;
-       }
-       else if (additional_entries > 1024) {
-           additional_entries = 1024;
-       }
-       /* neither + nor * overflows can happen: nentry_alloc * sizeof(struct zip_entry) < UINT64_MAX */
-       nalloc += additional_entries;
-       realloc_size = sizeof(struct zip_entry) * (size_t)nalloc;
+        if (additional_entries < 16) {
+            additional_entries = 16;
+        }
+        else if (additional_entries > 1024) {
+            additional_entries = 1024;
+        }
+        /* neither + nor * overflows can happen: nentry_alloc * sizeof(struct zip_entry) < UINT64_MAX */
+        nalloc += additional_entries;
+        realloc_size = sizeof(struct zip_entry) * (size_t)nalloc;
 
-       if (sizeof(struct zip_entry) * (size_t)za->nentry_alloc > realloc_size) {
-           zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-           return -1;
-       }
-       rentries = (zip_entry_t *)realloc(za->entry, sizeof(struct zip_entry) * (size_t)nalloc);
-       if (!rentries) {
-           zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-           return -1;
-       }
-       za->entry = rentries;
-       za->nentry_alloc = nalloc;
+        if (sizeof(struct zip_entry) * (size_t)za->nentry_alloc > realloc_size) {
+            zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+            return -1;
+        }
+        rentries = (zip_entry_t *)realloc(za->entry, sizeof(struct zip_entry) * (size_t)nalloc);
+        if (!rentries) {
+            zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+            return -1;
+        }
+        za->entry = rentries;
+        za->nentry_alloc = nalloc;
     }
 
     idx = za->nentry++;
index a4f27e5..ebc68d9 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_algorithm_bzip2.c -- bzip2 (de)compression routines
-  Copyright (C) 2017-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -46,19 +46,30 @@ struct ctx {
 };
 
 
+static zip_uint64_t
+maximum_compressed_size(zip_uint64_t uncompressed_size) {
+    zip_uint64_t compressed_size = (zip_uint64_t)((double)uncompressed_size * 1.006);
+
+    if (compressed_size < uncompressed_size) {
+        return ZIP_UINT64_MAX;
+    }
+    return compressed_size;
+}
+
+
 static void *
 allocate(bool compress, int compression_flags, zip_error_t *error) {
     struct ctx *ctx;
 
     if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) {
-       return NULL;
+        return NULL;
     }
 
     ctx->error = error;
     ctx->compress = compress;
     ctx->compression_flags = compression_flags;
     if (ctx->compression_flags < 1 || ctx->compression_flags > 9) {
-       ctx->compression_flags = 9;
+        ctx->compression_flags = 9;
     }
     ctx->end_of_input = false;
 
@@ -104,32 +115,32 @@ map_error(int ret) {
     case BZ_OK:
     case BZ_RUN_OK:
     case BZ_STREAM_END:
-       return ZIP_ER_OK;
+        return ZIP_ER_OK;
 
     case BZ_DATA_ERROR:
     case BZ_DATA_ERROR_MAGIC:
     case BZ_UNEXPECTED_EOF:
-       return ZIP_ER_COMPRESSED_DATA;
+        return ZIP_ER_COMPRESSED_DATA;
 
     case BZ_MEM_ERROR:
-       return ZIP_ER_MEMORY;
+        return ZIP_ER_MEMORY;
 
     case BZ_PARAM_ERROR:
-       return ZIP_ER_INVAL;
+        return ZIP_ER_INVAL;
 
     case BZ_CONFIG_ERROR: /* actually, bzip2 miscompiled */
     case BZ_IO_ERROR:
     case BZ_OUTBUFF_FULL:
     case BZ_SEQUENCE_ERROR:
-       return ZIP_ER_INTERNAL;
+        return ZIP_ER_INTERNAL;
 
     default:
-       return ZIP_ER_INTERNAL;
+        return ZIP_ER_INTERNAL;
     }
 }
 
 static bool
-start(void *ud) {
+start(void *ud, zip_stat_t *st, zip_file_attributes_t *attributes) {
     struct ctx *ctx = (struct ctx *)ud;
     int ret;
 
@@ -139,15 +150,15 @@ start(void *ud) {
     ctx->zstr.next_out = NULL;
 
     if (ctx->compress) {
-       ret = BZ2_bzCompressInit(&ctx->zstr, ctx->compression_flags, 0, 30);
+        ret = BZ2_bzCompressInit(&ctx->zstr, ctx->compression_flags, 0, 30);
     }
     else {
-       ret = BZ2_bzDecompressInit(&ctx->zstr, 0, 0);
+        ret = BZ2_bzDecompressInit(&ctx->zstr, 0, 0);
     }
 
     if (ret != BZ_OK) {
-       zip_error_set(ctx->error, map_error(ret), 0);
-       return false;
+        zip_error_set(ctx->error, map_error(ret), 0);
+        return false;
     }
 
     return true;
@@ -160,15 +171,15 @@ end(void *ud) {
     int err;
 
     if (ctx->compress) {
-       err = BZ2_bzCompressEnd(&ctx->zstr);
+        err = BZ2_bzCompressEnd(&ctx->zstr);
     }
     else {
-       err = BZ2_bzDecompressEnd(&ctx->zstr);
+        err = BZ2_bzDecompressEnd(&ctx->zstr);
     }
 
     if (err != BZ_OK) {
-       zip_error_set(ctx->error, map_error(err), 0);
-       return false;
+        zip_error_set(ctx->error, map_error(err), 0);
+        return false;
     }
 
     return true;
@@ -180,8 +191,8 @@ input(void *ud, zip_uint8_t *data, zip_uint64_t length) {
     struct ctx *ctx = (struct ctx *)ud;
 
     if (length > UINT_MAX || ctx->zstr.avail_in > 0) {
-       zip_error_set(ctx->error, ZIP_ER_INVAL, 0);
-       return false;
+        zip_error_set(ctx->error, ZIP_ER_INVAL, 0);
+        return false;
     }
 
     ctx->zstr.avail_in = (unsigned int)length;
@@ -206,45 +217,46 @@ process(void *ud, zip_uint8_t *data, zip_uint64_t *length) {
     int ret;
 
     if (ctx->zstr.avail_in == 0 && !ctx->end_of_input) {
-       *length = 0;
-       return ZIP_COMPRESSION_NEED_DATA;
+        *length = 0;
+        return ZIP_COMPRESSION_NEED_DATA;
     }
 
     ctx->zstr.avail_out = (unsigned int)ZIP_MIN(UINT_MAX, *length);
     ctx->zstr.next_out = (char *)data;
 
     if (ctx->compress) {
-       ret = BZ2_bzCompress(&ctx->zstr, ctx->end_of_input ? BZ_FINISH : BZ_RUN);
+        ret = BZ2_bzCompress(&ctx->zstr, ctx->end_of_input ? BZ_FINISH : BZ_RUN);
     }
     else {
-       ret = BZ2_bzDecompress(&ctx->zstr);
+        ret = BZ2_bzDecompress(&ctx->zstr);
     }
 
     *length = *length - ctx->zstr.avail_out;
 
     switch (ret) {
     case BZ_FINISH_OK: /* compression */
-       return ZIP_COMPRESSION_OK;
+        return ZIP_COMPRESSION_OK;
 
     case BZ_OK:     /* decompression */
     case BZ_RUN_OK: /* compression */
-       if (ctx->zstr.avail_in == 0) {
-           return ZIP_COMPRESSION_NEED_DATA;
-       }
-       return ZIP_COMPRESSION_OK;
+        if (ctx->zstr.avail_in == 0) {
+            return ZIP_COMPRESSION_NEED_DATA;
+        }
+        return ZIP_COMPRESSION_OK;
 
     case BZ_STREAM_END:
-       return ZIP_COMPRESSION_END;
+        return ZIP_COMPRESSION_END;
 
     default:
-       zip_error_set(ctx->error, map_error(ret), 0);
-       return ZIP_COMPRESSION_ERROR;
+        zip_error_set(ctx->error, map_error(ret), 0);
+        return ZIP_COMPRESSION_ERROR;
     }
 }
 
 /* clang-format off */
 
 zip_compression_algorithm_t zip_algorithm_bzip2_compress = {
+    maximum_compressed_size,
     compress_allocate,
     deallocate,
     general_purpose_bit_flags,
@@ -258,6 +270,7 @@ zip_compression_algorithm_t zip_algorithm_bzip2_compress = {
 
 
 zip_compression_algorithm_t zip_algorithm_bzip2_decompress = {
+    maximum_compressed_size,
     decompress_allocate,
     deallocate,
     general_purpose_bit_flags,
index d28a1ac..8707eec 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_algorithm_deflate.c -- deflate (de)compression routines
-  Copyright (C) 2017-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -46,20 +46,33 @@ struct ctx {
 };
 
 
+static zip_uint64_t
+maximum_compressed_size(zip_uint64_t uncompressed_size) {
+    /* max deflate size increase: size + ceil(size/16k)*5+6 */
+
+    zip_uint64_t compressed_size = uncompressed_size + (uncompressed_size + 16383) / 16384 * 5 + 6;
+
+    if (compressed_size < uncompressed_size) {
+        return ZIP_UINT64_MAX;
+    }
+    return compressed_size;
+}
+
+
 static void *
 allocate(bool compress, int compression_flags, zip_error_t *error) {
     struct ctx *ctx;
 
     if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) {
-       zip_error_set(error, ZIP_ET_SYS, errno);
-       return NULL;
+        zip_error_set(error, ZIP_ET_SYS, errno);
+        return NULL;
     }
 
     ctx->error = error;
     ctx->compress = compress;
     ctx->compression_flags = compression_flags;
     if (ctx->compression_flags < 1 || ctx->compression_flags > 9) {
-       ctx->compression_flags = Z_BEST_COMPRESSION;
+        ctx->compression_flags = Z_BEST_COMPRESSION;
     }
     ctx->end_of_input = false;
 
@@ -96,21 +109,21 @@ general_purpose_bit_flags(void *ud) {
     struct ctx *ctx = (struct ctx *)ud;
 
     if (!ctx->compress) {
-       return 0;
+        return 0;
     }
 
     if (ctx->compression_flags < 3) {
-       return 2 << 1;
+        return 2 << 1;
     }
     else if (ctx->compression_flags > 7) {
-       return 1 << 1;
+        return 1 << 1;
     }
     return 0;
 }
 
 
 static bool
-start(void *ud) {
+start(void *ud, zip_stat_t *st, zip_file_attributes_t *attributes) {
     struct ctx *ctx = (struct ctx *)ud;
     int ret;
 
@@ -120,16 +133,16 @@ start(void *ud) {
     ctx->zstr.next_out = NULL;
 
     if (ctx->compress) {
-       /* negative value to tell zlib not to write a header */
-       ret = deflateInit2(&ctx->zstr, ctx->compression_flags, Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
+        /* negative value to tell zlib not to write a header */
+        ret = deflateInit2(&ctx->zstr, ctx->compression_flags, Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
     }
     else {
-       ret = inflateInit2(&ctx->zstr, -MAX_WBITS);
+        ret = inflateInit2(&ctx->zstr, -MAX_WBITS);
     }
 
     if (ret != Z_OK) {
-       zip_error_set(ctx->error, ZIP_ER_ZLIB, ret);
-       return false;
+        zip_error_set(ctx->error, ZIP_ER_ZLIB, ret);
+        return false;
     }
 
 
@@ -143,15 +156,15 @@ end(void *ud) {
     int err;
 
     if (ctx->compress) {
-       err = deflateEnd(&ctx->zstr);
+        err = deflateEnd(&ctx->zstr);
     }
     else {
-       err = inflateEnd(&ctx->zstr);
+        err = inflateEnd(&ctx->zstr);
     }
 
     if (err != Z_OK) {
-       zip_error_set(ctx->error, ZIP_ER_ZLIB, err);
-       return false;
+        zip_error_set(ctx->error, ZIP_ER_ZLIB, err);
+        return false;
     }
 
     return true;
@@ -163,8 +176,8 @@ input(void *ud, zip_uint8_t *data, zip_uint64_t length) {
     struct ctx *ctx = (struct ctx *)ud;
 
     if (length > UINT_MAX || ctx->zstr.avail_in > 0) {
-       zip_error_set(ctx->error, ZIP_ER_INVAL, 0);
-       return false;
+        zip_error_set(ctx->error, ZIP_ER_INVAL, 0);
+        return false;
     }
 
     ctx->zstr.avail_in = (uInt)length;
@@ -192,37 +205,38 @@ process(void *ud, zip_uint8_t *data, zip_uint64_t *length) {
     ctx->zstr.next_out = (Bytef *)data;
 
     if (ctx->compress) {
-       ret = deflate(&ctx->zstr, ctx->end_of_input ? Z_FINISH : 0);
+        ret = deflate(&ctx->zstr, ctx->end_of_input ? Z_FINISH : 0);
     }
     else {
-       ret = inflate(&ctx->zstr, Z_SYNC_FLUSH);
+        ret = inflate(&ctx->zstr, Z_SYNC_FLUSH);
     }
 
     *length = *length - ctx->zstr.avail_out;
 
     switch (ret) {
     case Z_OK:
-       return ZIP_COMPRESSION_OK;
+        return ZIP_COMPRESSION_OK;
 
     case Z_STREAM_END:
-       return ZIP_COMPRESSION_END;
+        return ZIP_COMPRESSION_END;
 
     case Z_BUF_ERROR:
-       if (ctx->zstr.avail_in == 0) {
-           return ZIP_COMPRESSION_NEED_DATA;
-       }
+        if (ctx->zstr.avail_in == 0) {
+            return ZIP_COMPRESSION_NEED_DATA;
+        }
 
-       /* fallthrough */
+        /* fallthrough */
 
     default:
-       zip_error_set(ctx->error, ZIP_ER_ZLIB, ret);
-       return ZIP_COMPRESSION_ERROR;
+        zip_error_set(ctx->error, ZIP_ER_ZLIB, ret);
+        return ZIP_COMPRESSION_ERROR;
     }
 }
 
 /* clang-format off */
 
 zip_compression_algorithm_t zip_algorithm_deflate_compress = {
+    maximum_compressed_size,
     compress_allocate,
     deallocate,
     general_purpose_bit_flags,
@@ -236,6 +250,7 @@ zip_compression_algorithm_t zip_algorithm_deflate_compress = {
 
 
 zip_compression_algorithm_t zip_algorithm_deflate_decompress = {
+    maximum_compressed_size,
     decompress_allocate,
     deallocate,
     general_purpose_bit_flags,
index 945ab4e..f0c2fd3 100644 (file)
@@ -1,7 +1,7 @@
 /*
-  zip_algorithm_xz.c      -- XZ (de)compression routines
+  zip_algorithm_xz.c -- LZMA/XZ (de)compression routines
   Bazed on zip_algorithm_deflate.c -- deflate (de)compression routines
-  Copyright (C) 2017-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 #include <stdlib.h>
 #include <zlib.h>
 
+enum header_state { INCOMPLETE, OUTPUT, DONE };
+
+#define HEADER_BYTES_ZIP 9
+#define HEADER_MAGIC_LENGTH 4
+#define HEADER_MAGIC1_OFFSET 0
+#define HEADER_MAGIC2_OFFSET 2
+#define HEADER_SIZE_OFFSET 9
+#define HEADER_SIZE_LENGTH 8
+#define HEADER_PARAMETERS_LENGTH 5
+#define HEADER_LZMA_ALONE_LENGTH (HEADER_PARAMETERS_LENGTH + HEADER_SIZE_LENGTH)
+
 struct ctx {
     zip_error_t *error;
     bool compress;
@@ -46,28 +57,78 @@ struct ctx {
     bool end_of_input;
     lzma_stream zstr;
     zip_uint16_t method;
+    /* header member is used for converting from zip to "lzma alone"
+     * format
+     *
+     * "lzma alone" file format starts with:
+     * 5 bytes lzma parameters
+     * 8 bytes uncompressed size
+     * compressed data
+     *
+     * zip archive on-disk format starts with
+     * 4 bytes magic (first two bytes vary, e.g. 0x0914 or 0x1002, next bytes are 0x0500)
+     * 5 bytes lzma parameters
+     * compressed data
+     *
+     * we read the data into a header of the form
+     * 4 bytes magic
+     * 5 bytes lzma parameters
+     * 8 bytes uncompressed size
+     */
+    zip_uint8_t header[HEADER_MAGIC_LENGTH + HEADER_LZMA_ALONE_LENGTH];
+    zip_uint8_t header_bytes_offset;
+    enum header_state header_state;
+    zip_uint64_t uncompresssed_size;
 };
 
 
+static zip_uint64_t
+maximum_compressed_size(zip_uint64_t uncompressed_size) {
+    /*
+     According to https://sourceforge.net/p/sevenzip/discussion/45797/thread/b6bd62f8/
+
+     1) you can use
+     outSize = 1.10 * originalSize + 64 KB.
+     in most cases outSize is less then 1.02 from originalSize.
+     2) You can try LZMA2, where
+     outSize can be = 1.001 * originalSize + 1 KB.
+     */
+    /* 13 bytes added for lzma alone header */
+    zip_uint64_t compressed_size = (zip_uint64_t)((double)uncompressed_size * 1.1) + 64 * 1024 + 13;
+
+    if (compressed_size < uncompressed_size) {
+        return ZIP_UINT64_MAX;
+    }
+    return compressed_size;
+}
+
+
 static void *
 allocate(bool compress, int compression_flags, zip_error_t *error, zip_uint16_t method) {
     struct ctx *ctx;
 
-    if (compression_flags < 0) {
-       zip_error_set(error, ZIP_ER_INVAL, 0);
-       return NULL;
-    }
-
     if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     ctx->error = error;
     ctx->compress = compress;
-    ctx->compression_flags = (zip_uint32_t)compression_flags;
+    if (compression_flags < 0 || compression_flags > 9) {
+        ctx->compression_flags = 6; /* default value */
+    } else {
+       ctx->compression_flags = (zip_uint32_t)compression_flags;
+    }
     ctx->compression_flags |= LZMA_PRESET_EXTREME;
     ctx->end_of_input = false;
+    memset(ctx->header, 0, sizeof(ctx->header));
+    ctx->header_bytes_offset = 0;
+    if (ZIP_CM_LZMA) {
+        ctx->header_state = INCOMPLETE;
+    }
+    else {
+        ctx->header_state = DONE;
+    }
     memset(&ctx->zstr, 0, sizeof(ctx->zstr));
     ctx->method = method;
     return ctx;
@@ -95,38 +156,49 @@ deallocate(void *ud) {
 
 static zip_uint16_t
 general_purpose_bit_flags(void *ud) {
-    /* struct ctx *ctx = (struct ctx *)ud; */
+    struct ctx *ctx = (struct ctx *)ud;
+
+    if (!ctx->compress) {
+        return 0;
+    }
+
+    if (ctx->method == ZIP_CM_LZMA) {
+        /* liblzma always returns an EOS/EOPM marker, see
+        * https://sourceforge.net/p/lzmautils/discussion/708858/thread/84c5dbb9/#a5e4/3764 */
+       return 1 << 1;
+    }
     return 0;
 }
 
 static int
 map_error(lzma_ret ret) {
     switch (ret) {
+    case LZMA_DATA_ERROR:
     case LZMA_UNSUPPORTED_CHECK:
-       return ZIP_ER_COMPRESSED_DATA;
+        return ZIP_ER_COMPRESSED_DATA;
 
     case LZMA_MEM_ERROR:
-       return ZIP_ER_MEMORY;
+        return ZIP_ER_MEMORY;
 
     case LZMA_OPTIONS_ERROR:
-       return ZIP_ER_INVAL;
+        return ZIP_ER_INVAL;
 
     default:
-       return ZIP_ER_INTERNAL;
+        return ZIP_ER_INTERNAL;
     }
 }
 
 
 static bool
-start(void *ud) {
+start(void *ud, zip_stat_t *st, zip_file_attributes_t *attributes) {
     struct ctx *ctx = (struct ctx *)ud;
     lzma_ret ret;
 
     lzma_options_lzma opt_lzma;
     lzma_lzma_preset(&opt_lzma, ctx->compression_flags);
     lzma_filter filters[] = {
-       {.id = (ctx->method == ZIP_CM_LZMA ? LZMA_FILTER_LZMA1 : LZMA_FILTER_LZMA2), .options = &opt_lzma},
-       {.id = LZMA_VLI_UNKNOWN, .options = NULL},
+        {.id = (ctx->method == ZIP_CM_LZMA ? LZMA_FILTER_LZMA1 : LZMA_FILTER_LZMA2), .options = &opt_lzma},
+        {.id = LZMA_VLI_UNKNOWN, .options = NULL},
     };
 
     ctx->zstr.avail_in = 0;
@@ -135,21 +207,29 @@ start(void *ud) {
     ctx->zstr.next_out = NULL;
 
     if (ctx->compress) {
-       if (ctx->method == ZIP_CM_LZMA)
-           ret = lzma_alone_encoder(&ctx->zstr, filters[0].options);
-       else
-           ret = lzma_stream_encoder(&ctx->zstr, filters, LZMA_CHECK_CRC64);
+        if (ctx->method == ZIP_CM_LZMA)
+            ret = lzma_alone_encoder(&ctx->zstr, filters[0].options);
+        else
+            ret = lzma_stream_encoder(&ctx->zstr, filters, LZMA_CHECK_CRC64);
     }
     else {
-       if (ctx->method == ZIP_CM_LZMA)
-           ret = lzma_alone_decoder(&ctx->zstr, UINT64_MAX);
-       else
-           ret = lzma_stream_decoder(&ctx->zstr, UINT64_MAX, LZMA_CONCATENATED);
+        if (ctx->method == ZIP_CM_LZMA)
+            ret = lzma_alone_decoder(&ctx->zstr, UINT64_MAX);
+        else
+            ret = lzma_stream_decoder(&ctx->zstr, UINT64_MAX, LZMA_CONCATENATED);
     }
 
     if (ret != LZMA_OK) {
-       zip_error_set(ctx->error, map_error(ret), 0);
-       return false;
+        zip_error_set(ctx->error, map_error(ret), 0);
+        return false;
+    }
+
+    /* If general purpose bits 1 & 2 are both zero, write real uncompressed size in header. */
+    if ((attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) && (attributes->general_purpose_bit_mask & 0x6) == 0x6 && (attributes->general_purpose_bit_flags & 0x06) == 0 && (st->valid & ZIP_STAT_SIZE)) {
+        ctx->uncompresssed_size = st->size;
+    }
+    else {
+        ctx->uncompresssed_size = ZIP_UINT64_MAX;
     }
 
     return true;
@@ -170,10 +250,51 @@ input(void *ud, zip_uint8_t *data, zip_uint64_t length) {
     struct ctx *ctx = (struct ctx *)ud;
 
     if (length > UINT_MAX || ctx->zstr.avail_in > 0) {
-       zip_error_set(ctx->error, ZIP_ER_INVAL, 0);
-       return false;
+        zip_error_set(ctx->error, ZIP_ER_INVAL, 0);
+        return false;
     }
 
+    /* For decompression of LZMA1: Have we read the full "lzma alone" header yet? */
+    if (ctx->method == ZIP_CM_LZMA && !ctx->compress && ctx->header_state == INCOMPLETE) {
+        /* if not, get more of the data */
+        zip_uint8_t got = (zip_uint8_t)ZIP_MIN(HEADER_BYTES_ZIP - ctx->header_bytes_offset, length);
+        memcpy(ctx->header + ctx->header_bytes_offset, data, got);
+        ctx->header_bytes_offset += got;
+        length -= got;
+        data += got;
+        /* Do we have a complete header now? */
+        if (ctx->header_bytes_offset == HEADER_BYTES_ZIP) {
+            Bytef empty_buffer[1];
+            zip_buffer_t *buffer;
+            /* check magic */
+            if (ctx->header[HEADER_MAGIC2_OFFSET] != 0x05 || ctx->header[HEADER_MAGIC2_OFFSET + 1] != 0x00) {
+                /* magic does not match */
+                zip_error_set(ctx->error, ZIP_ER_COMPRESSED_DATA, 0);
+                return false;
+            }
+            /* set size of uncompressed data in "lzma alone" header to "unknown" */
+            if ((buffer = _zip_buffer_new(ctx->header + HEADER_SIZE_OFFSET, HEADER_SIZE_LENGTH)) == NULL) {
+                zip_error_set(ctx->error, ZIP_ER_MEMORY, 0);
+                return false;
+            }
+            _zip_buffer_put_64(buffer, ctx->uncompresssed_size);
+            _zip_buffer_free(buffer);
+            /* Feed header into "lzma alone" decoder, for
+             * initialization; this should not produce output. */
+            ctx->zstr.next_in = (void *)(ctx->header + HEADER_MAGIC_LENGTH);
+            ctx->zstr.avail_in = HEADER_LZMA_ALONE_LENGTH;
+            ctx->zstr.total_in = 0;
+            ctx->zstr.next_out = empty_buffer;
+            ctx->zstr.avail_out = sizeof(*empty_buffer);
+            ctx->zstr.total_out = 0;
+            /* this just initializes the decoder and does not produce output, so it consumes the complete header */
+            if (lzma_code(&ctx->zstr, LZMA_RUN) != LZMA_OK || ctx->zstr.total_out > 0) {
+                zip_error_set(ctx->error, ZIP_ER_COMPRESSED_DATA, 0);
+                return false;
+            }
+            ctx->header_state = DONE;
+        }
+    }
     ctx->zstr.avail_in = (uInt)length;
     ctx->zstr.next_in = (Bytef *)data;
 
@@ -193,6 +314,36 @@ static zip_compression_status_t
 process(void *ud, zip_uint8_t *data, zip_uint64_t *length) {
     struct ctx *ctx = (struct ctx *)ud;
     lzma_ret ret;
+    /* for compression of LZMA1 */
+    if (ctx->method == ZIP_CM_LZMA && ctx->compress) {
+        if (ctx->header_state == INCOMPLETE) {
+            /* write magic to output buffer */
+            ctx->header[0] = 0x09;
+            ctx->header[1] = 0x14;
+            ctx->header[2] = 0x05;
+            ctx->header[3] = 0x00;
+            /* generate lzma parameters into output buffer */
+            ctx->zstr.avail_out = HEADER_LZMA_ALONE_LENGTH;
+            ctx->zstr.next_out = ctx->header + HEADER_MAGIC_LENGTH;
+            ret = lzma_code(&ctx->zstr, LZMA_RUN);
+            if (ret != LZMA_OK || ctx->zstr.avail_out != 0) {
+                /* assume that the whole header will be provided with the first call to lzma_code */
+                return ZIP_COMPRESSION_ERROR;
+            }
+            ctx->header_state = OUTPUT;
+        }
+        if (ctx->header_state == OUTPUT) {
+            /* write header */
+            zip_uint8_t write_len = (zip_uint8_t)ZIP_MIN(HEADER_BYTES_ZIP - ctx->header_bytes_offset, *length);
+            memcpy(data, ctx->header + ctx->header_bytes_offset, write_len);
+            ctx->header_bytes_offset += write_len;
+            *length = write_len;
+            if (ctx->header_bytes_offset == HEADER_BYTES_ZIP) {
+                ctx->header_state = DONE;
+            }
+            return ZIP_COMPRESSION_OK;
+        }
+    }
 
     ctx->zstr.avail_out = (uInt)ZIP_MIN(UINT_MAX, *length);
     ctx->zstr.next_out = (Bytef *)data;
@@ -202,30 +353,35 @@ process(void *ud, zip_uint8_t *data, zip_uint64_t *length) {
 
     switch (ret) {
     case LZMA_OK:
-       return ZIP_COMPRESSION_OK;
+        return ZIP_COMPRESSION_OK;
 
     case LZMA_STREAM_END:
-       return ZIP_COMPRESSION_END;
+        return ZIP_COMPRESSION_END;
 
     case LZMA_BUF_ERROR:
-       if (ctx->zstr.avail_in == 0) {
-           return ZIP_COMPRESSION_NEED_DATA;
-       }
+        if (ctx->zstr.avail_in == 0) {
+            return ZIP_COMPRESSION_NEED_DATA;
+        }
 
-       /* fallthrough */
+        /* fallthrough */
     default:
-       zip_error_set(ctx->error, map_error(ret), 0);
-       return ZIP_COMPRESSION_ERROR;
+        zip_error_set(ctx->error, map_error(ret), 0);
+        return ZIP_COMPRESSION_ERROR;
     }
 }
 
+/* Version Required should be set to 63 (6.3) because this compression
+   method was only defined in appnote.txt version 6.3.8, but Winzip
+   does not unpack it if the value is not 20. */
+
 /* clang-format off */
 
 zip_compression_algorithm_t zip_algorithm_xz_compress = {
+    maximum_compressed_size,
     compress_allocate,
     deallocate,
     general_purpose_bit_flags,
-    63,
+    20,
     start,
     end,
     input,
@@ -235,10 +391,11 @@ zip_compression_algorithm_t zip_algorithm_xz_compress = {
 
 
 zip_compression_algorithm_t zip_algorithm_xz_decompress = {
+    maximum_compressed_size,
     decompress_allocate,
     deallocate,
     general_purpose_bit_flags,
-    63,
+    20,
     start,
     end,
     input,
diff --git a/lib/zip_algorithm_zstd.c b/lib/zip_algorithm_zstd.c
new file mode 100644 (file)
index 0000000..a7e2d67
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+  zip_algorithm_zstd.c -- zstd (de)compression routines
+  Copyright (C) 2020-2021 Dieter Baron and Thomas Klausner
+
+  This file is part of libzip, a library to manipulate ZIP archives.
+  The authors can be contacted at <libzip@nih.at>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+  3. The names of the authors may not be used to endorse or promote
+     products derived from this software without specific prior
+     written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "zipint.h"
+
+#include <limits.h>
+#include <stdlib.h>
+#include <zstd.h>
+#include <zstd_errors.h>
+
+struct ctx {
+    zip_error_t *error;
+    bool compress;
+    int compression_flags;
+    bool end_of_input;
+    ZSTD_DStream *zdstream;
+    ZSTD_CStream *zcstream;
+    ZSTD_outBuffer out;
+    ZSTD_inBuffer in;
+};
+
+static zip_uint64_t
+maximum_compressed_size(zip_uint64_t uncompressed_size) {
+    return ZSTD_compressBound(uncompressed_size);
+}
+
+
+static void *
+allocate(bool compress, int compression_flags, zip_error_t *error) {
+    struct ctx *ctx;
+
+    /* 0: let zstd choose */
+    if (compression_flags < ZSTD_minCLevel() || compression_flags > ZSTD_maxCLevel()) {
+        compression_flags = 0;
+    }
+
+    if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) {
+        return NULL;
+    }
+
+    ctx->error = error;
+    ctx->compress = compress;
+    ctx->compression_flags = compression_flags;
+    ctx->end_of_input = false;
+
+    ctx->zdstream = NULL;
+    ctx->zcstream = NULL;
+    ctx->in.src = NULL;
+    ctx->in.pos = 0;
+    ctx->in.size = 0;
+    ctx->out.dst = NULL;
+    ctx->out.pos = 0;
+    ctx->out.size = 0;
+
+    return ctx;
+}
+
+
+static void *
+compress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
+    return allocate(true, compression_flags, error);
+}
+
+
+static void *
+decompress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
+    return allocate(false, compression_flags, error);
+}
+
+
+static void
+deallocate(void *ud) {
+    struct ctx *ctx = (struct ctx *)ud;
+    free(ctx);
+}
+
+
+static zip_uint16_t
+general_purpose_bit_flags(void *ud) {
+    /* struct ctx *ctx = (struct ctx *)ud; */
+    return 0;
+}
+
+static int
+map_error(size_t ret) {
+    switch (ret) {
+    case ZSTD_error_no_error:
+        return ZIP_ER_OK;
+
+    case ZSTD_error_corruption_detected:
+    case ZSTD_error_checksum_wrong:
+    case ZSTD_error_dictionary_corrupted:
+    case ZSTD_error_dictionary_wrong:
+        return ZIP_ER_COMPRESSED_DATA;
+
+    case ZSTD_error_memory_allocation:
+        return ZIP_ER_MEMORY;
+
+    case ZSTD_error_parameter_unsupported:
+    case ZSTD_error_parameter_outOfBound:
+        return ZIP_ER_INVAL;
+
+    default:
+        return ZIP_ER_INTERNAL;
+    }
+}
+
+
+static bool
+start(void *ud, zip_stat_t *st, zip_file_attributes_t *attributes) {
+    struct ctx *ctx = (struct ctx *)ud;
+    ctx->in.src = NULL;
+    ctx->in.pos = 0;
+    ctx->in.size = 0;
+    ctx->out.dst = NULL;
+    ctx->out.pos = 0;
+    ctx->out.size = 0;
+    if (ctx->compress) {
+        size_t ret;
+        ctx->zcstream = ZSTD_createCStream();
+        if (ctx->zcstream == NULL) {
+            zip_error_set(ctx->error, ZIP_ER_MEMORY, 0);
+            return false;
+        }
+        ret = ZSTD_initCStream(ctx->zcstream, ctx->compression_flags);
+        if (ZSTD_isError(ret)) {
+            zip_error_set(ctx->error, ZIP_ER_ZLIB, map_error(ret));
+            return false;
+        }
+    }
+    else {
+        ctx->zdstream = ZSTD_createDStream();
+        if (ctx->zdstream == NULL) {
+            zip_error_set(ctx->error, ZIP_ER_MEMORY, 0);
+            return false;
+        }
+    }
+
+    return true;
+}
+
+
+static bool
+end(void *ud) {
+    struct ctx *ctx = (struct ctx *)ud;
+    size_t ret;
+
+    if (ctx->compress) {
+        ret = ZSTD_freeCStream(ctx->zcstream);
+        ctx->zcstream = NULL;
+    }
+    else {
+        ret = ZSTD_freeDStream(ctx->zdstream);
+        ctx->zdstream = NULL;
+    }
+
+    if (ZSTD_isError(ret)) {
+        zip_error_set(ctx->error, map_error(ret), 0);
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool
+input(void *ud, zip_uint8_t *data, zip_uint64_t length) {
+    struct ctx *ctx = (struct ctx *)ud;
+    if (length > SIZE_MAX || ctx->in.pos != ctx->in.size) {
+        zip_error_set(ctx->error, ZIP_ER_INVAL, 0);
+        return false;
+    }
+    ctx->in.src = (const void *)data;
+    ctx->in.size = (size_t)length;
+    ctx->in.pos = 0;
+    return true;
+}
+
+
+static void
+end_of_input(void *ud) {
+    struct ctx *ctx = (struct ctx *)ud;
+
+    ctx->end_of_input = true;
+}
+
+
+static zip_compression_status_t
+process(void *ud, zip_uint8_t *data, zip_uint64_t *length) {
+    struct ctx *ctx = (struct ctx *)ud;
+
+    size_t ret;
+
+    if (ctx->in.pos == ctx->in.size && !ctx->end_of_input) {
+        *length = 0;
+        return ZIP_COMPRESSION_NEED_DATA;
+    }
+
+    ctx->out.dst = data;
+    ctx->out.pos = 0;
+    ctx->out.size = ZIP_MIN(SIZE_MAX, *length);
+
+    if (ctx->compress) {
+        if (ctx->in.pos == ctx->in.size && ctx->end_of_input) {
+            ret = ZSTD_endStream(ctx->zcstream, &ctx->out);
+            if (ret == 0) {
+                *length = ctx->out.pos;
+                return ZIP_COMPRESSION_END;
+            }
+        }
+        else {
+            ret = ZSTD_compressStream(ctx->zcstream, &ctx->out, &ctx->in);
+        }
+    }
+    else {
+        ret = ZSTD_decompressStream(ctx->zdstream, &ctx->out, &ctx->in);
+    }
+    if (ZSTD_isError(ret)) {
+        zip_error_set(ctx->error, map_error(ret), 0);
+        return ZIP_COMPRESSION_ERROR;
+    }
+
+    *length = ctx->out.pos;
+    if (ctx->in.pos == ctx->in.size) {
+        return ZIP_COMPRESSION_NEED_DATA;
+    }
+
+    return ZIP_COMPRESSION_OK;
+}
+
+/* Version Required should be set to 63 (6.3) because this compression
+   method was only defined in appnote.txt version 6.3.7, but Winzip
+   does not unpack it if the value is not 20. */
+
+/* clang-format off */
+
+zip_compression_algorithm_t zip_algorithm_zstd_compress = {
+    maximum_compressed_size,
+    compress_allocate,
+    deallocate,
+    general_purpose_bit_flags,
+    20,
+    start,
+    end,
+    input,
+    end_of_input,
+    process
+};
+
+
+zip_compression_algorithm_t zip_algorithm_zstd_decompress = {
+    maximum_compressed_size,
+    decompress_allocate,
+    deallocate,
+    general_purpose_bit_flags,
+    20,
+    start,
+    end,
+    input,
+    end_of_input,
+    process
+};
+
+/* clang-format on */
index 8c24b27..4e5783e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  zip_buffer.c -- bounds checked access to memory buffer
- Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
+ Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
 
  This file is part of libzip, a library to manipulate ZIP archives.
  The authors can be contacted at <libzip@nih.at>
@@ -45,11 +45,11 @@ _zip_buffer_data(zip_buffer_t *buffer) {
 void
 _zip_buffer_free(zip_buffer_t *buffer) {
     if (buffer == NULL) {
-       return;
+        return;
     }
 
     if (buffer->free_data) {
-       free(buffer->data);
+        free(buffer->data);
     }
 
     free(buffer);
@@ -69,7 +69,7 @@ _zip_buffer_get(zip_buffer_t *buffer, zip_uint64_t length) {
     data = _zip_buffer_peek(buffer, length);
 
     if (data != NULL) {
-       buffer->offset += length;
+        buffer->offset += length;
     }
 
     return data;
@@ -81,7 +81,7 @@ _zip_buffer_get_16(zip_buffer_t *buffer) {
     zip_uint8_t *data = _zip_buffer_get(buffer, 2);
 
     if (data == NULL) {
-       return 0;
+        return 0;
     }
 
     return (zip_uint16_t)(data[0] + (data[1] << 8));
@@ -93,7 +93,7 @@ _zip_buffer_get_32(zip_buffer_t *buffer) {
     zip_uint8_t *data = _zip_buffer_get(buffer, 4);
 
     if (data == NULL) {
-       return 0;
+        return 0;
     }
 
     return ((((((zip_uint32_t)data[3] << 8) + data[2]) << 8) + data[1]) << 8) + data[0];
@@ -105,7 +105,7 @@ _zip_buffer_get_64(zip_buffer_t *buffer) {
     zip_uint8_t *data = _zip_buffer_get(buffer, 8);
 
     if (data == NULL) {
-       return 0;
+        return 0;
     }
 
     return ((zip_uint64_t)data[7] << 56) + ((zip_uint64_t)data[6] << 48) + ((zip_uint64_t)data[5] << 40) + ((zip_uint64_t)data[4] << 32) + ((zip_uint64_t)data[3] << 24) + ((zip_uint64_t)data[2] << 16) + ((zip_uint64_t)data[1] << 8) + (zip_uint64_t)data[0];
@@ -117,7 +117,7 @@ _zip_buffer_get_8(zip_buffer_t *buffer) {
     zip_uint8_t *data = _zip_buffer_get(buffer, 1);
 
     if (data == NULL) {
-       return 0;
+        return 0;
     }
 
     return data[0];
@@ -133,7 +133,7 @@ _zip_buffer_left(zip_buffer_t *buffer) {
 zip_uint64_t
 _zip_buffer_read(zip_buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length) {
     if (_zip_buffer_left(buffer) < length) {
-       length = _zip_buffer_left(buffer);
+        length = _zip_buffer_left(buffer);
     }
 
     memcpy(data, _zip_buffer_get(buffer, length), length);
@@ -148,16 +148,16 @@ _zip_buffer_new(zip_uint8_t *data, zip_uint64_t size) {
     zip_buffer_t *buffer;
 
     if (data == NULL) {
-       if ((data = (zip_uint8_t *)malloc(size)) == NULL) {
-           return NULL;
-       }
+        if ((data = (zip_uint8_t *)malloc(size)) == NULL) {
+            return NULL;
+        }
     }
 
     if ((buffer = (zip_buffer_t *)malloc(sizeof(*buffer))) == NULL) {
-       if (free_data) {
-           free(data);
-       }
-       return NULL;
+        if (free_data) {
+            free(data);
+        }
+        return NULL;
     }
 
     buffer->ok = true;
@@ -175,13 +175,13 @@ _zip_buffer_new_from_source(zip_source_t *src, zip_uint64_t size, zip_uint8_t *b
     zip_buffer_t *buffer;
 
     if ((buffer = _zip_buffer_new(buf, size)) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     if (_zip_read(src, buffer->data, size, error) < 0) {
-       _zip_buffer_free(buffer);
-       return NULL;
+        _zip_buffer_free(buffer);
+        return NULL;
     }
 
     return buffer;
@@ -205,8 +205,8 @@ _zip_buffer_peek(zip_buffer_t *buffer, zip_uint64_t length) {
     zip_uint8_t *data;
 
     if (!buffer->ok || buffer->offset + length < length || buffer->offset + length > buffer->size) {
-       buffer->ok = false;
-       return NULL;
+        buffer->ok = false;
+        return NULL;
     }
 
     data = buffer->data + buffer->offset;
@@ -218,7 +218,7 @@ _zip_buffer_put(zip_buffer_t *buffer, const void *src, size_t length) {
     zip_uint8_t *dst = _zip_buffer_get(buffer, length);
 
     if (dst == NULL) {
-       return -1;
+        return -1;
     }
 
     memcpy(dst, src, length);
@@ -231,7 +231,7 @@ _zip_buffer_put_16(zip_buffer_t *buffer, zip_uint16_t i) {
     zip_uint8_t *data = _zip_buffer_get(buffer, 2);
 
     if (data == NULL) {
-       return -1;
+        return -1;
     }
 
     data[0] = (zip_uint8_t)(i & 0xff);
@@ -246,7 +246,7 @@ _zip_buffer_put_32(zip_buffer_t *buffer, zip_uint32_t i) {
     zip_uint8_t *data = _zip_buffer_get(buffer, 4);
 
     if (data == NULL) {
-       return -1;
+        return -1;
     }
 
     data[0] = (zip_uint8_t)(i & 0xff);
@@ -263,7 +263,7 @@ _zip_buffer_put_64(zip_buffer_t *buffer, zip_uint64_t i) {
     zip_uint8_t *data = _zip_buffer_get(buffer, 8);
 
     if (data == NULL) {
-       return -1;
+        return -1;
     }
 
     data[0] = (zip_uint8_t)(i & 0xff);
@@ -284,7 +284,7 @@ _zip_buffer_put_8(zip_buffer_t *buffer, zip_uint8_t i) {
     zip_uint8_t *data = _zip_buffer_get(buffer, 1);
 
     if (data == NULL) {
-       return -1;
+        return -1;
     }
 
     data[0] = i;
@@ -296,8 +296,8 @@ _zip_buffer_put_8(zip_buffer_t *buffer, zip_uint8_t i) {
 int
 _zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset) {
     if (offset > buffer->size) {
-       buffer->ok = false;
-       return -1;
+        buffer->ok = false;
+        return -1;
     }
 
     buffer->ok = true;
@@ -312,8 +312,8 @@ _zip_buffer_skip(zip_buffer_t *buffer, zip_uint64_t length) {
     zip_uint64_t offset = buffer->offset + length;
 
     if (offset < buffer->offset) {
-       buffer->ok = false;
-       return -1;
+        buffer->ok = false;
+        return -1;
     }
     return _zip_buffer_set_offset(buffer, offset);
 }
index 816fcef..a990c2f 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_close.c -- close zip archive and update changes
-  Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -57,225 +57,225 @@ zip_close(zip_t *za) {
     int changed;
 
     if (za == NULL)
-       return -1;
+        return -1;
 
     changed = _zip_changed(za, &survivors);
 
     /* don't create zip files with no entries */
     if (survivors == 0) {
-       if ((za->open_flags & ZIP_TRUNCATE) || changed) {
-           if (zip_source_remove(za->src) < 0) {
-               if (!((zip_error_code_zip(zip_source_error(za->src)) == ZIP_ER_REMOVE) && (zip_error_code_system(zip_source_error(za->src)) == ENOENT))) {
-                   _zip_error_set_from_source(&za->error, za->src);
-                   return -1;
-               }
-           }
-       }
-       zip_discard(za);
-       return 0;
+        if ((za->open_flags & ZIP_TRUNCATE) || changed) {
+            if (zip_source_remove(za->src) < 0) {
+                if (!((zip_error_code_zip(zip_source_error(za->src)) == ZIP_ER_REMOVE) && (zip_error_code_system(zip_source_error(za->src)) == ENOENT))) {
+                    _zip_error_set_from_source(&za->error, za->src);
+                    return -1;
+                }
+            }
+        }
+        zip_discard(za);
+        return 0;
     }
 
     if (!changed) {
-       zip_discard(za);
-       return 0;
+        zip_discard(za);
+        return 0;
     }
 
     if (survivors > za->nentry) {
-       zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+        return -1;
     }
 
     if ((filelist = (zip_filelist_t *)malloc(sizeof(filelist[0]) * (size_t)survivors)) == NULL)
-       return -1;
+        return -1;
 
     unchanged_offset = ZIP_UINT64_MAX;
     /* create list of files with index into original archive  */
     for (i = j = 0; i < za->nentry; i++) {
-       if (za->entry[i].orig != NULL && ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) {
-           unchanged_offset = ZIP_MIN(unchanged_offset, za->entry[i].orig->offset);
-       }
-       if (za->entry[i].deleted) {
-           continue;
-       }
-
-       if (j >= survivors) {
-           free(filelist);
-           zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
-           return -1;
-       }
-
-       filelist[j].idx = i;
-       j++;
+        if (za->entry[i].orig != NULL && ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) {
+            unchanged_offset = ZIP_MIN(unchanged_offset, za->entry[i].orig->offset);
+        }
+        if (za->entry[i].deleted) {
+            continue;
+        }
+
+        if (j >= survivors) {
+            free(filelist);
+            zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+            return -1;
+        }
+
+        filelist[j].idx = i;
+        j++;
     }
     if (j < survivors) {
-       free(filelist);
-       zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
-       return -1;
+        free(filelist);
+        zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+        return -1;
     }
 
     if ((zip_source_supports(za->src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING)) == 0) {
-       unchanged_offset = 0;
+        unchanged_offset = 0;
     }
     else {
-       if (unchanged_offset == ZIP_UINT64_MAX) {
-           /* we're keeping all file data, find the end of the last one */
-           zip_uint64_t last_index = ZIP_UINT64_MAX;
-           unchanged_offset = 0;
-
-           for (i = 0; i < za->nentry; i++) {
-               if (za->entry[i].orig != NULL) {
-                   if (za->entry[i].orig->offset >= unchanged_offset) {
-                       unchanged_offset = za->entry[i].orig->offset;
-                       last_index = i;
-                   }
-               }
-           }
-           if (last_index != ZIP_UINT64_MAX) {
-               if ((unchanged_offset = _zip_file_get_end(za, last_index, &za->error)) == 0) {
-                   free(filelist);
-                   return -1;
-               }
-           }
-       }
-       if (unchanged_offset > 0) {
-           if (zip_source_begin_write_cloning(za->src, unchanged_offset) < 0) {
-               /* cloning not supported, need to copy everything */
-               unchanged_offset = 0;
-           }
-       }
+        if (unchanged_offset == ZIP_UINT64_MAX) {
+            /* we're keeping all file data, find the end of the last one */
+            zip_uint64_t last_index = ZIP_UINT64_MAX;
+            unchanged_offset = 0;
+
+            for (i = 0; i < za->nentry; i++) {
+                if (za->entry[i].orig != NULL) {
+                    if (za->entry[i].orig->offset >= unchanged_offset) {
+                        unchanged_offset = za->entry[i].orig->offset;
+                        last_index = i;
+                    }
+                }
+            }
+            if (last_index != ZIP_UINT64_MAX) {
+                if ((unchanged_offset = _zip_file_get_end(za, last_index, &za->error)) == 0) {
+                    free(filelist);
+                    return -1;
+                }
+            }
+        }
+        if (unchanged_offset > 0) {
+            if (zip_source_begin_write_cloning(za->src, unchanged_offset) < 0) {
+                /* cloning not supported, need to copy everything */
+                unchanged_offset = 0;
+            }
+        }
     }
     if (unchanged_offset == 0) {
-       if (zip_source_begin_write(za->src) < 0) {
-           _zip_error_set_from_source(&za->error, za->src);
-           free(filelist);
-           return -1;
-       }
+        if (zip_source_begin_write(za->src) < 0) {
+            _zip_error_set_from_source(&za->error, za->src);
+            free(filelist);
+            return -1;
+        }
     }
 
     if (_zip_progress_start(za->progress) != 0) {
-       zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
-       zip_source_rollback_write(za->src);
-       free(filelist);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
+        zip_source_rollback_write(za->src);
+        free(filelist);
+        return -1;
     }
     error = 0;
     for (j = 0; j < survivors; j++) {
-       int new_data;
-       zip_entry_t *entry;
-       zip_dirent_t *de;
-
-       if (_zip_progress_subrange(za->progress, (double)j / (double)survivors, (double)(j + 1) / (double)survivors) != 0) {
-           zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
-           error = 1;
-           break;
-       }
-
-       i = filelist[j].idx;
-       entry = za->entry + i;
-
-       if (entry->orig != NULL && entry->orig->offset < unchanged_offset) {
-           /* already implicitly copied by cloning */
-           continue;
-       }
-
-       new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_ENCRYPTION_METHOD));
-
-       /* create new local directory entry */
-       if (entry->changes == NULL) {
-           if ((entry->changes = _zip_dirent_clone(entry->orig)) == NULL) {
-               zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-               error = 1;
-               break;
-           }
-       }
-       de = entry->changes;
-
-       if (_zip_read_local_ef(za, i) < 0) {
-           error = 1;
-           break;
-       }
-
-       if ((off = zip_source_tell_write(za->src)) < 0) {
+        int new_data;
+        zip_entry_t *entry;
+        zip_dirent_t *de;
+
+        if (_zip_progress_subrange(za->progress, (double)j / (double)survivors, (double)(j + 1) / (double)survivors) != 0) {
+            zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
+            error = 1;
+            break;
+        }
+
+        i = filelist[j].idx;
+        entry = za->entry + i;
+
+        if (entry->orig != NULL && entry->orig->offset < unchanged_offset) {
+            /* already implicitly copied by cloning */
+            continue;
+        }
+
+        new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_ENCRYPTION_METHOD));
+
+        /* create new local directory entry */
+        if (entry->changes == NULL) {
+            if ((entry->changes = _zip_dirent_clone(entry->orig)) == NULL) {
+                zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+                error = 1;
+                break;
+            }
+        }
+        de = entry->changes;
+
+        if (_zip_read_local_ef(za, i) < 0) {
+            error = 1;
+            break;
+        }
+
+        if ((off = zip_source_tell_write(za->src)) < 0) {
             _zip_error_set_from_source(&za->error, za->src);
-           error = 1;
-           break;
-       }
-       de->offset = (zip_uint64_t)off;
-
-       if (new_data) {
-           zip_source_t *zs;
-
-           zs = NULL;
-           if (!ZIP_ENTRY_DATA_CHANGED(entry)) {
-               if ((zs = _zip_source_zip_new(za, za, i, ZIP_FL_UNCHANGED, 0, 0, NULL)) == NULL) {
-                   error = 1;
-                   break;
-               }
-           }
-
-           /* add_data writes dirent */
-           if (add_data(za, zs ? zs : entry->source, de, entry->changes ? entry->changes->changed : 0) < 0) {
-               error = 1;
-               if (zs)
-                   zip_source_free(zs);
-               break;
-           }
-           if (zs)
-               zip_source_free(zs);
-       }
-       else {
-           zip_uint64_t offset;
-
-           if (de->encryption_method != ZIP_EM_TRAD_PKWARE) {
-               /* when copying data, all sizes are known -> no data descriptor needed */
-               /* except for PKWare encryption, where removing the data descriptor breaks password validation */
-               de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
-           }
-           if (_zip_dirent_write(za, de, ZIP_FL_LOCAL) < 0) {
-               error = 1;
-               break;
-           }
-           if ((offset = _zip_file_get_offset(za, i, &za->error)) == 0) {
-               error = 1;
-               break;
-           }
-           if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) {
-               _zip_error_set_from_source(&za->error, za->src);
+            error = 1;
+            break;
+        }
+        de->offset = (zip_uint64_t)off;
+
+        if (new_data) {
+            zip_source_t *zs;
+
+            zs = NULL;
+            if (!ZIP_ENTRY_DATA_CHANGED(entry)) {
+                if ((zs = _zip_source_zip_new(za, i, ZIP_FL_UNCHANGED, 0, 0, NULL, &za->error)) == NULL) {
+                    error = 1;
+                    break;
+                }
+            }
+
+            /* add_data writes dirent */
+            if (add_data(za, zs ? zs : entry->source, de, entry->changes ? entry->changes->changed : 0) < 0) {
+                error = 1;
+                if (zs)
+                    zip_source_free(zs);
+                break;
+            }
+            if (zs)
+                zip_source_free(zs);
+        }
+        else {
+            zip_uint64_t offset;
+
+            if (de->encryption_method != ZIP_EM_TRAD_PKWARE) {
+                /* when copying data, all sizes are known -> no data descriptor needed */
+                /* except for PKWare encryption, where removing the data descriptor breaks password validation */
+                de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
+            }
+            if (_zip_dirent_write(za, de, ZIP_FL_LOCAL) < 0) {
                 error = 1;
-               break;
-           }
-           if (copy_data(za, de->comp_size) < 0) {
-               error = 1;
-               break;
-           }
-
-           if (de->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
-               if (write_data_descriptor(za, de, _zip_dirent_needs_zip64(de, 0)) < 0) {
-                   error = 1;
-                   break;
-               }
-           }
-       }
+                break;
+            }
+            if ((offset = _zip_file_get_offset(za, i, &za->error)) == 0) {
+                error = 1;
+                break;
+            }
+            if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) {
+                _zip_error_set_from_source(&za->error, za->src);
+                error = 1;
+                break;
+            }
+            if (copy_data(za, de->comp_size) < 0) {
+                error = 1;
+                break;
+            }
+
+            if (de->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
+                if (write_data_descriptor(za, de, _zip_dirent_needs_zip64(de, 0)) < 0) {
+                    error = 1;
+                    break;
+                }
+            }
+        }
     }
 
     if (!error) {
-       if (write_cdir(za, filelist, survivors) < 0)
-           error = 1;
+        if (write_cdir(za, filelist, survivors) < 0)
+            error = 1;
     }
 
     free(filelist);
 
     if (!error) {
-       if (zip_source_commit_write(za->src) != 0) {
-           _zip_error_set_from_source(&za->error, za->src);
-           error = 1;
-       }
-       _zip_progress_end(za->progress);
+        if (zip_source_commit_write(za->src) != 0) {
+            _zip_error_set_from_source(&za->error, za->src);
+            error = 1;
+        }
+        _zip_progress_end(za->progress);
     }
 
     if (error) {
-       zip_source_rollback_write(za->src);
-       return -1;
+        zip_source_rollback_write(za->src);
+        return -1;
     }
 
     zip_discard(za);
@@ -296,86 +296,83 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
     bool needs_recompress, needs_decompress, needs_crc, needs_compress, needs_reencrypt, needs_decrypt, needs_encrypt;
 
     if (zip_source_stat(src, &st) < 0) {
-       _zip_error_set_from_source(&za->error, src);
-       return -1;
+        _zip_error_set_from_source(&za->error, src);
+        return -1;
     }
 
     if ((st.valid & ZIP_STAT_COMP_METHOD) == 0) {
-       st.valid |= ZIP_STAT_COMP_METHOD;
-       st.comp_method = ZIP_CM_STORE;
+        st.valid |= ZIP_STAT_COMP_METHOD;
+        st.comp_method = ZIP_CM_STORE;
     }
 
     if (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != ZIP_CM_STORE)
-       de->comp_method = st.comp_method;
+        de->comp_method = st.comp_method;
     else if (de->comp_method == ZIP_CM_STORE && (st.valid & ZIP_STAT_SIZE)) {
-       st.valid |= ZIP_STAT_COMP_SIZE;
-       st.comp_size = st.size;
+        st.valid |= ZIP_STAT_COMP_SIZE;
+        st.comp_size = st.size;
     }
     else {
-       /* we'll recompress */
-       st.valid &= ~ZIP_STAT_COMP_SIZE;
+        /* we'll recompress */
+        st.valid &= ~ZIP_STAT_COMP_SIZE;
     }
 
     if ((st.valid & ZIP_STAT_ENCRYPTION_METHOD) == 0) {
-       st.valid |= ZIP_STAT_ENCRYPTION_METHOD;
-       st.encryption_method = ZIP_EM_NONE;
+        st.valid |= ZIP_STAT_ENCRYPTION_METHOD;
+        st.encryption_method = ZIP_EM_NONE;
     }
 
     flags = ZIP_EF_LOCAL;
 
     if ((st.valid & ZIP_STAT_SIZE) == 0) {
-       flags |= ZIP_FL_FORCE_ZIP64;
-       data_length = -1;
+        flags |= ZIP_FL_FORCE_ZIP64;
+        data_length = -1;
     }
     else {
-       de->uncomp_size = st.size;
-       /* this is technically incorrect (copy_source counts compressed data), but it's the best we have */
-       data_length = (zip_int64_t)st.size;
-
-       if ((st.valid & ZIP_STAT_COMP_SIZE) == 0) {
-           zip_uint64_t max_size;
-
-           switch (ZIP_CM_ACTUAL(de->comp_method)) {
-           case ZIP_CM_BZIP2:
-               /* computed by looking at increase of 10 random files of size 1MB when
-                * compressed with bzip2, rounded up: 1.006 */
-               max_size = 4269351188u;
-               break;
-
-           case ZIP_CM_DEFLATE:
-               /* max deflate size increase: size + ceil(size/16k)*5+6 */
-               max_size = 4293656963u;
-               break;
-
-           case ZIP_CM_STORE:
-               max_size = 0xffffffffu;
-               break;
-
-           default:
-               max_size = 0;
-           }
-
-           if (st.size > max_size) {
-               flags |= ZIP_FL_FORCE_ZIP64;
-           }
-       }
-       else
-           de->comp_size = st.comp_size;
+        de->uncomp_size = st.size;
+        /* this is technically incorrect (copy_source counts compressed data), but it's the best we have */
+        data_length = (zip_int64_t)st.size;
+
+        if ((st.valid & ZIP_STAT_COMP_SIZE) == 0) {
+            zip_uint64_t max_compressed_size;
+            zip_uint16_t compression_method = ZIP_CM_ACTUAL(de->comp_method);
+
+            if (compression_method == ZIP_CM_STORE) {
+                max_compressed_size = st.size;
+            }
+            else {
+                zip_compression_algorithm_t *algorithm = _zip_get_compression_algorithm(compression_method, true);
+                if (algorithm == NULL) {
+                    max_compressed_size = ZIP_UINT64_MAX;
+                }
+                else {
+                    max_compressed_size = algorithm->maximum_compressed_size(st.size);
+                }
+            }
+
+            if (max_compressed_size > 0xffffffffu) {
+                flags |= ZIP_FL_FORCE_ZIP64;
+            }
+        }
+        else {
+            de->comp_size = st.comp_size;
+            data_length = (zip_int64_t)st.comp_size;
+        }
     }
 
     if ((offstart = zip_source_tell_write(za->src)) < 0) {
-       _zip_error_set_from_source(&za->error, za->src);
-       return -1;
+        _zip_error_set_from_source(&za->error, za->src);
+        return -1;
     }
 
     /* as long as we don't support non-seekable output, clear data descriptor bit */
     de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
     if ((is_zip64 = _zip_dirent_write(za, de, flags)) < 0) {
-       return -1;
+        return -1;
     }
 
     needs_recompress = st.comp_method != ZIP_CM_ACTUAL(de->comp_method);
     needs_decompress = needs_recompress && (st.comp_method != ZIP_CM_STORE);
+    /* in these cases we can compute the CRC ourselves, so we do */
     needs_crc = (st.comp_method == ZIP_CM_STORE) || needs_decompress;
     needs_compress = needs_recompress && (de->comp_method != ZIP_CM_STORE);
 
@@ -387,127 +384,127 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
     zip_source_keep(src_final);
 
     if (needs_decrypt) {
-       zip_encryption_implementation impl;
+        zip_encryption_implementation impl;
 
-       if ((impl = _zip_get_encryption_implementation(st.encryption_method, ZIP_CODEC_DECODE)) == NULL) {
-           zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
-           zip_source_free(src_final);
-           return -1;
-       }
-       if ((src_tmp = impl(za, src_final, st.encryption_method, ZIP_CODEC_DECODE, za->default_password)) == NULL) {
-           /* error set by impl */
-           zip_source_free(src_final);
-           return -1;
-       }
+        if ((impl = _zip_get_encryption_implementation(st.encryption_method, ZIP_CODEC_DECODE)) == NULL) {
+            zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
+            zip_source_free(src_final);
+            return -1;
+        }
+        if ((src_tmp = impl(za, src_final, st.encryption_method, ZIP_CODEC_DECODE, za->default_password)) == NULL) {
+            /* error set by impl */
+            zip_source_free(src_final);
+            return -1;
+        }
 
-       zip_source_free(src_final);
-       src_final = src_tmp;
+        zip_source_free(src_final);
+        src_final = src_tmp;
     }
 
     if (needs_decompress) {
-       if ((src_tmp = zip_source_decompress(za, src_final, st.comp_method)) == NULL) {
-           zip_source_free(src_final);
-           return -1;
-       }
+        if ((src_tmp = zip_source_decompress(za, src_final, st.comp_method)) == NULL) {
+            zip_source_free(src_final);
+            return -1;
+        }
 
-       zip_source_free(src_final);
-       src_final = src_tmp;
+        zip_source_free(src_final);
+        src_final = src_tmp;
     }
 
     if (needs_crc) {
-       if ((src_tmp = zip_source_crc(za, src_final, 0)) == NULL) {
-           zip_source_free(src_final);
-           return -1;
-       }
+        if ((src_tmp = zip_source_crc_create(src_final, 0, &za->error)) == NULL) {
+            zip_source_free(src_final);
+            return -1;
+        }
 
-       zip_source_free(src_final);
-       src_final = src_tmp;
+        zip_source_free(src_final);
+        src_final = src_tmp;
     }
 
     if (needs_compress) {
-       if ((src_tmp = zip_source_compress(za, src_final, de->comp_method, de->compression_level)) == NULL) {
-           zip_source_free(src_final);
-           return -1;
-       }
+        if ((src_tmp = zip_source_compress(za, src_final, de->comp_method, de->compression_level)) == NULL) {
+            zip_source_free(src_final);
+            return -1;
+        }
 
-       zip_source_free(src_final);
-       src_final = src_tmp;
+        zip_source_free(src_final);
+        src_final = src_tmp;
     }
 
 
     if (needs_encrypt) {
-       zip_encryption_implementation impl;
-       const char *password = NULL;
-
-       if (de->password) {
-           password = de->password;
-       }
-       else if (za->default_password) {
-           password = za->default_password;
-       }
-
-       if ((impl = _zip_get_encryption_implementation(de->encryption_method, ZIP_CODEC_ENCODE)) == NULL) {
-           zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
-           zip_source_free(src_final);
-           return -1;
-       }
-       if ((src_tmp = impl(za, src_final, de->encryption_method, ZIP_CODEC_ENCODE, password)) == NULL) {
-           /* error set by impl */
-           zip_source_free(src_final);
-           return -1;
-       }
-       if (de->encryption_method == ZIP_EM_TRAD_PKWARE) {
-           de->bitflags |= ZIP_GPBF_DATA_DESCRIPTOR;
-       }
-
-       zip_source_free(src_final);
-       src_final = src_tmp;
+        zip_encryption_implementation impl;
+        const char *password = NULL;
+
+        if (de->password) {
+            password = de->password;
+        }
+        else if (za->default_password) {
+            password = za->default_password;
+        }
+
+        if ((impl = _zip_get_encryption_implementation(de->encryption_method, ZIP_CODEC_ENCODE)) == NULL) {
+            zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
+            zip_source_free(src_final);
+            return -1;
+        }
+        if ((src_tmp = impl(za, src_final, de->encryption_method, ZIP_CODEC_ENCODE, password)) == NULL) {
+            /* error set by impl */
+            zip_source_free(src_final);
+            return -1;
+        }
+        if (de->encryption_method == ZIP_EM_TRAD_PKWARE) {
+            de->bitflags |= ZIP_GPBF_DATA_DESCRIPTOR;
+        }
+
+        zip_source_free(src_final);
+        src_final = src_tmp;
     }
 
 
     if ((offdata = zip_source_tell_write(za->src)) < 0) {
-       _zip_error_set_from_source(&za->error, za->src);
-       return -1;
+        _zip_error_set_from_source(&za->error, za->src);
+        return -1;
     }
 
     ret = copy_source(za, src_final, data_length);
 
     if (zip_source_stat(src_final, &st) < 0) {
-       _zip_error_set_from_source(&za->error, src_final);
-       ret = -1;
+        _zip_error_set_from_source(&za->error, src_final);
+        ret = -1;
     }
 
     if (zip_source_get_file_attributes(src_final, &attributes) != 0) {
-       _zip_error_set_from_source(&za->error, src_final);
-       ret = -1;
+        _zip_error_set_from_source(&za->error, src_final);
+        ret = -1;
     }
 
     zip_source_free(src_final);
 
     if (ret < 0) {
-       return -1;
+        return -1;
     }
 
     if ((offend = zip_source_tell_write(za->src)) < 0) {
-       _zip_error_set_from_source(&za->error, za->src);
-       return -1;
+        _zip_error_set_from_source(&za->error, za->src);
+        return -1;
     }
 
     if (zip_source_seek_write(za->src, offstart, SEEK_SET) < 0) {
-       _zip_error_set_from_source(&za->error, za->src);
-       return -1;
+        _zip_error_set_from_source(&za->error, za->src);
+        return -1;
     }
 
     if ((st.valid & (ZIP_STAT_COMP_METHOD | ZIP_STAT_CRC | ZIP_STAT_SIZE)) != (ZIP_STAT_COMP_METHOD | ZIP_STAT_CRC | ZIP_STAT_SIZE)) {
-       zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+        return -1;
     }
 
     if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0) {
-       if (st.valid & ZIP_STAT_MTIME)
-           de->last_mod = st.mtime;
-       else
-           time(&de->last_mod);
+        if (st.valid & ZIP_STAT_MTIME)
+            de->last_mod = st.mtime;
+        else
+            time(&de->last_mod);
     }
     de->comp_method = st.comp_method;
     de->crc = st.crc;
@@ -516,23 +513,23 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
     _zip_dirent_apply_attributes(de, &attributes, (flags & ZIP_FL_FORCE_ZIP64) != 0, changed);
 
     if ((ret = _zip_dirent_write(za, de, flags)) < 0)
-       return -1;
+        return -1;
 
     if (is_zip64 != ret) {
-       /* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */
-       zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
-       return -1;
+        /* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */
+        zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+        return -1;
     }
 
     if (zip_source_seek_write(za->src, offend, SEEK_SET) < 0) {
-       _zip_error_set_from_source(&za->error, za->src);
-       return -1;
+        _zip_error_set_from_source(&za->error, za->src);
+        return -1;
     }
 
     if (de->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
-       if (write_data_descriptor(za, de, is_zip64) < 0) {
-           return -1;
-       }
+        if (write_data_descriptor(za, de, is_zip64) < 0) {
+            return -1;
+        }
     }
 
     return 0;
@@ -546,28 +543,28 @@ copy_data(zip_t *za, zip_uint64_t len) {
     double total = (double)len;
 
     if (!byte_array_init(buf, BUFSIZE)) {
-       zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+        return -1;
     }
 
     while (len > 0) {
-       n = len > BUFSIZE ? BUFSIZE : len;
-       if (_zip_read(za->src, buf, n, &za->error) < 0) {
-           byte_array_fini(buf);
-           return -1;
-       }
+        n = len > BUFSIZE ? BUFSIZE : len;
+        if (_zip_read(za->src, buf, n, &za->error) < 0) {
+            byte_array_fini(buf);
+            return -1;
+        }
 
-       if (_zip_write(za, buf, n) < 0) {
-           byte_array_fini(buf);
-           return -1;
-       }
+        if (_zip_write(za, buf, n) < 0) {
+            byte_array_fini(buf);
+            return -1;
+        }
 
-       len -= n;
+        len -= n;
 
-       if (_zip_progress_update(za->progress, (total - (double)len) / total) != 0) {
-           zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
-           return -1;
-       }
+        if (_zip_progress_update(za->progress, (total - (double)len) / total) != 0) {
+            zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
+            return -1;
+        }
     }
 
     byte_array_fini(buf);
@@ -582,35 +579,35 @@ copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length) {
     int ret;
 
     if (zip_source_open(src) < 0) {
-       _zip_error_set_from_source(&za->error, src);
-       return -1;
+        _zip_error_set_from_source(&za->error, src);
+        return -1;
     }
 
     if (!byte_array_init(buf, BUFSIZE)) {
-       zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+        return -1;
     }
 
     ret = 0;
     current = 0;
     while ((n = zip_source_read(src, buf, BUFSIZE)) > 0) {
-       if (_zip_write(za, buf, (zip_uint64_t)n) < 0) {
-           ret = -1;
-           break;
-       }
-       if (n == BUFSIZE && za->progress && data_length > 0) {
-           current += n;
-           if (_zip_progress_update(za->progress, (double)current / (double)data_length) != 0) {
-               zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
-               ret = -1;
-               break;
-           }
-       }
+        if (_zip_write(za, buf, (zip_uint64_t)n) < 0) {
+            ret = -1;
+            break;
+        }
+        if (n == BUFSIZE && za->progress && data_length > 0) {
+            current += n;
+            if (_zip_progress_update(za->progress, (double)current / (double)data_length) != 0) {
+                zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
+                ret = -1;
+                break;
+            }
+        }
     }
 
     if (n < 0) {
-       _zip_error_set_from_source(&za->error, src);
-       ret = -1;
+        _zip_error_set_from_source(&za->error, src);
+        ret = -1;
     }
 
     byte_array_fini(buf);
@@ -622,18 +619,16 @@ copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length) {
 
 static int
 write_cdir(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors) {
-    zip_int64_t cd_start, end, size;
-
-    if ((cd_start = zip_source_tell_write(za->src)) < 0) {
-       return -1;
+    if (zip_source_tell_write(za->src) < 0) {
+        return -1;
     }
 
-    if ((size = _zip_cdir_write(za, filelist, survivors)) < 0) {
-       return -1;
+    if (_zip_cdir_write(za, filelist, survivors) < 0) {
+        return -1;
     }
 
-    if ((end = zip_source_tell_write(za->src)) < 0) {
-       return -1;
+    if (zip_source_tell_write(za->src) < 0) {
+        return -1;
     }
 
     return 0;
@@ -649,20 +644,20 @@ _zip_changed(const zip_t *za, zip_uint64_t *survivorsp) {
     survivors = 0;
 
     if (za->comment_changed || za->ch_flags != za->flags) {
-       changed = 1;
+        changed = 1;
     }
 
     for (i = 0; i < za->nentry; i++) {
-       if (ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) {
-           changed = 1;
-       }
-       if (!za->entry[i].deleted) {
-           survivors++;
-       }
+        if (ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) {
+            changed = 1;
+        }
+        if (!za->entry[i].deleted) {
+            survivors++;
+        }
     }
 
     if (survivorsp) {
-       *survivorsp = survivors;
+        *survivorsp = survivors;
     }
 
     return changed;
@@ -674,27 +669,27 @@ write_data_descriptor(zip_t *za, const zip_dirent_t *de, int is_zip64) {
     int ret = 0;
 
     if (buffer == NULL) {
-       zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+        return -1;
     }
 
     _zip_buffer_put(buffer, DATADES_MAGIC, 4);
     _zip_buffer_put_32(buffer, de->crc);
     if (is_zip64) {
-       _zip_buffer_put_64(buffer, de->comp_size);
-       _zip_buffer_put_64(buffer, de->uncomp_size);
+        _zip_buffer_put_64(buffer, de->comp_size);
+        _zip_buffer_put_64(buffer, de->uncomp_size);
     }
     else {
-       _zip_buffer_put_32(buffer, (zip_uint32_t)de->comp_size);
-       _zip_buffer_put_32(buffer, (zip_uint32_t)de->uncomp_size);
+        _zip_buffer_put_32(buffer, (zip_uint32_t)de->comp_size);
+        _zip_buffer_put_32(buffer, (zip_uint32_t)de->uncomp_size);
     }
 
     if (!_zip_buffer_ok(buffer)) {
-       zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
-       ret = -1;
+        zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+        ret = -1;
     }
     else {
-       ret = _zip_write(za, _zip_buffer_data(buffer), _zip_buffer_offset(buffer));
+        ret = _zip_write(za, _zip_buffer_data(buffer), _zip_buffer_offset(buffer));
     }
 
     _zip_buffer_free(buffer);
index f46c7d8..ac6e109 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_crypto.h -- crypto definitions
-  Copyright (C) 2017-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
index 2d57bd4..58b797d 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_crypto_commoncrypto.c -- CommonCrypto wrapper.
-  Copyright (C) 2018-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -43,7 +43,7 @@
 void
 _zip_crypto_aes_free(_zip_crypto_aes_t *aes) {
     if (aes == NULL) {
-       return;
+        return;
     }
 
     CCCryptorRelease(aes);
@@ -67,19 +67,19 @@ _zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *
 
     switch (ret) {
     case kCCSuccess:
-       return aes;
+        return aes;
 
     case kCCMemoryFailure:
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
 
     case kCCParamError:
-       zip_error_set(error, ZIP_ER_INVAL, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return NULL;
 
     default:
-       zip_error_set(error, ZIP_ER_INTERNAL, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INTERNAL, 0);
+        return NULL;
     }
 }
 
@@ -87,7 +87,7 @@ _zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *
 void
 _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) {
     if (hmac == NULL) {
-       return;
+        return;
     }
 
     _zip_crypto_clear(hmac, sizeof(*hmac));
@@ -100,8 +100,8 @@ _zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_
     _zip_crypto_hmac_t *hmac;
 
     if ((hmac = (_zip_crypto_hmac_t *)malloc(sizeof(*hmac))) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     CCHmacInit(hmac, kCCHmacAlgSHA1, secret, secret_length);
index 9aa9efd..406fceb 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_crypto_gnutls.c -- GnuTLS wrapper.
-  Copyright (C) 2018-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -42,26 +42,26 @@ _zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *
     _zip_crypto_aes_t *aes;
 
     if ((aes = (_zip_crypto_aes_t *)malloc(sizeof(*aes))) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     aes->key_size = key_size;
 
     switch (aes->key_size) {
     case 128:
-       nettle_aes128_set_encrypt_key(&aes->ctx.ctx_128, key);
-       break;
+        nettle_aes128_set_encrypt_key(&aes->ctx.ctx_128, key);
+        break;
     case 192:
-       nettle_aes192_set_encrypt_key(&aes->ctx.ctx_192, key);
-       break;
+        nettle_aes192_set_encrypt_key(&aes->ctx.ctx_192, key);
+        break;
     case 256:
-       nettle_aes256_set_encrypt_key(&aes->ctx.ctx_256, key);
-       break;
+        nettle_aes256_set_encrypt_key(&aes->ctx.ctx_256, key);
+        break;
     default:
-       zip_error_set(error, ZIP_ER_INVAL, 0);
-       free(aes);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        free(aes);
+        return NULL;
     }
 
     return aes;
@@ -71,14 +71,14 @@ bool
 _zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out) {
     switch (aes->key_size) {
     case 128:
-       nettle_aes128_encrypt(&aes->ctx.ctx_128, ZIP_CRYPTO_AES_BLOCK_LENGTH, out, in);
-       break;
+        nettle_aes128_encrypt(&aes->ctx.ctx_128, ZIP_CRYPTO_AES_BLOCK_LENGTH, out, in);
+        break;
     case 192:
-       nettle_aes192_encrypt(&aes->ctx.ctx_192, ZIP_CRYPTO_AES_BLOCK_LENGTH, out, in);
-       break;
+        nettle_aes192_encrypt(&aes->ctx.ctx_192, ZIP_CRYPTO_AES_BLOCK_LENGTH, out, in);
+        break;
     case 256:
-       nettle_aes256_encrypt(&aes->ctx.ctx_256, ZIP_CRYPTO_AES_BLOCK_LENGTH, out, in);
-       break;
+        nettle_aes256_encrypt(&aes->ctx.ctx_256, ZIP_CRYPTO_AES_BLOCK_LENGTH, out, in);
+        break;
     }
 
     return true;
@@ -87,7 +87,7 @@ _zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip
 void
 _zip_crypto_aes_free(_zip_crypto_aes_t *aes) {
     if (aes == NULL) {
-       return;
+        return;
     }
 
     _zip_crypto_clear(aes, sizeof(*aes));
@@ -98,17 +98,16 @@ _zip_crypto_aes_free(_zip_crypto_aes_t *aes) {
 _zip_crypto_hmac_t *
 _zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error) {
     _zip_crypto_hmac_t *hmac;
-    int ret;
 
     if ((hmac = (_zip_crypto_hmac_t *)malloc(sizeof(*hmac))) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
-    if ((ret = gnutls_hmac_init(hmac, GNUTLS_MAC_SHA1, secret, secret_length)) < 0) {
-       /* TODO: set error */
-       free(hmac);
-       return NULL;
+    if (gnutls_hmac_init(hmac, GNUTLS_MAC_SHA1, secret, secret_length) < 0) {
+        zip_error_set(error, ZIP_ER_INTERNAL, 0);
+        free(hmac);
+        return NULL;
     }
 
     return hmac;
@@ -120,7 +119,7 @@ _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) {
     zip_uint8_t buf[ZIP_CRYPTO_SHA1_LENGTH];
 
     if (hmac == NULL) {
-       return;
+        return;
     }
 
     gnutls_hmac_deinit(*hmac, buf);
index 30645ef..6743186 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_crypto_gnutls.h -- definitions for GnuTLS wrapper.
-  Copyright (C) 2018-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -45,9 +45,9 @@
 
 typedef struct {
     union {
-       struct aes128_ctx ctx_128;
-       struct aes192_ctx ctx_192;
-       struct aes256_ctx ctx_256;
+        struct aes128_ctx ctx_128;
+        struct aes192_ctx ctx_192;
+        struct aes256_ctx ctx_256;
     } ctx;
     zip_uint16_t key_size;
 } _zip_crypto_aes_t;
index c348ad2..09cdf09 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_crypto_mbedtls.c -- mbed TLS wrapper
-  Copyright (C) 2018-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 #include <mbedtls/entropy.h>
 #include <mbedtls/pkcs5.h>
 
+#include <limits.h>
 
 _zip_crypto_aes_t *
 _zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error) {
     _zip_crypto_aes_t *aes;
 
     if ((aes = (_zip_crypto_aes_t *)malloc(sizeof(*aes))) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     mbedtls_aes_init(aes);
@@ -60,7 +61,7 @@ _zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *
 void
 _zip_crypto_aes_free(_zip_crypto_aes_t *aes) {
     if (aes == NULL) {
-       return;
+        return;
     }
 
     mbedtls_aes_free(aes);
@@ -73,27 +74,27 @@ _zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_
     _zip_crypto_hmac_t *hmac;
 
     if (secret_length > INT_MAX) {
-       zip_error_set(error, ZIP_ER_INVAL, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
 
     if ((hmac = (_zip_crypto_hmac_t *)malloc(sizeof(*hmac))) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     mbedtls_md_init(hmac);
 
     if (mbedtls_md_setup(hmac, mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), 1) != 0) {
-       zip_error_set(error, ZIP_ER_INTERNAL, 0);
-       free(hmac);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INTERNAL, 0);
+        free(hmac);
+        return NULL;
     }
 
     if (mbedtls_md_hmac_starts(hmac, (const unsigned char *)secret, (size_t)secret_length) != 0) {
-       zip_error_set(error, ZIP_ER_INTERNAL, 0);
-       free(hmac);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INTERNAL, 0);
+        free(hmac);
+        return NULL;
     }
 
     return hmac;
@@ -103,7 +104,7 @@ _zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_
 void
 _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) {
     if (hmac == NULL) {
-       return;
+        return;
     }
 
     mbedtls_md_free(hmac);
@@ -119,11 +120,11 @@ _zip_crypto_pbkdf2(const zip_uint8_t *key, zip_uint64_t key_length, const zip_ui
     mbedtls_md_init(&sha1_ctx);
 
     if (mbedtls_md_setup(&sha1_ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), 1) != 0) {
-       ok = false;
+        ok = false;
     }
 
     if (ok && mbedtls_pkcs5_pbkdf2_hmac(&sha1_ctx, (const unsigned char *)key, (size_t)key_length, (const unsigned char *)salt, (size_t)salt_length, (unsigned int)iterations, (uint32_t)output_length, (unsigned char *)output) != 0) {
-       ok = false;
+        ok = false;
     }
 
     mbedtls_md_free(&sha1_ctx);
@@ -142,19 +143,19 @@ zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) {
     const unsigned char *pers = "zip_crypto_mbedtls";
 
     if (!ctx) {
-       ctx = (zip_random_context_t *)malloc(sizeof(zip_random_context_t));
-       if (!ctx) {
-           return false;
-       }
-       mbedtls_entropy_init(&ctx->entropy);
-       mbedtls_ctr_drbg_init(&ctx->ctr_drbg);
-       if (mbedtls_ctr_drbg_seed(&ctx->ctr_drbg, mbedtls_entropy_func, &ctx->entropy, pers, strlen(pers)) != 0) {
-           mbedtls_ctr_drbg_free(&ctx->ctr_drbg);
-           mbedtls_entropy_free(&ctx->entropy);
-           free(ctx);
-           ctx = NULL;
-           return false;
-       }
+        ctx = (zip_random_context_t *)malloc(sizeof(zip_random_context_t));
+        if (!ctx) {
+            return false;
+        }
+        mbedtls_entropy_init(&ctx->entropy);
+        mbedtls_ctr_drbg_init(&ctx->ctr_drbg);
+        if (mbedtls_ctr_drbg_seed(&ctx->ctr_drbg, mbedtls_entropy_func, &ctx->entropy, pers, strlen(pers)) != 0) {
+            mbedtls_ctr_drbg_free(&ctx->ctr_drbg);
+            mbedtls_entropy_free(&ctx->entropy);
+            free(ctx);
+            ctx = NULL;
+            return false;
+        }
     }
 
     return mbedtls_ctr_drbg_random(&ctx->ctr_drbg, (unsigned char *)buffer, (size_t)length) == 0;
index 7381951..a82b2fd 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_crypto_mbedtls.h -- definitions for mbedtls wrapper
-  Copyright (C) 2018-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
index 1cb0047..5cbc5ce 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_crypto_openssl.c -- OpenSSL wrapper.
-  Copyright (C) 2018-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 
 #include "zip_crypto.h"
 
+#include <limits.h>
 #include <openssl/rand.h>
 
-#if OPENSSL_VERSION_NUMBER < 0x1010000fL || defined(LIBRESSL_VERSION_NUMBER)
+#if OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
 #define USE_OPENSSL_1_0_API
 #endif
 
@@ -49,8 +50,8 @@ _zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *
     _zip_crypto_aes_t *aes;
 
     if ((aes = (_zip_crypto_aes_t *)malloc(sizeof(*aes))) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     AES_set_encrypt_key(key, key_size, aes);
@@ -61,7 +62,7 @@ _zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *
 void
 _zip_crypto_aes_free(_zip_crypto_aes_t *aes) {
     if (aes == NULL) {
-       return;
+        return;
     }
 
     _zip_crypto_clear(aes, sizeof(*aes));
@@ -74,32 +75,32 @@ _zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_
     _zip_crypto_hmac_t *hmac;
 
     if (secret_length > INT_MAX) {
-       zip_error_set(error, ZIP_ER_INVAL, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
 
 #ifdef USE_OPENSSL_1_0_API
     if ((hmac = (_zip_crypto_hmac_t *)malloc(sizeof(*hmac))) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     HMAC_CTX_init(hmac);
 #else
     if ((hmac = HMAC_CTX_new()) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 #endif
 
     if (HMAC_Init_ex(hmac, secret, (int)secret_length, EVP_sha1(), NULL) != 1) {
-       zip_error_set(error, ZIP_ER_INTERNAL, 0);
+        zip_error_set(error, ZIP_ER_INTERNAL, 0);
 #ifdef USE_OPENSSL_1_0_API
-       free(hmac);
+        free(hmac);
 #else
-       HMAC_CTX_free(hmac);
+        HMAC_CTX_free(hmac);
 #endif
-       return NULL;
+        return NULL;
     }
 
     return hmac;
@@ -109,7 +110,7 @@ _zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_
 void
 _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) {
     if (hmac == NULL) {
-       return;
+        return;
     }
 
 #ifdef USE_OPENSSL_1_0_API
index 51bd4ed..d959b8d 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_crypto_openssl.h -- definitions for OpenSSL wrapper.
-  Copyright (C) 2018-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
index 7eb42c3..8202bfe 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_crypto_win.c -- Windows Crypto API wrapper.
-  Copyright (C) 2018-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -31,6 +31,7 @@
   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 #include <stdlib.h>
+#include <limits.h>
 
 #include "zipint.h"
 
@@ -89,12 +90,13 @@ There is no #ifdef to control that, because this is working for all supported OS
 bool
 _zip_crypto_pbkdf2(const zip_uint8_t *key, zip_uint64_t key_length, const zip_uint8_t *salt, zip_uint16_t salt_length, zip_uint16_t iterations, zip_uint8_t *output, zip_uint16_t output_length) {
     BCRYPT_ALG_HANDLE hAlgorithm = NULL;
+    bool result;
 
     if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&hAlgorithm, BCRYPT_SHA1_ALGORITHM, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG))) {
-       return false;
+        return false;
     }
 
-    bool result = BCRYPT_SUCCESS(BCryptDeriveKeyPBKDF2(hAlgorithm, (PUCHAR)key, (ULONG)key_length, (PUCHAR)salt, salt_length, iterations, output, output_length, 0));
+    result = BCRYPT_SUCCESS(BCryptDeriveKeyPBKDF2(hAlgorithm, (PUCHAR)key, (ULONG)key_length, (PUCHAR)salt, salt_length, iterations, output, output_length, 0));
 
     BCryptCloseAlgorithmProvider(hAlgorithm, 0);
 
@@ -120,13 +122,13 @@ typedef struct {
 static void
 hmacFree(PRF_CTX *pContext) {
     if (pContext->hOuterHash)
-       BCryptDestroyHash(pContext->hOuterHash);
+        BCryptDestroyHash(pContext->hOuterHash);
     if (pContext->hInnerHash)
-       BCryptDestroyHash(pContext->hInnerHash);
+        BCryptDestroyHash(pContext->hInnerHash);
     free(pContext->pbOuterHash);
     free(pContext->pbInnerHash);
     if (pContext->hAlgorithm)
-       BCryptCloseAlgorithmProvider(pContext->hAlgorithm, 0);
+        BCryptCloseAlgorithmProvider(pContext->hAlgorithm, 0);
 }
 
 static BOOL
@@ -135,13 +137,13 @@ hmacPrecomputeDigest(BCRYPT_HASH_HANDLE hHash, PUCHAR pbPassword, DWORD cbPasswo
     DWORD i;
 
     if (cbPassword > BLOCK_SIZE) {
-       return FALSE;
+        return FALSE;
     }
 
     memset(buffer, mask, sizeof(buffer));
 
     for (i = 0; i < cbPassword; ++i) {
-       buffer[i] = (char)(pbPassword[i] ^ mask);
+        buffer[i] = (char)(pbPassword[i] ^ mask);
     }
 
     return BCRYPT_SUCCESS(BCryptHashData(hHash, buffer, sizeof(buffer), 0));
@@ -154,27 +156,27 @@ hmacInit(PRF_CTX *pContext, PUCHAR pbPassword, DWORD cbPassword) {
     BYTE key[DIGEST_SIZE];
 
     if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&pContext->hAlgorithm, BCRYPT_SHA1_ALGORITHM, NULL, 0)) || !BCRYPT_SUCCESS(BCryptGetProperty(pContext->hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&pContext->cbHashObject, sizeof(pContext->cbHashObject), &cbResult, 0)) || ((pContext->pbInnerHash = malloc(pContext->cbHashObject)) == NULL) || ((pContext->pbOuterHash = malloc(pContext->cbHashObject)) == NULL) || !BCRYPT_SUCCESS(BCryptCreateHash(pContext->hAlgorithm, &pContext->hInnerHash, pContext->pbInnerHash, pContext->cbHashObject, NULL, 0, 0)) || !BCRYPT_SUCCESS(BCryptCreateHash(pContext->hAlgorithm, &pContext->hOuterHash, pContext->pbOuterHash, pContext->cbHashObject, NULL, 0, 0))) {
-       goto hmacInit_end;
+        goto hmacInit_end;
     }
 
     if (cbPassword > BLOCK_SIZE) {
-       BCRYPT_HASH_HANDLE hHash = NULL;
-       PUCHAR pbHashObject = malloc(pContext->cbHashObject);
-       if (pbHashObject == NULL) {
-           goto hmacInit_end;
-       }
+        BCRYPT_HASH_HANDLE hHash = NULL;
+        PUCHAR pbHashObject = malloc(pContext->cbHashObject);
+        if (pbHashObject == NULL) {
+            goto hmacInit_end;
+        }
 
-       bStatus = BCRYPT_SUCCESS(BCryptCreateHash(pContext->hAlgorithm, &hHash, pbHashObject, pContext->cbHashObject, NULL, 0, 0)) && BCRYPT_SUCCESS(BCryptHashData(hHash, pbPassword, cbPassword, 0)) && BCRYPT_SUCCESS(BCryptGetProperty(hHash, BCRYPT_HASH_LENGTH, (PUCHAR)&cbPassword, sizeof(cbPassword), &cbResult, 0)) && BCRYPT_SUCCESS(BCryptFinishHash(hHash, key, cbPassword, 0));
+        bStatus = BCRYPT_SUCCESS(BCryptCreateHash(pContext->hAlgorithm, &hHash, pbHashObject, pContext->cbHashObject, NULL, 0, 0)) && BCRYPT_SUCCESS(BCryptHashData(hHash, pbPassword, cbPassword, 0)) && BCRYPT_SUCCESS(BCryptGetProperty(hHash, BCRYPT_HASH_LENGTH, (PUCHAR)&cbPassword, sizeof(cbPassword), &cbResult, 0)) && BCRYPT_SUCCESS(BCryptFinishHash(hHash, key, cbPassword, 0));
 
-       if (hHash)
-           BCryptDestroyHash(hHash);
-       free(pbHashObject);
+        if (hHash)
+            BCryptDestroyHash(hHash);
+        free(pbHashObject);
 
-       if (!bStatus) {
-           goto hmacInit_end;
-       }
+        if (!bStatus) {
+            goto hmacInit_end;
+        }
 
-       pbPassword = key;
+        pbPassword = key;
     }
 
     bStatus = hmacPrecomputeDigest(pContext->hInnerHash, pbPassword, cbPassword, 0x36) && hmacPrecomputeDigest(pContext->hOuterHash, pbPassword, cbPassword, 0x5C);
@@ -182,7 +184,7 @@ hmacInit(PRF_CTX *pContext, PUCHAR pbPassword, DWORD cbPassword) {
 hmacInit_end:
 
     if (bStatus == FALSE)
-       hmacFree(pContext);
+        hmacFree(pContext);
 
     return bStatus;
 }
@@ -194,13 +196,13 @@ hmacCalculateInternal(BCRYPT_HASH_HANDLE hHashTemplate, PUCHAR pbData, DWORD cbD
     PUCHAR pbHashObject = malloc(cbHashObject);
 
     if (pbHashObject == NULL) {
-       return FALSE;
+        return FALSE;
     }
 
     if (BCRYPT_SUCCESS(BCryptDuplicateHash(hHashTemplate, &hHash, pbHashObject, cbHashObject, 0))) {
-       success = BCRYPT_SUCCESS(BCryptHashData(hHash, pbData, cbData, 0)) && BCRYPT_SUCCESS(BCryptFinishHash(hHash, pbOutput, cbOutput, 0));
+        success = BCRYPT_SUCCESS(BCryptHashData(hHash, pbData, cbData, 0)) && BCRYPT_SUCCESS(BCryptFinishHash(hHash, pbOutput, cbOutput, 0));
 
-       BCryptDestroyHash(hHash);
+        BCryptDestroyHash(hHash);
     }
 
     free(pbHashObject);
@@ -219,7 +221,7 @@ hmacCalculate(PRF_CTX *pContext, PUCHAR pbData, DWORD cbData, PUCHAR pbDigest) {
 static void
 myxor(LPBYTE ptr1, LPBYTE ptr2, DWORD dwLen) {
     while (dwLen--)
-       *ptr1++ ^= *ptr2++;
+        *ptr1++ ^= *ptr2++;
 }
 
 BOOL
@@ -232,52 +234,52 @@ pbkdf2(PUCHAR pbPassword, ULONG cbPassword, PUCHAR pbSalt, ULONG cbSalt, DWORD c
     PRF_CTX prfCtx = {0};
 
     if (U == NULL) {
-       return FALSE;
+        return FALSE;
     }
 
     if (pbPassword == NULL || cbPassword == 0 || pbSalt == NULL || cbSalt == 0 || cIterations == 0 || pbDerivedKey == NULL || cbDerivedKey == 0) {
-       free(U);
-       return FALSE;
+        free(U);
+        return FALSE;
     }
 
     if (!hmacInit(&prfCtx, pbPassword, cbPassword)) {
-       goto PBKDF2_end;
+        goto PBKDF2_end;
     }
 
     l = (DWORD)ceil((double)cbDerivedKey / (double)DIGEST_SIZE);
     r = cbDerivedKey - (l - 1) * DIGEST_SIZE;
 
     for (i = 1; i <= l; i++) {
-       ZeroMemory(Ti, DIGEST_SIZE);
-       for (j = 0; j < cIterations; j++) {
-           if (j == 0) {
-               /* construct first input for PRF */
-               memcpy(U, pbSalt, cbSalt);
-               U[cbSalt] = (BYTE)((i & 0xFF000000) >> 24);
-               U[cbSalt + 1] = (BYTE)((i & 0x00FF0000) >> 16);
-               U[cbSalt + 2] = (BYTE)((i & 0x0000FF00) >> 8);
-               U[cbSalt + 3] = (BYTE)((i & 0x000000FF));
-               dwULen = cbSalt + 4;
-           }
-           else {
-               memcpy(U, V, DIGEST_SIZE);
-               dwULen = DIGEST_SIZE;
-           }
-
-           if (!hmacCalculate(&prfCtx, U, dwULen, V)) {
-               goto PBKDF2_end;
-           }
-
-           myxor(Ti, V, DIGEST_SIZE);
-       }
-
-       if (i != l) {
-           memcpy(&pbDerivedKey[(i - 1) * DIGEST_SIZE], Ti, DIGEST_SIZE);
-       }
-       else {
-           /* Take only the first r bytes */
-           memcpy(&pbDerivedKey[(i - 1) * DIGEST_SIZE], Ti, r);
-       }
+        ZeroMemory(Ti, DIGEST_SIZE);
+        for (j = 0; j < cIterations; j++) {
+            if (j == 0) {
+                /* construct first input for PRF */
+                memcpy(U, pbSalt, cbSalt);
+                U[cbSalt] = (BYTE)((i & 0xFF000000) >> 24);
+                U[cbSalt + 1] = (BYTE)((i & 0x00FF0000) >> 16);
+                U[cbSalt + 2] = (BYTE)((i & 0x0000FF00) >> 8);
+                U[cbSalt + 3] = (BYTE)((i & 0x000000FF));
+                dwULen = cbSalt + 4;
+            }
+            else {
+                memcpy(U, V, DIGEST_SIZE);
+                dwULen = DIGEST_SIZE;
+            }
+
+            if (!hmacCalculate(&prfCtx, U, dwULen, V)) {
+                goto PBKDF2_end;
+            }
+
+            myxor(Ti, V, DIGEST_SIZE);
+        }
+
+        if (i != l) {
+            memcpy(&pbDerivedKey[(i - 1) * DIGEST_SIZE], Ti, DIGEST_SIZE);
+        }
+        else {
+            /* Take only the first r bytes */
+            memcpy(&pbDerivedKey[(i - 1) * DIGEST_SIZE], Ti, r);
+        }
     }
 
     bStatus = TRUE;
@@ -312,35 +314,35 @@ _zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *
     ULONG key_length = key_size / 8;
 
     if (aes == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&aes->hAlgorithm, BCRYPT_AES_ALGORITHM, NULL, 0))) {
-       _zip_crypto_aes_free(aes);
-       return NULL;
+        _zip_crypto_aes_free(aes);
+        return NULL;
     }
 
     if (!BCRYPT_SUCCESS(BCryptSetProperty(aes->hAlgorithm, BCRYPT_CHAINING_MODE, (PUCHAR)BCRYPT_CHAIN_MODE_ECB, sizeof(BCRYPT_CHAIN_MODE_ECB), 0))) {
-       _zip_crypto_aes_free(aes);
-       return NULL;
+        _zip_crypto_aes_free(aes);
+        return NULL;
     }
 
     if (!BCRYPT_SUCCESS(BCryptGetProperty(aes->hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&aes->cbKeyObject, sizeof(aes->cbKeyObject), &cbResult, 0))) {
-       _zip_crypto_aes_free(aes);
-       return NULL;
+        _zip_crypto_aes_free(aes);
+        return NULL;
     }
 
     aes->pbKeyObject = malloc(aes->cbKeyObject);
     if (aes->pbKeyObject == NULL) {
-       _zip_crypto_aes_free(aes);
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        _zip_crypto_aes_free(aes);
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     if (!BCRYPT_SUCCESS(BCryptGenerateSymmetricKey(aes->hAlgorithm, &aes->hKey, aes->pbKeyObject, aes->cbKeyObject, (PUCHAR)key, key_length, 0))) {
-       _zip_crypto_aes_free(aes);
-       return NULL;
+        _zip_crypto_aes_free(aes);
+        return NULL;
     }
 
     return aes;
@@ -349,19 +351,19 @@ _zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *
 void
 _zip_crypto_aes_free(_zip_crypto_aes_t *aes) {
     if (aes == NULL) {
-       return;
+        return;
     }
 
     if (aes->hKey != NULL) {
-       BCryptDestroyKey(aes->hKey);
+        BCryptDestroyKey(aes->hKey);
     }
 
     if (aes->pbKeyObject != NULL) {
-       free(aes->pbKeyObject);
+        free(aes->pbKeyObject);
     }
 
     if (aes->hAlgorithm != NULL) {
-       BCryptCloseAlgorithmProvider(aes->hAlgorithm, 0);
+        BCryptCloseAlgorithmProvider(aes->hAlgorithm, 0);
     }
 
     free(aes);
@@ -392,53 +394,53 @@ _zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_
     _zip_crypto_hmac_t *hmac;
 
     if (secret_length > INT_MAX) {
-       zip_error_set(error, ZIP_ER_INVAL, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
 
     hmac = (_zip_crypto_hmac_t *)calloc(1, sizeof(*hmac));
 
     if (hmac == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     status = BCryptOpenAlgorithmProvider(&hmac->hAlgorithm, BCRYPT_SHA1_ALGORITHM, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG);
     if (!BCRYPT_SUCCESS(status)) {
-       _zip_crypto_hmac_free(hmac);
-       return NULL;
+        _zip_crypto_hmac_free(hmac);
+        return NULL;
     }
 
     status = BCryptGetProperty(hmac->hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&hmac->cbHashObject, sizeof(hmac->cbHashObject), &cbResult, 0);
     if (!BCRYPT_SUCCESS(status)) {
-       _zip_crypto_hmac_free(hmac);
-       return NULL;
+        _zip_crypto_hmac_free(hmac);
+        return NULL;
     }
 
     hmac->pbHashObject = malloc(hmac->cbHashObject);
     if (hmac->pbHashObject == NULL) {
-       _zip_crypto_hmac_free(hmac);
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        _zip_crypto_hmac_free(hmac);
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     status = BCryptGetProperty(hmac->hAlgorithm, BCRYPT_HASH_LENGTH, (PUCHAR)&hmac->cbHash, sizeof(hmac->cbHash), &cbResult, 0);
     if (!BCRYPT_SUCCESS(status)) {
-       _zip_crypto_hmac_free(hmac);
-       return NULL;
+        _zip_crypto_hmac_free(hmac);
+        return NULL;
     }
 
     hmac->pbHash = malloc(hmac->cbHash);
     if (hmac->pbHash == NULL) {
-       _zip_crypto_hmac_free(hmac);
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        _zip_crypto_hmac_free(hmac);
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     status = BCryptCreateHash(hmac->hAlgorithm, &hmac->hHash, hmac->pbHashObject, hmac->cbHashObject, (PUCHAR)secret, (ULONG)secret_length, 0);
     if (!BCRYPT_SUCCESS(status)) {
-       _zip_crypto_hmac_free(hmac);
-       return NULL;
+        _zip_crypto_hmac_free(hmac);
+        return NULL;
     }
 
     return hmac;
@@ -447,23 +449,23 @@ _zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_
 void
 _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) {
     if (hmac == NULL) {
-       return;
+        return;
     }
 
     if (hmac->hHash != NULL) {
-       BCryptDestroyHash(hmac->hHash);
+        BCryptDestroyHash(hmac->hHash);
     }
 
     if (hmac->pbHash != NULL) {
-       free(hmac->pbHash);
+        free(hmac->pbHash);
     }
 
     if (hmac->pbHashObject != NULL) {
-       free(hmac->pbHashObject);
+        free(hmac->pbHashObject);
     }
 
     if (hmac->hAlgorithm) {
-       BCryptCloseAlgorithmProvider(hmac->hAlgorithm, 0);
+        BCryptCloseAlgorithmProvider(hmac->hAlgorithm, 0);
     }
 
     free(hmac);
@@ -472,7 +474,7 @@ _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) {
 bool
 _zip_crypto_hmac(_zip_crypto_hmac_t *hmac, zip_uint8_t *data, zip_uint64_t length) {
     if (hmac == NULL || length > ULONG_MAX) {
-       return false;
+        return false;
     }
 
     return BCRYPT_SUCCESS(BCryptHashData(hmac->hHash, data, (ULONG)length, 0));
@@ -481,7 +483,7 @@ _zip_crypto_hmac(_zip_crypto_hmac_t *hmac, zip_uint8_t *data, zip_uint64_t lengt
 bool
 _zip_crypto_hmac_output(_zip_crypto_hmac_t *hmac, zip_uint8_t *data) {
     if (hmac == NULL) {
-       return false;
+        return false;
     }
 
     return BCRYPT_SUCCESS(BCryptFinishHash(hmac->hHash, data, hmac->cbHash, 0));
index d5c22a9..be9fdc6 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_crypto_win.h -- Windows Crypto API wrapper.
-  Copyright (C) 2018-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
index 97701a0..7d82d9a 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_delete.c -- delete file from zip archive
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -40,27 +40,27 @@ zip_delete(zip_t *za, zip_uint64_t idx) {
     const char *name;
 
     if (idx >= za->nentry) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     if (ZIP_IS_RDONLY(za)) {
-       zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+        return -1;
     }
 
     if ((name = _zip_get_name(za, idx, 0, &za->error)) == NULL) {
-       return -1;
+        return -1;
     }
 
     if (!_zip_hash_delete(za->names, (const zip_uint8_t *)name, &za->error)) {
-       return -1;
+        return -1;
     }
 
     /* allow duplicate file names, because the file will
      * be removed directly afterwards */
     if (_zip_unchange(za, idx, 1) != 0)
-       return -1;
+        return -1;
 
     za->entry[idx].deleted = 1;
 
index c40b1cb..89eb432 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_dir_add.c -- add directory
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -48,31 +48,31 @@ zip_dir_add(zip_t *za, const char *name, zip_flags_t flags) {
     zip_source_t *source;
 
     if (ZIP_IS_RDONLY(za)) {
-       zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+        return -1;
     }
 
     if (name == NULL) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     s = NULL;
     len = strlen(name);
 
     if (name[len - 1] != '/') {
-       if ((s = (char *)malloc(len + 2)) == NULL) {
-           zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-           return -1;
-       }
-       strcpy(s, name);
-       s[len] = '/';
-       s[len + 1] = '\0';
+        if ((s = (char *)malloc(len + 2)) == NULL) {
+            zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+            return -1;
+        }
+        strcpy(s, name);
+        s[len] = '/';
+        s[len + 1] = '\0';
     }
 
     if ((source = zip_source_buffer(za, NULL, 0, 0)) == NULL) {
-       free(s);
-       return -1;
+        free(s);
+        return -1;
     }
 
     idx = _zip_file_replace(za, ZIP_UINT64_MAX, s ? s : name, source, flags);
@@ -80,12 +80,12 @@ zip_dir_add(zip_t *za, const char *name, zip_flags_t flags) {
     free(s);
 
     if (idx < 0)
-       zip_source_free(source);
+        zip_source_free(source);
     else {
-       if (zip_file_set_external_attributes(za, (zip_uint64_t)idx, 0, ZIP_OPSYS_DEFAULT, ZIP_EXT_ATTRIB_DEFAULT_DIR) < 0) {
-           zip_delete(za, (zip_uint64_t)idx);
-           return -1;
-       }
+        if (zip_file_set_external_attributes(za, (zip_uint64_t)idx, 0, ZIP_OPSYS_DEFAULT, ZIP_EXT_ATTRIB_DEFAULT_DIR) < 0) {
+            zip_delete(za, (zip_uint64_t)idx);
+            return -1;
+        }
     }
 
     return idx;
index 1691071..a7c336b 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_dirent.c -- read directory entry (local or central), clean dirent
-  Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -50,10 +50,10 @@ _zip_cdir_free(zip_cdir_t *cd) {
     zip_uint64_t i;
 
     if (!cd)
-       return;
+        return;
 
     for (i = 0; i < cd->nentry; i++)
-       _zip_entry_finalize(cd->entry + i);
+        _zip_entry_finalize(cd->entry + i);
     free(cd->entry);
     _zip_string_free(cd->comment);
     free(cd);
@@ -65,8 +65,8 @@ _zip_cdir_new(zip_uint64_t nentry, zip_error_t *error) {
     zip_cdir_t *cd;
 
     if ((cd = (zip_cdir_t *)malloc(sizeof(*cd))) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     cd->entry = NULL;
@@ -76,8 +76,8 @@ _zip_cdir_new(zip_uint64_t nentry, zip_error_t *error) {
     cd->is_zip64 = false;
 
     if (!_zip_cdir_grow(cd, nentry, error)) {
-       _zip_cdir_free(cd);
-       return NULL;
+        _zip_cdir_free(cd);
+        return NULL;
     }
 
     return cd;
@@ -90,25 +90,25 @@ _zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *err
     zip_entry_t *new_entry;
 
     if (additional_entries == 0) {
-       return true;
+        return true;
     }
 
     new_alloc = cd->nentry_alloc + additional_entries;
 
     if (new_alloc < additional_entries || new_alloc > SIZE_MAX / sizeof(*(cd->entry))) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return false;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return false;
     }
 
     if ((new_entry = (zip_entry_t *)realloc(cd->entry, sizeof(*(cd->entry)) * (size_t)new_alloc)) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return false;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return false;
     }
 
     cd->entry = new_entry;
 
     for (i = cd->nentry; i < new_alloc; i++) {
-       _zip_entry_init(cd->entry + i);
+        _zip_entry_init(cd->entry + i);
     }
 
     cd->nentry = cd->nentry_alloc = new_alloc;
@@ -129,52 +129,52 @@ _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivor
     int ret;
 
     if ((off = zip_source_tell_write(za->src)) < 0) {
-       _zip_error_set_from_source(&za->error, za->src);
-       return -1;
+        _zip_error_set_from_source(&za->error, za->src);
+        return -1;
     }
     offset = (zip_uint64_t)off;
 
     is_zip64 = false;
 
     for (i = 0; i < survivors; i++) {
-       zip_entry_t *entry = za->entry + filelist[i].idx;
+        zip_entry_t *entry = za->entry + filelist[i].idx;
 
-       if ((ret = _zip_dirent_write(za, entry->changes ? entry->changes : entry->orig, ZIP_FL_CENTRAL)) < 0)
-           return -1;
-       if (ret)
-           is_zip64 = true;
+        if ((ret = _zip_dirent_write(za, entry->changes ? entry->changes : entry->orig, ZIP_FL_CENTRAL)) < 0)
+            return -1;
+        if (ret)
+            is_zip64 = true;
     }
 
     if ((off = zip_source_tell_write(za->src)) < 0) {
-       _zip_error_set_from_source(&za->error, za->src);
-       return -1;
+        _zip_error_set_from_source(&za->error, za->src);
+        return -1;
     }
     size = (zip_uint64_t)off - offset;
 
     if (offset > ZIP_UINT32_MAX || survivors > ZIP_UINT16_MAX)
-       is_zip64 = true;
+        is_zip64 = true;
 
 
     if ((buffer = _zip_buffer_new(buf, sizeof(buf))) == NULL) {
-       zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+        return -1;
     }
 
     if (is_zip64) {
-       _zip_buffer_put(buffer, EOCD64_MAGIC, 4);
-       _zip_buffer_put_64(buffer, EOCD64LEN - 12);
-       _zip_buffer_put_16(buffer, 45);
-       _zip_buffer_put_16(buffer, 45);
-       _zip_buffer_put_32(buffer, 0);
-       _zip_buffer_put_32(buffer, 0);
-       _zip_buffer_put_64(buffer, survivors);
-       _zip_buffer_put_64(buffer, survivors);
-       _zip_buffer_put_64(buffer, size);
-       _zip_buffer_put_64(buffer, offset);
-       _zip_buffer_put(buffer, EOCD64LOC_MAGIC, 4);
-       _zip_buffer_put_32(buffer, 0);
-       _zip_buffer_put_64(buffer, offset + size);
-       _zip_buffer_put_32(buffer, 1);
+        _zip_buffer_put(buffer, EOCD64_MAGIC, 4);
+        _zip_buffer_put_64(buffer, EOCD64LEN - 12);
+        _zip_buffer_put_16(buffer, 45);
+        _zip_buffer_put_16(buffer, 45);
+        _zip_buffer_put_32(buffer, 0);
+        _zip_buffer_put_32(buffer, 0);
+        _zip_buffer_put_64(buffer, survivors);
+        _zip_buffer_put_64(buffer, survivors);
+        _zip_buffer_put_64(buffer, size);
+        _zip_buffer_put_64(buffer, offset);
+        _zip_buffer_put(buffer, EOCD64LOC_MAGIC, 4);
+        _zip_buffer_put_32(buffer, 0);
+        _zip_buffer_put_64(buffer, offset + size);
+        _zip_buffer_put_32(buffer, 1);
     }
 
     _zip_buffer_put(buffer, EOCD_MAGIC, 4);
@@ -189,22 +189,22 @@ _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivor
     _zip_buffer_put_16(buffer, (zip_uint16_t)(comment ? comment->length : 0));
 
     if (!_zip_buffer_ok(buffer)) {
-       zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
-       _zip_buffer_free(buffer);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+        _zip_buffer_free(buffer);
+        return -1;
     }
 
     if (_zip_write(za, _zip_buffer_data(buffer), _zip_buffer_offset(buffer)) < 0) {
-       _zip_buffer_free(buffer);
-       return -1;
+        _zip_buffer_free(buffer);
+        return -1;
     }
 
     _zip_buffer_free(buffer);
 
     if (comment) {
-       if (_zip_write(za, comment->raw, comment->length) < 0) {
-           return -1;
-       }
+        if (_zip_write(za, comment->raw, comment->length) < 0) {
+            return -1;
+        }
     }
 
     return (zip_int64_t)size;
@@ -216,12 +216,12 @@ _zip_dirent_clone(const zip_dirent_t *sde) {
     zip_dirent_t *tde;
 
     if ((tde = (zip_dirent_t *)malloc(sizeof(*tde))) == NULL)
-       return NULL;
+        return NULL;
 
     if (sde)
-       memcpy(tde, sde, sizeof(*sde));
+        memcpy(tde, sde, sizeof(*sde));
     else
-       _zip_dirent_init(tde);
+        _zip_dirent_init(tde);
 
     tde->changed = 0;
     tde->cloned = 1;
@@ -233,23 +233,23 @@ _zip_dirent_clone(const zip_dirent_t *sde) {
 void
 _zip_dirent_finalize(zip_dirent_t *zde) {
     if (!zde->cloned || zde->changed & ZIP_DIRENT_FILENAME) {
-       _zip_string_free(zde->filename);
-       zde->filename = NULL;
+        _zip_string_free(zde->filename);
+        zde->filename = NULL;
     }
     if (!zde->cloned || zde->changed & ZIP_DIRENT_EXTRA_FIELD) {
-       _zip_ef_free(zde->extra_fields);
-       zde->extra_fields = NULL;
+        _zip_ef_free(zde->extra_fields);
+        zde->extra_fields = NULL;
     }
     if (!zde->cloned || zde->changed & ZIP_DIRENT_COMMENT) {
-       _zip_string_free(zde->comment);
-       zde->comment = NULL;
+        _zip_string_free(zde->comment);
+        zde->comment = NULL;
     }
     if (!zde->cloned || zde->changed & ZIP_DIRENT_PASSWORD) {
-       if (zde->password) {
-           _zip_crypto_clear(zde->password, strlen(zde->password));
-       }
-       free(zde->password);
-       zde->password = NULL;
+        if (zde->password) {
+            _zip_crypto_clear(zde->password, strlen(zde->password));
+        }
+        free(zde->password);
+        zde->password = NULL;
     }
 }
 
@@ -257,7 +257,7 @@ _zip_dirent_finalize(zip_dirent_t *zde) {
 void
 _zip_dirent_free(zip_dirent_t *zde) {
     if (zde == NULL)
-       return;
+        return;
 
     _zip_dirent_finalize(zde);
     free(zde);
@@ -295,7 +295,7 @@ _zip_dirent_init(zip_dirent_t *de) {
 bool
 _zip_dirent_needs_zip64(const zip_dirent_t *de, zip_flags_t flags) {
     if (de->uncomp_size >= ZIP_UINT32_MAX || de->comp_size >= ZIP_UINT32_MAX || ((flags & ZIP_FL_CENTRAL) && de->offset >= ZIP_UINT32_MAX))
-       return true;
+        return true;
 
     return false;
 }
@@ -306,7 +306,7 @@ _zip_dirent_new(void) {
     zip_dirent_t *de;
 
     if ((de = (zip_dirent_t *)malloc(sizeof(*de))) == NULL)
-       return NULL;
+        return NULL;
 
     _zip_dirent_init(de);
     return de;
@@ -335,32 +335,32 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
     size = local ? LENTRYSIZE : CDENTRYSIZE;
 
     if (buffer) {
-       if (_zip_buffer_left(buffer) < size) {
-           zip_error_set(error, ZIP_ER_NOZIP, 0);
-           return -1;
-       }
+        if (_zip_buffer_left(buffer) < size) {
+            zip_error_set(error, ZIP_ER_NOZIP, 0);
+            return -1;
+        }
     }
     else {
-       if ((buffer = _zip_buffer_new_from_source(src, size, buf, error)) == NULL) {
-           return -1;
-       }
+        if ((buffer = _zip_buffer_new_from_source(src, size, buf, error)) == NULL) {
+            return -1;
+        }
     }
 
     if (memcmp(_zip_buffer_get(buffer, 4), (local ? LOCAL_MAGIC : CENTRAL_MAGIC), 4) != 0) {
-       zip_error_set(error, ZIP_ER_NOZIP, 0);
-       if (!from_buffer) {
-           _zip_buffer_free(buffer);
-       }
-       return -1;
+        zip_error_set(error, ZIP_ER_NOZIP, 0);
+        if (!from_buffer) {
+            _zip_buffer_free(buffer);
+        }
+        return -1;
     }
 
     /* convert buffercontents to zip_dirent */
 
     _zip_dirent_init(zde);
     if (!local)
-       zde->version_madeby = _zip_buffer_get_16(buffer);
+        zde->version_madeby = _zip_buffer_get_16(buffer);
     else
-       zde->version_madeby = 0;
+        zde->version_madeby = 0;
     zde->version_needed = _zip_buffer_get_16(buffer);
     zde->bitflags = _zip_buffer_get_16(buffer);
     zde->comp_method = _zip_buffer_get_16(buffer);
@@ -378,39 +378,39 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
     ef_len = _zip_buffer_get_16(buffer);
 
     if (local) {
-       comment_len = 0;
-       zde->disk_number = 0;
-       zde->int_attrib = 0;
-       zde->ext_attrib = 0;
-       zde->offset = 0;
+        comment_len = 0;
+        zde->disk_number = 0;
+        zde->int_attrib = 0;
+        zde->ext_attrib = 0;
+        zde->offset = 0;
     }
     else {
-       comment_len = _zip_buffer_get_16(buffer);
-       zde->disk_number = _zip_buffer_get_16(buffer);
-       zde->int_attrib = _zip_buffer_get_16(buffer);
-       zde->ext_attrib = _zip_buffer_get_32(buffer);
-       zde->offset = _zip_buffer_get_32(buffer);
+        comment_len = _zip_buffer_get_16(buffer);
+        zde->disk_number = _zip_buffer_get_16(buffer);
+        zde->int_attrib = _zip_buffer_get_16(buffer);
+        zde->ext_attrib = _zip_buffer_get_32(buffer);
+        zde->offset = _zip_buffer_get_32(buffer);
     }
 
     if (!_zip_buffer_ok(buffer)) {
-       zip_error_set(error, ZIP_ER_INTERNAL, 0);
-       if (!from_buffer) {
-           _zip_buffer_free(buffer);
-       }
-       return -1;
+        zip_error_set(error, ZIP_ER_INTERNAL, 0);
+        if (!from_buffer) {
+            _zip_buffer_free(buffer);
+        }
+        return -1;
     }
 
     if (zde->bitflags & ZIP_GPBF_ENCRYPTED) {
-       if (zde->bitflags & ZIP_GPBF_STRONG_ENCRYPTION) {
-           /* TODO */
-           zde->encryption_method = ZIP_EM_UNKNOWN;
-       }
-       else {
-           zde->encryption_method = ZIP_EM_TRAD_PKWARE;
-       }
+        if (zde->bitflags & ZIP_GPBF_STRONG_ENCRYPTION) {
+            /* TODO */
+            zde->encryption_method = ZIP_EM_UNKNOWN;
+        }
+        else {
+            zde->encryption_method = ZIP_EM_TRAD_PKWARE;
+        }
     }
     else {
-       zde->encryption_method = ZIP_EM_NONE;
+        zde->encryption_method = ZIP_EM_NONE;
     }
 
     zde->filename = NULL;
@@ -420,80 +420,80 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
     variable_size = (zip_uint32_t)filename_len + (zip_uint32_t)ef_len + (zip_uint32_t)comment_len;
 
     if (from_buffer) {
-       if (_zip_buffer_left(buffer) < variable_size) {
-           zip_error_set(error, ZIP_ER_INCONS, 0);
-           return -1;
-       }
+        if (_zip_buffer_left(buffer) < variable_size) {
+            zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_VARIABLE_SIZE_OVERFLOW);
+            return -1;
+        }
     }
     else {
-       _zip_buffer_free(buffer);
+        _zip_buffer_free(buffer);
 
-       if ((buffer = _zip_buffer_new_from_source(src, variable_size, NULL, error)) == NULL) {
-           return -1;
-       }
+        if ((buffer = _zip_buffer_new_from_source(src, variable_size, NULL, error)) == NULL) {
+            return -1;
+        }
     }
 
     if (filename_len) {
-       zde->filename = _zip_read_string(buffer, src, filename_len, 1, error);
-       if (!zde->filename) {
-           if (zip_error_code_zip(error) == ZIP_ER_EOF) {
-               zip_error_set(error, ZIP_ER_INCONS, 0);
-           }
-           if (!from_buffer) {
-               _zip_buffer_free(buffer);
-           }
-           return -1;
-       }
-
-       if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) {
-           if (_zip_guess_encoding(zde->filename, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) {
-               zip_error_set(error, ZIP_ER_INCONS, 0);
-               if (!from_buffer) {
-                   _zip_buffer_free(buffer);
-               }
-               return -1;
-           }
-       }
+        zde->filename = _zip_read_string(buffer, src, filename_len, 1, error);
+        if (!zde->filename) {
+            if (zip_error_code_zip(error) == ZIP_ER_EOF) {
+                zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_VARIABLE_SIZE_OVERFLOW);
+            }
+            if (!from_buffer) {
+                _zip_buffer_free(buffer);
+            }
+            return -1;
+        }
+
+        if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) {
+            if (_zip_guess_encoding(zde->filename, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) {
+                zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_UTF8_IN_FILENAME);
+                if (!from_buffer) {
+                    _zip_buffer_free(buffer);
+                }
+                return -1;
+            }
+        }
     }
 
     if (ef_len) {
-       zip_uint8_t *ef = _zip_read_data(buffer, src, ef_len, 0, error);
-
-       if (ef == NULL) {
-           if (!from_buffer) {
-               _zip_buffer_free(buffer);
-           }
-           return -1;
-       }
-       if (!_zip_ef_parse(ef, ef_len, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, &zde->extra_fields, error)) {
-           free(ef);
-           if (!from_buffer) {
-               _zip_buffer_free(buffer);
-           }
-           return -1;
-       }
-       free(ef);
-       if (local)
-           zde->local_extra_fields_read = 1;
+        zip_uint8_t *ef = _zip_read_data(buffer, src, ef_len, 0, error);
+
+        if (ef == NULL) {
+            if (!from_buffer) {
+                _zip_buffer_free(buffer);
+            }
+            return -1;
+        }
+        if (!_zip_ef_parse(ef, ef_len, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, &zde->extra_fields, error)) {
+            free(ef);
+            if (!from_buffer) {
+                _zip_buffer_free(buffer);
+            }
+            return -1;
+        }
+        free(ef);
+        if (local)
+            zde->local_extra_fields_read = 1;
     }
 
     if (comment_len) {
-       zde->comment = _zip_read_string(buffer, src, comment_len, 0, error);
-       if (!zde->comment) {
-           if (!from_buffer) {
-               _zip_buffer_free(buffer);
-           }
-           return -1;
-       }
-       if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) {
-           if (_zip_guess_encoding(zde->comment, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) {
-               zip_error_set(error, ZIP_ER_INCONS, 0);
-               if (!from_buffer) {
-                   _zip_buffer_free(buffer);
-               }
-               return -1;
-           }
-       }
+        zde->comment = _zip_read_string(buffer, src, comment_len, 0, error);
+        if (!zde->comment) {
+            if (!from_buffer) {
+                _zip_buffer_free(buffer);
+            }
+            return -1;
+        }
+        if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) {
+            if (_zip_guess_encoding(zde->comment, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) {
+                zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_UTF8_IN_COMMENT);
+                if (!from_buffer) {
+                    _zip_buffer_free(buffer);
+                }
+                return -1;
+            }
+        }
     }
 
     zde->filename = _zip_dirent_process_ef_utf_8(zde, ZIP_EF_UTF_8_NAME, zde->filename);
@@ -502,96 +502,96 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
     /* Zip64 */
 
     if (zde->uncomp_size == ZIP_UINT32_MAX || zde->comp_size == ZIP_UINT32_MAX || zde->offset == ZIP_UINT32_MAX) {
-       zip_uint16_t got_len;
-       zip_buffer_t *ef_buffer;
-       const zip_uint8_t *ef = _zip_ef_get_by_id(zde->extra_fields, &got_len, ZIP_EF_ZIP64, 0, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, error);
-       /* TODO: if got_len == 0 && !ZIP64_EOCD: no error, 0xffffffff is valid value */
-       if (ef == NULL) {
-           if (!from_buffer) {
-               _zip_buffer_free(buffer);
-           }
-           return -1;
-       }
-
-       if ((ef_buffer = _zip_buffer_new((zip_uint8_t *)ef, got_len)) == NULL) {
-           zip_error_set(error, ZIP_ER_MEMORY, 0);
-           if (!from_buffer) {
-               _zip_buffer_free(buffer);
-           }
-           return -1;
-       }
-
-       if (zde->uncomp_size == ZIP_UINT32_MAX) {
-           zde->uncomp_size = _zip_buffer_get_64(ef_buffer);
-       }
-       else if (local) {
-           /* From appnote.txt: This entry in the Local header MUST
-              include BOTH original and compressed file size fields. */
-           (void)_zip_buffer_skip(ef_buffer, 8); /* error is caught by _zip_buffer_eof() call */
-       }
-       if (zde->comp_size == ZIP_UINT32_MAX) {
-           zde->comp_size = _zip_buffer_get_64(ef_buffer);
-       }
-       if (!local) {
-           if (zde->offset == ZIP_UINT32_MAX) {
-               zde->offset = _zip_buffer_get_64(ef_buffer);
-           }
-           if (zde->disk_number == ZIP_UINT16_MAX) {
-               zde->disk_number = _zip_buffer_get_32(ef_buffer);
-           }
-       }
-
-       if (!_zip_buffer_eof(ef_buffer)) {
-           /* accept additional fields if values match */
-           bool ok = true;
-           switch (got_len) {
-           case 28:
-               _zip_buffer_set_offset(ef_buffer, 24);
-               if (zde->disk_number != _zip_buffer_get_32(ef_buffer)) {
-                   ok = false;
-               }
-               /* fallthrough */
-           case 24:
-               _zip_buffer_set_offset(ef_buffer, 0);
-               if ((zde->uncomp_size != _zip_buffer_get_64(ef_buffer)) || (zde->comp_size != _zip_buffer_get_64(ef_buffer)) || (zde->offset != _zip_buffer_get_64(ef_buffer))) {
-                   ok = false;
-               }
-               break;
-
-           default:
-               ok = false;
-           }
-           if (!ok) {
-               zip_error_set(error, ZIP_ER_INCONS, 0);
-               _zip_buffer_free(ef_buffer);
-               if (!from_buffer) {
-                   _zip_buffer_free(buffer);
-               }
-               return -1;
-           }
-       }
-       _zip_buffer_free(ef_buffer);
+        zip_uint16_t got_len;
+        zip_buffer_t *ef_buffer;
+        const zip_uint8_t *ef = _zip_ef_get_by_id(zde->extra_fields, &got_len, ZIP_EF_ZIP64, 0, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, error);
+        /* TODO: if got_len == 0 && !ZIP64_EOCD: no error, 0xffffffff is valid value */
+        if (ef == NULL) {
+            if (!from_buffer) {
+                _zip_buffer_free(buffer);
+            }
+            return -1;
+        }
+
+        if ((ef_buffer = _zip_buffer_new((zip_uint8_t *)ef, got_len)) == NULL) {
+            zip_error_set(error, ZIP_ER_MEMORY, 0);
+            if (!from_buffer) {
+                _zip_buffer_free(buffer);
+            }
+            return -1;
+        }
+
+        if (zde->uncomp_size == ZIP_UINT32_MAX) {
+            zde->uncomp_size = _zip_buffer_get_64(ef_buffer);
+        }
+        else if (local) {
+            /* From appnote.txt: This entry in the Local header MUST
+               include BOTH original and compressed file size fields. */
+            (void)_zip_buffer_skip(ef_buffer, 8); /* error is caught by _zip_buffer_eof() call */
+        }
+        if (zde->comp_size == ZIP_UINT32_MAX) {
+            zde->comp_size = _zip_buffer_get_64(ef_buffer);
+        }
+        if (!local) {
+            if (zde->offset == ZIP_UINT32_MAX) {
+                zde->offset = _zip_buffer_get_64(ef_buffer);
+            }
+            if (zde->disk_number == ZIP_UINT16_MAX) {
+                zde->disk_number = _zip_buffer_get_32(ef_buffer);
+            }
+        }
+
+        if (!_zip_buffer_eof(ef_buffer)) {
+            /* accept additional fields if values match */
+            bool ok = true;
+            switch (got_len) {
+            case 28:
+                _zip_buffer_set_offset(ef_buffer, 24);
+                if (zde->disk_number != _zip_buffer_get_32(ef_buffer)) {
+                    ok = false;
+                }
+                /* fallthrough */
+            case 24:
+                _zip_buffer_set_offset(ef_buffer, 0);
+                if ((zde->uncomp_size != _zip_buffer_get_64(ef_buffer)) || (zde->comp_size != _zip_buffer_get_64(ef_buffer)) || (zde->offset != _zip_buffer_get_64(ef_buffer))) {
+                    ok = false;
+                }
+                break;
+
+            default:
+                ok = false;
+            }
+            if (!ok) {
+                zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_ZIP64_EF);
+                _zip_buffer_free(ef_buffer);
+                if (!from_buffer) {
+                    _zip_buffer_free(buffer);
+                }
+                return -1;
+            }
+        }
+        _zip_buffer_free(ef_buffer);
     }
 
     if (!_zip_buffer_ok(buffer)) {
-       zip_error_set(error, ZIP_ER_INTERNAL, 0);
-       if (!from_buffer) {
-           _zip_buffer_free(buffer);
-       }
-       return -1;
+        zip_error_set(error, ZIP_ER_INTERNAL, 0);
+        if (!from_buffer) {
+            _zip_buffer_free(buffer);
+        }
+        return -1;
     }
     if (!from_buffer) {
-       _zip_buffer_free(buffer);
+        _zip_buffer_free(buffer);
     }
 
     /* zip_source_seek / zip_source_tell don't support values > ZIP_INT64_MAX */
     if (zde->offset > ZIP_INT64_MAX) {
-       zip_error_set(error, ZIP_ER_SEEK, EFBIG);
-       return -1;
+        zip_error_set(error, ZIP_ER_SEEK, EFBIG);
+        return -1;
     }
 
     if (!_zip_dirent_process_winzip_aes(zde, error)) {
-       return -1;
+        return -1;
     }
 
     zde->extra_fields = _zip_ef_remove_internal(zde->extra_fields);
@@ -609,24 +609,24 @@ _zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string
     const zip_uint8_t *ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, id, 0, ZIP_EF_BOTH, NULL);
 
     if (ef == NULL || ef_len < 5 || ef[0] != 1) {
-       return str;
+        return str;
     }
 
     if ((buffer = _zip_buffer_new((zip_uint8_t *)ef, ef_len)) == NULL) {
-       return str;
+        return str;
     }
 
     _zip_buffer_get_8(buffer);
     ef_crc = _zip_buffer_get_32(buffer);
 
     if (_zip_string_crc32(str) == ef_crc) {
-       zip_uint16_t len = (zip_uint16_t)_zip_buffer_left(buffer);
-       zip_string_t *ef_str = _zip_string_new(_zip_buffer_get(buffer, len), len, ZIP_FL_ENC_UTF_8, NULL);
+        zip_uint16_t len = (zip_uint16_t)_zip_buffer_left(buffer);
+        zip_string_t *ef_str = _zip_string_new(_zip_buffer_get(buffer, len), len, ZIP_FL_ENC_UTF_8, NULL);
 
-       if (ef_str != NULL) {
-           _zip_string_free(str);
-           str = ef_str;
-       }
+        if (ef_str != NULL) {
+            _zip_string_free(str);
+            str = ef_str;
+        }
     }
 
     _zip_buffer_free(buffer);
@@ -645,19 +645,19 @@ _zip_dirent_process_winzip_aes(zip_dirent_t *de, zip_error_t *error) {
 
 
     if (de->comp_method != ZIP_CM_WINZIP_AES) {
-       return true;
+        return true;
     }
 
     ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, ZIP_EF_WINZIP_AES, 0, ZIP_EF_BOTH, NULL);
 
     if (ef == NULL || ef_len < 7) {
-       zip_error_set(error, ZIP_ER_INCONS, 0);
-       return false;
+        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_WINZIPAES_EF);
+        return false;
     }
 
     if ((buffer = _zip_buffer_new((zip_uint8_t *)ef, ef_len)) == NULL) {
-       zip_error_set(error, ZIP_ER_INTERNAL, 0);
-       return false;
+        zip_error_set(error, ZIP_ER_INTERNAL, 0);
+        return false;
     }
 
     /* version */
@@ -665,48 +665,48 @@ _zip_dirent_process_winzip_aes(zip_dirent_t *de, zip_error_t *error) {
     crc_valid = true;
     switch (_zip_buffer_get_16(buffer)) {
     case 1:
-       break;
+        break;
 
     case 2:
-       if (de->uncomp_size < 20 /* TODO: constant */) {
-           crc_valid = false;
-       }
-       break;
+        if (de->uncomp_size < 20 /* TODO: constant */) {
+            crc_valid = false;
+        }
+        break;
 
     default:
-       zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
-       _zip_buffer_free(buffer);
-       return false;
+        zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
+        _zip_buffer_free(buffer);
+        return false;
     }
 
     /* vendor */
     if (memcmp(_zip_buffer_get(buffer, 2), "AE", 2) != 0) {
-       zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
-       _zip_buffer_free(buffer);
-       return false;
+        zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
+        _zip_buffer_free(buffer);
+        return false;
     }
 
     /* mode */
     switch (_zip_buffer_get_8(buffer)) {
     case 1:
-       enc_method = ZIP_EM_AES_128;
-       break;
+        enc_method = ZIP_EM_AES_128;
+        break;
     case 2:
-       enc_method = ZIP_EM_AES_192;
-       break;
+        enc_method = ZIP_EM_AES_192;
+        break;
     case 3:
-       enc_method = ZIP_EM_AES_256;
-       break;
+        enc_method = ZIP_EM_AES_256;
+        break;
     default:
-       zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
-       _zip_buffer_free(buffer);
-       return false;
+        zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
+        _zip_buffer_free(buffer);
+        return false;
     }
 
     if (ef_len != 7) {
-       zip_error_set(error, ZIP_ER_INCONS, 0);
-       _zip_buffer_free(buffer);
-       return false;
+        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_WINZIPAES_EF);
+        _zip_buffer_free(buffer);
+        return false;
     }
 
     de->crc_valid = crc_valid;
@@ -729,22 +729,22 @@ _zip_dirent_size(zip_source_t *src, zip_uint16_t flags, zip_error_t *error) {
     size = local ? LENTRYSIZE : CDENTRYSIZE;
 
     if (zip_source_seek(src, local ? 26 : 28, SEEK_CUR) < 0) {
-       _zip_error_set_from_source(error, src);
-       return -1;
+        _zip_error_set_from_source(error, src);
+        return -1;
     }
 
     if ((buffer = _zip_buffer_new_from_source(src, local ? 4 : 6, b, error)) == NULL) {
-       return -1;
+        return -1;
     }
 
     for (i = 0; i < (local ? 2 : 3); i++) {
-       size += _zip_buffer_get_16(buffer);
+        size += _zip_buffer_get_16(buffer);
     }
 
     if (!_zip_buffer_eof(buffer)) {
-       zip_error_set(error, ZIP_ER_INTERNAL, 0);
-       _zip_buffer_free(buffer);
-       return -1;
+        zip_error_set(error, ZIP_ER_INTERNAL, 0);
+        _zip_buffer_free(buffer);
+        return -1;
     }
 
     _zip_buffer_free(buffer);
@@ -781,30 +781,30 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) {
     com_enc = _zip_guess_encoding(de->comment, ZIP_ENCODING_UNKNOWN);
 
     if ((name_enc == ZIP_ENCODING_UTF8_KNOWN && com_enc == ZIP_ENCODING_ASCII) || (name_enc == ZIP_ENCODING_ASCII && com_enc == ZIP_ENCODING_UTF8_KNOWN) || (name_enc == ZIP_ENCODING_UTF8_KNOWN && com_enc == ZIP_ENCODING_UTF8_KNOWN))
-       de->bitflags |= ZIP_GPBF_ENCODING_UTF_8;
+        de->bitflags |= ZIP_GPBF_ENCODING_UTF_8;
     else {
-       de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCODING_UTF_8;
-       if (name_enc == ZIP_ENCODING_UTF8_KNOWN) {
-           ef = _zip_ef_utf8(ZIP_EF_UTF_8_NAME, de->filename, &za->error);
-           if (ef == NULL)
-               return -1;
-       }
-       if ((flags & ZIP_FL_LOCAL) == 0 && com_enc == ZIP_ENCODING_UTF8_KNOWN) {
-           zip_extra_field_t *ef2 = _zip_ef_utf8(ZIP_EF_UTF_8_COMMENT, de->comment, &za->error);
-           if (ef2 == NULL) {
-               _zip_ef_free(ef);
-               return -1;
-           }
-           ef2->next = ef;
-           ef = ef2;
-       }
+        de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCODING_UTF_8;
+        if (name_enc == ZIP_ENCODING_UTF8_KNOWN) {
+            ef = _zip_ef_utf8(ZIP_EF_UTF_8_NAME, de->filename, &za->error);
+            if (ef == NULL)
+                return -1;
+        }
+        if ((flags & ZIP_FL_LOCAL) == 0 && com_enc == ZIP_ENCODING_UTF8_KNOWN) {
+            zip_extra_field_t *ef2 = _zip_ef_utf8(ZIP_EF_UTF_8_COMMENT, de->comment, &za->error);
+            if (ef2 == NULL) {
+                _zip_ef_free(ef);
+                return -1;
+            }
+            ef2->next = ef;
+            ef = ef2;
+        }
     }
 
     if (de->encryption_method == ZIP_EM_NONE) {
-       de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCRYPTED;
+        de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCRYPTED;
     }
     else {
-       de->bitflags |= (zip_uint16_t)ZIP_GPBF_ENCRYPTED;
+        de->bitflags |= (zip_uint16_t)ZIP_GPBF_ENCRYPTED;
     }
 
     is_really_zip64 = _zip_dirent_needs_zip64(de, flags);
@@ -812,94 +812,94 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) {
     is_winzip_aes = de->encryption_method == ZIP_EM_AES_128 || de->encryption_method == ZIP_EM_AES_192 || de->encryption_method == ZIP_EM_AES_256;
 
     if (is_zip64) {
-       zip_uint8_t ef_zip64[EFZIP64SIZE];
-       zip_buffer_t *ef_buffer = _zip_buffer_new(ef_zip64, sizeof(ef_zip64));
-       if (ef_buffer == NULL) {
-           zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-           _zip_ef_free(ef);
-           return -1;
-       }
-
-       if (flags & ZIP_FL_LOCAL) {
-           if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX) {
-               _zip_buffer_put_64(ef_buffer, de->uncomp_size);
-               _zip_buffer_put_64(ef_buffer, de->comp_size);
-           }
-       }
-       else {
-           if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX || de->offset > ZIP_UINT32_MAX) {
-               if (de->uncomp_size >= ZIP_UINT32_MAX) {
-                   _zip_buffer_put_64(ef_buffer, de->uncomp_size);
-               }
-               if (de->comp_size >= ZIP_UINT32_MAX) {
-                   _zip_buffer_put_64(ef_buffer, de->comp_size);
-               }
-               if (de->offset >= ZIP_UINT32_MAX) {
-                   _zip_buffer_put_64(ef_buffer, de->offset);
-               }
-           }
-       }
-
-       if (!_zip_buffer_ok(ef_buffer)) {
-           zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
-           _zip_buffer_free(ef_buffer);
-           _zip_ef_free(ef);
-           return -1;
-       }
-
-       ef64 = _zip_ef_new(ZIP_EF_ZIP64, (zip_uint16_t)(_zip_buffer_offset(ef_buffer)), ef_zip64, ZIP_EF_BOTH);
-       _zip_buffer_free(ef_buffer);
-       ef64->next = ef;
-       ef = ef64;
+        zip_uint8_t ef_zip64[EFZIP64SIZE];
+        zip_buffer_t *ef_buffer = _zip_buffer_new(ef_zip64, sizeof(ef_zip64));
+        if (ef_buffer == NULL) {
+            zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+            _zip_ef_free(ef);
+            return -1;
+        }
+
+        if (flags & ZIP_FL_LOCAL) {
+            if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX) {
+                _zip_buffer_put_64(ef_buffer, de->uncomp_size);
+                _zip_buffer_put_64(ef_buffer, de->comp_size);
+            }
+        }
+        else {
+            if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX || de->offset > ZIP_UINT32_MAX) {
+                if (de->uncomp_size >= ZIP_UINT32_MAX) {
+                    _zip_buffer_put_64(ef_buffer, de->uncomp_size);
+                }
+                if (de->comp_size >= ZIP_UINT32_MAX) {
+                    _zip_buffer_put_64(ef_buffer, de->comp_size);
+                }
+                if (de->offset >= ZIP_UINT32_MAX) {
+                    _zip_buffer_put_64(ef_buffer, de->offset);
+                }
+            }
+        }
+
+        if (!_zip_buffer_ok(ef_buffer)) {
+            zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+            _zip_buffer_free(ef_buffer);
+            _zip_ef_free(ef);
+            return -1;
+        }
+
+        ef64 = _zip_ef_new(ZIP_EF_ZIP64, (zip_uint16_t)(_zip_buffer_offset(ef_buffer)), ef_zip64, ZIP_EF_BOTH);
+        _zip_buffer_free(ef_buffer);
+        ef64->next = ef;
+        ef = ef64;
     }
 
     if (is_winzip_aes) {
-       zip_uint8_t data[EF_WINZIP_AES_SIZE];
-       zip_buffer_t *ef_buffer = _zip_buffer_new(data, sizeof(data));
-       zip_extra_field_t *ef_winzip;
-
-       if (ef_buffer == NULL) {
-           zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-           _zip_ef_free(ef);
-           return -1;
-       }
-
-       _zip_buffer_put_16(ef_buffer, 2);
-       _zip_buffer_put(ef_buffer, "AE", 2);
-       _zip_buffer_put_8(ef_buffer, (zip_uint8_t)(de->encryption_method & 0xff));
-       _zip_buffer_put_16(ef_buffer, (zip_uint16_t)de->comp_method);
-
-       if (!_zip_buffer_ok(ef_buffer)) {
-           zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
-           _zip_buffer_free(ef_buffer);
-           _zip_ef_free(ef);
-           return -1;
-       }
-
-       ef_winzip = _zip_ef_new(ZIP_EF_WINZIP_AES, EF_WINZIP_AES_SIZE, data, ZIP_EF_BOTH);
-       _zip_buffer_free(ef_buffer);
-       ef_winzip->next = ef;
-       ef = ef_winzip;
+        zip_uint8_t data[EF_WINZIP_AES_SIZE];
+        zip_buffer_t *ef_buffer = _zip_buffer_new(data, sizeof(data));
+        zip_extra_field_t *ef_winzip;
+
+        if (ef_buffer == NULL) {
+            zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+            _zip_ef_free(ef);
+            return -1;
+        }
+
+        _zip_buffer_put_16(ef_buffer, 2);
+        _zip_buffer_put(ef_buffer, "AE", 2);
+        _zip_buffer_put_8(ef_buffer, (zip_uint8_t)(de->encryption_method & 0xff));
+        _zip_buffer_put_16(ef_buffer, (zip_uint16_t)de->comp_method);
+
+        if (!_zip_buffer_ok(ef_buffer)) {
+            zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+            _zip_buffer_free(ef_buffer);
+            _zip_ef_free(ef);
+            return -1;
+        }
+
+        ef_winzip = _zip_ef_new(ZIP_EF_WINZIP_AES, EF_WINZIP_AES_SIZE, data, ZIP_EF_BOTH);
+        _zip_buffer_free(ef_buffer);
+        ef_winzip->next = ef;
+        ef = ef_winzip;
     }
 
     if ((buffer = _zip_buffer_new(buf, sizeof(buf))) == NULL) {
-       zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-       _zip_ef_free(ef);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+        _zip_ef_free(ef);
+        return -1;
     }
 
     _zip_buffer_put(buffer, (flags & ZIP_FL_LOCAL) ? LOCAL_MAGIC : CENTRAL_MAGIC, 4);
 
     if ((flags & ZIP_FL_LOCAL) == 0) {
-       _zip_buffer_put_16(buffer, de->version_madeby);
+        _zip_buffer_put_16(buffer, de->version_madeby);
     }
     _zip_buffer_put_16(buffer, ZIP_MAX(is_really_zip64 ? 45 : 0, de->version_needed));
     _zip_buffer_put_16(buffer, de->bitflags);
     if (is_winzip_aes) {
-       _zip_buffer_put_16(buffer, ZIP_CM_WINZIP_AES);
+        _zip_buffer_put_16(buffer, ZIP_CM_WINZIP_AES);
     }
     else {
-       _zip_buffer_put_16(buffer, (zip_uint16_t)de->comp_method);
+        _zip_buffer_put_16(buffer, (zip_uint16_t)de->comp_method);
     }
 
     _zip_u2d_time(de->last_mod, &dostime, &dosdate);
@@ -907,34 +907,34 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) {
     _zip_buffer_put_16(buffer, dosdate);
 
     if (is_winzip_aes && de->uncomp_size < 20) {
-       _zip_buffer_put_32(buffer, 0);
+        _zip_buffer_put_32(buffer, 0);
     }
     else {
-       _zip_buffer_put_32(buffer, de->crc);
+        _zip_buffer_put_32(buffer, de->crc);
     }
 
     if (((flags & ZIP_FL_LOCAL) == ZIP_FL_LOCAL) && ((de->comp_size >= ZIP_UINT32_MAX) || (de->uncomp_size >= ZIP_UINT32_MAX))) {
-       /* In local headers, if a ZIP64 EF is written, it MUST contain
-        * both compressed and uncompressed sizes (even if one of the
-        * two is smaller than 0xFFFFFFFF); on the other hand, those
-        * may only appear when the corresponding standard entry is
-        * 0xFFFFFFFF.  (appnote.txt 4.5.3) */
-       _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
-       _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
+        /* In local headers, if a ZIP64 EF is written, it MUST contain
+         * both compressed and uncompressed sizes (even if one of the
+         * two is smaller than 0xFFFFFFFF); on the other hand, those
+         * may only appear when the corresponding standard entry is
+         * 0xFFFFFFFF.  (appnote.txt 4.5.3) */
+        _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
+        _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
     }
     else {
-       if (de->comp_size < ZIP_UINT32_MAX) {
-           _zip_buffer_put_32(buffer, (zip_uint32_t)de->comp_size);
-       }
-       else {
-           _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
-       }
-       if (de->uncomp_size < ZIP_UINT32_MAX) {
-           _zip_buffer_put_32(buffer, (zip_uint32_t)de->uncomp_size);
-       }
-       else {
-           _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
-       }
+        if (de->comp_size < ZIP_UINT32_MAX) {
+            _zip_buffer_put_32(buffer, (zip_uint32_t)de->comp_size);
+        }
+        else {
+            _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
+        }
+        if (de->uncomp_size < ZIP_UINT32_MAX) {
+            _zip_buffer_put_32(buffer, (zip_uint32_t)de->uncomp_size);
+        }
+        else {
+            _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
+        }
     }
 
     _zip_buffer_put_16(buffer, _zip_string_length(de->filename));
@@ -943,57 +943,57 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) {
     _zip_buffer_put_16(buffer, (zip_uint16_t)ef_total_size);
 
     if ((flags & ZIP_FL_LOCAL) == 0) {
-       _zip_buffer_put_16(buffer, _zip_string_length(de->comment));
-       _zip_buffer_put_16(buffer, (zip_uint16_t)de->disk_number);
-       _zip_buffer_put_16(buffer, de->int_attrib);
-       _zip_buffer_put_32(buffer, de->ext_attrib);
-       if (de->offset < ZIP_UINT32_MAX)
-           _zip_buffer_put_32(buffer, (zip_uint32_t)de->offset);
-       else
-           _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
+        _zip_buffer_put_16(buffer, _zip_string_length(de->comment));
+        _zip_buffer_put_16(buffer, (zip_uint16_t)de->disk_number);
+        _zip_buffer_put_16(buffer, de->int_attrib);
+        _zip_buffer_put_32(buffer, de->ext_attrib);
+        if (de->offset < ZIP_UINT32_MAX)
+            _zip_buffer_put_32(buffer, (zip_uint32_t)de->offset);
+        else
+            _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
     }
 
     if (!_zip_buffer_ok(buffer)) {
-       zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
-       _zip_buffer_free(buffer);
-       _zip_ef_free(ef);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+        _zip_buffer_free(buffer);
+        _zip_ef_free(ef);
+        return -1;
     }
 
     if (_zip_write(za, buf, _zip_buffer_offset(buffer)) < 0) {
-       _zip_buffer_free(buffer);
-       _zip_ef_free(ef);
-       return -1;
+        _zip_buffer_free(buffer);
+        _zip_ef_free(ef);
+        return -1;
     }
 
     _zip_buffer_free(buffer);
 
     if (de->filename) {
-       if (_zip_string_write(za, de->filename) < 0) {
-           _zip_ef_free(ef);
-           return -1;
-       }
+        if (_zip_string_write(za, de->filename) < 0) {
+            _zip_ef_free(ef);
+            return -1;
+        }
     }
 
     if (ef) {
-       if (_zip_ef_write(za, ef, ZIP_EF_BOTH) < 0) {
-           _zip_ef_free(ef);
-           return -1;
-       }
+        if (_zip_ef_write(za, ef, ZIP_EF_BOTH) < 0) {
+            _zip_ef_free(ef);
+            return -1;
+        }
     }
     _zip_ef_free(ef);
     if (de->extra_fields) {
-       if (_zip_ef_write(za, de->extra_fields, flags) < 0) {
-           return -1;
-       }
+        if (_zip_ef_write(za, de->extra_fields, flags) < 0) {
+            return -1;
+        }
     }
 
     if ((flags & ZIP_FL_LOCAL) == 0) {
-       if (de->comment) {
-           if (_zip_string_write(za, de->comment) < 0) {
-               return -1;
-           }
-       }
+        if (de->comment) {
+            if (_zip_string_write(za, de->comment) < 0) {
+                return -1;
+            }
+        }
     }
 
 
@@ -1030,18 +1030,18 @@ _zip_ef_utf8(zip_uint16_t id, zip_string_t *str, zip_error_t *error) {
     zip_extra_field_t *ef;
 
     if ((raw = _zip_string_get(str, &len, ZIP_FL_ENC_RAW, NULL)) == NULL) {
-       /* error already set */
-       return NULL;
+        /* error already set */
+        return NULL;
     }
 
     if (len + 5 > ZIP_UINT16_MAX) {
-       zip_error_set(error, ZIP_ER_INVAL, 0); /* TODO: better error code? */
-       return NULL;
+        zip_error_set(error, ZIP_ER_INVAL, 0); /* TODO: better error code? */
+        return NULL;
     }
 
     if ((buffer = _zip_buffer_new(NULL, len + 5)) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     _zip_buffer_put_8(buffer, 1);
@@ -1049,9 +1049,9 @@ _zip_ef_utf8(zip_uint16_t id, zip_string_t *str, zip_error_t *error) {
     _zip_buffer_put(buffer, raw, len);
 
     if (!_zip_buffer_ok(buffer)) {
-       zip_error_set(error, ZIP_ER_INTERNAL, 0);
-       _zip_buffer_free(buffer);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INTERNAL, 0);
+        _zip_buffer_free(buffer);
+        return NULL;
     }
 
     ef = _zip_ef_new(id, (zip_uint16_t)(_zip_buffer_offset(buffer)), _zip_buffer_data(buffer), ZIP_EF_BOTH);
@@ -1064,26 +1064,26 @@ _zip_ef_utf8(zip_uint16_t id, zip_string_t *str, zip_error_t *error) {
 zip_dirent_t *
 _zip_get_dirent(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *error) {
     if (error == NULL)
-       error = &za->error;
+        error = &za->error;
 
     if (idx >= za->nentry) {
-       zip_error_set(error, ZIP_ER_INVAL, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
 
     if ((flags & ZIP_FL_UNCHANGED) || za->entry[idx].changes == NULL) {
-       if (za->entry[idx].orig == NULL) {
-           zip_error_set(error, ZIP_ER_INVAL, 0);
-           return NULL;
-       }
-       if (za->entry[idx].deleted && (flags & ZIP_FL_UNCHANGED) == 0) {
-           zip_error_set(error, ZIP_ER_DELETED, 0);
-           return NULL;
-       }
-       return za->entry[idx].orig;
+        if (za->entry[idx].orig == NULL) {
+            zip_error_set(error, ZIP_ER_INVAL, 0);
+            return NULL;
+        }
+        if (za->entry[idx].deleted && (flags & ZIP_FL_UNCHANGED) == 0) {
+            zip_error_set(error, ZIP_ER_DELETED, 0);
+            return NULL;
+        }
+        return za->entry[idx].orig;
     }
     else
-       return za->entry[idx].changes;
+        return za->entry[idx].changes;
 }
 
 
@@ -1098,13 +1098,13 @@ _zip_u2d_time(time_t intime, zip_uint16_t *dtime, zip_uint16_t *ddate) {
     tpm = localtime(&intime);
 #endif
     if (tpm == NULL) {
-       /* if localtime() fails, return an arbitrary date (1980-01-01 00:00:00) */
-       *ddate = (1 << 5) + 1;
-       *dtime = 0;
-       return;
+        /* if localtime() fails, return an arbitrary date (1980-01-01 00:00:00) */
+        *ddate = (1 << 5) + 1;
+        *dtime = 0;
+        return;
     }
     if (tpm->tm_year < 80) {
-       tpm->tm_year = 80;
+        tpm->tm_year = 80;
     }
 
     *ddate = (zip_uint16_t)(((tpm->tm_year + 1900 - 1980) << 9) + ((tpm->tm_mon + 1) << 5) + tpm->tm_mday);
@@ -1119,45 +1119,45 @@ _zip_dirent_apply_attributes(zip_dirent_t *de, zip_file_attributes_t *attributes
     zip_uint16_t length;
 
     if (attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) {
-       zip_uint16_t mask = attributes->general_purpose_bit_mask & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK;
-       de->bitflags = (de->bitflags & ~mask) | (attributes->general_purpose_bit_flags & mask);
+        zip_uint16_t mask = attributes->general_purpose_bit_mask & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK;
+        de->bitflags = (de->bitflags & ~mask) | (attributes->general_purpose_bit_flags & mask);
     }
     if (attributes->valid & ZIP_FILE_ATTRIBUTES_ASCII) {
-       de->int_attrib = (de->int_attrib & ~0x1) | (attributes->ascii ? 1 : 0);
+        de->int_attrib = (de->int_attrib & ~0x1) | (attributes->ascii ? 1 : 0);
     }
     /* manually set attributes are preferred over attributes provided by source */
     if ((changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES)) {
-       de->ext_attrib = attributes->external_file_attributes;
+        de->ext_attrib = attributes->external_file_attributes;
     }
 
     if (de->comp_method == ZIP_CM_LZMA) {
-       de->version_needed = 63;
+        de->version_needed = 63;
     }
     else if (de->encryption_method == ZIP_EM_AES_128 || de->encryption_method == ZIP_EM_AES_192 || de->encryption_method == ZIP_EM_AES_256) {
-       de->version_needed = 51;
+        de->version_needed = 51;
     }
     else if (de->comp_method == ZIP_CM_BZIP2) {
-       de->version_needed = 46;
+        de->version_needed = 46;
     }
     else if (force_zip64 || _zip_dirent_needs_zip64(de, 0)) {
-       de->version_needed = 45;
+        de->version_needed = 45;
     }
     else if (de->comp_method == ZIP_CM_DEFLATE || de->encryption_method == ZIP_EM_TRAD_PKWARE) {
-       de->version_needed = 20;
+        de->version_needed = 20;
     }
     else if ((length = _zip_string_length(de->filename)) > 0 && de->filename->raw[length - 1] == '/') {
-       de->version_needed = 20;
+        de->version_needed = 20;
     }
     else {
-       de->version_needed = 10;
+        de->version_needed = 10;
     }
 
     if (attributes->valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED) {
-       de->version_needed = ZIP_MAX(de->version_needed, attributes->version_needed);
+        de->version_needed = ZIP_MAX(de->version_needed, attributes->version_needed);
     }
 
     de->version_madeby = 63 | (de->version_madeby & 0xff00);
     if ((changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM)) {
-       de->version_madeby = (de->version_madeby & 0xff) | (zip_uint16_t)(attributes->host_system << 8);
+        de->version_madeby = (de->version_madeby & 0xff) | (zip_uint16_t)(attributes->host_system << 8);
     }
 }
index 12f0636..42f4eb8 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_discard.c -- discard and free struct zip
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -46,11 +46,11 @@ zip_discard(zip_t *za) {
     zip_uint64_t i;
 
     if (za == NULL)
-       return;
+        return;
 
     if (za->src) {
-       zip_source_close(za->src);
-       zip_source_free(za->src);
+        zip_source_close(za->src);
+        zip_source_free(za->src);
     }
 
     free(za->default_password);
@@ -60,13 +60,13 @@ zip_discard(zip_t *za) {
     _zip_hash_free(za->names);
 
     if (za->entry) {
-       for (i = 0; i < za->nentry; i++)
-           _zip_entry_finalize(za->entry + i);
-       free(za->entry);
+        for (i = 0; i < za->nentry; i++)
+            _zip_entry_finalize(za->entry + i);
+        free(za->entry);
     }
 
     for (i = 0; i < za->nopen_source; i++) {
-       _zip_source_invalidate(za->open_source[i]);
+        _zip_source_invalidate(za->open_source[i]);
     }
     free(za->open_source);
 
index 52ecaef..dfc6419 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_entry.c -- struct zip_entry helper functions
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
index a0f74f0..6c7e49f 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_error.c -- zip_error_t helper functions
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -67,30 +67,31 @@ zip_error_init_with_code(zip_error_t *error, int ze) {
     zip_error_init(error);
     error->zip_err = ze;
     switch (zip_error_system_type(error)) {
-    case ZIP_ET_SYS:
-       error->sys_err = errno;
-       break;
-
-    default:
-       error->sys_err = 0;
-       break;
+        case ZIP_ET_SYS:
+        case ZIP_ET_LIBZIP:
+            error->sys_err = errno;
+            break;
+            
+        default:
+            error->sys_err = 0;
+            break;
     }
 }
 
 
 ZIP_EXTERN int
 zip_error_system_type(const zip_error_t *error) {
-    if (error->zip_err < 0 || error->zip_err >= _zip_nerr_str)
-       return ZIP_ET_NONE;
+    if (error->zip_err < 0 || error->zip_err >= _zip_err_str_count)
+        return ZIP_ET_NONE;
 
-    return _zip_err_type[error->zip_err];
+    return _zip_err_str[error->zip_err].type;
 }
 
 
 void
 _zip_error_clear(zip_error_t *err) {
     if (err == NULL)
-       return;
+        return;
 
     err->zip_err = ZIP_ER_OK;
     err->sys_err = 0;
@@ -100,7 +101,7 @@ _zip_error_clear(zip_error_t *err) {
 void
 _zip_error_copy(zip_error_t *dst, const zip_error_t *src) {
     if (dst == NULL) {
-       return;
+        return;
     }
 
     dst->zip_err = src->zip_err;
@@ -111,12 +112,12 @@ _zip_error_copy(zip_error_t *dst, const zip_error_t *src) {
 void
 _zip_error_get(const zip_error_t *err, int *zep, int *sep) {
     if (zep)
-       *zep = err->zip_err;
+        *zep = err->zip_err;
     if (sep) {
-       if (zip_error_system_type(err) != ZIP_ET_NONE)
-           *sep = err->sys_err;
-       else
-           *sep = 0;
+        if (zip_error_system_type(err) != ZIP_ET_NONE)
+            *sep = err->sys_err;
+        else
+            *sep = 0;
     }
 }
 
@@ -124,8 +125,8 @@ _zip_error_get(const zip_error_t *err, int *zep, int *sep) {
 void
 zip_error_set(zip_error_t *err, int ze, int se) {
     if (err) {
-       err->zip_err = ze;
-       err->sys_err = se;
+        err->zip_err = ze;
+        err->sys_err = se;
     }
 }
 
@@ -141,7 +142,7 @@ zip_error_to_data(const zip_error_t *error, void *data, zip_uint64_t length) {
     int *e = (int *)data;
 
     if (length < sizeof(int) * 2) {
-       return -1;
+        return -1;
     }
 
     e[0] = zip_error_code_zip(error);
index eec1568..f655539 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_error_clear.c -- clear zip error
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -38,7 +38,7 @@
 ZIP_EXTERN void
 zip_error_clear(zip_t *za) {
     if (za == NULL)
-       return;
+        return;
 
     _zip_error_clear(&za->error);
 }
index 9588b4c..f310ed3 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_error_get.c -- get zip error
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
index 3dfe5c2..d9eb47a 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_error_get_sys_type.c -- return type of system error code
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -37,8 +37,9 @@
 
 ZIP_EXTERN int
 zip_error_get_sys_type(int ze) {
-    if (ze < 0 || ze >= _zip_nerr_str)
-       return 0;
+    if (ze < 0 || ze >= _zip_err_str_count) {
+        return 0;
+    }
 
-    return _zip_err_type[ze];
+    return _zip_err_str[ze].type;
 }
index 93b24ea..c283d88 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_error_sterror.c -- get string representation of struct zip_error
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 
 #include "zipint.h"
 
-
 ZIP_EXTERN const char *
 zip_error_strerror(zip_error_t *err) {
-    const char *zs, *ss;
+    const char *zip_error_string, *system_error_string;
     char buf[128], *s;
 
     zip_error_fini(err);
 
-    if (err->zip_err < 0 || err->zip_err >= _zip_nerr_str) {
-       sprintf(buf, "Unknown error %d", err->zip_err);
-       zs = NULL;
-       ss = buf;
+    if (err->zip_err < 0 || err->zip_err >= _zip_err_str_count) {
+        snprintf(buf, sizeof(buf), "Unknown error %d", err->zip_err);
+        buf[sizeof(buf) - 1] = '\0'; /* make sure string is NUL-terminated */
+        zip_error_string = NULL;
+        system_error_string = buf;
     }
     else {
-       zs = _zip_err_str[err->zip_err];
-
-       switch (_zip_err_type[err->zip_err]) {
-       case ZIP_ET_SYS:
-           ss = strerror(err->sys_err);
-           break;
-
-       case ZIP_ET_ZLIB:
-           ss = zError(err->sys_err);
-           break;
-
-       default:
-           ss = NULL;
-       }
+        zip_error_string = _zip_err_str[err->zip_err].description;
+
+        switch (_zip_err_str[err->zip_err].type) {
+            case ZIP_ET_SYS:
+                system_error_string = strerror(err->sys_err);
+                break;
+                
+            case ZIP_ET_ZLIB:
+                system_error_string = zError(err->sys_err);
+                break;
+                
+            case ZIP_ET_LIBZIP: {
+                zip_uint8_t error = GET_ERROR_FROM_DETAIL(err->sys_err);
+                int index = GET_INDEX_FROM_DETAIL(err->sys_err);
+                
+                if (error == 0) {
+                    system_error_string = NULL;
+                }
+                else if (error >= _zip_err_details_count) {
+                    snprintf(buf, sizeof(buf), "invalid detail error %u", error);
+                    buf[sizeof(buf) - 1] = '\0'; /* make sure string is NUL-terminated */
+                    system_error_string = buf;
+                }
+                else if (_zip_err_details[error].type == ZIP_DETAIL_ET_ENTRY && index < MAX_DETAIL_INDEX) {
+                    snprintf(buf, sizeof(buf), "entry %d: %s", index, _zip_err_details[error].description);
+                    buf[sizeof(buf) - 1] = '\0'; /* make sure string is NUL-terminated */
+                    system_error_string = buf;
+                }
+                else {
+                    system_error_string = _zip_err_details[error].description;
+                }
+                break;
+            }
+                
+            default:
+                system_error_string = NULL;
+        }
     }
 
-    if (ss == NULL)
-       return zs;
+    if (system_error_string == NULL) {
+        return zip_error_string;
+    }
     else {
-       if ((s = (char *)malloc(strlen(ss) + (zs ? strlen(zs) + 2 : 0) + 1)) == NULL)
-           return _zip_err_str[ZIP_ER_MEMORY];
+        if ((s = (char *)malloc(strlen(system_error_string) + (zip_error_string ? strlen(zip_error_string) + 2 : 0) + 1)) == NULL) {
+            return _zip_err_str[ZIP_ER_MEMORY].description;
+        }
 
-       sprintf(s, "%s%s%s", (zs ? zs : ""), (zs ? ": " : ""), ss);
-       err->str = s;
+        sprintf(s, "%s%s%s", (zip_error_string ? zip_error_string : ""), (zip_error_string ? ": " : ""), system_error_string);
+        err->str = s;
 
-       return s;
+        return s;
     }
 }
index 34a3331..f13ac19 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_error_to_str.c -- get string representation of zip error code
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -44,22 +44,23 @@ ZIP_EXTERN int
 zip_error_to_str(char *buf, zip_uint64_t len, int ze, int se) {
     const char *zs, *ss;
 
-    if (ze < 0 || ze >= _zip_nerr_str)
-       return snprintf(buf, len, "Unknown error %d", ze);
-
-    zs = _zip_err_str[ze];
-
-    switch (_zip_err_type[ze]) {
-    case ZIP_ET_SYS:
-       ss = strerror(se);
-       break;
+    if (ze < 0 || ze >= _zip_err_str_count) {
+        return snprintf(buf, len, "Unknown error %d", ze);
+    }
 
-    case ZIP_ET_ZLIB:
-       ss = zError(se);
-       break;
+    zs = _zip_err_str[ze].description;
 
-    default:
-       ss = NULL;
+    switch (_zip_err_str[ze].type) {
+        case ZIP_ET_SYS:
+            ss = strerror(se);
+            break;
+            
+        case ZIP_ET_ZLIB:
+            ss = zError(se);
+            break;
+            
+        default:
+            ss = NULL;
     }
 
     return snprintf(buf, len, "%s%s%s", zs, (ss ? ": " : ""), (ss ? ss : ""));
index 7114a25..8983f75 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_extra_field.c -- manipulate extra fields
-  Copyright (C) 2012-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -44,19 +44,19 @@ _zip_ef_clone(const zip_extra_field_t *ef, zip_error_t *error) {
     head = prev = NULL;
 
     while (ef) {
-       if ((def = _zip_ef_new(ef->id, ef->size, ef->data, ef->flags)) == NULL) {
-           zip_error_set(error, ZIP_ER_MEMORY, 0);
-           _zip_ef_free(head);
-           return NULL;
-       }
-
-       if (head == NULL)
-           head = def;
-       if (prev)
-           prev->next = def;
-       prev = def;
-
-       ef = ef->next;
+        if ((def = _zip_ef_new(ef->id, ef->size, ef->data, ef->flags)) == NULL) {
+            zip_error_set(error, ZIP_ER_MEMORY, 0);
+            _zip_ef_free(head);
+            return NULL;
+        }
+
+        if (head == NULL)
+            head = def;
+        if (prev)
+            prev->next = def;
+        prev = def;
+
+        ef = ef->next;
     }
 
     return head;
@@ -72,27 +72,27 @@ _zip_ef_delete_by_id(zip_extra_field_t *ef, zip_uint16_t id, zip_uint16_t id_idx
     head = ef;
     prev = NULL;
     for (; ef; ef = (prev ? prev->next : head)) {
-       if ((ef->flags & flags & ZIP_EF_BOTH) && ((ef->id == id) || (id == ZIP_EXTRA_FIELD_ALL))) {
-           if (id_idx == ZIP_EXTRA_FIELD_ALL || i == id_idx) {
-               ef->flags &= ~(flags & ZIP_EF_BOTH);
-               if ((ef->flags & ZIP_EF_BOTH) == 0) {
-                   if (prev)
-                       prev->next = ef->next;
-                   else
-                       head = ef->next;
-                   ef->next = NULL;
-                   _zip_ef_free(ef);
-
-                   if (id_idx == ZIP_EXTRA_FIELD_ALL)
-                       continue;
-               }
-           }
-
-           i++;
-           if (i > id_idx)
-               break;
-       }
-       prev = ef;
+        if ((ef->flags & flags & ZIP_EF_BOTH) && ((ef->id == id) || (id == ZIP_EXTRA_FIELD_ALL))) {
+            if (id_idx == ZIP_EXTRA_FIELD_ALL || i == id_idx) {
+                ef->flags &= ~(flags & ZIP_EF_BOTH);
+                if ((ef->flags & ZIP_EF_BOTH) == 0) {
+                    if (prev)
+                        prev->next = ef->next;
+                    else
+                        head = ef->next;
+                    ef->next = NULL;
+                    _zip_ef_free(ef);
+
+                    if (id_idx == ZIP_EXTRA_FIELD_ALL)
+                        continue;
+                }
+            }
+
+            i++;
+            if (i > id_idx)
+                break;
+        }
+        prev = ef;
     }
 
     return head;
@@ -104,10 +104,10 @@ _zip_ef_free(zip_extra_field_t *ef) {
     zip_extra_field_t *ef2;
 
     while (ef) {
-       ef2 = ef->next;
-       free(ef->data);
-       free(ef);
-       ef = ef2;
+        ef2 = ef->next;
+        free(ef->data);
+        free(ef);
+        ef = ef2;
     }
 }
 
@@ -120,19 +120,19 @@ _zip_ef_get_by_id(const zip_extra_field_t *ef, zip_uint16_t *lenp, zip_uint16_t
 
     i = 0;
     for (; ef; ef = ef->next) {
-       if (ef->id == id && (ef->flags & flags & ZIP_EF_BOTH)) {
-           if (i < id_idx) {
-               i++;
-               continue;
-           }
-
-           if (lenp)
-               *lenp = ef->size;
-           if (ef->size > 0)
-               return ef->data;
-           else
-               return empty;
-       }
+        if (ef->id == id && (ef->flags & flags & ZIP_EF_BOTH)) {
+            if (i < id_idx) {
+                i++;
+                continue;
+            }
+
+            if (lenp)
+                *lenp = ef->size;
+            if (ef->size > 0)
+                return ef->data;
+            else
+                return empty;
+        }
     }
 
     zip_error_set(error, ZIP_ER_NOENT, 0);
@@ -146,28 +146,28 @@ _zip_ef_merge(zip_extra_field_t *to, zip_extra_field_t *from) {
     int duplicate;
 
     if (to == NULL)
-       return from;
+        return from;
 
     for (tail = to; tail->next; tail = tail->next)
-       ;
+        ;
 
     for (; from; from = ef2) {
-       ef2 = from->next;
-
-       duplicate = 0;
-       for (tt = to; tt; tt = tt->next) {
-           if (tt->id == from->id && tt->size == from->size && (tt->size == 0 || memcmp(tt->data, from->data, tt->size) == 0)) {
-               tt->flags |= (from->flags & ZIP_EF_BOTH);
-               duplicate = 1;
-               break;
-           }
-       }
-
-       from->next = NULL;
-       if (duplicate)
-           _zip_ef_free(from);
-       else
-           tail = tail->next = from;
+        ef2 = from->next;
+
+        duplicate = 0;
+        for (tt = to; tt; tt = tt->next) {
+            if (tt->id == from->id && tt->size == from->size && (tt->size == 0 || memcmp(tt->data, from->data, tt->size) == 0)) {
+                tt->flags |= (from->flags & ZIP_EF_BOTH);
+                duplicate = 1;
+                break;
+            }
+        }
+
+        from->next = NULL;
+        if (duplicate)
+            _zip_ef_free(from);
+        else
+            tail = tail->next = from;
     }
 
     return to;
@@ -179,20 +179,20 @@ _zip_ef_new(zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, zip_fla
     zip_extra_field_t *ef;
 
     if ((ef = (zip_extra_field_t *)malloc(sizeof(*ef))) == NULL)
-       return NULL;
+        return NULL;
 
     ef->next = NULL;
     ef->flags = flags;
     ef->id = id;
     ef->size = size;
     if (size > 0) {
-       if ((ef->data = (zip_uint8_t *)_zip_memdup(data, size, NULL)) == NULL) {
-           free(ef);
-           return NULL;
-       }
+        if ((ef->data = (zip_uint8_t *)_zip_memdup(data, size, NULL)) == NULL) {
+            free(ef);
+            return NULL;
+        }
     }
     else
-       ef->data = NULL;
+        ef->data = NULL;
 
     return ef;
 }
@@ -204,63 +204,63 @@ _zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_
     zip_extra_field_t *ef, *ef2, *ef_head;
 
     if ((buffer = _zip_buffer_new((zip_uint8_t *)data, len)) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return false;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return false;
     }
 
     ef_head = ef = NULL;
 
     while (_zip_buffer_ok(buffer) && _zip_buffer_left(buffer) >= 4) {
-       zip_uint16_t fid, flen;
-       zip_uint8_t *ef_data;
-
-       fid = _zip_buffer_get_16(buffer);
-       flen = _zip_buffer_get_16(buffer);
-       ef_data = _zip_buffer_get(buffer, flen);
-
-       if (ef_data == NULL) {
-           zip_error_set(error, ZIP_ER_INCONS, 0);
-           _zip_buffer_free(buffer);
-           _zip_ef_free(ef_head);
-           return false;
-       }
-
-       if ((ef2 = _zip_ef_new(fid, flen, ef_data, flags)) == NULL) {
-           zip_error_set(error, ZIP_ER_MEMORY, 0);
-           _zip_buffer_free(buffer);
-           _zip_ef_free(ef_head);
-           return false;
-       }
-
-       if (ef_head) {
-           ef->next = ef2;
-           ef = ef2;
-       }
-       else
-           ef_head = ef = ef2;
+        zip_uint16_t fid, flen;
+        zip_uint8_t *ef_data;
+
+        fid = _zip_buffer_get_16(buffer);
+        flen = _zip_buffer_get_16(buffer);
+        ef_data = _zip_buffer_get(buffer, flen);
+
+        if (ef_data == NULL) {
+            zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_EF_LENGTH);
+            _zip_buffer_free(buffer);
+            _zip_ef_free(ef_head);
+            return false;
+        }
+
+        if ((ef2 = _zip_ef_new(fid, flen, ef_data, flags)) == NULL) {
+            zip_error_set(error, ZIP_ER_MEMORY, 0);
+            _zip_buffer_free(buffer);
+            _zip_ef_free(ef_head);
+            return false;
+        }
+
+        if (ef_head) {
+            ef->next = ef2;
+            ef = ef2;
+        }
+        else
+            ef_head = ef = ef2;
     }
 
     if (!_zip_buffer_eof(buffer)) {
-       /* Android APK files align stored file data with padding in extra fields; ignore. */
-       /* see https://android.googlesource.com/platform/build/+/master/tools/zipalign/ZipAlign.cpp */
-       size_t glen = _zip_buffer_left(buffer);
-       zip_uint8_t *garbage;
-       garbage = _zip_buffer_get(buffer, glen);
-       if (glen >= 4 || garbage == NULL || memcmp(garbage, "\0\0\0", glen) != 0) {
-           zip_error_set(error, ZIP_ER_INCONS, 0);
-           _zip_buffer_free(buffer);
-           _zip_ef_free(ef_head);
-           return false;
-       }
+        /* Android APK files align stored file data with padding in extra fields; ignore. */
+        /* see https://android.googlesource.com/platform/build/+/master/tools/zipalign/ZipAlign.cpp */
+        size_t glen = _zip_buffer_left(buffer);
+        zip_uint8_t *garbage;
+        garbage = _zip_buffer_get(buffer, glen);
+        if (glen >= 4 || garbage == NULL || memcmp(garbage, "\0\0\0", glen) != 0) {
+            zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EF_TRAILING_GARBAGE);
+            _zip_buffer_free(buffer);
+            _zip_ef_free(ef_head);
+            return false;
+        }
     }
 
     _zip_buffer_free(buffer);
 
     if (ef_head_p) {
-       *ef_head_p = ef_head;
+        *ef_head_p = ef_head;
     }
     else {
-       _zip_ef_free(ef_head);
+        _zip_ef_free(ef_head);
     }
 
     return true;
@@ -276,20 +276,20 @@ _zip_ef_remove_internal(zip_extra_field_t *ef) {
     prev = NULL;
 
     while (ef) {
-       if (ZIP_EF_IS_INTERNAL(ef->id)) {
-           next = ef->next;
-           if (ef_head == ef)
-               ef_head = next;
-           ef->next = NULL;
-           _zip_ef_free(ef);
-           if (prev)
-               prev->next = next;
-           ef = next;
-       }
-       else {
-           prev = ef;
-           ef = ef->next;
-       }
+        if (ZIP_EF_IS_INTERNAL(ef->id)) {
+            next = ef->next;
+            if (ef_head == ef)
+                ef_head = next;
+            ef->next = NULL;
+            _zip_ef_free(ef);
+            if (prev)
+                prev->next = next;
+            ef = next;
+        }
+        else {
+            prev = ef;
+            ef = ef->next;
+        }
     }
 
     return ef_head;
@@ -302,8 +302,8 @@ _zip_ef_size(const zip_extra_field_t *ef, zip_flags_t flags) {
 
     size = 0;
     for (; ef; ef = ef->next) {
-       if (ef->flags & flags & ZIP_EF_BOTH)
-           size = (zip_uint16_t)(size + 4 + ef->size);
+        if (ef->flags & flags & ZIP_EF_BOTH)
+            size = (zip_uint16_t)(size + 4 + ef->size);
     }
 
     return size;
@@ -316,30 +316,30 @@ _zip_ef_write(zip_t *za, const zip_extra_field_t *ef, zip_flags_t flags) {
     zip_buffer_t *buffer = _zip_buffer_new(b, sizeof(b));
 
     if (buffer == NULL) {
-       return -1;
+        return -1;
     }
 
     for (; ef; ef = ef->next) {
-       if (ef->flags & flags & ZIP_EF_BOTH) {
-           _zip_buffer_set_offset(buffer, 0);
-           _zip_buffer_put_16(buffer, ef->id);
-           _zip_buffer_put_16(buffer, ef->size);
-           if (!_zip_buffer_ok(buffer)) {
-               zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
-               _zip_buffer_free(buffer);
-               return -1;
-           }
-           if (_zip_write(za, b, 4) < 0) {
-               _zip_buffer_free(buffer);
-               return -1;
-           }
-           if (ef->size > 0) {
-               if (_zip_write(za, ef->data, ef->size) < 0) {
-                   _zip_buffer_free(buffer);
-                   return -1;
-               }
-           }
-       }
+        if (ef->flags & flags & ZIP_EF_BOTH) {
+            _zip_buffer_set_offset(buffer, 0);
+            _zip_buffer_put_16(buffer, ef->id);
+            _zip_buffer_put_16(buffer, ef->size);
+            if (!_zip_buffer_ok(buffer)) {
+                zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+                _zip_buffer_free(buffer);
+                return -1;
+            }
+            if (_zip_write(za, b, 4) < 0) {
+                _zip_buffer_free(buffer);
+                return -1;
+            }
+            if (ef->size > 0) {
+                if (_zip_write(za, ef->data, ef->size) < 0) {
+                    _zip_buffer_free(buffer);
+                    return -1;
+                }
+            }
+        }
     }
 
     _zip_buffer_free(buffer);
@@ -355,71 +355,71 @@ _zip_read_local_ef(zip_t *za, zip_uint64_t idx) {
     zip_uint16_t fname_len, ef_len;
 
     if (idx >= za->nentry) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     e = za->entry + idx;
 
     if (e->orig == NULL || e->orig->local_extra_fields_read)
-       return 0;
+        return 0;
 
     if (e->orig->offset + 26 > ZIP_INT64_MAX) {
-       zip_error_set(&za->error, ZIP_ER_SEEK, EFBIG);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_SEEK, EFBIG);
+        return -1;
     }
 
     if (zip_source_seek(za->src, (zip_int64_t)(e->orig->offset + 26), SEEK_SET) < 0) {
-       _zip_error_set_from_source(&za->error, za->src);
-       return -1;
+        _zip_error_set_from_source(&za->error, za->src);
+        return -1;
     }
 
     if ((buffer = _zip_buffer_new_from_source(za->src, sizeof(b), b, &za->error)) == NULL) {
-       return -1;
+        return -1;
     }
 
     fname_len = _zip_buffer_get_16(buffer);
     ef_len = _zip_buffer_get_16(buffer);
 
     if (!_zip_buffer_eof(buffer)) {
-       _zip_buffer_free(buffer);
-       zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
-       return -1;
+        _zip_buffer_free(buffer);
+        zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+        return -1;
     }
 
     _zip_buffer_free(buffer);
 
     if (ef_len > 0) {
-       zip_extra_field_t *ef;
-       zip_uint8_t *ef_raw;
+        zip_extra_field_t *ef;
+        zip_uint8_t *ef_raw;
 
-       if (zip_source_seek(za->src, fname_len, SEEK_CUR) < 0) {
-           zip_error_set(&za->error, ZIP_ER_SEEK, errno);
-           return -1;
-       }
+        if (zip_source_seek(za->src, fname_len, SEEK_CUR) < 0) {
+            zip_error_set(&za->error, ZIP_ER_SEEK, errno);
+            return -1;
+        }
 
-       ef_raw = _zip_read_data(NULL, za->src, ef_len, 0, &za->error);
+        ef_raw = _zip_read_data(NULL, za->src, ef_len, 0, &za->error);
 
-       if (ef_raw == NULL)
-           return -1;
+        if (ef_raw == NULL)
+            return -1;
 
-       if (!_zip_ef_parse(ef_raw, ef_len, ZIP_EF_LOCAL, &ef, &za->error)) {
-           free(ef_raw);
-           return -1;
-       }
-       free(ef_raw);
+        if (!_zip_ef_parse(ef_raw, ef_len, ZIP_EF_LOCAL, &ef, &za->error)) {
+            free(ef_raw);
+            return -1;
+        }
+        free(ef_raw);
 
-       if (ef) {
-           ef = _zip_ef_remove_internal(ef);
-           e->orig->extra_fields = _zip_ef_merge(e->orig->extra_fields, ef);
-       }
+        if (ef) {
+            ef = _zip_ef_remove_internal(ef);
+            e->orig->extra_fields = _zip_ef_merge(e->orig->extra_fields, ef);
+        }
     }
 
     e->orig->local_extra_fields_read = 1;
 
     if (e->changes && e->changes->local_extra_fields_read == 0) {
-       e->changes->extra_fields = e->orig->extra_fields;
-       e->changes->local_extra_fields_read = 1;
+        e->changes->extra_fields = e->orig->extra_fields;
+        e->changes->local_extra_fields_read = 1;
     }
 
     return 0;
index 605f95d..9a828e4 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_extra_field_api.c -- public extra fields API functions
-  Copyright (C) 2012-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -40,25 +40,25 @@ zip_file_extra_field_delete(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_idx, zi
     zip_dirent_t *de;
 
     if ((flags & ZIP_EF_BOTH) == 0) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     if (((flags & ZIP_EF_BOTH) == ZIP_EF_BOTH) && (ef_idx != ZIP_EXTRA_FIELD_ALL)) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
-       return -1;
+        return -1;
 
     if (ZIP_IS_RDONLY(za)) {
-       zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+        return -1;
     }
 
     if (_zip_file_extra_field_prepare_for_change(za, idx) < 0)
-       return -1;
+        return -1;
 
     de = za->entry[idx].changes;
 
@@ -72,25 +72,25 @@ zip_file_extra_field_delete_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_i
     zip_dirent_t *de;
 
     if ((flags & ZIP_EF_BOTH) == 0) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     if (((flags & ZIP_EF_BOTH) == ZIP_EF_BOTH) && (ef_idx != ZIP_EXTRA_FIELD_ALL)) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
-       return -1;
+        return -1;
 
     if (ZIP_IS_RDONLY(za)) {
-       zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+        return -1;
     }
 
     if (_zip_file_extra_field_prepare_for_change(za, idx) < 0)
-       return -1;
+        return -1;
 
     de = za->entry[idx].changes;
 
@@ -108,34 +108,34 @@ zip_file_extra_field_get(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_u
     int i;
 
     if ((flags & ZIP_EF_BOTH) == 0) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return NULL;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
 
     if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL)
-       return NULL;
+        return NULL;
 
     if (flags & ZIP_FL_LOCAL)
-       if (_zip_read_local_ef(za, idx) < 0)
-           return NULL;
+        if (_zip_read_local_ef(za, idx) < 0)
+            return NULL;
 
     i = 0;
     for (ef = de->extra_fields; ef; ef = ef->next) {
-       if (ef->flags & flags & ZIP_EF_BOTH) {
-           if (i < ef_idx) {
-               i++;
-               continue;
-           }
-
-           if (idp)
-               *idp = ef->id;
-           if (lenp)
-               *lenp = ef->size;
-           if (ef->size > 0)
-               return ef->data;
-           else
-               return empty;
-       }
+        if (ef->flags & flags & ZIP_EF_BOTH) {
+            if (i < ef_idx) {
+                i++;
+                continue;
+            }
+
+            if (idp)
+                *idp = ef->id;
+            if (lenp)
+                *lenp = ef->size;
+            if (ef->size > 0)
+                return ef->data;
+            else
+                return empty;
+        }
     }
 
     zip_error_set(&za->error, ZIP_ER_NOENT, 0);
@@ -148,16 +148,16 @@ zip_file_extra_field_get_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id,
     zip_dirent_t *de;
 
     if ((flags & ZIP_EF_BOTH) == 0) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return NULL;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
 
     if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL)
-       return NULL;
+        return NULL;
 
     if (flags & ZIP_FL_LOCAL)
-       if (_zip_read_local_ef(za, idx) < 0)
-           return NULL;
+        if (_zip_read_local_ef(za, idx) < 0)
+            return NULL;
 
     return _zip_ef_get_by_id(de->extra_fields, lenp, ef_id, ef_idx, flags, &za->error);
 }
@@ -170,21 +170,21 @@ zip_file_extra_fields_count(zip_t *za, zip_uint64_t idx, zip_flags_t flags) {
     zip_uint16_t n;
 
     if ((flags & ZIP_EF_BOTH) == 0) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL)
-       return -1;
+        return -1;
 
     if (flags & ZIP_FL_LOCAL)
-       if (_zip_read_local_ef(za, idx) < 0)
-           return -1;
+        if (_zip_read_local_ef(za, idx) < 0)
+            return -1;
 
     n = 0;
     for (ef = de->extra_fields; ef; ef = ef->next)
-       if (ef->flags & flags & ZIP_EF_BOTH)
-           n++;
+        if (ef->flags & flags & ZIP_EF_BOTH)
+            n++;
 
     return (zip_int16_t)n;
 }
@@ -197,21 +197,21 @@ zip_file_extra_fields_count_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_i
     zip_uint16_t n;
 
     if ((flags & ZIP_EF_BOTH) == 0) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL)
-       return -1;
+        return -1;
 
     if (flags & ZIP_FL_LOCAL)
-       if (_zip_read_local_ef(za, idx) < 0)
-           return -1;
+        if (_zip_read_local_ef(za, idx) < 0)
+            return -1;
 
     n = 0;
     for (ef = de->extra_fields; ef; ef = ef->next)
-       if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH))
-           n++;
+        if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH))
+            n++;
 
     return (zip_int16_t)n;
 }
@@ -225,25 +225,25 @@ zip_file_extra_field_set(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_ui
     int i, found, new_len;
 
     if ((flags & ZIP_EF_BOTH) == 0) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
-       return -1;
+        return -1;
 
     if (ZIP_IS_RDONLY(za)) {
-       zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+        return -1;
     }
 
     if (ZIP_EF_IS_INTERNAL(ef_id)) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     if (_zip_file_extra_field_prepare_for_change(za, idx) < 0)
-       return -1;
+        return -1;
 
     de = za->entry[idx].changes;
 
@@ -253,67 +253,67 @@ zip_file_extra_field_set(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_ui
     found = 0;
 
     for (; ef; ef = ef->next) {
-       if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH)) {
-           if (i == ef_idx) {
-               found = 1;
-               break;
-           }
-           i++;
-       }
-       ef_prev = ef;
+        if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH)) {
+            if (i == ef_idx) {
+                found = 1;
+                break;
+            }
+            i++;
+        }
+        ef_prev = ef;
     }
 
     if (i < ef_idx && ef_idx != ZIP_EXTRA_FIELD_NEW) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     if (flags & ZIP_EF_LOCAL)
-       ls = _zip_ef_size(de->extra_fields, ZIP_EF_LOCAL);
+        ls = _zip_ef_size(de->extra_fields, ZIP_EF_LOCAL);
     else
-       ls = 0;
+        ls = 0;
     if (flags & ZIP_EF_CENTRAL)
-       cs = _zip_ef_size(de->extra_fields, ZIP_EF_CENTRAL);
+        cs = _zip_ef_size(de->extra_fields, ZIP_EF_CENTRAL);
     else
-       cs = 0;
+        cs = 0;
 
     new_len = ls > cs ? ls : cs;
     if (found)
-       new_len -= ef->size + 4;
+        new_len -= ef->size + 4;
     new_len += len + 4;
 
     if (new_len > ZIP_UINT16_MAX) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     if ((ef_new = _zip_ef_new(ef_id, len, data, flags)) == NULL) {
-       zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+        return -1;
     }
 
     if (found) {
-       if ((ef->flags & ZIP_EF_BOTH) == (flags & ZIP_EF_BOTH)) {
-           ef_new->next = ef->next;
-           ef->next = NULL;
-           _zip_ef_free(ef);
-           if (ef_prev)
-               ef_prev->next = ef_new;
-           else
-               de->extra_fields = ef_new;
-       }
-       else {
-           ef->flags &= ~(flags & ZIP_EF_BOTH);
-           ef_new->next = ef->next;
-           ef->next = ef_new;
-       }
+        if ((ef->flags & ZIP_EF_BOTH) == (flags & ZIP_EF_BOTH)) {
+            ef_new->next = ef->next;
+            ef->next = NULL;
+            _zip_ef_free(ef);
+            if (ef_prev)
+                ef_prev->next = ef_new;
+            else
+                de->extra_fields = ef_new;
+        }
+        else {
+            ef->flags &= ~(flags & ZIP_EF_BOTH);
+            ef_new->next = ef->next;
+            ef->next = ef_new;
+        }
     }
     else if (ef_prev) {
-       ef_new->next = ef_prev->next;
-       ef_prev->next = ef_new;
+        ef_new->next = ef_prev->next;
+        ef_prev->next = ef_new;
     }
     else
-       de->extra_fields = ef_new;
+        de->extra_fields = ef_new;
 
     return 0;
 }
@@ -324,30 +324,30 @@ _zip_file_extra_field_prepare_for_change(zip_t *za, zip_uint64_t idx) {
     zip_entry_t *e;
 
     if (idx >= za->nentry) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     e = za->entry + idx;
 
     if (e->changes && (e->changes->changed & ZIP_DIRENT_EXTRA_FIELD))
-       return 0;
+        return 0;
 
     if (e->orig) {
-       if (_zip_read_local_ef(za, idx) < 0)
-           return -1;
+        if (_zip_read_local_ef(za, idx) < 0)
+            return -1;
     }
 
     if (e->changes == NULL) {
-       if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
-           zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-           return -1;
-       }
+        if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
+            zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+            return -1;
+        }
     }
 
     if (e->orig && e->orig->extra_fields) {
-       if ((e->changes->extra_fields = _zip_ef_clone(e->orig->extra_fields, &za->error)) == NULL)
-           return -1;
+        if ((e->changes->extra_fields = _zip_ef_clone(e->orig->extra_fields, &za->error)) == NULL)
+            return -1;
     }
     e->changes->changed |= ZIP_DIRENT_EXTRA_FIELD;
 
index 6eb9dc9..3984b98 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_fclose.c -- close file in zip archive
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -42,11 +42,11 @@ zip_fclose(zip_file_t *zf) {
     int ret;
 
     if (zf->src)
-       zip_source_free(zf->src);
+        zip_source_free(zf->src);
 
     ret = 0;
     if (zf->error.zip_err)
-       ret = zf->error.zip_err;
+        ret = zf->error.zip_err;
 
     zip_error_fini(&zf->error);
     free(zf);
index 5a732cd..c2708c6 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_fdopen.c -- open read-only archive from file descriptor
-  Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -47,37 +47,37 @@ zip_fdopen(int fd_orig, int _flags, int *zep) {
     struct zip_error error;
 
     if (_flags < 0 || (_flags & ~(ZIP_CHECKCONS | ZIP_RDONLY))) {
-       _zip_set_open_error(zep, NULL, ZIP_ER_INVAL);
-       return NULL;
+        _zip_set_open_error(zep, NULL, ZIP_ER_INVAL);
+        return NULL;
     }
 
     /* We dup() here to avoid messing with the passed in fd.
        We could not restore it to the original state in case of error. */
 
     if ((fd = dup(fd_orig)) < 0) {
-       _zip_set_open_error(zep, NULL, ZIP_ER_OPEN);
-       return NULL;
+        _zip_set_open_error(zep, NULL, ZIP_ER_OPEN);
+        return NULL;
     }
 
     if ((fp = fdopen(fd, "rb")) == NULL) {
-       close(fd);
-       _zip_set_open_error(zep, NULL, ZIP_ER_OPEN);
-       return NULL;
+        close(fd);
+        _zip_set_open_error(zep, NULL, ZIP_ER_OPEN);
+        return NULL;
     }
 
     zip_error_init(&error);
     if ((src = zip_source_filep_create(fp, 0, -1, &error)) == NULL) {
-       fclose(fp);
-       _zip_set_open_error(zep, &error, 0);
-       zip_error_fini(&error);
-       return NULL;
+        fclose(fp);
+        _zip_set_open_error(zep, &error, 0);
+        zip_error_fini(&error);
+        return NULL;
     }
 
     if ((za = zip_open_from_source(src, _flags, &error)) == NULL) {
-       zip_source_free(src);
-       _zip_set_open_error(zep, &error, 0);
-       zip_error_fini(&error);
-       return NULL;
+        zip_source_free(src);
+        _zip_set_open_error(zep, &error, 0);
+        zip_error_fini(&error);
+        return NULL;
     }
 
     zip_error_fini(&error);
index c019d8d..02b6599 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_file_add.c -- add file via callback function
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 
 /*
   NOTE: Return type is signed so we can return -1 on error.
-       The index can not be larger than ZIP_INT64_MAX since the size
-       of the central directory cannot be larger than
-       ZIP_UINT64_MAX, and each entry is larger than 2 bytes.
+        The index can not be larger than ZIP_INT64_MAX since the size
+        of the central directory cannot be larger than
+        ZIP_UINT64_MAX, and each entry is larger than 2 bytes.
 */
 
 ZIP_EXTERN zip_int64_t
 zip_file_add(zip_t *za, const char *name, zip_source_t *source, zip_flags_t flags) {
     if (name == NULL || source == NULL) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     return _zip_file_replace(za, ZIP_UINT64_MAX, name, source, flags);
index 47e5da6..b47e3d2 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_file_error_clear.c -- clear zip file error
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -38,7 +38,7 @@
 ZIP_EXTERN void
 zip_file_error_clear(zip_file_t *zf) {
     if (zf == NULL)
-       return;
+        return;
 
     _zip_error_clear(&zf->error);
 }
index 1ed68df..cce1ac2 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_file_error_get.c -- get zip file error
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
index 8f68141..59b768a 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_file_get_comment.c -- get file comment
-  Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -43,13 +43,13 @@ zip_file_get_comment(zip_t *za, zip_uint64_t idx, zip_uint32_t *lenp, zip_flags_
     const zip_uint8_t *str;
 
     if ((de = _zip_get_dirent(za, idx, flags, NULL)) == NULL)
-       return NULL;
+        return NULL;
 
     if ((str = _zip_string_get(de->comment, &len, flags, &za->error)) == NULL)
-       return NULL;
+        return NULL;
 
     if (lenp)
-       *lenp = len;
+        *lenp = len;
 
     return (const char *)str;
 }
index ebc2058..f642918 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_file_get_external_attributes.c -- get opsys/external attributes
-  Copyright (C) 2013-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2013-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -38,13 +38,13 @@ zip_file_get_external_attributes(zip_t *za, zip_uint64_t idx, zip_flags_t flags,
     zip_dirent_t *de;
 
     if ((de = _zip_get_dirent(za, idx, flags, NULL)) == NULL)
-       return -1;
+        return -1;
 
     if (opsys)
-       *opsys = (zip_uint8_t)((de->version_madeby >> 8) & 0xff);
+        *opsys = (zip_uint8_t)((de->version_madeby >> 8) & 0xff);
 
     if (attributes)
-       *attributes = de->ext_attrib;
+        *attributes = de->ext_attrib;
 
     return 0;
 }
index 2cf4480..c9c8fd8 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_file_get_offset.c -- get offset of file data in archive.
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -50,24 +50,24 @@ _zip_file_get_offset(const zip_t *za, zip_uint64_t idx, zip_error_t *error) {
     zip_int32_t size;
 
     if (za->entry[idx].orig == NULL) {
-       zip_error_set(error, ZIP_ER_INTERNAL, 0);
-       return 0;
+        zip_error_set(error, ZIP_ER_INTERNAL, 0);
+        return 0;
     }
 
     offset = za->entry[idx].orig->offset;
 
     if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) {
-       _zip_error_set_from_source(error, za->src);
-       return 0;
+        _zip_error_set_from_source(error, za->src);
+        return 0;
     }
 
     /* TODO: cache? */
     if ((size = _zip_dirent_size(za->src, ZIP_EF_LOCAL, error)) < 0)
-       return 0;
+        return 0;
 
     if (offset + (zip_uint32_t)size > ZIP_INT64_MAX) {
-       zip_error_set(error, ZIP_ER_SEEK, EFBIG);
-       return 0;
+        zip_error_set(error, ZIP_ER_SEEK, EFBIG);
+        return 0;
     }
 
     return offset + (zip_uint32_t)size;
@@ -79,38 +79,38 @@ _zip_file_get_end(const zip_t *za, zip_uint64_t index, zip_error_t *error) {
     zip_dirent_t *entry;
 
     if ((offset = _zip_file_get_offset(za, index, error)) == 0) {
-       return 0;
+        return 0;
     }
 
     entry = za->entry[index].orig;
 
     if (offset + entry->comp_size < offset || offset + entry->comp_size > ZIP_INT64_MAX) {
-       zip_error_set(error, ZIP_ER_SEEK, EFBIG);
-       return 0;
+        zip_error_set(error, ZIP_ER_SEEK, EFBIG);
+        return 0;
     }
     offset += entry->comp_size;
 
     if (entry->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
-       zip_uint8_t buf[4];
-       if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) {
-           _zip_error_set_from_source(error, za->src);
-           return 0;
-       }
-       if (zip_source_read(za->src, buf, 4) != 4) {
-           _zip_error_set_from_source(error, za->src);
-           return 0;
-       }
-       if (memcmp(buf, DATADES_MAGIC, 4) == 0) {
-           offset += 4;
-       }
-       offset += 12;
-       if (_zip_dirent_needs_zip64(entry, 0)) {
-           offset += 8;
-       }
-       if (offset > ZIP_INT64_MAX) {
-           zip_error_set(error, ZIP_ER_SEEK, EFBIG);
-           return 0;
-       }
+        zip_uint8_t buf[4];
+        if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) {
+            _zip_error_set_from_source(error, za->src);
+            return 0;
+        }
+        if (zip_source_read(za->src, buf, 4) != 4) {
+            _zip_error_set_from_source(error, za->src);
+            return 0;
+        }
+        if (memcmp(buf, DATADES_MAGIC, 4) == 0) {
+            offset += 4;
+        }
+        offset += 12;
+        if (_zip_dirent_needs_zip64(entry, 0)) {
+            offset += 8;
+        }
+        if (offset > ZIP_INT64_MAX) {
+            zip_error_set(error, ZIP_ER_SEEK, EFBIG);
+            return 0;
+        }
     }
 
     return offset;
index 7ca428c..d65f64a 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_file_rename.c -- rename file in zip archive
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -43,24 +43,24 @@ zip_file_rename(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags
     int old_is_dir, new_is_dir;
 
     if (idx >= za->nentry || (name != NULL && strlen(name) > ZIP_UINT16_MAX)) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     if (ZIP_IS_RDONLY(za)) {
-       zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+        return -1;
     }
 
     if ((old_name = zip_get_name(za, idx, 0)) == NULL)
-       return -1;
+        return -1;
 
     new_is_dir = (name != NULL && name[strlen(name) - 1] == '/');
     old_is_dir = (old_name[strlen(old_name) - 1] == '/');
 
     if (new_is_dir != old_is_dir) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     return _zip_set_name(za, idx, name, flags);
index 87401f4..a8cf86c 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_file_replace.c -- replace file via callback function
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 ZIP_EXTERN int
 zip_file_replace(zip_t *za, zip_uint64_t idx, zip_source_t *source, zip_flags_t flags) {
     if (idx >= za->nentry || source == NULL) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     if (_zip_file_replace(za, idx, NULL, source, flags) == -1)
-       return -1;
+        return -1;
 
     return 0;
 }
@@ -56,31 +56,31 @@ _zip_file_replace(zip_t *za, zip_uint64_t idx, const char *name, zip_source_t *s
     zip_uint64_t za_nentry_prev;
 
     if (ZIP_IS_RDONLY(za)) {
-       zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+        return -1;
     }
 
     za_nentry_prev = za->nentry;
     if (idx == ZIP_UINT64_MAX) {
-       zip_int64_t i = -1;
+        zip_int64_t i = -1;
 
-       if (flags & ZIP_FL_OVERWRITE)
-           i = _zip_name_locate(za, name, flags, NULL);
+        if (flags & ZIP_FL_OVERWRITE)
+            i = _zip_name_locate(za, name, flags, NULL);
 
-       if (i == -1) {
-           /* create and use new entry, used by zip_add */
-           if ((i = _zip_add_entry(za)) < 0)
-               return -1;
-       }
-       idx = (zip_uint64_t)i;
+        if (i == -1) {
+            /* create and use new entry, used by zip_add */
+            if ((i = _zip_add_entry(za)) < 0)
+                return -1;
+        }
+        idx = (zip_uint64_t)i;
     }
 
     if (name && _zip_set_name(za, idx, name, flags) != 0) {
-       if (za->nentry != za_nentry_prev) {
-           _zip_entry_finalize(za->entry + idx);
-           za->nentry = za_nentry_prev;
-       }
-       return -1;
+        if (za->nentry != za_nentry_prev) {
+            _zip_entry_finalize(za->entry + idx);
+            za->nentry = za_nentry_prev;
+        }
+        return -1;
     }
 
     /* does not change any name related data, so we can do it here;
@@ -88,15 +88,15 @@ _zip_file_replace(zip_t *za, zip_uint64_t idx, const char *name, zip_source_t *s
     _zip_unchange_data(za->entry + idx);
 
     if (za->entry[idx].orig != NULL && (za->entry[idx].changes == NULL || (za->entry[idx].changes->changed & ZIP_DIRENT_COMP_METHOD) == 0)) {
-       if (za->entry[idx].changes == NULL) {
-           if ((za->entry[idx].changes = _zip_dirent_clone(za->entry[idx].orig)) == NULL) {
-               zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-               return -1;
-           }
-       }
-
-       za->entry[idx].changes->comp_method = ZIP_CM_REPLACED_DEFAULT;
-       za->entry[idx].changes->changed |= ZIP_DIRENT_COMP_METHOD;
+        if (za->entry[idx].changes == NULL) {
+            if ((za->entry[idx].changes = _zip_dirent_clone(za->entry[idx].orig)) == NULL) {
+                zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+                return -1;
+            }
+        }
+
+        za->entry[idx].changes->comp_method = ZIP_CM_REPLACED_DEFAULT;
+        za->entry[idx].changes->changed |= ZIP_DIRENT_COMP_METHOD;
     }
 
     za->entry[idx].source = source;
index c309db8..0276a47 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_file_set_comment.c -- set comment for file in archive
-  Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -44,57 +44,57 @@ zip_file_set_comment(zip_t *za, zip_uint64_t idx, const char *comment, zip_uint1
     int changed;
 
     if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
-       return -1;
+        return -1;
 
     if (ZIP_IS_RDONLY(za)) {
-       zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+        return -1;
     }
 
     if (len > 0 && comment == NULL) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     if (len > 0) {
-       if ((cstr = _zip_string_new((const zip_uint8_t *)comment, len, flags, &za->error)) == NULL)
-           return -1;
-       if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED)
-           cstr->encoding = ZIP_ENCODING_UTF8_KNOWN;
+        if ((cstr = _zip_string_new((const zip_uint8_t *)comment, len, flags, &za->error)) == NULL)
+            return -1;
+        if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED)
+            cstr->encoding = ZIP_ENCODING_UTF8_KNOWN;
     }
     else
-       cstr = NULL;
+        cstr = NULL;
 
     e = za->entry + idx;
 
     if (e->changes) {
-       _zip_string_free(e->changes->comment);
-       e->changes->comment = NULL;
-       e->changes->changed &= ~ZIP_DIRENT_COMMENT;
+        _zip_string_free(e->changes->comment);
+        e->changes->comment = NULL;
+        e->changes->changed &= ~ZIP_DIRENT_COMMENT;
     }
 
     if (e->orig && e->orig->comment)
-       changed = !_zip_string_equal(e->orig->comment, cstr);
+        changed = !_zip_string_equal(e->orig->comment, cstr);
     else
-       changed = (cstr != NULL);
+        changed = (cstr != NULL);
 
     if (changed) {
-       if (e->changes == NULL) {
-           if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
-               zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-               _zip_string_free(cstr);
-               return -1;
-           }
-       }
-       e->changes->comment = cstr;
-       e->changes->changed |= ZIP_DIRENT_COMMENT;
+        if (e->changes == NULL) {
+            if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
+                zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+                _zip_string_free(cstr);
+                return -1;
+            }
+        }
+        e->changes->comment = cstr;
+        e->changes->changed |= ZIP_DIRENT_COMMENT;
     }
     else {
-       _zip_string_free(cstr);
-       if (e->changes && e->changes->changed == 0) {
-           _zip_dirent_free(e->changes);
-           e->changes = NULL;
-       }
+        _zip_string_free(cstr);
+        if (e->changes && e->changes->changed == 0) {
+            _zip_dirent_free(e->changes);
+            e->changes = NULL;
+        }
     }
 
     return 0;
index a66a1b5..aa0d707 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_file_set_encryption.c -- set encryption for file in archive
-  Copyright (C) 2016-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -43,18 +43,18 @@ zip_file_set_encryption(zip_t *za, zip_uint64_t idx, zip_uint16_t method, const
     zip_uint16_t old_method;
 
     if (idx >= za->nentry) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     if (ZIP_IS_RDONLY(za)) {
-       zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+        return -1;
     }
 
     if (method != ZIP_EM_NONE && _zip_get_encryption_implementation(method, ZIP_CODEC_ENCODE) == NULL) {
-       zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
+        return -1;
     }
 
     e = za->entry + idx;
@@ -62,54 +62,54 @@ zip_file_set_encryption(zip_t *za, zip_uint64_t idx, zip_uint16_t method, const
     old_method = (e->orig == NULL ? ZIP_EM_NONE : e->orig->encryption_method);
 
     if (method == old_method && password == NULL) {
-       if (e->changes) {
-           if (e->changes->changed & ZIP_DIRENT_PASSWORD) {
-               _zip_crypto_clear(e->changes->password, strlen(e->changes->password));
-               free(e->changes->password);
-               e->changes->password = (e->orig == NULL ? NULL : e->orig->password);
-           }
-           e->changes->changed &= ~(ZIP_DIRENT_ENCRYPTION_METHOD | ZIP_DIRENT_PASSWORD);
-           if (e->changes->changed == 0) {
-               _zip_dirent_free(e->changes);
-               e->changes = NULL;
-           }
-       }
+        if (e->changes) {
+            if (e->changes->changed & ZIP_DIRENT_PASSWORD) {
+                _zip_crypto_clear(e->changes->password, strlen(e->changes->password));
+                free(e->changes->password);
+                e->changes->password = (e->orig == NULL ? NULL : e->orig->password);
+            }
+            e->changes->changed &= ~(ZIP_DIRENT_ENCRYPTION_METHOD | ZIP_DIRENT_PASSWORD);
+            if (e->changes->changed == 0) {
+                _zip_dirent_free(e->changes);
+                e->changes = NULL;
+            }
+        }
     }
     else {
-       char *our_password = NULL;
-
-       if (password) {
-           if ((our_password = strdup(password)) == NULL) {
-               zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-               return -1;
-           }
-       }
-
-       if (e->changes == NULL) {
-           if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
-               if (our_password) {
-                   _zip_crypto_clear(our_password, strlen(our_password));
-               }
-               free(our_password);
-               zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-               return -1;
-           }
-       }
-
-       e->changes->encryption_method = method;
-       e->changes->changed |= ZIP_DIRENT_ENCRYPTION_METHOD;
-       if (password) {
-           e->changes->password = our_password;
-           e->changes->changed |= ZIP_DIRENT_PASSWORD;
-       }
-       else {
-           if (e->changes->changed & ZIP_DIRENT_PASSWORD) {
-               _zip_crypto_clear(e->changes->password, strlen(e->changes->password));
-               free(e->changes->password);
-               e->changes->password = e->orig ? e->orig->password : NULL;
-               e->changes->changed &= ~ZIP_DIRENT_PASSWORD;
-           }
-       }
+        char *our_password = NULL;
+
+        if (password) {
+            if ((our_password = strdup(password)) == NULL) {
+                zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+                return -1;
+            }
+        }
+
+        if (e->changes == NULL) {
+            if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
+                if (our_password) {
+                    _zip_crypto_clear(our_password, strlen(our_password));
+                }
+                free(our_password);
+                zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+                return -1;
+            }
+        }
+
+        e->changes->encryption_method = method;
+        e->changes->changed |= ZIP_DIRENT_ENCRYPTION_METHOD;
+        if (password) {
+            e->changes->password = our_password;
+            e->changes->changed |= ZIP_DIRENT_PASSWORD;
+        }
+        else {
+            if (e->changes->changed & ZIP_DIRENT_PASSWORD) {
+                _zip_crypto_clear(e->changes->password, strlen(e->changes->password));
+                free(e->changes->password);
+                e->changes->password = e->orig ? e->orig->password : NULL;
+                e->changes->changed &= ~ZIP_DIRENT_PASSWORD;
+            }
+        }
     }
 
     return 0;
index bb2ea61..6ca01f2 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_file_set_external_attributes.c -- set external attributes for entry
-  Copyright (C) 2013-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2013-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -41,11 +41,11 @@ zip_file_set_external_attributes(zip_t *za, zip_uint64_t idx, zip_flags_t flags,
     zip_uint32_t unchanged_attributes;
 
     if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
-       return -1;
+        return -1;
 
     if (ZIP_IS_RDONLY(za)) {
-       zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+        return -1;
     }
 
     e = za->entry + idx;
@@ -56,26 +56,26 @@ zip_file_set_external_attributes(zip_t *za, zip_uint64_t idx, zip_flags_t flags,
     changed = (opsys != unchanged_opsys || attributes != unchanged_attributes);
 
     if (changed) {
-       if (e->changes == NULL) {
-           if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
-               zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-               return -1;
-           }
-       }
-       e->changes->version_madeby = (zip_uint16_t)((opsys << 8) | (e->changes->version_madeby & 0xff));
-       e->changes->ext_attrib = attributes;
-       e->changes->changed |= ZIP_DIRENT_ATTRIBUTES;
+        if (e->changes == NULL) {
+            if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
+                zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+                return -1;
+            }
+        }
+        e->changes->version_madeby = (zip_uint16_t)((opsys << 8) | (e->changes->version_madeby & 0xff));
+        e->changes->ext_attrib = attributes;
+        e->changes->changed |= ZIP_DIRENT_ATTRIBUTES;
     }
     else if (e->changes) {
-       e->changes->changed &= ~ZIP_DIRENT_ATTRIBUTES;
-       if (e->changes->changed == 0) {
-           _zip_dirent_free(e->changes);
-           e->changes = NULL;
-       }
-       else {
-           e->changes->version_madeby = (zip_uint16_t)((unchanged_opsys << 8) | (e->changes->version_madeby & 0xff));
-           e->changes->ext_attrib = unchanged_attributes;
-       }
+        e->changes->changed &= ~ZIP_DIRENT_ATTRIBUTES;
+        if (e->changes->changed == 0) {
+            _zip_dirent_free(e->changes);
+            e->changes = NULL;
+        }
+        else {
+            e->changes->version_madeby = (zip_uint16_t)((unchanged_opsys << 8) | (e->changes->version_madeby & 0xff));
+            e->changes->ext_attrib = unchanged_attributes;
+        }
     }
 
     return 0;
index 838548e..2753d59 100644 (file)
@@ -45,20 +45,20 @@ zip_file_set_mtime(zip_t *za, zip_uint64_t idx, time_t mtime, zip_flags_t flags)
     zip_entry_t *e;
 
     if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
-       return -1;
+        return -1;
 
     if (ZIP_IS_RDONLY(za)) {
-       zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+        return -1;
     }
 
     e = za->entry + idx;
 
     if (e->changes == NULL) {
-       if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
-           zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-           return -1;
-       }
+        if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
+            zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+            return -1;
+        }
     }
 
     e->changes->last_mod = mtime;
index 1fa7fff..e21c1dc 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_file_sterror.c -- get string representation of zip file error
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
index 4f1a051..513f78b 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_fopen.c -- open file in zip archive for reading
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -40,7 +40,7 @@ zip_fopen(zip_t *za, const char *fname, zip_flags_t flags) {
     zip_int64_t idx;
 
     if ((idx = zip_name_locate(za, fname, flags)) < 0)
-       return NULL;
+        return NULL;
 
     return zip_fopen_index_encrypted(za, (zip_uint64_t)idx, flags, za->default_password);
 }
index 9e9b13e..5a48437 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_fopen_encrypted.c -- open file for reading with password
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -40,7 +40,7 @@ zip_fopen_encrypted(zip_t *za, const char *fname, zip_flags_t flags, const char
     zip_int64_t idx;
 
     if ((idx = zip_name_locate(za, fname, flags)) < 0)
-       return NULL;
+        return NULL;
 
     return zip_fopen_index_encrypted(za, (zip_uint64_t)idx, flags, password);
 }
index e5205b7..1f7ce8c 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_fopen_index.c -- open file in zip archive for reading by index
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
index 6712c32..dfdeffa 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_fopen_index_encrypted.c -- open file for reading by index w/ password
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -45,18 +45,22 @@ zip_fopen_index_encrypted(zip_t *za, zip_uint64_t index, zip_flags_t flags, cons
     zip_file_t *zf;
     zip_source_t *src;
 
-    if ((src = _zip_source_zip_new(za, za, index, flags, 0, 0, password)) == NULL)
-       return NULL;
+    if (password != NULL && password[0] == '\0') {
+        password = NULL;
+    }
+    
+    if ((src = _zip_source_zip_new(za, index, flags, 0, 0, password, &za->error)) == NULL)
+        return NULL;
 
     if (zip_source_open(src) < 0) {
-       _zip_error_set_from_source(&za->error, src);
-       zip_source_free(src);
-       return NULL;
+        _zip_error_set_from_source(&za->error, src);
+        zip_source_free(src);
+        return NULL;
     }
 
     if ((zf = _zip_file_new(za)) == NULL) {
-       zip_source_free(src);
-       return NULL;
+        zip_source_free(src);
+        return NULL;
     }
 
     zf->src = src;
@@ -70,8 +74,8 @@ _zip_file_new(zip_t *za) {
     zip_file_t *zf;
 
     if ((zf = (zip_file_t *)malloc(sizeof(struct zip_file))) == NULL) {
-       zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     zf->za = za;
index 646d712..edad9d2 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_fread.c -- read from file
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -40,22 +40,22 @@ zip_fread(zip_file_t *zf, void *outbuf, zip_uint64_t toread) {
     zip_int64_t n;
 
     if (!zf)
-       return -1;
+        return -1;
 
     if (zf->error.zip_err != 0)
-       return -1;
+        return -1;
 
     if (toread > ZIP_INT64_MAX) {
-       zip_error_set(&zf->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&zf->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     if ((zf->eof) || (toread == 0))
-       return 0;
+        return 0;
 
     if ((n = zip_source_read(zf->src, outbuf, toread)) < 0) {
-       _zip_error_set_from_source(&zf->error, zf->src);
-       return -1;
+        _zip_error_set_from_source(&zf->error, zf->src);
+        return -1;
     }
 
     return n;
index dc6d978..542ca07 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_fseek.c -- seek in file
-  Copyright (C) 2016-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 ZIP_EXTERN zip_int8_t
 zip_fseek(zip_file_t *zf, zip_int64_t offset, int whence) {
     if (!zf)
-       return -1;
+        return -1;
 
     if (zf->error.zip_err != 0)
-       return -1;
+        return -1;
 
     if (zip_source_seek(zf->src, offset, whence) < 0) {
-       _zip_error_set_from_source(&zf->error, zf->src);
-       return -1;
+        _zip_error_set_from_source(&zf->error, zf->src);
+        return -1;
     }
 
     return 0;
index 944db7b..42067a1 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_ftell.c -- tell position in file
-  Copyright (C) 2016-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -39,15 +39,15 @@ zip_ftell(zip_file_t *zf) {
     zip_int64_t res;
 
     if (!zf)
-       return -1;
+        return -1;
 
     if (zf->error.zip_err != 0)
-       return -1;
+        return -1;
 
     res = zip_source_tell(zf->src);
     if (res < 0) {
-       _zip_error_set_from_source(&zf->error, zf->src);
-       return -1;
+        _zip_error_set_from_source(&zf->error, zf->src);
+        return -1;
     }
 
     return res;
index 953c6f4..6752380 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_get_archive_comment.c -- get archive comment
-  Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -44,15 +44,15 @@ zip_get_archive_comment(zip_t *za, int *lenp, zip_flags_t flags) {
     const zip_uint8_t *str;
 
     if ((flags & ZIP_FL_UNCHANGED) || (za->comment_changes == NULL))
-       comment = za->comment_orig;
+        comment = za->comment_orig;
     else
-       comment = za->comment_changes;
+        comment = za->comment_changes;
 
     if ((str = _zip_string_get(comment, &len, flags, &za->error)) == NULL)
-       return NULL;
+        return NULL;
 
     if (lenp)
-       *lenp = (int)len;
+        *lenp = (int)len;
 
     return (const char *)str;
 }
index fa4dd50..e4d412c 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_get_archive_flag.c -- get archive global flag
-  Copyright (C) 2008-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2008-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
index 3909e6f..191e805 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_get_encryption_implementation.c -- get encryption implementation
-  Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -39,24 +39,24 @@ zip_encryption_implementation
 _zip_get_encryption_implementation(zip_uint16_t em, int operation) {
     switch (em) {
     case ZIP_EM_TRAD_PKWARE:
-       return operation == ZIP_CODEC_DECODE ? zip_source_pkware_decode : zip_source_pkware_encode;
+        return operation == ZIP_CODEC_DECODE ? zip_source_pkware_decode : zip_source_pkware_encode;
 
 #if defined(HAVE_CRYPTO)
     case ZIP_EM_AES_128:
     case ZIP_EM_AES_192:
     case ZIP_EM_AES_256:
-       return operation == ZIP_CODEC_DECODE ? zip_source_winzip_aes_decode : zip_source_winzip_aes_encode;
+        return operation == ZIP_CODEC_DECODE ? zip_source_winzip_aes_decode : zip_source_winzip_aes_encode;
 #endif
 
     default:
-       return NULL;
+        return NULL;
     }
 }
 
 ZIP_EXTERN int
 zip_encryption_method_supported(zip_uint16_t method, int encode) {
     if (method == ZIP_EM_NONE) {
-       return 1;
+        return 1;
     }
     return _zip_get_encryption_implementation(method, encode ? ZIP_CODEC_ENCODE : ZIP_CODEC_DECODE) != NULL;
 }
index f800686..dd11816 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_get_file_comment.c -- get file comment
-  Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -42,8 +42,8 @@ zip_get_file_comment(zip_t *za, zip_uint64_t idx, int *lenp, int flags) {
     const char *s;
 
     if ((s = zip_file_get_comment(za, idx, &len, (zip_flags_t)flags)) != NULL) {
-       if (lenp)
-           *lenp = (int)len;
+        if (lenp)
+            *lenp = (int)len;
     }
 
     return s;
index 4344209..8777868 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_get_name.c -- get filename for a file in zip file
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -49,10 +49,10 @@ _zip_get_name(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *error
     const zip_uint8_t *str;
 
     if ((de = _zip_get_dirent(za, idx, flags, error)) == NULL)
-       return NULL;
+        return NULL;
 
     if ((str = _zip_string_get(de->filename, NULL, flags, error)) == NULL)
-       return NULL;
+        return NULL;
 
     return (const char *)str;
 }
index 410d26e..16d901c 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_get_num_entries.c -- get number of entries in archive
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -40,13 +40,13 @@ zip_get_num_entries(zip_t *za, zip_flags_t flags) {
     zip_uint64_t n;
 
     if (za == NULL)
-       return -1;
+        return -1;
 
     if (flags & ZIP_FL_UNCHANGED) {
-       n = za->nentry;
-       while (n > 0 && za->entry[n - 1].orig == NULL)
-           --n;
-       return (zip_int64_t)n;
+        n = za->nentry;
+        while (n > 0 && za->entry[n - 1].orig == NULL)
+            --n;
+        return (zip_int64_t)n;
     }
     return (zip_int64_t)za->nentry;
 }
index 4895eaa..1c6d6bb 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_get_num_files.c -- get number of files in archive
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 ZIP_EXTERN int
 zip_get_num_files(zip_t *za) {
     if (za == NULL)
-       return -1;
+        return -1;
 
     if (za->nentry > INT_MAX) {
-       zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 0);
+        return -1;
     }
 
     return (int)za->nentry;
index 3206dbf..e01d935 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_hash.c -- hash table string -> uint64
-  Copyright (C) 2015-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2015-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -67,9 +67,9 @@ struct zip_hash {
 static void
 free_list(zip_hash_entry_t *entry) {
     while (entry != NULL) {
-       zip_hash_entry_t *next = entry->next;
-       free(entry);
-       entry = next;
+        zip_hash_entry_t *next = entry->next;
+        free(entry);
+        entry = next;
     }
 }
 
@@ -80,12 +80,12 @@ hash_string(const zip_uint8_t *name) {
     zip_uint64_t value = HASH_START;
 
     if (name == NULL) {
-       return 0;
+        return 0;
     }
 
     while (*name != 0) {
-       value = (zip_uint64_t)(((value * HASH_MULTIPLIER) + (zip_uint8_t)*name) % 0x100000000ul);
-       name++;
+        value = (zip_uint64_t)(((value * HASH_MULTIPLIER) + (zip_uint8_t)*name) % 0x100000000ul);
+        name++;
     }
 
     return (zip_uint32_t)value;
@@ -98,30 +98,30 @@ hash_resize(zip_hash_t *hash, zip_uint32_t new_size, zip_error_t *error) {
     zip_hash_entry_t **new_table;
 
     if (new_size == hash->table_size) {
-       return true;
+        return true;
     }
 
     if ((new_table = (zip_hash_entry_t **)calloc(new_size, sizeof(zip_hash_entry_t *))) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return false;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return false;
     }
 
     if (hash->nentries > 0) {
-       zip_uint32_t i;
+        zip_uint32_t i;
 
-       for (i = 0; i < hash->table_size; i++) {
-           zip_hash_entry_t *entry = hash->table[i];
-           while (entry) {
-               zip_hash_entry_t *next = entry->next;
+        for (i = 0; i < hash->table_size; i++) {
+            zip_hash_entry_t *entry = hash->table[i];
+            while (entry) {
+                zip_hash_entry_t *next = entry->next;
 
-               zip_uint32_t new_index = entry->hash_value % new_size;
+                zip_uint32_t new_index = entry->hash_value % new_size;
 
-               entry->next = new_table[new_index];
-               new_table[new_index] = entry;
+                entry->next = new_table[new_index];
+                new_table[new_index] = entry;
 
-               entry = next;
-           }
-       }
+                entry = next;
+            }
+        }
     }
 
     free(hash->table);
@@ -138,14 +138,14 @@ size_for_capacity(zip_uint64_t capacity) {
     zip_uint32_t v;
 
     if (needed_size > ZIP_UINT32_MAX) {
-       v = ZIP_UINT32_MAX;
+        v = ZIP_UINT32_MAX;
     }
     else {
-       v = (zip_uint32_t)needed_size;
+        v = (zip_uint32_t)needed_size;
     }
 
     if (v > HASH_MAX_SIZE) {
-       return HASH_MAX_SIZE;
+        return HASH_MAX_SIZE;
     }
 
     /* From Bit Twiddling Hacks by Sean Eron Anderson <seander@cs.stanford.edu>
@@ -168,8 +168,8 @@ _zip_hash_new(zip_error_t *error) {
     zip_hash_t *hash;
 
     if ((hash = (zip_hash_t *)malloc(sizeof(zip_hash_t))) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     hash->table_size = 0;
@@ -185,16 +185,16 @@ _zip_hash_free(zip_hash_t *hash) {
     zip_uint32_t i;
 
     if (hash == NULL) {
-       return;
+        return;
     }
 
     if (hash->table != NULL) {
-       for (i = 0; i < hash->table_size; i++) {
-           if (hash->table[i] != NULL) {
-               free_list(hash->table[i]);
-           }
-       }
-       free(hash->table);
+        for (i = 0; i < hash->table_size; i++) {
+            if (hash->table[i] != NULL) {
+                free_list(hash->table[i]);
+            }
+        }
+        free(hash->table);
     }
     free(hash);
 }
@@ -207,51 +207,51 @@ _zip_hash_add(zip_hash_t *hash, const zip_uint8_t *name, zip_uint64_t index, zip
     zip_hash_entry_t *entry;
 
     if (hash == NULL || name == NULL || index > ZIP_INT64_MAX) {
-       zip_error_set(error, ZIP_ER_INVAL, 0);
-       return false;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return false;
     }
 
     if (hash->table_size == 0) {
-       if (!hash_resize(hash, HASH_MIN_SIZE, error)) {
-           return false;
-       }
+        if (!hash_resize(hash, HASH_MIN_SIZE, error)) {
+            return false;
+        }
     }
 
     hash_value = hash_string(name);
     table_index = hash_value % hash->table_size;
 
     for (entry = hash->table[table_index]; entry != NULL; entry = entry->next) {
-       if (entry->hash_value == hash_value && strcmp((const char *)name, (const char *)entry->name) == 0) {
-           if (((flags & ZIP_FL_UNCHANGED) && entry->orig_index != -1) || entry->current_index != -1) {
-               zip_error_set(error, ZIP_ER_EXISTS, 0);
-               return false;
-           }
-           else {
-               break;
-           }
-       }
+        if (entry->hash_value == hash_value && strcmp((const char *)name, (const char *)entry->name) == 0) {
+            if (((flags & ZIP_FL_UNCHANGED) && entry->orig_index != -1) || entry->current_index != -1) {
+                zip_error_set(error, ZIP_ER_EXISTS, 0);
+                return false;
+            }
+            else {
+                break;
+            }
+        }
     }
 
     if (entry == NULL) {
-       if ((entry = (zip_hash_entry_t *)malloc(sizeof(zip_hash_entry_t))) == NULL) {
-           zip_error_set(error, ZIP_ER_MEMORY, 0);
-           return false;
-       }
-       entry->name = name;
-       entry->next = hash->table[table_index];
-       hash->table[table_index] = entry;
-       entry->hash_value = hash_value;
-       entry->orig_index = -1;
-       hash->nentries++;
-       if (hash->nentries > hash->table_size * HASH_MAX_FILL && hash->table_size < HASH_MAX_SIZE) {
-           if (!hash_resize(hash, hash->table_size * 2, error)) {
-               return false;
-           }
-       }
+        if ((entry = (zip_hash_entry_t *)malloc(sizeof(zip_hash_entry_t))) == NULL) {
+            zip_error_set(error, ZIP_ER_MEMORY, 0);
+            return false;
+        }
+        entry->name = name;
+        entry->next = hash->table[table_index];
+        hash->table[table_index] = entry;
+        entry->hash_value = hash_value;
+        entry->orig_index = -1;
+        hash->nentries++;
+        if (hash->nentries > hash->table_size * HASH_MAX_FILL && hash->table_size < HASH_MAX_SIZE) {
+            if (!hash_resize(hash, hash->table_size * 2, error)) {
+                return false;
+            }
+        }
     }
 
     if (flags & ZIP_FL_UNCHANGED) {
-       entry->orig_index = (zip_int64_t)index;
+        entry->orig_index = (zip_int64_t)index;
     }
     entry->current_index = (zip_int64_t)index;
 
@@ -266,40 +266,40 @@ _zip_hash_delete(zip_hash_t *hash, const zip_uint8_t *name, zip_error_t *error)
     zip_hash_entry_t *entry, *previous;
 
     if (hash == NULL || name == NULL) {
-       zip_error_set(error, ZIP_ER_INVAL, 0);
-       return false;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return false;
     }
 
     if (hash->nentries > 0) {
-       hash_value = hash_string(name);
-       index = hash_value % hash->table_size;
-       previous = NULL;
-       entry = hash->table[index];
-       while (entry) {
-           if (entry->hash_value == hash_value && strcmp((const char *)name, (const char *)entry->name) == 0) {
-               if (entry->orig_index == -1) {
-                   if (previous) {
-                       previous->next = entry->next;
-                   }
-                   else {
-                       hash->table[index] = entry->next;
-                   }
-                   free(entry);
-                   hash->nentries--;
-                   if (hash->nentries < hash->table_size * HASH_MIN_FILL && hash->table_size > HASH_MIN_SIZE) {
-                       if (!hash_resize(hash, hash->table_size / 2, error)) {
-                           return false;
-                       }
-                   }
-               }
-               else {
-                   entry->current_index = -1;
-               }
-               return true;
-           }
-           previous = entry;
-           entry = entry->next;
-       }
+        hash_value = hash_string(name);
+        index = hash_value % hash->table_size;
+        previous = NULL;
+        entry = hash->table[index];
+        while (entry) {
+            if (entry->hash_value == hash_value && strcmp((const char *)name, (const char *)entry->name) == 0) {
+                if (entry->orig_index == -1) {
+                    if (previous) {
+                        previous->next = entry->next;
+                    }
+                    else {
+                        hash->table[index] = entry->next;
+                    }
+                    free(entry);
+                    hash->nentries--;
+                    if (hash->nentries < hash->table_size * HASH_MIN_FILL && hash->table_size > HASH_MIN_SIZE) {
+                        if (!hash_resize(hash, hash->table_size / 2, error)) {
+                            return false;
+                        }
+                    }
+                }
+                else {
+                    entry->current_index = -1;
+                }
+                return true;
+            }
+            previous = entry;
+            entry = entry->next;
+        }
     }
 
     zip_error_set(error, ZIP_ER_NOENT, 0);
@@ -314,28 +314,28 @@ _zip_hash_lookup(zip_hash_t *hash, const zip_uint8_t *name, zip_flags_t flags, z
     zip_hash_entry_t *entry;
 
     if (hash == NULL || name == NULL) {
-       zip_error_set(error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     if (hash->nentries > 0) {
-       hash_value = hash_string(name);
-       index = hash_value % hash->table_size;
-       for (entry = hash->table[index]; entry != NULL; entry = entry->next) {
-           if (strcmp((const char *)name, (const char *)entry->name) == 0) {
-               if (flags & ZIP_FL_UNCHANGED) {
-                   if (entry->orig_index != -1) {
-                       return entry->orig_index;
-                   }
-               }
-               else {
-                   if (entry->current_index != -1) {
-                       return entry->current_index;
-                   }
-               }
-               break;
-           }
-       }
+        hash_value = hash_string(name);
+        index = hash_value % hash->table_size;
+        for (entry = hash->table[index]; entry != NULL; entry = entry->next) {
+            if (strcmp((const char *)name, (const char *)entry->name) == 0) {
+                if (flags & ZIP_FL_UNCHANGED) {
+                    if (entry->orig_index != -1) {
+                        return entry->orig_index;
+                    }
+                }
+                else {
+                    if (entry->current_index != -1) {
+                        return entry->current_index;
+                    }
+                }
+                break;
+            }
+        }
     }
 
     zip_error_set(error, ZIP_ER_NOENT, 0);
@@ -348,17 +348,17 @@ _zip_hash_reserve_capacity(zip_hash_t *hash, zip_uint64_t capacity, zip_error_t
     zip_uint32_t new_size;
 
     if (capacity == 0) {
-       return true;
+        return true;
     }
 
     new_size = size_for_capacity(capacity);
 
     if (new_size <= hash->table_size) {
-       return true;
+        return true;
     }
 
     if (!hash_resize(hash, new_size, error)) {
-       return false;
+        return false;
     }
 
     return true;
@@ -371,39 +371,39 @@ _zip_hash_revert(zip_hash_t *hash, zip_error_t *error) {
     zip_hash_entry_t *entry, *previous;
 
     for (i = 0; i < hash->table_size; i++) {
-       previous = NULL;
-       entry = hash->table[i];
-       while (entry) {
-           if (entry->orig_index == -1) {
-               zip_hash_entry_t *p;
-               if (previous) {
-                   previous->next = entry->next;
-               }
-               else {
-                   hash->table[i] = entry->next;
-               }
-               p = entry;
-               entry = entry->next;
-               /* previous does not change */
-               free(p);
-               hash->nentries--;
-           }
-           else {
-               entry->current_index = entry->orig_index;
-               previous = entry;
-               entry = entry->next;
-           }
-       }
+        previous = NULL;
+        entry = hash->table[i];
+        while (entry) {
+            if (entry->orig_index == -1) {
+                zip_hash_entry_t *p;
+                if (previous) {
+                    previous->next = entry->next;
+                }
+                else {
+                    hash->table[i] = entry->next;
+                }
+                p = entry;
+                entry = entry->next;
+                /* previous does not change */
+                free(p);
+                hash->nentries--;
+            }
+            else {
+                entry->current_index = entry->orig_index;
+                previous = entry;
+                entry = entry->next;
+            }
+        }
     }
 
     if (hash->nentries < hash->table_size * HASH_MIN_FILL && hash->table_size > HASH_MIN_SIZE) {
-       zip_uint32_t new_size = hash->table_size / 2;
-       while (hash->nentries < new_size * HASH_MIN_FILL && new_size > HASH_MIN_SIZE) {
-           new_size /= 2;
-       }
-       if (!hash_resize(hash, new_size, error)) {
-           return false;
-       }
+        zip_uint32_t new_size = hash->table_size / 2;
+        while (hash->nentries < new_size * HASH_MIN_FILL && new_size > HASH_MIN_SIZE) {
+            new_size /= 2;
+        }
+        if (!hash_resize(hash, new_size, error)) {
+            return false;
+        }
     }
 
     return true;
index dd07cbb..3ee3670 100644 (file)
@@ -1,6 +1,6 @@
 /*
  zip_io_util.c -- I/O helper functions
- Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
  This file is part of libzip, a library to manipulate ZIP archives.
  The authors can be contacted at <libzip@nih.at>
@@ -41,18 +41,18 @@ _zip_read(zip_source_t *src, zip_uint8_t *b, zip_uint64_t length, zip_error_t *e
     zip_int64_t n;
 
     if (length > ZIP_INT64_MAX) {
-       zip_error_set(error, ZIP_ER_INTERNAL, 0);
-       return -1;
+        zip_error_set(error, ZIP_ER_INTERNAL, 0);
+        return -1;
     }
 
     if ((n = zip_source_read(src, b, length)) < 0) {
-       _zip_error_set_from_source(error, src);
-       return -1;
+        _zip_error_set_from_source(error, src);
+        return -1;
     }
 
     if (n < (zip_int64_t)length) {
-       zip_error_set(error, ZIP_ER_EOF, 0);
-       return -1;
+        zip_error_set(error, ZIP_ER_EOF, 0);
+        return -1;
     }
 
     return 0;
@@ -64,39 +64,39 @@ _zip_read_data(zip_buffer_t *buffer, zip_source_t *src, size_t length, bool nulp
     zip_uint8_t *r;
 
     if (length == 0 && !nulp) {
-       return NULL;
+        return NULL;
     }
 
     r = (zip_uint8_t *)malloc(length + (nulp ? 1 : 0));
     if (!r) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     if (buffer) {
-       zip_uint8_t *data = _zip_buffer_get(buffer, length);
-
-       if (data == NULL) {
-           zip_error_set(error, ZIP_ER_MEMORY, 0);
-           free(r);
-           return NULL;
-       }
-       memcpy(r, data, length);
+        zip_uint8_t *data = _zip_buffer_get(buffer, length);
+
+        if (data == NULL) {
+            zip_error_set(error, ZIP_ER_MEMORY, 0);
+            free(r);
+            return NULL;
+        }
+        memcpy(r, data, length);
     }
     else {
-       if (_zip_read(src, r, length, error) < 0) {
-           free(r);
-           return NULL;
-       }
+        if (_zip_read(src, r, length, error) < 0) {
+            free(r);
+            return NULL;
+        }
     }
 
     if (nulp) {
-       zip_uint8_t *o;
-       /* replace any in-string NUL characters with spaces */
-       r[length] = 0;
-       for (o = r; o < r + length; o++)
-           if (*o == '\0')
-               *o = ' ';
+        zip_uint8_t *o;
+        /* replace any in-string NUL characters with spaces */
+        r[length] = 0;
+        for (o = r; o < r + length; o++)
+            if (*o == '\0')
+                *o = ' ';
     }
 
     return r;
@@ -109,7 +109,7 @@ _zip_read_string(zip_buffer_t *buffer, zip_source_t *src, zip_uint16_t len, bool
     zip_string_t *s;
 
     if ((raw = _zip_read_data(buffer, src, len, nulp, error)) == NULL)
-       return NULL;
+        return NULL;
 
     s = _zip_string_new(raw, len, ZIP_FL_ENC_GUESS, error);
     free(raw);
@@ -122,12 +122,12 @@ _zip_write(zip_t *za, const void *data, zip_uint64_t length) {
     zip_int64_t n;
 
     if ((n = zip_source_write(za->src, data, length)) < 0) {
-       _zip_error_set_from_source(&za->error, za->src);
-       return -1;
+        _zip_error_set_from_source(&za->error, za->src);
+        return -1;
     }
     if ((zip_uint64_t)n != length) {
-       zip_error_set(&za->error, ZIP_ER_WRITE, EINTR);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_WRITE, EINTR);
+        return -1;
     }
 
     return 0;
index fadbc69..6e20724 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_libzip_version.c -- return run-time version of library
-  Copyright (C) 2017-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
index 05fcb7b..8f6175b 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_memdup.c -- internal zip function, "strdup" with len
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -42,12 +42,12 @@ _zip_memdup(const void *mem, size_t len, zip_error_t *error) {
     void *ret;
 
     if (len == 0)
-       return NULL;
+        return NULL;
 
     ret = malloc(len);
     if (!ret) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     memcpy(ret, mem, len);
index c1afade..ccdd62a 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_mkstempm.c -- mkstemp replacement that accepts a mode argument
-  Copyright (C) 2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2019-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -52,42 +52,42 @@ _zip_mkstempm(char *path, int mode) {
     end = path + strlen(path);
     start = end - 1;
     while (start >= path && *start == 'X') {
-       xcnt++;
-       start--;
+        xcnt++;
+        start--;
     }
 
     if (xcnt == 0) {
-       errno = EINVAL;
-       return -1;
+        errno = EINVAL;
+        return -1;
     }
 
     start++;
 
     for (;;) {
-       zip_uint32_t value = zip_random_uint32();
+        zip_uint32_t value = zip_random_uint32();
 
-       xs = start;
+        xs = start;
 
-       while (xs < end) {
-           char digit = value % 36;
-           if (digit < 10) {
-               *(xs++) = digit + '0';
-           }
-           else {
-               *(xs++) = digit - 10 + 'a';
-           }
-           value /= 36;
-       }
+        while (xs < end) {
+            char digit = value % 36;
+            if (digit < 10) {
+                *(xs++) = digit + '0';
+            }
+            else {
+                *(xs++) = digit - 10 + 'a';
+            }
+            value /= 36;
+        }
 
-       if ((fd = open(path, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, mode == -1 ? 0666 : (mode_t)mode)) >= 0) {
-           if (mode != -1) {
-               /* open() honors umask(), which we don't want in this case */
-               (void)chmod(path, (mode_t)mode);
-           }
-           return fd;
-       }
-       if (errno != EEXIST) {
-           return -1;
-       }
+        if ((fd = open(path, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, mode == -1 ? 0666 : (mode_t)mode)) >= 0) {
+            if (mode != -1) {
+                /* open() honors umask(), which we don't want in this case */
+                (void)chmod(path, (mode_t)mode);
+            }
+            return fd;
+        }
+        if (errno != EEXIST) {
+            return -1;
+        }
     }
 }
index f7318ec..8a88404 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_name_locate.c -- get index by name
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -53,40 +53,40 @@ _zip_name_locate(zip_t *za, const char *fname, zip_flags_t flags, zip_error_t *e
     zip_uint64_t i;
 
     if (za == NULL)
-       return -1;
+        return -1;
 
     if (fname == NULL) {
-       zip_error_set(error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     if (flags & (ZIP_FL_NOCASE | ZIP_FL_NODIR | ZIP_FL_ENC_CP437)) {
-       /* can't use hash table */
-       cmp = (flags & ZIP_FL_NOCASE) ? strcasecmp : strcmp;
-
-       for (i = 0; i < za->nentry; i++) {
-           fn = _zip_get_name(za, i, flags, error);
-
-           /* newly added (partially filled) entry or error */
-           if (fn == NULL)
-               continue;
-
-           if (flags & ZIP_FL_NODIR) {
-               p = strrchr(fn, '/');
-               if (p)
-                   fn = p + 1;
-           }
-
-           if (cmp(fname, fn) == 0) {
-               _zip_error_clear(error);
-               return (zip_int64_t)i;
-           }
-       }
-
-       zip_error_set(error, ZIP_ER_NOENT, 0);
-       return -1;
+        /* can't use hash table */
+        cmp = (flags & ZIP_FL_NOCASE) ? strcasecmp : strcmp;
+
+        for (i = 0; i < za->nentry; i++) {
+            fn = _zip_get_name(za, i, flags, error);
+
+            /* newly added (partially filled) entry or error */
+            if (fn == NULL)
+                continue;
+
+            if (flags & ZIP_FL_NODIR) {
+                p = strrchr(fn, '/');
+                if (p)
+                    fn = p + 1;
+            }
+
+            if (cmp(fname, fn) == 0) {
+                _zip_error_clear(error);
+                return (zip_int64_t)i;
+            }
+        }
+
+        zip_error_set(error, ZIP_ER_NOENT, 0);
+        return -1;
     }
     else {
-       return _zip_hash_lookup(za->names, (const zip_uint8_t *)fname, flags, error);
+        return _zip_hash_lookup(za->names, (const zip_uint8_t *)fname, flags, error);
     }
 }
index 4f58ecc..3768d5b 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_new.c -- create and init struct zip
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -47,13 +47,13 @@ _zip_new(zip_error_t *error) {
 
     za = (zip_t *)malloc(sizeof(struct zip));
     if (!za) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     if ((za->names = _zip_hash_new(error)) == NULL) {
-       free(za);
-       return NULL;
+        free(za);
+        return NULL;
     }
 
     za->src = NULL;
index 019cd98..1d2f69a 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_open.c -- open zip archive by name
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -58,16 +58,16 @@ zip_open(const char *fn, int _flags, int *zep) {
 
     zip_error_init(&error);
     if ((src = zip_source_file_create(fn, 0, -1, &error)) == NULL) {
-       _zip_set_open_error(zep, &error, 0);
-       zip_error_fini(&error);
-       return NULL;
+        _zip_set_open_error(zep, &error, 0);
+        zip_error_fini(&error);
+        return NULL;
     }
 
     if ((za = zip_open_from_source(src, _flags, &error)) == NULL) {
-       zip_source_free(src);
-       _zip_set_open_error(zep, &error, 0);
-       zip_error_fini(&error);
-       return NULL;
+        zip_source_free(src);
+        _zip_set_open_error(zep, &error, 0);
+        zip_error_fini(&error);
+        return NULL;
     }
 
     zip_error_fini(&error);
@@ -85,65 +85,65 @@ zip_open_from_source(zip_source_t *src, int _flags, zip_error_t *error) {
     exists_t exists;
 
     if (_flags < 0 || src == NULL) {
-       zip_error_set(error, ZIP_ER_INVAL, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
     flags = (unsigned int)_flags;
 
     supported = zip_source_supports(src);
     if (needed_support_read == -1) {
-       needed_support_read = zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_SEEK, ZIP_SOURCE_TELL, ZIP_SOURCE_STAT, -1);
-       needed_support_write = zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, -1);
+        needed_support_read = zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_SEEK, ZIP_SOURCE_TELL, ZIP_SOURCE_STAT, -1);
+        needed_support_write = zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, -1);
     }
     if ((supported & needed_support_read) != needed_support_read) {
-       zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
+        return NULL;
     }
     if ((supported & needed_support_write) != needed_support_write) {
-       flags |= ZIP_RDONLY;
+        flags |= ZIP_RDONLY;
     }
 
     if ((flags & (ZIP_RDONLY | ZIP_TRUNCATE)) == (ZIP_RDONLY | ZIP_TRUNCATE)) {
-       zip_error_set(error, ZIP_ER_RDONLY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_RDONLY, 0);
+        return NULL;
     }
 
     exists = _zip_file_exists(src, error);
     switch (exists) {
     case EXISTS_ERROR:
-       return NULL;
+        return NULL;
 
     case EXISTS_NOT:
-       if ((flags & ZIP_CREATE) == 0) {
-           zip_error_set(error, ZIP_ER_NOENT, 0);
-           return NULL;
-       }
-       return _zip_allocate_new(src, flags, error);
+        if ((flags & ZIP_CREATE) == 0) {
+            zip_error_set(error, ZIP_ER_NOENT, 0);
+            return NULL;
+        }
+        return _zip_allocate_new(src, flags, error);
 
     default: {
-       zip_t *za;
-       if (flags & ZIP_EXCL) {
-           zip_error_set(error, ZIP_ER_EXISTS, 0);
-           return NULL;
-       }
-       if (zip_source_open(src) < 0) {
-           _zip_error_set_from_source(error, src);
-           return NULL;
-       }
-
-       if (flags & ZIP_TRUNCATE) {
-           za = _zip_allocate_new(src, flags, error);
-       }
-       else {
-           /* ZIP_CREATE gets ignored if file exists and not ZIP_EXCL, just like open() */
-           za = _zip_open(src, flags, error);
-       }
-
-       if (za == NULL) {
-           zip_source_close(src);
-           return NULL;
-       }
-       return za;
+        zip_t *za;
+        if (flags & ZIP_EXCL) {
+            zip_error_set(error, ZIP_ER_EXISTS, 0);
+            return NULL;
+        }
+        if (zip_source_open(src) < 0) {
+            _zip_error_set_from_source(error, src);
+            return NULL;
+        }
+
+        if (flags & ZIP_TRUNCATE) {
+            za = _zip_allocate_new(src, flags, error);
+        }
+        else {
+            /* ZIP_CREATE gets ignored if file exists and not ZIP_EXCL, just like open() */
+            za = _zip_open(src, flags, error);
+        }
+
+        if (za == NULL) {
+            zip_source_close(src);
+            return NULL;
+        }
+        return za;
     }
     }
 }
@@ -158,31 +158,31 @@ _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error) {
 
     zip_stat_init(&st);
     if (zip_source_stat(src, &st) < 0) {
-       _zip_error_set_from_source(error, src);
-       return NULL;
+        _zip_error_set_from_source(error, src);
+        return NULL;
     }
     if ((st.valid & ZIP_STAT_SIZE) == 0) {
-       zip_error_set(error, ZIP_ER_SEEK, EOPNOTSUPP);
-       return NULL;
+        zip_error_set(error, ZIP_ER_SEEK, EOPNOTSUPP);
+        return NULL;
     }
     len = st.size;
 
 
     if ((za = _zip_allocate_new(src, flags, error)) == NULL) {
-       return NULL;
+        return NULL;
     }
 
     /* treat empty files as empty archives */
     if (len == 0 && zip_source_accept_empty(src)) {
-       return za;
+        return za;
     }
 
     if ((cdir = _zip_find_central_dir(za, len)) == NULL) {
-       _zip_error_copy(error, &za->error);
-       /* keep src so discard does not get rid of it */
-       zip_source_keep(src);
-       zip_discard(za);
-       return NULL;
+        _zip_error_copy(error, &za->error);
+        /* keep src so discard does not get rid of it */
+        zip_source_keep(src);
+        zip_discard(za);
+        return NULL;
     }
 
     za->entry = cdir->entry;
@@ -195,23 +195,23 @@ _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error) {
     _zip_hash_reserve_capacity(za->names, za->nentry, &za->error);
 
     for (idx = 0; idx < za->nentry; idx++) {
-       const zip_uint8_t *name = _zip_string_get(za->entry[idx].orig->filename, NULL, 0, error);
-       if (name == NULL) {
-           /* keep src so discard does not get rid of it */
-           zip_source_keep(src);
-           zip_discard(za);
-           return NULL;
-       }
-
-       if (_zip_hash_add(za->names, name, idx, ZIP_FL_UNCHANGED, &za->error) == false) {
-           if (za->error.zip_err != ZIP_ER_EXISTS || (flags & ZIP_CHECKCONS)) {
-               _zip_error_copy(error, &za->error);
-               /* keep src so discard does not get rid of it */
-               zip_source_keep(src);
-               zip_discard(za);
-               return NULL;
-           }
-       }
+        const zip_uint8_t *name = _zip_string_get(za->entry[idx].orig->filename, NULL, 0, error);
+        if (name == NULL) {
+            /* keep src so discard does not get rid of it */
+            zip_source_keep(src);
+            zip_discard(za);
+            return NULL;
+        }
+
+        if (_zip_hash_add(za->names, name, idx, ZIP_FL_UNCHANGED, &za->error) == false) {
+            if (za->error.zip_err != ZIP_ER_EXISTS || (flags & ZIP_CHECKCONS)) {
+                _zip_error_copy(error, &za->error);
+                /* keep src so discard does not get rid of it */
+                zip_source_keep(src);
+                zip_discard(za);
+                return NULL;
+            }
+        }
     }
 
     za->ch_flags = za->flags;
@@ -223,14 +223,20 @@ _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error) {
 void
 _zip_set_open_error(int *zep, const zip_error_t *err, int ze) {
     if (err) {
-       ze = zip_error_code_zip(err);
-       if (zip_error_system_type(err) == ZIP_ET_SYS) {
-           errno = zip_error_code_system(err);
-       }
+        ze = zip_error_code_zip(err);
+       switch (zip_error_system_type(err)) {
+           case ZIP_ET_SYS:
+           case ZIP_ET_LIBZIP:
+               errno = zip_error_code_system(err);
+               break;
+               
+           default:
+               break;
+        }
     }
 
     if (zep)
-       *zep = ze;
+        *zep = ze;
 }
 
 
@@ -249,156 +255,159 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_err
     zip_buffer_t *cd_buffer;
 
     if (_zip_buffer_left(buffer) < EOCDLEN) {
-       /* not enough bytes left for comment */
-       zip_error_set(error, ZIP_ER_NOZIP, 0);
-       return NULL;
+        /* not enough bytes left for comment */
+        zip_error_set(error, ZIP_ER_NOZIP, 0);
+        return NULL;
     }
 
     /* check for end-of-central-dir magic */
     if (memcmp(_zip_buffer_get(buffer, 4), EOCD_MAGIC, 4) != 0) {
-       zip_error_set(error, ZIP_ER_NOZIP, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_NOZIP, 0);
+        return NULL;
     }
 
     if (eocd_offset >= EOCD64LOCLEN && memcmp(_zip_buffer_data(buffer) + eocd_offset - EOCD64LOCLEN, EOCD64LOC_MAGIC, 4) == 0) {
-       _zip_buffer_set_offset(buffer, eocd_offset - EOCD64LOCLEN);
-       cd = _zip_read_eocd64(za->src, buffer, buf_offset, za->flags, error);
+        _zip_buffer_set_offset(buffer, eocd_offset - EOCD64LOCLEN);
+        cd = _zip_read_eocd64(za->src, buffer, buf_offset, za->flags, error);
     }
     else {
-       _zip_buffer_set_offset(buffer, eocd_offset);
-       cd = _zip_read_eocd(buffer, buf_offset, za->flags, error);
+        _zip_buffer_set_offset(buffer, eocd_offset);
+        cd = _zip_read_eocd(buffer, buf_offset, za->flags, error);
     }
 
     if (cd == NULL)
-       return NULL;
+        return NULL;
 
     _zip_buffer_set_offset(buffer, eocd_offset + 20);
     comment_len = _zip_buffer_get_16(buffer);
 
     if (cd->offset + cd->size > buf_offset + eocd_offset) {
-       /* cdir spans past EOCD record */
-       zip_error_set(error, ZIP_ER_INCONS, 0);
-       _zip_cdir_free(cd);
-       return NULL;
+        /* cdir spans past EOCD record */
+        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_OVERLAPS_EOCD);
+        _zip_cdir_free(cd);
+        return NULL;
     }
 
     if (comment_len || (za->open_flags & ZIP_CHECKCONS)) {
-       zip_uint64_t tail_len;
+        zip_uint64_t tail_len;
 
-       _zip_buffer_set_offset(buffer, eocd_offset + EOCDLEN);
-       tail_len = _zip_buffer_left(buffer);
+        _zip_buffer_set_offset(buffer, eocd_offset + EOCDLEN);
+        tail_len = _zip_buffer_left(buffer);
 
-       if (tail_len < comment_len || ((za->open_flags & ZIP_CHECKCONS) && tail_len != comment_len)) {
-           zip_error_set(error, ZIP_ER_INCONS, 0);
-           _zip_cdir_free(cd);
-           return NULL;
-       }
+        if (tail_len < comment_len || ((za->open_flags & ZIP_CHECKCONS) && tail_len != comment_len)) {
+            zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_COMMENT_LENGTH_INVALID);
+            _zip_cdir_free(cd);
+            return NULL;
+        }
 
-       if (comment_len) {
-           if ((cd->comment = _zip_string_new(_zip_buffer_get(buffer, comment_len), comment_len, ZIP_FL_ENC_GUESS, error)) == NULL) {
-               _zip_cdir_free(cd);
-               return NULL;
-           }
-       }
+        if (comment_len) {
+            if ((cd->comment = _zip_string_new(_zip_buffer_get(buffer, comment_len), comment_len, ZIP_FL_ENC_GUESS, error)) == NULL) {
+                _zip_cdir_free(cd);
+                return NULL;
+            }
+        }
     }
 
     if (cd->offset >= buf_offset) {
-       zip_uint8_t *data;
-       /* if buffer already read in, use it */
-       _zip_buffer_set_offset(buffer, cd->offset - buf_offset);
-
-       if ((data = _zip_buffer_get(buffer, cd->size)) == NULL) {
-           zip_error_set(error, ZIP_ER_INCONS, 0);
-           _zip_cdir_free(cd);
-           return NULL;
-       }
-       if ((cd_buffer = _zip_buffer_new(data, cd->size)) == NULL) {
-           zip_error_set(error, ZIP_ER_MEMORY, 0);
-           _zip_cdir_free(cd);
-           return NULL;
-       }
+        zip_uint8_t *data;
+        /* if buffer already read in, use it */
+        _zip_buffer_set_offset(buffer, cd->offset - buf_offset);
+
+        if ((data = _zip_buffer_get(buffer, cd->size)) == NULL) {
+            zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_LENGTH_INVALID);
+            _zip_cdir_free(cd);
+            return NULL;
+        }
+        if ((cd_buffer = _zip_buffer_new(data, cd->size)) == NULL) {
+            zip_error_set(error, ZIP_ER_MEMORY, 0);
+            _zip_cdir_free(cd);
+            return NULL;
+        }
     }
     else {
-       cd_buffer = NULL;
+        cd_buffer = NULL;
 
-       if (zip_source_seek(za->src, (zip_int64_t)cd->offset, SEEK_SET) < 0) {
-           _zip_error_set_from_source(error, za->src);
-           _zip_cdir_free(cd);
-           return NULL;
-       }
+        if (zip_source_seek(za->src, (zip_int64_t)cd->offset, SEEK_SET) < 0) {
+            _zip_error_set_from_source(error, za->src);
+            _zip_cdir_free(cd);
+            return NULL;
+        }
 
-       /* possible consistency check: cd->offset = len-(cd->size+cd->comment_len+EOCDLEN) ? */
-       if (zip_source_tell(za->src) != (zip_int64_t)cd->offset) {
-           zip_error_set(error, ZIP_ER_NOZIP, 0);
-           _zip_cdir_free(cd);
-           return NULL;
-       }
+        /* possible consistency check: cd->offset = len-(cd->size+cd->comment_len+EOCDLEN) ? */
+        if (zip_source_tell(za->src) != (zip_int64_t)cd->offset) {
+            zip_error_set(error, ZIP_ER_NOZIP, 0);
+            _zip_cdir_free(cd);
+            return NULL;
+        }
     }
 
     left = (zip_uint64_t)cd->size;
     i = 0;
     while (left > 0) {
-       bool grown = false;
-       zip_int64_t entry_size;
-
-       if (i == cd->nentry) {
-           /* InfoZIP has a hack to avoid using Zip64: it stores nentries % 0x10000 */
-           /* This hack isn't applicable if we're using Zip64, or if there is no central directory entry following. */
-
-           if (cd->is_zip64 || left < CDENTRYSIZE) {
-               break;
-           }
-
-           if (!_zip_cdir_grow(cd, 0x10000, error)) {
-               _zip_cdir_free(cd);
-               _zip_buffer_free(cd_buffer);
-               return NULL;
-           }
-           grown = true;
-       }
-
-       if ((cd->entry[i].orig = _zip_dirent_new()) == NULL || (entry_size = _zip_dirent_read(cd->entry[i].orig, za->src, cd_buffer, false, error)) < 0) {
-           if (grown && zip_error_code_zip(error) == ZIP_ER_NOZIP) {
-               zip_error_set(error, ZIP_ER_INCONS, 0);
+        bool grown = false;
+        zip_int64_t entry_size;
+
+        if (i == cd->nentry) {
+            /* InfoZIP has a hack to avoid using Zip64: it stores nentries % 0x10000 */
+            /* This hack isn't applicable if we're using Zip64, or if there is no central directory entry following. */
+
+            if (cd->is_zip64 || left < CDENTRYSIZE) {
+                break;
+            }
+
+            if (!_zip_cdir_grow(cd, 0x10000, error)) {
+                _zip_cdir_free(cd);
+                _zip_buffer_free(cd_buffer);
+                return NULL;
+            }
+            grown = true;
+        }
+
+        if ((cd->entry[i].orig = _zip_dirent_new()) == NULL || (entry_size = _zip_dirent_read(cd->entry[i].orig, za->src, cd_buffer, false, error)) < 0) {
+           if (zip_error_code_zip(error) == ZIP_ER_INCONS) {
+               zip_error_set(error, ZIP_ER_INCONS, ADD_INDEX_TO_DETAIL(zip_error_code_system(error), i));
            }
-           _zip_cdir_free(cd);
-           _zip_buffer_free(cd_buffer);
-           return NULL;
-       }
-       i++;
-       left -= (zip_uint64_t)entry_size;
+           else if (grown && zip_error_code_zip(error) == ZIP_ER_NOZIP) {
+                zip_error_set(error, ZIP_ER_INCONS, MAKE_DETAIL_WITH_INDEX(ZIP_ER_DETAIL_CDIR_ENTRY_INVALID, i));
+            }
+            _zip_cdir_free(cd);
+            _zip_buffer_free(cd_buffer);
+            return NULL;
+        }
+        i++;
+        left -= (zip_uint64_t)entry_size;
     }
 
     if (i != cd->nentry || left > 0) {
-       zip_error_set(error, ZIP_ER_INCONS, 0);
-       _zip_buffer_free(cd_buffer);
-       _zip_cdir_free(cd);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_WRONG_ENTRIES_COUNT);
+        _zip_buffer_free(cd_buffer);
+        _zip_cdir_free(cd);
+        return NULL;
     }
 
     if (za->open_flags & ZIP_CHECKCONS) {
-       bool ok;
-
-       if (cd_buffer) {
-           ok = _zip_buffer_eof(cd_buffer);
-       }
-       else {
-           zip_int64_t offset = zip_source_tell(za->src);
-
-           if (offset < 0) {
-               _zip_error_set_from_source(error, za->src);
-               _zip_cdir_free(cd);
-               return NULL;
-           }
-           ok = ((zip_uint64_t)offset == cd->offset + cd->size);
-       }
-
-       if (!ok) {
-           zip_error_set(error, ZIP_ER_INCONS, 0);
-           _zip_buffer_free(cd_buffer);
-           _zip_cdir_free(cd);
-           return NULL;
-       }
+        bool ok;
+
+        if (cd_buffer) {
+            ok = _zip_buffer_eof(cd_buffer);
+        }
+        else {
+            zip_int64_t offset = zip_source_tell(za->src);
+
+            if (offset < 0) {
+                _zip_error_set_from_source(error, za->src);
+                _zip_cdir_free(cd);
+                return NULL;
+            }
+            ok = ((zip_uint64_t)offset == cd->offset + cd->size);
+        }
+
+        if (!ok) {
+            zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_LENGTH_INVALID);
+            _zip_buffer_free(cd_buffer);
+            _zip_cdir_free(cd);
+            return NULL;
+        }
     }
 
     _zip_buffer_free(cd_buffer);
@@ -420,49 +429,52 @@ _zip_checkcons(zip_t *za, zip_cdir_t *cd, zip_error_t *error) {
 
     _zip_dirent_init(&temp);
     if (cd->nentry) {
-       max = cd->entry[0].orig->offset;
-       min = cd->entry[0].orig->offset;
+        max = cd->entry[0].orig->offset;
+        min = cd->entry[0].orig->offset;
     }
     else
-       min = max = 0;
+        min = max = 0;
 
     for (i = 0; i < cd->nentry; i++) {
-       if (cd->entry[i].orig->offset < min)
-           min = cd->entry[i].orig->offset;
-       if (min > (zip_uint64_t)cd->offset) {
-           zip_error_set(error, ZIP_ER_NOZIP, 0);
-           return -1;
-       }
-
-       j = cd->entry[i].orig->offset + cd->entry[i].orig->comp_size + _zip_string_length(cd->entry[i].orig->filename) + LENTRYSIZE;
-       if (j > max)
-           max = j;
-       if (max > (zip_uint64_t)cd->offset) {
-           zip_error_set(error, ZIP_ER_NOZIP, 0);
-           return -1;
-       }
-
-       if (zip_source_seek(za->src, (zip_int64_t)cd->entry[i].orig->offset, SEEK_SET) < 0) {
-           _zip_error_set_from_source(error, za->src);
-           return -1;
-       }
-
-       if (_zip_dirent_read(&temp, za->src, NULL, true, error) == -1) {
-           _zip_dirent_finalize(&temp);
-           return -1;
-       }
-
-       if (_zip_headercomp(cd->entry[i].orig, &temp) != 0) {
-           zip_error_set(error, ZIP_ER_INCONS, 0);
-           _zip_dirent_finalize(&temp);
-           return -1;
-       }
-
-       cd->entry[i].orig->extra_fields = _zip_ef_merge(cd->entry[i].orig->extra_fields, temp.extra_fields);
-       cd->entry[i].orig->local_extra_fields_read = 1;
-       temp.extra_fields = NULL;
-
-       _zip_dirent_finalize(&temp);
+        if (cd->entry[i].orig->offset < min)
+            min = cd->entry[i].orig->offset;
+        if (min > (zip_uint64_t)cd->offset) {
+            zip_error_set(error, ZIP_ER_NOZIP, 0);
+            return -1;
+        }
+
+        j = cd->entry[i].orig->offset + cd->entry[i].orig->comp_size + _zip_string_length(cd->entry[i].orig->filename) + LENTRYSIZE;
+        if (j > max)
+            max = j;
+        if (max > (zip_uint64_t)cd->offset) {
+            zip_error_set(error, ZIP_ER_NOZIP, 0);
+            return -1;
+        }
+
+        if (zip_source_seek(za->src, (zip_int64_t)cd->entry[i].orig->offset, SEEK_SET) < 0) {
+            _zip_error_set_from_source(error, za->src);
+            return -1;
+        }
+
+        if (_zip_dirent_read(&temp, za->src, NULL, true, error) == -1) {
+           if (zip_error_code_zip(error) == ZIP_ER_INCONS) {
+               zip_error_set(error, ZIP_ER_INCONS, ADD_INDEX_TO_DETAIL(zip_error_code_system(error), i));
+           }
+            _zip_dirent_finalize(&temp);
+            return -1;
+        }
+
+        if (_zip_headercomp(cd->entry[i].orig, &temp) != 0) {
+            zip_error_set(error, ZIP_ER_INCONS, MAKE_DETAIL_WITH_INDEX(ZIP_ER_DETAIL_ENTRY_HEADER_MISMATCH, i));
+            _zip_dirent_finalize(&temp);
+            return -1;
+        }
+
+        cd->entry[i].orig->extra_fields = _zip_ef_merge(cd->entry[i].orig->extra_fields, temp.extra_fields);
+        cd->entry[i].orig->local_extra_fields_read = 1;
+        temp.extra_fields = NULL;
+
+        _zip_dirent_finalize(&temp);
     }
 
     return (max - min) < ZIP_INT64_MAX ? (zip_int64_t)(max - min) : ZIP_INT64_MAX;
@@ -481,14 +493,14 @@ _zip_headercomp(const zip_dirent_t *central, const zip_dirent_t *local) {
           and global headers for the bitflags */
        || (central->bitflags != local->bitflags)
 #endif
-       || (central->comp_method != local->comp_method) || (central->last_mod != local->last_mod) || !_zip_string_equal(central->filename, local->filename))
-       return -1;
+        || (central->comp_method != local->comp_method) || (central->last_mod != local->last_mod) || !_zip_string_equal(central->filename, local->filename))
+        return -1;
 
     if ((central->crc != local->crc) || (central->comp_size != local->comp_size) || (central->uncomp_size != local->uncomp_size)) {
-       /* InfoZip stores valid values in local header even when data descriptor is used.
-          This is in violation of the appnote. */
-       if (((local->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) == 0 || local->crc != 0 || local->comp_size != 0 || local->uncomp_size != 0))
-           return -1;
+        /* InfoZip stores valid values in local header even when data descriptor is used.
+           This is in violation of the appnote. */
+        if (((local->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) == 0 || local->crc != 0 || local->comp_size != 0 || local->uncomp_size != 0))
+            return -1;
     }
 
     return 0;
@@ -500,14 +512,14 @@ _zip_allocate_new(zip_source_t *src, unsigned int flags, zip_error_t *error) {
     zip_t *za;
 
     if ((za = _zip_new(error)) == NULL) {
-       return NULL;
+        return NULL;
     }
 
     za->src = src;
     za->open_flags = flags;
     if (flags & ZIP_RDONLY) {
-       za->flags |= ZIP_AFL_RDONLY;
-       za->ch_flags |= ZIP_AFL_RDONLY;
+        za->flags |= ZIP_AFL_RDONLY;
+        za->ch_flags |= ZIP_AFL_RDONLY;
     }
     return za;
 }
@@ -522,12 +534,12 @@ _zip_file_exists(zip_source_t *src, zip_error_t *error) {
 
     zip_stat_init(&st);
     if (zip_source_stat(src, &st) != 0) {
-       zip_error_t *src_error = zip_source_error(src);
-       if (zip_error_code_zip(src_error) == ZIP_ER_READ && zip_error_code_system(src_error) == ENOENT) {
-           return EXISTS_NOT;
-       }
-       _zip_error_copy(error, src_error);
-       return EXISTS_ERROR;
+        zip_error_t *src_error = zip_source_error(src);
+        if (zip_error_code_zip(src_error) == ZIP_ER_READ && zip_error_code_system(src_error) == ENOENT) {
+            return EXISTS_NOT;
+        }
+        _zip_error_copy(error, src_error);
+        return EXISTS_ERROR;
     }
 
     return EXISTS_OK;
@@ -546,76 +558,76 @@ _zip_find_central_dir(zip_t *za, zip_uint64_t len) {
     zip_buffer_t *buffer;
 
     if (len < EOCDLEN) {
-       zip_error_set(&za->error, ZIP_ER_NOZIP, 0);
-       return NULL;
+        zip_error_set(&za->error, ZIP_ER_NOZIP, 0);
+        return NULL;
     }
 
     buflen = (len < CDBUFSIZE ? len : CDBUFSIZE);
     if (zip_source_seek(za->src, -(zip_int64_t)buflen, SEEK_END) < 0) {
-       zip_error_t *src_error = zip_source_error(za->src);
-       if (zip_error_code_zip(src_error) != ZIP_ER_SEEK || zip_error_code_system(src_error) != EFBIG) {
-           /* seek before start of file on my machine */
-           _zip_error_copy(&za->error, src_error);
-           return NULL;
-       }
+        zip_error_t *src_error = zip_source_error(za->src);
+        if (zip_error_code_zip(src_error) != ZIP_ER_SEEK || zip_error_code_system(src_error) != EFBIG) {
+            /* seek before start of file on my machine */
+            _zip_error_copy(&za->error, src_error);
+            return NULL;
+        }
     }
     if ((buf_offset = zip_source_tell(za->src)) < 0) {
-       _zip_error_set_from_source(&za->error, za->src);
-       return NULL;
+        _zip_error_set_from_source(&za->error, za->src);
+        return NULL;
     }
 
     if ((buffer = _zip_buffer_new_from_source(za->src, buflen, NULL, &za->error)) == NULL) {
-       return NULL;
+        return NULL;
     }
 
     best = -1;
     cdir = NULL;
     if (buflen >= CDBUFSIZE) {
-       /* EOCD64 locator is before EOCD, so leave place for it */
-       _zip_buffer_set_offset(buffer, EOCD64LOCLEN);
+        /* EOCD64 locator is before EOCD, so leave place for it */
+        _zip_buffer_set_offset(buffer, EOCD64LOCLEN);
     }
     zip_error_set(&error, ZIP_ER_NOZIP, 0);
 
     match = _zip_buffer_get(buffer, 0);
     while ((match = _zip_memmem(match, _zip_buffer_left(buffer) - (EOCDLEN - 4), (const unsigned char *)EOCD_MAGIC, 4)) != NULL) {
-       _zip_buffer_set_offset(buffer, (zip_uint64_t)(match - _zip_buffer_data(buffer)));
-       if ((cdirnew = _zip_read_cdir(za, buffer, (zip_uint64_t)buf_offset, &error)) != NULL) {
-           if (cdir) {
-               if (best <= 0) {
-                   best = _zip_checkcons(za, cdir, &error);
-               }
-
-               a = _zip_checkcons(za, cdirnew, &error);
-               if (best < a) {
-                   _zip_cdir_free(cdir);
-                   cdir = cdirnew;
-                   best = a;
-               }
-               else {
-                   _zip_cdir_free(cdirnew);
-               }
-           }
-           else {
-               cdir = cdirnew;
-               if (za->open_flags & ZIP_CHECKCONS)
-                   best = _zip_checkcons(za, cdir, &error);
-               else {
-                   best = 0;
-               }
-           }
-           cdirnew = NULL;
-       }
-
-       match++;
-       _zip_buffer_set_offset(buffer, (zip_uint64_t)(match - _zip_buffer_data(buffer)));
+        _zip_buffer_set_offset(buffer, (zip_uint64_t)(match - _zip_buffer_data(buffer)));
+        if ((cdirnew = _zip_read_cdir(za, buffer, (zip_uint64_t)buf_offset, &error)) != NULL) {
+            if (cdir) {
+                if (best <= 0) {
+                    best = _zip_checkcons(za, cdir, &error);
+                }
+
+                a = _zip_checkcons(za, cdirnew, &error);
+                if (best < a) {
+                    _zip_cdir_free(cdir);
+                    cdir = cdirnew;
+                    best = a;
+                }
+                else {
+                    _zip_cdir_free(cdirnew);
+                }
+            }
+            else {
+                cdir = cdirnew;
+                if (za->open_flags & ZIP_CHECKCONS)
+                    best = _zip_checkcons(za, cdir, &error);
+                else {
+                    best = 0;
+                }
+            }
+            cdirnew = NULL;
+        }
+
+        match++;
+        _zip_buffer_set_offset(buffer, (zip_uint64_t)(match - _zip_buffer_data(buffer)));
     }
 
     _zip_buffer_free(buffer);
 
     if (best < 0) {
-       _zip_error_copy(&za->error, &error);
-       _zip_cdir_free(cdir);
-       return NULL;
+        _zip_error_copy(&za->error, &error);
+        _zip_cdir_free(cdir);
+        return NULL;
     }
 
     return cdir;
@@ -627,11 +639,11 @@ _zip_memmem(const unsigned char *big, size_t biglen, const unsigned char *little
     const unsigned char *p;
 
     if ((biglen < littlelen) || (littlelen == 0))
-       return NULL;
+        return NULL;
     p = big - 1;
     while ((p = (const unsigned char *)memchr(p + 1, little[0], (size_t)(big - (p + 1)) + (size_t)(biglen - littlelen) + 1)) != NULL) {
-       if (memcmp(p + 1, little + 1, littlelen - 1) == 0)
-           return (unsigned char *)p;
+        if (memcmp(p + 1, little + 1, littlelen - 1) == 0)
+            return (unsigned char *)p;
     }
 
     return NULL;
@@ -644,8 +656,8 @@ _zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags
     zip_uint64_t i, nentry, size, offset, eocd_offset;
 
     if (_zip_buffer_left(buffer) < EOCDLEN) {
-       zip_error_set(error, ZIP_ER_INCONS, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EOCD_LENGTH_INVALID);
+        return NULL;
     }
 
     eocd_offset = _zip_buffer_offset(buffer);
@@ -653,8 +665,8 @@ _zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags
     _zip_buffer_get(buffer, 4); /* magic already verified */
 
     if (_zip_buffer_get_32(buffer) != 0) {
-       zip_error_set(error, ZIP_ER_MULTIDISK, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MULTIDISK, 0);
+        return NULL;
     }
 
     /* number of cdir-entries on this disk */
@@ -663,31 +675,31 @@ _zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags
     nentry = _zip_buffer_get_16(buffer);
 
     if (nentry != i) {
-       zip_error_set(error, ZIP_ER_NOZIP, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_NOZIP, 0);
+        return NULL;
     }
 
     size = _zip_buffer_get_32(buffer);
     offset = _zip_buffer_get_32(buffer);
 
     if (offset + size < offset) {
-       zip_error_set(error, ZIP_ER_SEEK, EFBIG);
-       return NULL;
+        zip_error_set(error, ZIP_ER_SEEK, EFBIG);
+        return NULL;
     }
 
     if (offset + size > buf_offset + eocd_offset) {
-       /* cdir spans past EOCD record */
-       zip_error_set(error, ZIP_ER_INCONS, 0);
-       return NULL;
+        /* cdir spans past EOCD record */
+        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_OVERLAPS_EOCD);
+        return NULL;
     }
 
     if ((flags & ZIP_CHECKCONS) && offset + size != buf_offset + eocd_offset) {
-       zip_error_set(error, ZIP_ER_INCONS, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_LENGTH_INVALID);
+        return NULL;
     }
 
     if ((cd = _zip_cdir_new(nentry, error)) == NULL)
-       return NULL;
+        return NULL;
 
     cd->is_zip64 = false;
     cd->size = size;
@@ -717,38 +729,38 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse
 
     /* valid seek value for start of EOCD */
     if (eocd_offset > ZIP_INT64_MAX) {
-       zip_error_set(error, ZIP_ER_SEEK, EFBIG);
-       return NULL;
+        zip_error_set(error, ZIP_ER_SEEK, EFBIG);
+        return NULL;
     }
 
     /* does EOCD fit before EOCD locator? */
     if (eocd_offset + EOCD64LEN > eocdloc_offset + buf_offset) {
-       zip_error_set(error, ZIP_ER_INCONS, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EOCD64_OVERLAPS_EOCD);
+        return NULL;
     }
 
     /* make sure current position of buffer is beginning of EOCD */
     if (eocd_offset >= buf_offset && eocd_offset + EOCD64LEN <= buf_offset + _zip_buffer_size(buffer)) {
-       _zip_buffer_set_offset(buffer, eocd_offset - buf_offset);
-       free_buffer = false;
+        _zip_buffer_set_offset(buffer, eocd_offset - buf_offset);
+        free_buffer = false;
     }
     else {
-       if (zip_source_seek(src, (zip_int64_t)eocd_offset, SEEK_SET) < 0) {
-           _zip_error_set_from_source(error, src);
-           return NULL;
-       }
-       if ((buffer = _zip_buffer_new_from_source(src, EOCD64LEN, eocd, error)) == NULL) {
-           return NULL;
-       }
-       free_buffer = true;
+        if (zip_source_seek(src, (zip_int64_t)eocd_offset, SEEK_SET) < 0) {
+            _zip_error_set_from_source(error, src);
+            return NULL;
+        }
+        if ((buffer = _zip_buffer_new_from_source(src, EOCD64LEN, eocd, error)) == NULL) {
+            return NULL;
+        }
+        free_buffer = true;
     }
 
     if (memcmp(_zip_buffer_get(buffer, 4), EOCD64_MAGIC, 4) != 0) {
-       zip_error_set(error, ZIP_ER_INCONS, 0);
-       if (free_buffer) {
-           _zip_buffer_free(buffer);
-       }
-       return NULL;
+        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EOCD64_WRONG_MAGIC);
+        if (free_buffer) {
+            _zip_buffer_free(buffer);
+        }
+        return NULL;
     }
 
     /* size of EOCD */
@@ -756,11 +768,11 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse
 
     /* is there a hole between EOCD and EOCD locator, or do they overlap? */
     if ((flags & ZIP_CHECKCONS) && size + eocd_offset + 12 != buf_offset + eocdloc_offset) {
-       zip_error_set(error, ZIP_ER_INCONS, 0);
-       if (free_buffer) {
-           _zip_buffer_free(buffer);
-       }
-       return NULL;
+        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EOCD64_OVERLAPS_EOCD);
+        if (free_buffer) {
+            _zip_buffer_free(buffer);
+        }
+        return NULL;
     }
 
     _zip_buffer_get(buffer, 4); /* skip version made by/needed */
@@ -772,35 +784,35 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse
        otherwise, if the values are not the same, it's inconsistent;
        in any case, if the value is not 0, we don't support it */
     if (num_disks == 0xffff) {
-       num_disks = num_disks64;
+        num_disks = num_disks64;
     }
     if (eocd_disk == 0xffff) {
-       eocd_disk = eocd_disk64;
+        eocd_disk = eocd_disk64;
     }
     if ((flags & ZIP_CHECKCONS) && (eocd_disk != eocd_disk64 || num_disks != num_disks64)) {
-       zip_error_set(error, ZIP_ER_INCONS, 0);
-       if (free_buffer) {
-           _zip_buffer_free(buffer);
-       }
-       return NULL;
+        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EOCD64_MISMATCH);
+        if (free_buffer) {
+            _zip_buffer_free(buffer);
+        }
+        return NULL;
     }
     if (num_disks != 0 || eocd_disk != 0) {
-       zip_error_set(error, ZIP_ER_MULTIDISK, 0);
-       if (free_buffer) {
-           _zip_buffer_free(buffer);
-       }
-       return NULL;
+        zip_error_set(error, ZIP_ER_MULTIDISK, 0);
+        if (free_buffer) {
+            _zip_buffer_free(buffer);
+        }
+        return NULL;
     }
 
     nentry = _zip_buffer_get_64(buffer);
     i = _zip_buffer_get_64(buffer);
 
     if (nentry != i) {
-       zip_error_set(error, ZIP_ER_MULTIDISK, 0);
-       if (free_buffer) {
-           _zip_buffer_free(buffer);
-       }
-       return NULL;
+        zip_error_set(error, ZIP_ER_MULTIDISK, 0);
+        if (free_buffer) {
+            _zip_buffer_free(buffer);
+        }
+        return NULL;
     }
 
     size = _zip_buffer_get_64(buffer);
@@ -808,38 +820,38 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse
 
     /* did we read past the end of the buffer? */
     if (!_zip_buffer_ok(buffer)) {
-       zip_error_set(error, ZIP_ER_INTERNAL, 0);
-       if (free_buffer) {
-           _zip_buffer_free(buffer);
-       }
-       return NULL;
+        zip_error_set(error, ZIP_ER_INTERNAL, 0);
+        if (free_buffer) {
+            _zip_buffer_free(buffer);
+        }
+        return NULL;
     }
 
     if (free_buffer) {
-       _zip_buffer_free(buffer);
+        _zip_buffer_free(buffer);
     }
 
     if (offset > ZIP_INT64_MAX || offset + size < offset) {
-       zip_error_set(error, ZIP_ER_SEEK, EFBIG);
-       return NULL;
+        zip_error_set(error, ZIP_ER_SEEK, EFBIG);
+        return NULL;
     }
     if (offset + size > buf_offset + eocd_offset) {
-       /* cdir spans past EOCD record */
-       zip_error_set(error, ZIP_ER_INCONS, 0);
-       return NULL;
+        /* cdir spans past EOCD record */
+        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_OVERLAPS_EOCD);
+        return NULL;
     }
     if ((flags & ZIP_CHECKCONS) && offset + size != buf_offset + eocd_offset) {
-       zip_error_set(error, ZIP_ER_INCONS, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_OVERLAPS_EOCD);
+        return NULL;
     }
 
     if (nentry > size / CDENTRYSIZE) {
-       zip_error_set(error, ZIP_ER_INCONS, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_INVALID);
+        return NULL;
     }
 
     if ((cd = _zip_cdir_new(nentry, error)) == NULL)
-       return NULL;
+        return NULL;
 
     cd->is_zip64 = true;
     cd->size = size;
index eb12b1e..1b1b461 100644 (file)
@@ -75,18 +75,18 @@ _zip_pkware_encrypt(zip_pkware_keys_t *keys, zip_uint8_t *out, const zip_uint8_t
     zip_uint8_t tmp;
 
     for (i = 0; i < len; i++) {
-       b = in[i];
-
-       if (out != NULL) {
-           tmp = crypt_byte(keys);
-           update_keys(keys, b);
-           b ^= tmp;
-           out[i] = b;
-       }
-       else {
-           /* during initialization, we're only interested in key updates */
-           update_keys(keys, b);
-       }
+        b = in[i];
+
+        if (out != NULL) {
+            tmp = crypt_byte(keys);
+            update_keys(keys, b);
+            b ^= tmp;
+            out[i] = b;
+        }
+        else {
+            /* during initialization, we're only interested in key updates */
+            update_keys(keys, b);
+        }
     }
 }
 
@@ -98,15 +98,15 @@ _zip_pkware_decrypt(zip_pkware_keys_t *keys, zip_uint8_t *out, const zip_uint8_t
     zip_uint8_t tmp;
 
     for (i = 0; i < len; i++) {
-       b = in[i];
+        b = in[i];
 
-       /* during initialization, we're only interested in key updates */
-       if (out != NULL) {
-           tmp = crypt_byte(keys);
-           b ^= tmp;
-           out[i] = b;
-       }
+        /* during initialization, we're only interested in key updates */
+        if (out != NULL) {
+            tmp = crypt_byte(keys);
+            b ^= tmp;
+            out[i] = b;
+        }
 
-       update_keys(keys, b);
+        update_keys(keys, b);
     }
 }
index ddb47c7..a881df4 100644 (file)
@@ -73,7 +73,7 @@ _zip_progress_end(zip_progress_t *progress) {
 void
 _zip_progress_free(zip_progress_t *progress) {
     if (progress == NULL) {
-       return;
+        return;
     }
 
     _zip_progress_free_progress_callback(progress);
@@ -88,8 +88,8 @@ _zip_progress_new(zip_t *za) {
     zip_progress_t *progress = (zip_progress_t *)malloc(sizeof(*progress));
 
     if (progress == NULL) {
-       zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     progress->za = za;
@@ -109,7 +109,7 @@ _zip_progress_new(zip_t *za) {
 static void
 _zip_progress_free_progress_callback(zip_progress_t *progress) {
     if (progress->ud_progress_free) {
-       progress->ud_progress_free(progress->ud_progress);
+        progress->ud_progress_free(progress->ud_progress);
     }
 
     progress->callback_progress = NULL;
@@ -120,7 +120,7 @@ _zip_progress_free_progress_callback(zip_progress_t *progress) {
 static void
 _zip_progress_free_cancel_callback(zip_progress_t *progress) {
     if (progress->ud_cancel_free) {
-       progress->ud_cancel_free(progress->ud_cancel);
+        progress->ud_cancel_free(progress->ud_cancel);
     }
 
     progress->callback_cancel = NULL;
@@ -150,18 +150,18 @@ _zip_progress_set_cancel_callback(zip_progress_t *progress, zip_cancel_callback
 int
 _zip_progress_start(zip_progress_t *progress) {
     if (progress == NULL) {
-       return 0;
+        return 0;
     }
 
     if (progress->callback_progress != NULL) {
-       progress->last_update = 0.0;
-       progress->callback_progress(progress->za, 0.0, progress->ud_progress);
+        progress->last_update = 0.0;
+        progress->callback_progress(progress->za, 0.0, progress->ud_progress);
     }
 
     if (progress->callback_cancel != NULL) {
-       if (progress->callback_cancel(progress->za, progress->ud_cancel)) {
-           return -1;
-       }
+        if (progress->callback_cancel(progress->za, progress->ud_cancel)) {
+            return -1;
+        }
     }
 
     return 0;
@@ -171,7 +171,7 @@ _zip_progress_start(zip_progress_t *progress) {
 int
 _zip_progress_subrange(zip_progress_t *progress, double start, double end) {
     if (progress == NULL) {
-       return 0;
+        return 0;
     }
 
     progress->start = start;
@@ -185,22 +185,22 @@ _zip_progress_update(zip_progress_t *progress, double sub_current) {
     double current;
 
     if (progress == NULL) {
-       return 0;
+        return 0;
     }
 
     if (progress->callback_progress != NULL) {
-       current = ZIP_MIN(ZIP_MAX(sub_current, 0.0), 1.0) * (progress->end - progress->start) + progress->start;
+        current = ZIP_MIN(ZIP_MAX(sub_current, 0.0), 1.0) * (progress->end - progress->start) + progress->start;
 
-       if (current - progress->last_update > progress->precision) {
-           progress->callback_progress(progress->za, current, progress->ud_progress);
-           progress->last_update = current;
-       }
+        if (current - progress->last_update > progress->precision) {
+            progress->callback_progress(progress->za, current, progress->ud_progress);
+            progress->last_update = current;
+        }
     }
 
     if (progress->callback_cancel != NULL) {
-       if (progress->callback_cancel(progress->za, progress->ud_cancel)) {
-           return -1;
-       }
+        if (progress->callback_cancel(progress->za, progress->ud_cancel)) {
+            return -1;
+        }
     }
 
     return 0;
@@ -210,24 +210,24 @@ _zip_progress_update(zip_progress_t *progress, double sub_current) {
 ZIP_EXTERN int
 zip_register_progress_callback_with_state(zip_t *za, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud) {
     if (callback != NULL) {
-       if (za->progress == NULL) {
-           if ((za->progress = _zip_progress_new(za)) == NULL) {
-               return -1;
-           }
-       }
+        if (za->progress == NULL) {
+            if ((za->progress = _zip_progress_new(za)) == NULL) {
+                return -1;
+            }
+        }
 
-       _zip_progress_set_progress_callback(za->progress, precision, callback, ud_free, ud);
+        _zip_progress_set_progress_callback(za->progress, precision, callback, ud_free, ud);
     }
     else {
-       if (za->progress != NULL) {
-           if (za->progress->callback_cancel == NULL) {
-               _zip_progress_free(za->progress);
-               za->progress = NULL;
-           }
-           else {
-               _zip_progress_free_progress_callback(za->progress);
-           }
-       }
+        if (za->progress != NULL) {
+            if (za->progress->callback_cancel == NULL) {
+                _zip_progress_free(za->progress);
+                za->progress = NULL;
+            }
+            else {
+                _zip_progress_free_progress_callback(za->progress);
+            }
+        }
     }
 
     return 0;
@@ -237,24 +237,24 @@ zip_register_progress_callback_with_state(zip_t *za, double precision, zip_progr
 ZIP_EXTERN int
 zip_register_cancel_callback_with_state(zip_t *za, zip_cancel_callback callback, void (*ud_free)(void *), void *ud) {
     if (callback != NULL) {
-       if (za->progress == NULL) {
-           if ((za->progress = _zip_progress_new(za)) == NULL) {
-               return -1;
-           }
-       }
+        if (za->progress == NULL) {
+            if ((za->progress = _zip_progress_new(za)) == NULL) {
+                return -1;
+            }
+        }
 
-       _zip_progress_set_cancel_callback(za->progress, callback, ud_free, ud);
+        _zip_progress_set_cancel_callback(za->progress, callback, ud_free, ud);
     }
     else {
-       if (za->progress != NULL) {
-           if (za->progress->callback_progress == NULL) {
-               _zip_progress_free(za->progress);
-               za->progress = NULL;
-           }
-           else {
-               _zip_progress_free_cancel_callback(za->progress);
-           }
-       }
+        if (za->progress != NULL) {
+            if (za->progress->callback_progress == NULL) {
+                _zip_progress_free(za->progress);
+                za->progress = NULL;
+            }
+            else {
+                _zip_progress_free_cancel_callback(za->progress);
+            }
+        }
     }
 
     return 0;
@@ -278,16 +278,16 @@ zip_register_progress_callback(zip_t *za, zip_progress_callback_t progress_callb
     struct legacy_ud *ud;
 
     if (progress_callback == NULL) {
-       zip_register_progress_callback_with_state(za, 0, NULL, NULL, NULL);
+        zip_register_progress_callback_with_state(za, 0, NULL, NULL, NULL);
     }
 
     if ((ud = (struct legacy_ud *)malloc(sizeof(*ud))) == NULL) {
-       return;
+        return;
     }
 
     ud->callback = progress_callback;
 
     if (zip_register_progress_callback_with_state(za, 0.001, _zip_legacy_progress_callback, free, ud) < 0) {
-       free(ud);
+        free(ud);
     }
 }
index 1d0c967..da44d3c 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_random_unix.c -- fill the user's buffer with random stuff (Unix version)
-  Copyright (C) 2016-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -67,12 +67,12 @@ zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) {
     int fd;
 
     if ((fd = open("/dev/urandom", O_RDONLY)) < 0) {
-       return false;
+        return false;
     }
 
     if (read(fd, buffer, length) != length) {
-       close(fd);
-       return false;
+        close(fd);
+        return false;
     }
 
     close(fd);
@@ -90,11 +90,11 @@ zip_random_uint32(void) {
     zip_uint32_t value;
 
     if (zip_secure_random((zip_uint8_t *)&value, sizeof(value))) {
-       return value;
+        return value;
     }
 
     if (!seeded) {
-       srandom((unsigned int)time(NULL));
+        srandom((unsigned int)time(NULL));
     }
 
     return (zip_uint32_t)random();
index f83c78f..04b03b4 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_random_uwp.c -- fill the user's buffer with random stuff (UWP version)
-  Copyright (C) 2017-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -48,12 +48,12 @@ zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) {
     BCRYPT_ALG_HANDLE hAlg = NULL;
     NTSTATUS hr = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_RNG_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
     if (hr != STATUS_SUCCESS || hAlg == NULL) {
-       return false;
+        return false;
     }
     hr = BCryptGenRandom(&hAlg, buffer, length, 0);
     BCryptCloseAlgorithmProvider(&hAlg, 0);
     if (hr != STATUS_SUCCESS) {
-       return false;
+        return false;
     }
     return true;
 }
@@ -70,11 +70,11 @@ zip_random_uint32(void) {
     zip_uint32_t value;
 
     if (zip_secure_random((zip_uint8_t *)&value, sizeof(value))) {
-       return value;
+        return value;
     }
 
     if (!seeded) {
-       srand((unsigned int)time(NULL));
+        srand((unsigned int)time(NULL));
     }
 
     return (zip_uint32_t)rand();
index 19d488e..436306b 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_random_win32.c -- fill the user's buffer with random stuff (Windows version)
-  Copyright (C) 2016-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -47,13 +47,13 @@ ZIP_EXTERN bool
 zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) {
     HCRYPTPROV hprov;
     if (!CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
-       return false;
+        return false;
     }
     if (!CryptGenRandom(hprov, length, buffer)) {
-       return false;
+        return false;
     }
     if (!CryptReleaseContext(hprov, 0)) {
-       return false;
+        return false;
     }
     return true;
 }
@@ -69,11 +69,11 @@ zip_random_uint32(void) {
     zip_uint32_t value;
 
     if (zip_secure_random((zip_uint8_t *)&value, sizeof(value))) {
-       return value;
+        return value;
     }
 
     if (!seeded) {
-       srand((unsigned int)time(NULL));
+        srand((unsigned int)time(NULL));
     }
 
     return (zip_uint32_t)rand();
index 75b456d..3e67b7c 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_rename.c -- rename file in zip archive
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
index 30a2eb1..e9a2973 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_replace.c -- replace file via callback function
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
index 3f050b3..ee6f2ba 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_set_archive_comment.c -- set archive comment
-  Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -42,38 +42,38 @@ zip_set_archive_comment(zip_t *za, const char *comment, zip_uint16_t len) {
     zip_string_t *cstr;
 
     if (ZIP_IS_RDONLY(za)) {
-       zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+        return -1;
     }
 
     if (len > 0 && comment == NULL) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     if (len > 0) {
-       if ((cstr = _zip_string_new((const zip_uint8_t *)comment, len, ZIP_FL_ENC_GUESS, &za->error)) == NULL)
-           return -1;
+        if ((cstr = _zip_string_new((const zip_uint8_t *)comment, len, ZIP_FL_ENC_GUESS, &za->error)) == NULL)
+            return -1;
 
-       if (_zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_CP437) {
-           _zip_string_free(cstr);
-           zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-           return -1;
-       }
+        if (_zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_CP437) {
+            _zip_string_free(cstr);
+            zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+            return -1;
+        }
     }
     else
-       cstr = NULL;
+        cstr = NULL;
 
     _zip_string_free(za->comment_changes);
     za->comment_changes = NULL;
 
     if (((za->comment_orig && _zip_string_equal(za->comment_orig, cstr)) || (za->comment_orig == NULL && cstr == NULL))) {
-       _zip_string_free(cstr);
-       za->comment_changed = 0;
+        _zip_string_free(cstr);
+        za->comment_changed = 0;
     }
     else {
-       za->comment_changes = cstr;
-       za->comment_changed = 1;
+        za->comment_changes = cstr;
+        za->comment_changed = 1;
     }
 
     return 0;
index e0d5502..a5afc81 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_get_archive_flag.c -- set archive global flag
-  Copyright (C) 2008-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2008-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -40,23 +40,23 @@ zip_set_archive_flag(zip_t *za, zip_flags_t flag, int value) {
     unsigned int new_flags;
 
     if (value)
-       new_flags = za->ch_flags | flag;
+        new_flags = za->ch_flags | flag;
     else
-       new_flags = za->ch_flags & ~flag;
+        new_flags = za->ch_flags & ~flag;
 
     if (new_flags == za->ch_flags)
-       return 0;
+        return 0;
 
     if (ZIP_IS_RDONLY(za)) {
-       zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+        return -1;
     }
 
     if ((flag & ZIP_AFL_RDONLY) && value && (za->ch_flags & ZIP_AFL_RDONLY) == 0) {
-       if (_zip_changed(za, NULL)) {
-           zip_error_set(&za->error, ZIP_ER_CHANGED, 0);
-           return -1;
-       }
+        if (_zip_changed(za, NULL)) {
+            zip_error_set(&za->error, ZIP_ER_CHANGED, 0);
+            return -1;
+        }
     }
 
     za->ch_flags = new_flags;
index 41c7c51..625ac3f 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_set_default_password.c -- set default password for decryption
-  Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 ZIP_EXTERN int
 zip_set_default_password(zip_t *za, const char *passwd) {
     if (za == NULL)
-       return -1;
+        return -1;
 
     free(za->default_password);
 
-    if (passwd) {
-       if ((za->default_password = strdup(passwd)) == NULL) {
-           zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-           return -1;
-       }
+    if (passwd && passwd[0] != '\0') {
+        if ((za->default_password = strdup(passwd)) == NULL) {
+            zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+            return -1;
+        }
     }
     else
-       za->default_password = NULL;
+        za->default_password = NULL;
 
     return 0;
 }
index 4277893..2e7dcb7 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_set_file_comment.c -- set comment for file in archive
-  Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -39,8 +39,8 @@
 ZIP_EXTERN int
 zip_set_file_comment(zip_t *za, zip_uint64_t idx, const char *comment, int len) {
     if (len < 0 || len > ZIP_UINT16_MAX) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
     return zip_file_set_comment(za, idx, comment, (zip_uint16_t)len, 0);
 }
index 927fbb7..d2027c9 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_set_file_compression.c -- set compression for file in archive
-  Copyright (C) 2012-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -40,19 +40,19 @@ zip_set_file_compression(zip_t *za, zip_uint64_t idx, zip_int32_t method, zip_ui
     zip_entry_t *e;
     zip_int32_t old_method;
 
-    if (idx >= za->nentry || flags > 9) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
+    if (idx >= za->nentry) {
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     if (ZIP_IS_RDONLY(za)) {
-       zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+        return -1;
     }
 
     if (!zip_compression_method_supported(method, true)) {
-       zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
+        return -1;
     }
 
     e = za->entry + idx;
@@ -65,26 +65,26 @@ zip_set_file_compression(zip_t *za, zip_uint64_t idx, zip_int32_t method, zip_ui
      * to levels */
 
     if (method == old_method) {
-       if (e->changes) {
-           e->changes->changed &= ~ZIP_DIRENT_COMP_METHOD;
-           e->changes->compression_level = 0;
-           if (e->changes->changed == 0) {
-               _zip_dirent_free(e->changes);
-               e->changes = NULL;
-           }
-       }
+        if (e->changes) {
+            e->changes->changed &= ~ZIP_DIRENT_COMP_METHOD;
+            e->changes->compression_level = 0;
+            if (e->changes->changed == 0) {
+                _zip_dirent_free(e->changes);
+                e->changes = NULL;
+            }
+        }
     }
     else {
-       if (e->changes == NULL) {
-           if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
-               zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-               return -1;
-           }
-       }
-
-       e->changes->comp_method = method;
-       e->changes->compression_level = (zip_uint16_t)flags;
-       e->changes->changed |= ZIP_DIRENT_COMP_METHOD;
+        if (e->changes == NULL) {
+            if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
+                zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+                return -1;
+            }
+        }
+
+        e->changes->comp_method = method;
+        e->changes->compression_level = (zip_uint16_t)flags;
+        e->changes->changed |= ZIP_DIRENT_COMP_METHOD;
     }
 
     return 0;
index 43c772e..af4ec93 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_set_name.c -- rename helper function
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -48,109 +48,109 @@ _zip_set_name(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags)
     zip_string_t *old_str;
 
     if (idx >= za->nentry) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     if (ZIP_IS_RDONLY(za)) {
-       zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+        return -1;
     }
 
     if (name && name[0] != '\0') {
-       /* TODO: check for string too long */
-       if ((str = _zip_string_new((const zip_uint8_t *)name, (zip_uint16_t)strlen(name), flags, &za->error)) == NULL)
-           return -1;
-       if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(str, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED)
-           str->encoding = ZIP_ENCODING_UTF8_KNOWN;
+        /* TODO: check for string too long */
+        if ((str = _zip_string_new((const zip_uint8_t *)name, (zip_uint16_t)strlen(name), flags, &za->error)) == NULL)
+            return -1;
+        if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(str, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED)
+            str->encoding = ZIP_ENCODING_UTF8_KNOWN;
     }
     else
-       str = NULL;
+        str = NULL;
 
     /* TODO: encoding flags needed for CP437? */
     if ((i = _zip_name_locate(za, name, 0, NULL)) >= 0 && (zip_uint64_t)i != idx) {
-       _zip_string_free(str);
-       zip_error_set(&za->error, ZIP_ER_EXISTS, 0);
-       return -1;
+        _zip_string_free(str);
+        zip_error_set(&za->error, ZIP_ER_EXISTS, 0);
+        return -1;
     }
 
     /* no effective name change */
     if (i >= 0 && (zip_uint64_t)i == idx) {
-       _zip_string_free(str);
-       return 0;
+        _zip_string_free(str);
+        return 0;
     }
 
     e = za->entry + idx;
 
     if (e->orig)
-       same_as_orig = _zip_string_equal(e->orig->filename, str);
+        same_as_orig = _zip_string_equal(e->orig->filename, str);
     else
-       same_as_orig = false;
+        same_as_orig = false;
 
     if (!same_as_orig && e->changes == NULL) {
-       if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
-           zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-           _zip_string_free(str);
-           return -1;
-       }
+        if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
+            zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+            _zip_string_free(str);
+            return -1;
+        }
     }
 
     if ((new_name = _zip_string_get(same_as_orig ? e->orig->filename : str, NULL, 0, &za->error)) == NULL) {
-       _zip_string_free(str);
-       return -1;
+        _zip_string_free(str);
+        return -1;
     }
 
     if (e->changes) {
-       old_str = e->changes->filename;
+        old_str = e->changes->filename;
     }
     else if (e->orig) {
-       old_str = e->orig->filename;
+        old_str = e->orig->filename;
     }
     else {
-       old_str = NULL;
+        old_str = NULL;
     }
 
     if (old_str) {
-       if ((old_name = _zip_string_get(old_str, NULL, 0, &za->error)) == NULL) {
-           _zip_string_free(str);
-           return -1;
-       }
+        if ((old_name = _zip_string_get(old_str, NULL, 0, &za->error)) == NULL) {
+            _zip_string_free(str);
+            return -1;
+        }
     }
     else {
-       old_name = NULL;
+        old_name = NULL;
     }
 
     if (_zip_hash_add(za->names, new_name, idx, 0, &za->error) == false) {
-       _zip_string_free(str);
-       return -1;
+        _zip_string_free(str);
+        return -1;
     }
     if (old_name) {
-       _zip_hash_delete(za->names, old_name, NULL);
+        _zip_hash_delete(za->names, old_name, NULL);
     }
 
     if (same_as_orig) {
-       if (e->changes) {
-           if (e->changes->changed & ZIP_DIRENT_FILENAME) {
-               _zip_string_free(e->changes->filename);
-               e->changes->changed &= ~ZIP_DIRENT_FILENAME;
-               if (e->changes->changed == 0) {
-                   _zip_dirent_free(e->changes);
-                   e->changes = NULL;
-               }
-               else {
-                   /* TODO: what if not cloned? can that happen? */
-                   e->changes->filename = e->orig->filename;
-               }
-           }
-       }
-       _zip_string_free(str);
+        if (e->changes) {
+            if (e->changes->changed & ZIP_DIRENT_FILENAME) {
+                _zip_string_free(e->changes->filename);
+                e->changes->changed &= ~ZIP_DIRENT_FILENAME;
+                if (e->changes->changed == 0) {
+                    _zip_dirent_free(e->changes);
+                    e->changes = NULL;
+                }
+                else {
+                    /* TODO: what if not cloned? can that happen? */
+                    e->changes->filename = e->orig->filename;
+                }
+            }
+        }
+        _zip_string_free(str);
     }
     else {
-       if (e->changes->changed & ZIP_DIRENT_FILENAME) {
-           _zip_string_free(e->changes->filename);
-       }
-       e->changes->changed |= ZIP_DIRENT_FILENAME;
-       e->changes->filename = str;
+        if (e->changes->changed & ZIP_DIRENT_FILENAME) {
+            _zip_string_free(e->changes->filename);
+        }
+        e->changes->changed |= ZIP_DIRENT_FILENAME;
+        e->changes->filename = str;
     }
 
     return 0;
index e6d5151..10f4012 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_accept_empty.c -- if empty source is a valid archive
-  Copyright (C) 2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2019-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -40,10 +40,10 @@ zip_source_accept_empty(zip_source_t *src) {
     int ret;
 
     if ((zip_source_supports(src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ACCEPT_EMPTY)) == 0) {
-       if (ZIP_SOURCE_IS_LAYERED(src)) {
-           return zip_source_accept_empty(src->src);
-       }
-       return true;
+        if (ZIP_SOURCE_IS_LAYERED(src)) {
+            return zip_source_accept_empty(src->src);
+        }
+        return true;
     }
 
     ret = (int)_zip_source_call(src, NULL, 0, ZIP_SOURCE_ACCEPT_EMPTY);
index 432c2c1..cefb809 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_begin_write.c -- start a new file for writing
-  Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 ZIP_EXTERN int
 zip_source_begin_write(zip_source_t *src) {
     if (ZIP_SOURCE_IS_OPEN_WRITING(src)) {
-       zip_error_set(&src->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&src->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_BEGIN_WRITE) < 0) {
-       return -1;
+        return -1;
     }
 
     src->write_state = ZIP_SOURCE_WRITE_OPEN;
index 41b4c73..71911e7 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_begin_write_cloning.c -- clone part of file for writing
-  Copyright (C) 2017-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 ZIP_EXTERN int
 zip_source_begin_write_cloning(zip_source_t *src, zip_uint64_t offset) {
     if (ZIP_SOURCE_IS_OPEN_WRITING(src)) {
-       zip_error_set(&src->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&src->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     if (_zip_source_call(src, NULL, offset, ZIP_SOURCE_BEGIN_WRITE_CLONING) < 0) {
-       return -1;
+        return -1;
     }
 
     src->write_state = ZIP_SOURCE_WRITE_OPEN;
index 519d2c3..e0ab72b 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_buffer.c -- create zip data source from buffer
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -87,7 +87,7 @@ zip_source_t *zip_source_buffer_fragment_with_attributes_create(const zip_buffer
 ZIP_EXTERN zip_source_t *
 zip_source_buffer(zip_t *za, const void *data, zip_uint64_t len, int freep) {
     if (za == NULL)
-       return NULL;
+        return NULL;
 
     return zip_source_buffer_with_attributes_create(data, len, freep, NULL, &za->error);
 }
@@ -104,12 +104,12 @@ zip_source_buffer_with_attributes_create(const void *data, zip_uint64_t len, int
     zip_buffer_fragment_t fragment;
 
     if (data == NULL) {
-       if (len > 0) {
-           zip_error_set(error, ZIP_ER_INVAL, 0);
-           return NULL;
-       }
+        if (len > 0) {
+            zip_error_set(error, ZIP_ER_INVAL, 0);
+            return NULL;
+        }
 
-       return zip_source_buffer_fragment_with_attributes_create(NULL, 0, freep, attributes, error);
+        return zip_source_buffer_fragment_with_attributes_create(NULL, 0, freep, attributes, error);
     }
 
     fragment.data = (zip_uint8_t *)data;
@@ -122,7 +122,7 @@ zip_source_buffer_with_attributes_create(const void *data, zip_uint64_t len, int
 ZIP_EXTERN zip_source_t *
 zip_source_buffer_fragment(zip_t *za, const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep) {
     if (za == NULL) {
-       return NULL;
+        return NULL;
     }
 
     return zip_source_buffer_fragment_with_attributes_create(fragments, nfragments, freep, NULL, &za->error);
@@ -141,35 +141,35 @@ zip_source_buffer_fragment_with_attributes_create(const zip_buffer_fragment_t *f
     buffer_t *buffer;
 
     if (fragments == NULL && nfragments > 0) {
-       zip_error_set(error, ZIP_ER_INVAL, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
 
     if ((buffer = buffer_new(fragments, nfragments, freep, error)) == NULL) {
-       return NULL;
+        return NULL;
     }
 
     if ((ctx = (struct read_data *)malloc(sizeof(*ctx))) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       buffer_free(buffer);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        buffer_free(buffer);
+        return NULL;
     }
 
     ctx->in = buffer;
     ctx->out = NULL;
     ctx->mtime = time(NULL);
     if (attributes) {
-       memcpy(&ctx->attributes, attributes, sizeof(ctx->attributes));
+        memcpy(&ctx->attributes, attributes, sizeof(ctx->attributes));
     }
     else {
-       zip_file_attributes_init(&ctx->attributes);
+        zip_file_attributes_init(&ctx->attributes);
     }
     zip_error_init(&ctx->error);
 
     if ((zs = zip_source_function_create(read_data, ctx, error)) == NULL) {
-       buffer_free(ctx->in);
-       free(ctx);
-       return NULL;
+        buffer_free(ctx->in);
+        free(ctx);
+        return NULL;
     }
 
     return zs;
@@ -187,133 +187,133 @@ read_data(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
 
     switch (cmd) {
     case ZIP_SOURCE_BEGIN_WRITE:
-       if ((ctx->out = buffer_new(NULL, 0, 0, &ctx->error)) == NULL) {
-           return -1;
-       }
-       ctx->out->offset = 0;
-       ctx->out->current_fragment = 0;
-       return 0;
+        if ((ctx->out = buffer_new(NULL, 0, 0, &ctx->error)) == NULL) {
+            return -1;
+        }
+        ctx->out->offset = 0;
+        ctx->out->current_fragment = 0;
+        return 0;
 
     case ZIP_SOURCE_BEGIN_WRITE_CLONING:
-       if ((ctx->out = buffer_clone(ctx->in, len, &ctx->error)) == NULL) {
-           return -1;
-       }
-       ctx->out->offset = len;
-       ctx->out->current_fragment = ctx->out->nfragments;
-       return 0;
+        if ((ctx->out = buffer_clone(ctx->in, len, &ctx->error)) == NULL) {
+            return -1;
+        }
+        ctx->out->offset = len;
+        ctx->out->current_fragment = ctx->out->nfragments;
+        return 0;
 
     case ZIP_SOURCE_CLOSE:
-       return 0;
+        return 0;
 
     case ZIP_SOURCE_COMMIT_WRITE:
-       buffer_free(ctx->in);
-       ctx->in = ctx->out;
-       ctx->out = NULL;
-       return 0;
+        buffer_free(ctx->in);
+        ctx->in = ctx->out;
+        ctx->out = NULL;
+        return 0;
 
     case ZIP_SOURCE_ERROR:
-       return zip_error_to_data(&ctx->error, data, len);
+        return zip_error_to_data(&ctx->error, data, len);
 
     case ZIP_SOURCE_FREE:
-       buffer_free(ctx->in);
-       buffer_free(ctx->out);
-       free(ctx);
-       return 0;
+        buffer_free(ctx->in);
+        buffer_free(ctx->out);
+        free(ctx);
+        return 0;
 
     case ZIP_SOURCE_GET_FILE_ATTRIBUTES: {
-       if (len < sizeof(ctx->attributes)) {
-           zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
-           return -1;
-       }
+        if (len < sizeof(ctx->attributes)) {
+            zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
+            return -1;
+        }
 
-       memcpy(data, &ctx->attributes, sizeof(ctx->attributes));
+        memcpy(data, &ctx->attributes, sizeof(ctx->attributes));
 
-       return sizeof(ctx->attributes);
+        return sizeof(ctx->attributes);
     }
 
     case ZIP_SOURCE_OPEN:
-       ctx->in->offset = 0;
-       ctx->in->current_fragment = 0;
-       return 0;
+        ctx->in->offset = 0;
+        ctx->in->current_fragment = 0;
+        return 0;
 
     case ZIP_SOURCE_READ:
-       if (len > ZIP_INT64_MAX) {
-           zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
-           return -1;
-       }
-       return buffer_read(ctx->in, data, len);
+        if (len > ZIP_INT64_MAX) {
+            zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
+            return -1;
+        }
+        return buffer_read(ctx->in, data, len);
 
     case ZIP_SOURCE_REMOVE: {
-       buffer_t *empty = buffer_new(NULL, 0, 0, &ctx->error);
-       if (empty == NULL) {
-           return -1;
-       }
+        buffer_t *empty = buffer_new(NULL, 0, 0, &ctx->error);
+        if (empty == NULL) {
+            return -1;
+        }
 
-       buffer_free(ctx->in);
-       ctx->in = empty;
-       return 0;
+        buffer_free(ctx->in);
+        ctx->in = empty;
+        return 0;
     }
 
     case ZIP_SOURCE_ROLLBACK_WRITE:
-       buffer_free(ctx->out);
-       ctx->out = NULL;
-       return 0;
+        buffer_free(ctx->out);
+        ctx->out = NULL;
+        return 0;
 
     case ZIP_SOURCE_SEEK:
-       return buffer_seek(ctx->in, data, len, &ctx->error);
+        return buffer_seek(ctx->in, data, len, &ctx->error);
 
     case ZIP_SOURCE_SEEK_WRITE:
-       return buffer_seek(ctx->out, data, len, &ctx->error);
+        return buffer_seek(ctx->out, data, len, &ctx->error);
 
     case ZIP_SOURCE_STAT: {
-       zip_stat_t *st;
+        zip_stat_t *st;
 
-       if (len < sizeof(*st)) {
-           zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
-           return -1;
-       }
+        if (len < sizeof(*st)) {
+            zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
+            return -1;
+        }
 
-       st = (zip_stat_t *)data;
+        st = (zip_stat_t *)data;
 
-       zip_stat_init(st);
-       st->mtime = ctx->mtime;
-       st->size = ctx->in->size;
-       st->comp_size = st->size;
-       st->comp_method = ZIP_CM_STORE;
-       st->encryption_method = ZIP_EM_NONE;
-       st->valid = ZIP_STAT_MTIME | ZIP_STAT_SIZE | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_ENCRYPTION_METHOD;
+        zip_stat_init(st);
+        st->mtime = ctx->mtime;
+        st->size = ctx->in->size;
+        st->comp_size = st->size;
+        st->comp_method = ZIP_CM_STORE;
+        st->encryption_method = ZIP_EM_NONE;
+        st->valid = ZIP_STAT_MTIME | ZIP_STAT_SIZE | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_ENCRYPTION_METHOD;
 
-       return sizeof(*st);
+        return sizeof(*st);
     }
 
     case ZIP_SOURCE_SUPPORTS:
-       return zip_source_make_command_bitmap(ZIP_SOURCE_GET_FILE_ATTRIBUTES, ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_SEEK, ZIP_SOURCE_TELL, ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_BEGIN_WRITE_CLONING, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_REMOVE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_WRITE, -1);
+        return zip_source_make_command_bitmap(ZIP_SOURCE_GET_FILE_ATTRIBUTES, ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_SEEK, ZIP_SOURCE_TELL, ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_BEGIN_WRITE_CLONING, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_REMOVE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_WRITE, -1);
 
     case ZIP_SOURCE_TELL:
-       if (ctx->in->offset > ZIP_INT64_MAX) {
-           zip_error_set(&ctx->error, ZIP_ER_TELL, EOVERFLOW);
-           return -1;
-       }
-       return (zip_int64_t)ctx->in->offset;
+        if (ctx->in->offset > ZIP_INT64_MAX) {
+            zip_error_set(&ctx->error, ZIP_ER_TELL, EOVERFLOW);
+            return -1;
+        }
+        return (zip_int64_t)ctx->in->offset;
 
 
     case ZIP_SOURCE_TELL_WRITE:
-       if (ctx->out->offset > ZIP_INT64_MAX) {
-           zip_error_set(&ctx->error, ZIP_ER_TELL, EOVERFLOW);
-           return -1;
-       }
-       return (zip_int64_t)ctx->out->offset;
+        if (ctx->out->offset > ZIP_INT64_MAX) {
+            zip_error_set(&ctx->error, ZIP_ER_TELL, EOVERFLOW);
+            return -1;
+        }
+        return (zip_int64_t)ctx->out->offset;
 
     case ZIP_SOURCE_WRITE:
-       if (len > ZIP_INT64_MAX) {
-           zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
-           return -1;
-       }
-       return buffer_write(ctx->out, data, len, &ctx->error);
+        if (len > ZIP_INT64_MAX) {
+            zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
+            return -1;
+        }
+        return buffer_write(ctx->out, data, len, &ctx->error);
 
     default:
-       zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
+        return -1;
     }
 }
 
@@ -324,34 +324,34 @@ buffer_clone(buffer_t *buffer, zip_uint64_t offset, zip_error_t *error) {
     buffer_t *clone;
 
     if (offset == 0) {
-       return buffer_new(NULL, 0, 1, error);
+        return buffer_new(NULL, 0, 1, error);
     }
 
     if (offset > buffer->size) {
-       zip_error_set(error, ZIP_ER_INVAL, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
     if (buffer->shared_buffer != NULL) {
-       zip_error_set(error, ZIP_ER_INUSE, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INUSE, 0);
+        return NULL;
     }
 
     fragment = buffer_find_fragment(buffer, offset);
     fragment_offset = offset - buffer->fragment_offsets[fragment];
 
     if (fragment_offset == 0) {
-       fragment--;
-       fragment_offset = buffer->fragments[fragment].length;
+        fragment--;
+        fragment_offset = buffer->fragments[fragment].length;
     }
 
     waste = buffer->fragments[fragment].length - fragment_offset;
     if (waste > offset) {
-       zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
+        return NULL;
     }
 
     if ((clone = buffer_new(buffer->fragments, fragment + 1, 0, error)) == NULL) {
-       return NULL;
+        return NULL;
     }
 
 #ifndef __clang_analyzer__
@@ -380,16 +380,16 @@ buffer_find_fragment(const buffer_t *buffer, zip_uint64_t offset) {
     high = buffer->nfragments - 1;
 
     while (low < high) {
-       mid = (high - low) / 2 + low;
-       if (buffer->fragment_offsets[mid] > offset) {
-           high = mid - 1;
-       }
-       else if (mid == buffer->nfragments || buffer->fragment_offsets[mid + 1] > offset) {
-           return mid;
-       }
-       else {
-           low = mid + 1;
-       }
+        mid = (high - low) / 2 + low;
+        if (buffer->fragment_offsets[mid] > offset) {
+            high = mid - 1;
+        }
+        else if (mid == buffer->nfragments || buffer->fragment_offsets[mid + 1] > offset) {
+            return mid;
+        }
+        else {
+            low = mid + 1;
+        }
     }
 
     return low;
@@ -401,18 +401,18 @@ buffer_free(buffer_t *buffer) {
     zip_uint64_t i;
 
     if (buffer == NULL) {
-       return;
+        return;
     }
 
     if (buffer->shared_buffer != NULL) {
-       buffer->shared_buffer->shared_buffer = NULL;
-       buffer->shared_buffer->shared_fragments = 0;
+        buffer->shared_buffer->shared_buffer = NULL;
+        buffer->shared_buffer->shared_fragments = 0;
 
-       buffer->first_owned_fragment = ZIP_MAX(buffer->first_owned_fragment, buffer->shared_fragments);
+        buffer->first_owned_fragment = ZIP_MAX(buffer->first_owned_fragment, buffer->shared_fragments);
     }
 
     for (i = buffer->first_owned_fragment; i < buffer->nfragments; i++) {
-       free(buffer->fragments[i].data);
+        free(buffer->fragments[i].data);
     }
     free(buffer->fragments);
     free(buffer->fragment_offsets);
@@ -426,17 +426,17 @@ buffer_grow_fragments(buffer_t *buffer, zip_uint64_t capacity, zip_error_t *erro
     zip_uint64_t *offsets;
 
     if (capacity < buffer->fragments_capacity) {
-       return true;
+        return true;
     }
 
     if ((fragments = realloc(buffer->fragments, sizeof(buffer->fragments[0]) * capacity)) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return false;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return false;
     }
     buffer->fragments = fragments;
     if ((offsets = realloc(buffer->fragment_offsets, sizeof(buffer->fragment_offsets[0]) * (capacity + 1))) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return false;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return false;
     }
     buffer->fragment_offsets = offsets;
     buffer->fragments_capacity = capacity;
@@ -450,7 +450,7 @@ buffer_new(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int
     buffer_t *buffer;
 
     if ((buffer = malloc(sizeof(*buffer))) == NULL) {
-       return NULL;
+        return NULL;
     }
 
     buffer->offset = 0;
@@ -464,42 +464,42 @@ buffer_new(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int
     buffer->shared_fragments = 0;
 
     if (nfragments == 0) {
-       if ((buffer->fragment_offsets = malloc(sizeof(buffer->fragment_offsets[0]))) == NULL) {
-           free(buffer);
-           zip_error_set(error, ZIP_ER_MEMORY, 0);
-           return NULL;
-       }
-       buffer->fragment_offsets[0] = 0;
+        if ((buffer->fragment_offsets = malloc(sizeof(buffer->fragment_offsets[0]))) == NULL) {
+            free(buffer);
+            zip_error_set(error, ZIP_ER_MEMORY, 0);
+            return NULL;
+        }
+        buffer->fragment_offsets[0] = 0;
     }
     else {
-       zip_uint64_t i, j, offset;
-
-       if (!buffer_grow_fragments(buffer, nfragments, NULL)) {
-           zip_error_set(error, ZIP_ER_MEMORY, 0);
-           buffer_free(buffer);
-           return NULL;
-       }
-
-       offset = 0;
-       for (i = 0, j = 0; i < nfragments; i++) {
-           if (fragments[i].length == 0) {
-               continue;
-           }
-           if (fragments[i].data == NULL) {
-               zip_error_set(error, ZIP_ER_INVAL, 0);
-               buffer_free(buffer);
-               return NULL;
-           }
-           buffer->fragments[j].data = fragments[i].data;
-           buffer->fragments[j].length = fragments[i].length;
-           buffer->fragment_offsets[i] = offset;
-           offset += fragments[i].length;
-           j++;
-       }
-       buffer->nfragments = j;
-       buffer->first_owned_fragment = free_data ? 0 : buffer->nfragments;
-       buffer->fragment_offsets[buffer->nfragments] = offset;
-       buffer->size = offset;
+        zip_uint64_t i, j, offset;
+
+        if (!buffer_grow_fragments(buffer, nfragments, NULL)) {
+            zip_error_set(error, ZIP_ER_MEMORY, 0);
+            buffer_free(buffer);
+            return NULL;
+        }
+
+        offset = 0;
+        for (i = 0, j = 0; i < nfragments; i++) {
+            if (fragments[i].length == 0) {
+                continue;
+            }
+            if (fragments[i].data == NULL) {
+                zip_error_set(error, ZIP_ER_INVAL, 0);
+                buffer_free(buffer);
+                return NULL;
+            }
+            buffer->fragments[j].data = fragments[i].data;
+            buffer->fragments[j].length = fragments[i].length;
+            buffer->fragment_offsets[i] = offset;
+            offset += fragments[i].length;
+            j++;
+        }
+        buffer->nfragments = j;
+        buffer->first_owned_fragment = free_data ? 0 : buffer->nfragments;
+        buffer->fragment_offsets[buffer->nfragments] = offset;
+        buffer->size = offset;
     }
 
     return buffer;
@@ -512,25 +512,25 @@ buffer_read(buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length) {
     length = ZIP_MIN(length, buffer->size - buffer->offset);
 
     if (length == 0) {
-       return 0;
+        return 0;
     }
     if (length > ZIP_INT64_MAX) {
-       return -1;
+        return -1;
     }
 
     i = buffer->current_fragment;
     fragment_offset = buffer->offset - buffer->fragment_offsets[i];
     n = 0;
     while (n < length) {
-       zip_uint64_t left = ZIP_MIN(length - n, buffer->fragments[i].length - fragment_offset);
+        zip_uint64_t left = ZIP_MIN(length - n, buffer->fragments[i].length - fragment_offset);
 
-       memcpy(data + n, buffer->fragments[i].data + fragment_offset, left);
+        memcpy(data + n, buffer->fragments[i].data + fragment_offset, left);
 
-       if (left == buffer->fragments[i].length - fragment_offset) {
-           i++;
-       }
-       n += left;
-       fragment_offset = 0;
+        if (left == buffer->fragments[i].length - fragment_offset) {
+            i++;
+        }
+        n += left;
+        fragment_offset = 0;
     }
 
     buffer->offset += n;
@@ -544,7 +544,7 @@ buffer_seek(buffer_t *buffer, void *data, zip_uint64_t len, zip_error_t *error)
     zip_int64_t new_offset = zip_source_seek_compute_offset(buffer->offset, buffer->size, data, len, error);
 
     if (new_offset < 0) {
-       return -1;
+        return -1;
     }
 
     buffer->offset = (zip_uint64_t)new_offset;
@@ -558,62 +558,62 @@ buffer_write(buffer_t *buffer, const zip_uint8_t *data, zip_uint64_t length, zip
     zip_uint64_t n, i, fragment_offset, capacity;
 
     if (buffer->offset + length + WRITE_FRAGMENT_SIZE - 1 < length) {
-       zip_error_set(error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     /* grow buffer if needed */
     capacity = buffer_capacity(buffer);
     if (buffer->offset + length > capacity) {
-       zip_uint64_t needed_fragments = buffer->nfragments + (length - (capacity - buffer->offset) + WRITE_FRAGMENT_SIZE - 1) / WRITE_FRAGMENT_SIZE;
-
-       if (needed_fragments > buffer->fragments_capacity) {
-           zip_uint64_t new_capacity = buffer->fragments_capacity;
-
-           if (new_capacity == 0) {
-               new_capacity = 16;
-           }
-           while (new_capacity < needed_fragments) {
-               new_capacity *= 2;
-           }
-
-           if (!buffer_grow_fragments(buffer, new_capacity, error)) {
-               zip_error_set(error, ZIP_ER_MEMORY, 0);
-               return -1;
-           }
-       }
-
-       while (buffer->nfragments < needed_fragments) {
-           if ((buffer->fragments[buffer->nfragments].data = malloc(WRITE_FRAGMENT_SIZE)) == NULL) {
-               zip_error_set(error, ZIP_ER_MEMORY, 0);
-               return -1;
-           }
-           buffer->fragments[buffer->nfragments].length = WRITE_FRAGMENT_SIZE;
-           buffer->nfragments++;
-           capacity += WRITE_FRAGMENT_SIZE;
-           buffer->fragment_offsets[buffer->nfragments] = capacity;
-       }
+        zip_uint64_t needed_fragments = buffer->nfragments + (length - (capacity - buffer->offset) + WRITE_FRAGMENT_SIZE - 1) / WRITE_FRAGMENT_SIZE;
+
+        if (needed_fragments > buffer->fragments_capacity) {
+            zip_uint64_t new_capacity = buffer->fragments_capacity;
+
+            if (new_capacity == 0) {
+                new_capacity = 16;
+            }
+            while (new_capacity < needed_fragments) {
+                new_capacity *= 2;
+            }
+
+            if (!buffer_grow_fragments(buffer, new_capacity, error)) {
+                zip_error_set(error, ZIP_ER_MEMORY, 0);
+                return -1;
+            }
+        }
+
+        while (buffer->nfragments < needed_fragments) {
+            if ((buffer->fragments[buffer->nfragments].data = malloc(WRITE_FRAGMENT_SIZE)) == NULL) {
+                zip_error_set(error, ZIP_ER_MEMORY, 0);
+                return -1;
+            }
+            buffer->fragments[buffer->nfragments].length = WRITE_FRAGMENT_SIZE;
+            buffer->nfragments++;
+            capacity += WRITE_FRAGMENT_SIZE;
+            buffer->fragment_offsets[buffer->nfragments] = capacity;
+        }
     }
 
     i = buffer->current_fragment;
     fragment_offset = buffer->offset - buffer->fragment_offsets[i];
     n = 0;
     while (n < length) {
-       zip_uint64_t left = ZIP_MIN(length - n, buffer->fragments[i].length - fragment_offset);
+        zip_uint64_t left = ZIP_MIN(length - n, buffer->fragments[i].length - fragment_offset);
 
-       memcpy(buffer->fragments[i].data + fragment_offset, data + n, left);
+        memcpy(buffer->fragments[i].data + fragment_offset, data + n, left);
 
-       if (left == buffer->fragments[i].length - fragment_offset) {
-           i++;
-       }
-       n += left;
-       fragment_offset = 0;
+        if (left == buffer->fragments[i].length - fragment_offset) {
+            i++;
+        }
+        n += left;
+        fragment_offset = 0;
     }
 
     buffer->offset += n;
     buffer->current_fragment = i;
     if (buffer->offset > buffer->size) {
-       buffer->size = buffer->offset;
+        buffer->size = buffer->offset;
     }
 
     return (zip_int64_t)n;
index e7c2954..41b5c0f 100644 (file)
@@ -1,6 +1,6 @@
 /*
  zip_source_call.c -- invoke callback command on zip_source
- Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
+ Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
 
  This file is part of libzip, a library to manipulate ZIP archives.
  The authors can be contacted at <libzip@nih.at>
@@ -40,28 +40,28 @@ _zip_source_call(zip_source_t *src, void *data, zip_uint64_t length, zip_source_
     zip_int64_t ret;
 
     if ((src->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(command)) == 0) {
-       zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0);
-       return -1;
+        zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0);
+        return -1;
     }
 
     if (src->src == NULL) {
-       ret = src->cb.f(src->ud, data, length, command);
+        ret = src->cb.f(src->ud, data, length, command);
     }
     else {
-       ret = src->cb.l(src->src, src->ud, data, length, command);
+        ret = src->cb.l(src->src, src->ud, data, length, command);
     }
 
     if (ret < 0) {
-       if (command != ZIP_SOURCE_ERROR && command != ZIP_SOURCE_SUPPORTS) {
-           int e[2];
+        if (command != ZIP_SOURCE_ERROR && command != ZIP_SOURCE_SUPPORTS) {
+            int e[2];
 
-           if (_zip_source_call(src, e, sizeof(e), ZIP_SOURCE_ERROR) < 0) {
-               zip_error_set(&src->error, ZIP_ER_INTERNAL, 0);
-           }
-           else {
-               zip_error_set(&src->error, e[0], e[1]);
-           }
-       }
+            if (_zip_source_call(src, e, sizeof(e), ZIP_SOURCE_ERROR) < 0) {
+                zip_error_set(&src->error, ZIP_ER_INTERNAL, 0);
+            }
+            else {
+                zip_error_set(&src->error, e[0], e[1]);
+            }
+        }
     }
 
     return ret;
index ab7898c..48efe8a 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_close.c -- close zip_source (stop reading)
-  Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 int
 zip_source_close(zip_source_t *src) {
     if (!ZIP_SOURCE_IS_OPEN_READING(src)) {
-       zip_error_set(&src->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&src->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     src->open_count--;
     if (src->open_count == 0) {
-       _zip_source_call(src, NULL, 0, ZIP_SOURCE_CLOSE);
+        _zip_source_call(src, NULL, 0, ZIP_SOURCE_CLOSE);
 
-       if (ZIP_SOURCE_IS_LAYERED(src)) {
-           if (zip_source_close(src->src) < 0) {
-               zip_error_set(&src->error, ZIP_ER_INTERNAL, 0);
-           }
-       }
+        if (ZIP_SOURCE_IS_LAYERED(src)) {
+            if (zip_source_close(src->src) < 0) {
+                zip_error_set(&src->error, ZIP_ER_INTERNAL, 0);
+            }
+        }
     }
 
     return 0;
index d1254bf..30243d5 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_commit_write.c -- commit changes to file
-  Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 ZIP_EXTERN int
 zip_source_commit_write(zip_source_t *src) {
     if (!ZIP_SOURCE_IS_OPEN_WRITING(src)) {
-       zip_error_set(&src->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&src->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     if (src->open_count > 1) {
-       zip_error_set(&src->error, ZIP_ER_INUSE, 0);
-       return -1;
+        zip_error_set(&src->error, ZIP_ER_INUSE, 0);
+        return -1;
     }
     else if (ZIP_SOURCE_IS_OPEN_READING(src)) {
-       if (zip_source_close(src) < 0) {
-           return -1;
-       }
+        if (zip_source_close(src) < 0) {
+            return -1;
+        }
     }
 
     if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_COMMIT_WRITE) < 0) {
-       src->write_state = ZIP_SOURCE_WRITE_FAILED;
-       return -1;
+        src->write_state = ZIP_SOURCE_WRITE_FAILED;
+        return -1;
     }
 
     src->write_state = ZIP_SOURCE_WRITE_CLOSED;
index e49929f..9776065 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_compress.c -- (de)compression routines
-  Copyright (C) 2017-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -67,14 +67,17 @@ static struct implementation implementations[] = {
     {ZIP_CM_BZIP2, &zip_algorithm_bzip2_compress, &zip_algorithm_bzip2_decompress},
 #endif
 #if defined(HAVE_LIBLZMA)
-    /*  Disabled - because 7z isn't able to unpack ZIP+LZMA ZIP+LZMA2
-       archives made this way - and vice versa.
+    {ZIP_CM_LZMA, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress},
+    /*  Disabled - because 7z isn't able to unpack ZIP+LZMA2
+        archives made this way - and vice versa.
 
-       {ZIP_CM_LZMA, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress},
-       {ZIP_CM_LZMA2, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress},
+        {ZIP_CM_LZMA2, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress},
     */
     {ZIP_CM_XZ, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress},
 #endif
+#if defined(HAVE_LIBZSTD)
+    {ZIP_CM_ZSTD, &zip_algorithm_zstd_compress, &zip_algorithm_zstd_decompress},
+#endif
 
 };
 
@@ -86,20 +89,20 @@ static void context_free(struct context *ctx);
 static struct context *context_new(zip_int32_t method, bool compress, int compression_flags, zip_compression_algorithm_t *algorithm);
 static zip_int64_t compress_read(zip_source_t *, struct context *, void *, zip_uint64_t);
 
-static zip_compression_algorithm_t *
-get_algorithm(zip_int32_t method, bool compress) {
+zip_compression_algorithm_t *
+_zip_get_compression_algorithm(zip_int32_t method, bool compress) {
     size_t i;
     zip_uint16_t real_method = ZIP_CM_ACTUAL(method);
 
     for (i = 0; i < implementations_size; i++) {
-       if (implementations[i].method == real_method) {
-           if (compress) {
-               return implementations[i].compress;
-           }
-           else {
-               return implementations[i].decompress;
-           }
-       }
+        if (implementations[i].method == real_method) {
+            if (compress) {
+                return implementations[i].compress;
+            }
+            else {
+                return implementations[i].decompress;
+            }
+        }
     }
 
     return NULL;
@@ -108,9 +111,9 @@ get_algorithm(zip_int32_t method, bool compress) {
 ZIP_EXTERN int
 zip_compression_method_supported(zip_int32_t method, int compress) {
     if (method == ZIP_CM_STORE) {
-       return 1;
+        return 1;
     }
-    return get_algorithm(method, compress) != NULL;
+    return _zip_get_compression_algorithm(method, compress) != NULL;
 }
 
 zip_source_t *
@@ -131,23 +134,23 @@ compression_source_new(zip_t *za, zip_source_t *src, zip_int32_t method, bool co
     zip_compression_algorithm_t *algorithm = NULL;
 
     if (src == NULL) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return NULL;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
 
-    if ((algorithm = get_algorithm(method, compress)) == NULL) {
-       zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
-       return NULL;
+    if ((algorithm = _zip_get_compression_algorithm(method, compress)) == NULL) {
+        zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
+        return NULL;
     }
 
     if ((ctx = context_new(method, compress, compression_flags, algorithm)) == NULL) {
-       zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     if ((s2 = zip_source_layered(za, src, compress_callback, ctx)) == NULL) {
-       context_free(ctx);
-       return NULL;
+        context_free(ctx);
+        return NULL;
     }
 
     return s2;
@@ -159,7 +162,7 @@ context_new(zip_int32_t method, bool compress, int compression_flags, zip_compre
     struct context *ctx;
 
     if ((ctx = (struct context *)malloc(sizeof(*ctx))) == NULL) {
-       return NULL;
+        return NULL;
     }
     zip_error_init(&ctx->error);
     ctx->can_store = compress ? ZIP_CM_IS_DEFAULT(method) : false;
@@ -171,9 +174,9 @@ context_new(zip_int32_t method, bool compress, int compression_flags, zip_compre
     ctx->is_stored = false;
 
     if ((ctx->ud = ctx->algorithm->allocate(ZIP_CM_ACTUAL(method), compression_flags, &ctx->error)) == NULL) {
-       zip_error_fini(&ctx->error);
-       free(ctx);
-       return NULL;
+        zip_error_fini(&ctx->error);
+        free(ctx);
+        return NULL;
     }
 
     return ctx;
@@ -183,7 +186,7 @@ context_new(zip_int32_t method, bool compress, int compression_flags, zip_compre
 static void
 context_free(struct context *ctx) {
     if (ctx == NULL) {
-       return;
+        return;
     }
 
     ctx->algorithm->deallocate(ctx->ud);
@@ -202,96 +205,96 @@ compress_read(zip_source_t *src, struct context *ctx, void *data, zip_uint64_t l
     zip_uint64_t out_len;
 
     if (zip_error_code_zip(&ctx->error) != ZIP_ER_OK) {
-       return -1;
+        return -1;
     }
 
     if (len == 0 || ctx->end_of_stream) {
-       return 0;
+        return 0;
     }
 
     out_offset = 0;
 
     end = false;
     while (!end && out_offset < len) {
-       out_len = len - out_offset;
-       ret = ctx->algorithm->process(ctx->ud, (zip_uint8_t *)data + out_offset, &out_len);
-
-       if (ret != ZIP_COMPRESSION_ERROR) {
-           out_offset += out_len;
-       }
-
-       switch (ret) {
-       case ZIP_COMPRESSION_END:
-           ctx->end_of_stream = true;
-
-           if (!ctx->end_of_input) {
-               /* TODO: garbage after stream, or compression ended before all data read */
-           }
-
-           if (ctx->first_read < 0) {
-               /* we got end of processed stream before reading any input data */
-               zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
-               end = true;
-               break;
-           }
-           if (ctx->can_store && (zip_uint64_t)ctx->first_read <= out_offset) {
-               ctx->is_stored = true;
-               ctx->size = (zip_uint64_t)ctx->first_read;
-               memcpy(data, ctx->buffer, ctx->size);
-               return (zip_int64_t)ctx->size;
-           }
-           end = true;
-           break;
-
-       case ZIP_COMPRESSION_OK:
-           break;
-
-       case ZIP_COMPRESSION_NEED_DATA:
-           if (ctx->end_of_input) {
-               /* TODO: error: stream not ended, but no more input */
-               end = true;
-               break;
-           }
-
-           if ((n = zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
-               _zip_error_set_from_source(&ctx->error, src);
-               end = true;
-               break;
-           }
-           else if (n == 0) {
-               ctx->end_of_input = true;
-               ctx->algorithm->end_of_input(ctx->ud);
-               if (ctx->first_read < 0) {
-                   ctx->first_read = 0;
-               }
-           }
-           else {
-               if (ctx->first_read >= 0) {
-                   /* we overwrote a previously filled ctx->buffer */
-                   ctx->can_store = false;
-               }
-               else {
-                   ctx->first_read = n;
-               }
-
-               ctx->algorithm->input(ctx->ud, ctx->buffer, (zip_uint64_t)n);
-           }
-           break;
-
-       case ZIP_COMPRESSION_ERROR:
-           /* error set by algorithm */
-           if (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) {
-               zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
-           }
-           end = true;
-           break;
-       }
+        out_len = len - out_offset;
+        ret = ctx->algorithm->process(ctx->ud, (zip_uint8_t *)data + out_offset, &out_len);
+
+        if (ret != ZIP_COMPRESSION_ERROR) {
+            out_offset += out_len;
+        }
+
+        switch (ret) {
+        case ZIP_COMPRESSION_END:
+            ctx->end_of_stream = true;
+
+            if (!ctx->end_of_input) {
+                /* TODO: garbage after stream, or compression ended before all data read */
+            }
+
+            if (ctx->first_read < 0) {
+                /* we got end of processed stream before reading any input data */
+                zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
+                end = true;
+                break;
+            }
+            if (ctx->can_store && (zip_uint64_t)ctx->first_read <= out_offset) {
+                ctx->is_stored = true;
+                ctx->size = (zip_uint64_t)ctx->first_read;
+                memcpy(data, ctx->buffer, ctx->size);
+                return (zip_int64_t)ctx->size;
+            }
+            end = true;
+            break;
+
+        case ZIP_COMPRESSION_OK:
+            break;
+
+        case ZIP_COMPRESSION_NEED_DATA:
+            if (ctx->end_of_input) {
+                /* TODO: error: stream not ended, but no more input */
+                end = true;
+                break;
+            }
+
+            if ((n = zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
+                _zip_error_set_from_source(&ctx->error, src);
+                end = true;
+                break;
+            }
+            else if (n == 0) {
+                ctx->end_of_input = true;
+                ctx->algorithm->end_of_input(ctx->ud);
+                if (ctx->first_read < 0) {
+                    ctx->first_read = 0;
+                }
+            }
+            else {
+                if (ctx->first_read >= 0) {
+                    /* we overwrote a previously filled ctx->buffer */
+                    ctx->can_store = false;
+                }
+                else {
+                    ctx->first_read = n;
+                }
+
+                ctx->algorithm->input(ctx->ud, ctx->buffer, (zip_uint64_t)n);
+            }
+            break;
+
+        case ZIP_COMPRESSION_ERROR:
+            /* error set by algorithm */
+            if (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) {
+                zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
+            }
+            end = true;
+            break;
+        }
     }
 
     if (out_offset > 0) {
-       ctx->can_store = false;
-       ctx->size += out_offset;
-       return (zip_int64_t)out_offset;
+        ctx->can_store = false;
+        ctx->size += out_offset;
+        return (zip_int64_t)out_offset;
     }
 
     return (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) ? 0 : -1;
@@ -305,85 +308,91 @@ compress_callback(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip
     ctx = (struct context *)ud;
 
     switch (cmd) {
-    case ZIP_SOURCE_OPEN:
-       ctx->size = 0;
-       ctx->end_of_input = false;
-       ctx->end_of_stream = false;
-       ctx->is_stored = false;
-       ctx->first_read = -1;
-
-       if (!ctx->algorithm->start(ctx->ud)) {
-           return -1;
-       }
-
-       return 0;
+    case ZIP_SOURCE_OPEN: {
+        zip_stat_t st;
+        zip_file_attributes_t attributes;
+        
+        ctx->size = 0;
+        ctx->end_of_input = false;
+        ctx->end_of_stream = false;
+        ctx->is_stored = false;
+        ctx->first_read = -1;
+        
+        if (zip_source_stat(src, &st) < 0 || zip_source_get_file_attributes(src, &attributes) < 0) {
+            _zip_error_set_from_source(&ctx->error, src);
+            return -1;
+        }
+
+        if (!ctx->algorithm->start(ctx->ud, &st, &attributes)) {
+            return -1;
+        }
+
+        return 0;
+    }
 
     case ZIP_SOURCE_READ:
-       return compress_read(src, ctx, data, len);
+        return compress_read(src, ctx, data, len);
 
     case ZIP_SOURCE_CLOSE:
-       if (!ctx->algorithm->end(ctx->ud)) {
-           return -1;
-       }
-       return 0;
+        if (!ctx->algorithm->end(ctx->ud)) {
+            return -1;
+        }
+        return 0;
 
     case ZIP_SOURCE_STAT: {
-       zip_stat_t *st;
-
-       st = (zip_stat_t *)data;
-
-       if (ctx->compress) {
-           if (ctx->end_of_stream) {
-               st->comp_method = ctx->is_stored ? ZIP_CM_STORE : ZIP_CM_ACTUAL(ctx->method);
-               st->comp_size = ctx->size;
-               st->valid |= ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD;
-           }
-           else {
-               st->valid &= ~(ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD);
-           }
-       }
-       else {
-           st->comp_method = ZIP_CM_STORE;
-           st->valid |= ZIP_STAT_COMP_METHOD;
-           if (ctx->end_of_stream) {
-               st->size = ctx->size;
-               st->valid |= ZIP_STAT_SIZE;
-           }
-           else {
-               st->valid &= ~ZIP_STAT_SIZE;
-           }
-       }
+        zip_stat_t *st;
+
+        st = (zip_stat_t *)data;
+
+        if (ctx->compress) {
+            if (ctx->end_of_stream) {
+                st->comp_method = ctx->is_stored ? ZIP_CM_STORE : ZIP_CM_ACTUAL(ctx->method);
+                st->comp_size = ctx->size;
+                st->valid |= ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD;
+            }
+            else {
+                st->valid &= ~(ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD);
+            }
+        }
+        else {
+            st->comp_method = ZIP_CM_STORE;
+            st->valid |= ZIP_STAT_COMP_METHOD;
+            if (ctx->end_of_stream) {
+                st->size = ctx->size;
+                st->valid |= ZIP_STAT_SIZE;
+            }
+        }
     }
-       return 0;
+        return 0;
 
     case ZIP_SOURCE_ERROR:
-       return zip_error_to_data(&ctx->error, data, len);
+        return zip_error_to_data(&ctx->error, data, len);
 
     case ZIP_SOURCE_FREE:
-       context_free(ctx);
-       return 0;
+        context_free(ctx);
+        return 0;
 
     case ZIP_SOURCE_GET_FILE_ATTRIBUTES: {
-       zip_file_attributes_t *attributes = (zip_file_attributes_t *)data;
+        zip_file_attributes_t *attributes = (zip_file_attributes_t *)data;
 
-       if (len < sizeof(*attributes)) {
-           zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
-           return -1;
-       }
+        if (len < sizeof(*attributes)) {
+            zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
+            return -1;
+        }
 
-       attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED | ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS;
-       attributes->version_needed = ctx->algorithm->version_needed;
-       attributes->general_purpose_bit_mask = ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK;
-       attributes->general_purpose_bit_flags = (ctx->is_stored ? 0 : ctx->algorithm->general_purpose_bit_flags(ctx->ud));
+        attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED | ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS;
+        attributes->version_needed = ctx->algorithm->version_needed;
+        attributes->general_purpose_bit_mask = ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK;
+        attributes->general_purpose_bit_flags = (ctx->is_stored ? 0 : ctx->algorithm->general_purpose_bit_flags(ctx->ud));
 
-       return sizeof(*attributes);
+        return sizeof(*attributes);
     }
 
     case ZIP_SOURCE_SUPPORTS:
-       return ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1);
+        return ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1);
 
     default:
-       zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
+        return -1;
     }
 }
index 4f3f223..ebbeaa7 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_crc.c -- pass-through source that calculates CRC32 and size
-  Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -52,17 +52,17 @@ static zip_int64_t crc_read(zip_source_t *, void *, void *, zip_uint64_t, zip_so
 
 
 zip_source_t *
-zip_source_crc(zip_t *za, zip_source_t *src, int validate) {
+zip_source_crc_create(zip_source_t *src, int validate, zip_error_t *error) {
     struct crc_context *ctx;
 
     if (src == NULL) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
 
     if ((ctx = (struct crc_context *)malloc(sizeof(*ctx))) == NULL) {
-       zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     zip_error_init(&ctx->error);
@@ -72,7 +72,7 @@ zip_source_crc(zip_t *za, zip_source_t *src, int validate) {
     ctx->crc = (zip_uint32_t)crc32(0, NULL, 0);
     ctx->size = 0;
 
-    return zip_source_layered(za, src, crc_read, ctx);
+    return zip_source_layered_create(src, crc_read, ctx, error);
 }
 
 
@@ -85,113 +85,114 @@ crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source
 
     switch (cmd) {
     case ZIP_SOURCE_OPEN:
-       ctx->position = 0;
-       return 0;
+        ctx->position = 0;
+        return 0;
 
     case ZIP_SOURCE_READ:
-       if ((n = zip_source_read(src, data, len)) < 0) {
-           _zip_error_set_from_source(&ctx->error, src);
-           return -1;
-       }
-
-       if (n == 0) {
-           if (ctx->crc_position == ctx->position) {
-               ctx->crc_complete = 1;
-               ctx->size = ctx->position;
-
-               if (ctx->validate) {
-                   struct zip_stat st;
-
-                   if (zip_source_stat(src, &st) < 0) {
-                       _zip_error_set_from_source(&ctx->error, src);
-                       return -1;
-                   }
-
-                   if ((st.valid & ZIP_STAT_CRC) && st.crc != ctx->crc) {
-                       zip_error_set(&ctx->error, ZIP_ER_CRC, 0);
-                       return -1;
-                   }
-                   if ((st.valid & ZIP_STAT_SIZE) && st.size != ctx->size) {
-                       zip_error_set(&ctx->error, ZIP_ER_INCONS, 0);
-                       return -1;
-                   }
-               }
-           }
-       }
-       else if (!ctx->crc_complete && ctx->position <= ctx->crc_position) {
-           zip_uint64_t i, nn;
-
-           for (i = ctx->crc_position - ctx->position; i < (zip_uint64_t)n; i += nn) {
-               nn = ZIP_MIN(UINT_MAX, (zip_uint64_t)n - i);
-
-               ctx->crc = (zip_uint32_t)crc32(ctx->crc, (const Bytef *)data + i, (uInt)nn);
-               ctx->crc_position += nn;
-           }
-       }
-       ctx->position += (zip_uint64_t)n;
-       return n;
+        if ((n = zip_source_read(src, data, len)) < 0) {
+            _zip_error_set_from_source(&ctx->error, src);
+            return -1;
+        }
+
+        if (n == 0) {
+            if (ctx->crc_position == ctx->position) {
+                ctx->crc_complete = 1;
+                ctx->size = ctx->position;
+
+                if (ctx->validate) {
+                    struct zip_stat st;
+
+                    if (zip_source_stat(src, &st) < 0) {
+                        _zip_error_set_from_source(&ctx->error, src);
+                        return -1;
+                    }
+
+                    if ((st.valid & ZIP_STAT_CRC) && st.crc != ctx->crc) {
+                        zip_error_set(&ctx->error, ZIP_ER_CRC, 0);
+                        return -1;
+                    }
+                    if ((st.valid & ZIP_STAT_SIZE) && st.size != ctx->size) {
+                        /* We don't have the index here, but the caller should know which file they are reading from. */
+                        zip_error_set(&ctx->error, ZIP_ER_INCONS, MAKE_DETAIL_WITH_INDEX(ZIP_ER_DETAIL_INVALID_FILE_LENGTH, MAX_DETAIL_INDEX));
+                        return -1;
+                    }
+                }
+            }
+        }
+        else if (!ctx->crc_complete && ctx->position <= ctx->crc_position) {
+            zip_uint64_t i, nn;
+
+            for (i = ctx->crc_position - ctx->position; i < (zip_uint64_t)n; i += nn) {
+                nn = ZIP_MIN(UINT_MAX, (zip_uint64_t)n - i);
+
+                ctx->crc = (zip_uint32_t)crc32(ctx->crc, (const Bytef *)data + i, (uInt)nn);
+                ctx->crc_position += nn;
+            }
+        }
+        ctx->position += (zip_uint64_t)n;
+        return n;
 
     case ZIP_SOURCE_CLOSE:
-       return 0;
+        return 0;
 
     case ZIP_SOURCE_STAT: {
-       zip_stat_t *st;
-
-       st = (zip_stat_t *)data;
-
-       if (ctx->crc_complete) {
-           /* TODO: Set comp_size, comp_method, encryption_method?
-                   After all, this only works for uncompressed data. */
-           st->size = ctx->size;
-           st->crc = ctx->crc;
-           st->comp_size = ctx->size;
-           st->comp_method = ZIP_CM_STORE;
-           st->encryption_method = ZIP_EM_NONE;
-           st->valid |= ZIP_STAT_SIZE | ZIP_STAT_CRC | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_ENCRYPTION_METHOD;
-       }
-       return 0;
+        zip_stat_t *st;
+
+        st = (zip_stat_t *)data;
+
+        if (ctx->crc_complete) {
+            /* TODO: Set comp_size, comp_method, encryption_method?
+                    After all, this only works for uncompressed data. */
+            st->size = ctx->size;
+            st->crc = ctx->crc;
+            st->comp_size = ctx->size;
+            st->comp_method = ZIP_CM_STORE;
+            st->encryption_method = ZIP_EM_NONE;
+            st->valid |= ZIP_STAT_SIZE | ZIP_STAT_CRC | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_ENCRYPTION_METHOD;
+        }
+        return 0;
     }
 
     case ZIP_SOURCE_ERROR:
-       return zip_error_to_data(&ctx->error, data, len);
+        return zip_error_to_data(&ctx->error, data, len);
 
     case ZIP_SOURCE_FREE:
-       free(ctx);
-       return 0;
+        free(ctx);
+        return 0;
 
     case ZIP_SOURCE_SUPPORTS: {
-       zip_int64_t mask = zip_source_supports(src);
+        zip_int64_t mask = zip_source_supports(src);
 
-       if (mask < 0) {
-           _zip_error_set_from_source(&ctx->error, src);
-           return -1;
-       }
+        if (mask < 0) {
+            _zip_error_set_from_source(&ctx->error, src);
+            return -1;
+        }
 
-       return mask & ~zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1);
+        return mask & ~zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1);
     }
 
     case ZIP_SOURCE_SEEK: {
-       zip_int64_t new_position;
-       zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);
+        zip_int64_t new_position;
+        zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);
 
-       if (args == NULL) {
-           return -1;
-       }
-       if (zip_source_seek(src, args->offset, args->whence) < 0 || (new_position = zip_source_tell(src)) < 0) {
-           _zip_error_set_from_source(&ctx->error, src);
-           return -1;
-       }
+        if (args == NULL) {
+            return -1;
+        }
+        if (zip_source_seek(src, args->offset, args->whence) < 0 || (new_position = zip_source_tell(src)) < 0) {
+            _zip_error_set_from_source(&ctx->error, src);
+            return -1;
+        }
 
-       ctx->position = (zip_uint64_t)new_position;
+        ctx->position = (zip_uint64_t)new_position;
 
-       return 0;
+        return 0;
     }
 
     case ZIP_SOURCE_TELL:
-       return (zip_int64_t)ctx->position;
+        return (zip_int64_t)ctx->position;
 
     default:
-       zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
+        return -1;
     }
 }
index 2257f71..042901f 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_error.c -- get last error from zip_source
-  Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
index 74e2100..0012395 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_file_common.c -- create data source from file
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -56,70 +56,70 @@ zip_source_file_common_new(const char *fname, void *file, zip_uint64_t start, zi
     zip_source_file_stat_t sb;
 
     if (ops == NULL) {
-       zip_error_set(error, ZIP_ER_INVAL, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
 
     if (ops->close == NULL || ops->read == NULL || ops->seek == NULL || ops->stat == NULL) {
-       zip_error_set(error, ZIP_ER_INTERNAL, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INTERNAL, 0);
+        return NULL;
     }
 
     if (ops->write != NULL && (ops->commit_write == NULL || ops->create_temp_output == NULL || ops->remove == NULL || ops->rollback_write == NULL || ops->tell == NULL)) {
-       zip_error_set(error, ZIP_ER_INTERNAL, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INTERNAL, 0);
+        return NULL;
     }
 
     if (fname != NULL) {
-       if (ops->open == NULL || ops->string_duplicate == NULL) {
-           zip_error_set(error, ZIP_ER_INTERNAL, 0);
-           return NULL;
-       }
+        if (ops->open == NULL || ops->string_duplicate == NULL) {
+            zip_error_set(error, ZIP_ER_INTERNAL, 0);
+            return NULL;
+        }
     }
     else if (file == NULL) {
-       zip_error_set(error, ZIP_ER_INVAL, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
 
     if (len < 0) {
-       len = 0;
+        len = 0;
     }
 
     if (start > ZIP_INT64_MAX || start + (zip_uint64_t)len < start) {
-       zip_error_set(error, ZIP_ER_INVAL, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
 
     if ((ctx = (zip_source_file_context_t *)malloc(sizeof(zip_source_file_context_t))) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     ctx->ops = ops;
     ctx->ops_userdata = ops_userdata;
     ctx->fname = NULL;
     if (fname) {
-       if ((ctx->fname = ops->string_duplicate(ctx, fname)) == NULL) {
-           zip_error_set(error, ZIP_ER_MEMORY, 0);
-           free(ctx);
-           return NULL;
-       }
+        if ((ctx->fname = ops->string_duplicate(ctx, fname)) == NULL) {
+            zip_error_set(error, ZIP_ER_MEMORY, 0);
+            free(ctx);
+            return NULL;
+        }
     }
     ctx->f = file;
     ctx->start = start;
     ctx->len = (zip_uint64_t)len;
     if (st) {
-       memcpy(&ctx->st, st, sizeof(ctx->st));
-       ctx->st.name = NULL;
-       ctx->st.valid &= ~ZIP_STAT_NAME;
+        memcpy(&ctx->st, st, sizeof(ctx->st));
+        ctx->st.name = NULL;
+        ctx->st.valid &= ~ZIP_STAT_NAME;
     }
     else {
-       zip_stat_init(&ctx->st);
+        zip_stat_init(&ctx->st);
     }
 
     if (ctx->len > 0) {
-       ctx->st.size = ctx->len;
-       ctx->st.valid |= ZIP_STAT_SIZE;
+        ctx->st.size = ctx->len;
+        ctx->st.valid |= ZIP_STAT_SIZE;
     }
 
     zip_error_init(&ctx->stat_error);
@@ -154,46 +154,46 @@ zip_source_file_common_new(const char *fname, void *file, zip_uint64_t start, zi
         }
     }
     else {
-       if ((ctx->st.valid & ZIP_STAT_MTIME) == 0) {
-           ctx->st.mtime = sb.mtime;
-           ctx->st.valid |= ZIP_STAT_MTIME;
-       }
-       if (sb.regular_file) {
-           ctx->supports = ZIP_SOURCE_SUPPORTS_SEEKABLE;
-
-           if (ctx->start + ctx->len > sb.size) {
-               zip_error_set(error, ZIP_ER_INVAL, 0);
-               free(ctx->fname);
-               free(ctx);
-               return NULL;
-           }
-
-           if (ctx->len == 0) {
-               ctx->len = sb.size - ctx->start;
-               ctx->st.size = ctx->len;
-               ctx->st.valid |= ZIP_STAT_SIZE;
-
-               /* when using a partial file, don't allow writing */
-               if (ctx->fname && start == 0 && ops->write != NULL) {
-                   ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE;
-               }
-           }
-       }
-
-       ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_GET_FILE_ATTRIBUTES);
+        if ((ctx->st.valid & ZIP_STAT_MTIME) == 0) {
+            ctx->st.mtime = sb.mtime;
+            ctx->st.valid |= ZIP_STAT_MTIME;
+        }
+        if (sb.regular_file) {
+            ctx->supports = ZIP_SOURCE_SUPPORTS_SEEKABLE;
+
+            if (ctx->start + ctx->len > sb.size) {
+                zip_error_set(error, ZIP_ER_INVAL, 0);
+                free(ctx->fname);
+                free(ctx);
+                return NULL;
+            }
+
+            if (ctx->len == 0) {
+                ctx->len = sb.size - ctx->start;
+                ctx->st.size = ctx->len;
+                ctx->st.valid |= ZIP_STAT_SIZE;
+
+                /* when using a partial file, don't allow writing */
+                if (ctx->fname && start == 0 && ops->write != NULL) {
+                    ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE;
+                }
+            }
+        }
+
+        ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_GET_FILE_ATTRIBUTES);
     }
 
     ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ACCEPT_EMPTY);
     if (ops->create_temp_output_cloning != NULL) {
-       if (ctx->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE)) {
-           ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING);
-       }
+        if (ctx->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE)) {
+            ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING);
+        }
     }
 
     if ((zs = zip_source_function_create(read_file, ctx, error)) == NULL) {
-       free(ctx->fname);
-       free(ctx);
-       return NULL;
+        free(ctx->fname);
+        free(ctx);
+        return NULL;
     }
 
     return zs;
@@ -210,169 +210,169 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
 
     switch (cmd) {
     case ZIP_SOURCE_ACCEPT_EMPTY:
-       return 0;
+        return 0;
 
     case ZIP_SOURCE_BEGIN_WRITE:
-       /* write support should not be set if fname is NULL */
-       if (ctx->fname == NULL) {
-           zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
-           return -1;
-       }
-       return ctx->ops->create_temp_output(ctx);
+        /* write support should not be set if fname is NULL */
+        if (ctx->fname == NULL) {
+            zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
+            return -1;
+        }
+        return ctx->ops->create_temp_output(ctx);
 
     case ZIP_SOURCE_BEGIN_WRITE_CLONING:
-       /* write support should not be set if fname is NULL */
-       if (ctx->fname == NULL) {
-           zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
-           return -1;
-       }
-       return ctx->ops->create_temp_output_cloning(ctx, len);
+        /* write support should not be set if fname is NULL */
+        if (ctx->fname == NULL) {
+            zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
+            return -1;
+        }
+        return ctx->ops->create_temp_output_cloning(ctx, len);
 
     case ZIP_SOURCE_CLOSE:
-       if (ctx->fname) {
-           ctx->ops->close(ctx);
-           ctx->f = NULL;
-       }
-       return 0;
+        if (ctx->fname) {
+            ctx->ops->close(ctx);
+            ctx->f = NULL;
+        }
+        return 0;
 
     case ZIP_SOURCE_COMMIT_WRITE: {
-       zip_int64_t ret = ctx->ops->commit_write(ctx);
-       ctx->fout = NULL;
-       if (ret == 0) {
-           free(ctx->tmpname);
-           ctx->tmpname = NULL;
-       }
-       return ret;
+        zip_int64_t ret = ctx->ops->commit_write(ctx);
+        ctx->fout = NULL;
+        if (ret == 0) {
+            free(ctx->tmpname);
+            ctx->tmpname = NULL;
+        }
+        return ret;
     }
 
     case ZIP_SOURCE_ERROR:
-       return zip_error_to_data(&ctx->error, data, len);
+        return zip_error_to_data(&ctx->error, data, len);
 
     case ZIP_SOURCE_FREE:
-       free(ctx->fname);
-       free(ctx->tmpname);
-       if (ctx->f) {
-           ctx->ops->close(ctx);
-       }
-       free(ctx);
-       return 0;
+        free(ctx->fname);
+        free(ctx->tmpname);
+        if (ctx->f) {
+            ctx->ops->close(ctx);
+        }
+        free(ctx);
+        return 0;
 
     case ZIP_SOURCE_GET_FILE_ATTRIBUTES:
-       if (len < sizeof(ctx->attributes)) {
-           zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
-           return -1;
-       }
-       memcpy(data, &ctx->attributes, sizeof(ctx->attributes));
-       return sizeof(ctx->attributes);
+        if (len < sizeof(ctx->attributes)) {
+            zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
+            return -1;
+        }
+        memcpy(data, &ctx->attributes, sizeof(ctx->attributes));
+        return sizeof(ctx->attributes);
 
     case ZIP_SOURCE_OPEN:
-       if (ctx->fname) {
-           if (ctx->ops->open(ctx) == false) {
-               return -1;
-           }
-       }
-
-       if (ctx->start > 0) { // TODO: rewind on re-open
-           if (ctx->ops->seek(ctx, ctx->f, (zip_int64_t)ctx->start, SEEK_SET) == false) {
-               /* TODO: skip by reading */
-               return -1;
-           }
-       }
-       ctx->offset = 0;
-       return 0;
+        if (ctx->fname) {
+            if (ctx->ops->open(ctx) == false) {
+                return -1;
+            }
+        }
+
+        if (ctx->start > 0) { // TODO: rewind on re-open
+            if (ctx->ops->seek(ctx, ctx->f, (zip_int64_t)ctx->start, SEEK_SET) == false) {
+                /* TODO: skip by reading */
+                return -1;
+            }
+        }
+        ctx->offset = 0;
+        return 0;
 
     case ZIP_SOURCE_READ: {
-       zip_int64_t i;
-       zip_uint64_t n;
-
-       if (ctx->len > 0) {
-           n = ZIP_MIN(ctx->len - ctx->offset, len);
-       }
-       else {
-           n = len;
-       }
-
-       if ((i = ctx->ops->read(ctx, buf, n)) < 0) {
-           zip_error_set(&ctx->error, ZIP_ER_READ, errno);
-           return -1;
-       }
-       ctx->offset += (zip_uint64_t)i;
-
-       return i;
+        zip_int64_t i;
+        zip_uint64_t n;
+
+        if (ctx->len > 0) {
+            n = ZIP_MIN(ctx->len - ctx->offset, len);
+        }
+        else {
+            n = len;
+        }
+
+        if ((i = ctx->ops->read(ctx, buf, n)) < 0) {
+            zip_error_set(&ctx->error, ZIP_ER_READ, errno);
+            return -1;
+        }
+        ctx->offset += (zip_uint64_t)i;
+
+        return i;
     }
 
     case ZIP_SOURCE_REMOVE:
-       return ctx->ops->remove(ctx);
+        return ctx->ops->remove(ctx);
 
     case ZIP_SOURCE_ROLLBACK_WRITE:
-       ctx->ops->rollback_write(ctx);
-       ctx->fout = NULL;
-       free(ctx->tmpname);
-       ctx->tmpname = NULL;
-       return 0;
+        ctx->ops->rollback_write(ctx);
+        ctx->fout = NULL;
+        free(ctx->tmpname);
+        ctx->tmpname = NULL;
+        return 0;
 
     case ZIP_SOURCE_SEEK: {
-       zip_int64_t new_offset = zip_source_seek_compute_offset(ctx->offset, ctx->len, data, len, &ctx->error);
+        zip_int64_t new_offset = zip_source_seek_compute_offset(ctx->offset, ctx->len, data, len, &ctx->error);
 
-       if (new_offset < 0) {
-           return -1;
-       }
+        if (new_offset < 0) {
+            return -1;
+        }
 
-       /* The actual offset inside the file must be representable as zip_int64_t. */
-       if (new_offset > ZIP_INT64_MAX - (zip_int64_t)ctx->start) {
-           zip_error_set(&ctx->error, ZIP_ER_SEEK, EOVERFLOW);
-           return -1;
-       }
+        /* The actual offset inside the file must be representable as zip_int64_t. */
+        if (new_offset > ZIP_INT64_MAX - (zip_int64_t)ctx->start) {
+            zip_error_set(&ctx->error, ZIP_ER_SEEK, EOVERFLOW);
+            return -1;
+        }
 
-       ctx->offset = (zip_uint64_t)new_offset;
+        ctx->offset = (zip_uint64_t)new_offset;
 
-       if (ctx->ops->seek(ctx, ctx->f, (zip_int64_t)(ctx->offset + ctx->start), SEEK_SET) == false) {
-           return -1;
-       }
-       return 0;
+        if (ctx->ops->seek(ctx, ctx->f, (zip_int64_t)(ctx->offset + ctx->start), SEEK_SET) == false) {
+            return -1;
+        }
+        return 0;
     }
 
     case ZIP_SOURCE_SEEK_WRITE: {
-       zip_source_args_seek_t *args;
+        zip_source_args_seek_t *args;
 
-       args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);
-       if (args == NULL) {
-           return -1;
-       }
+        args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);
+        if (args == NULL) {
+            return -1;
+        }
 
-       if (ctx->ops->seek(ctx, ctx->fout, args->offset, args->whence) == false) {
-           return -1;
-       }
-       return 0;
+        if (ctx->ops->seek(ctx, ctx->fout, args->offset, args->whence) == false) {
+            return -1;
+        }
+        return 0;
     }
 
     case ZIP_SOURCE_STAT: {
-       if (len < sizeof(ctx->st))
-           return -1;
+        if (len < sizeof(ctx->st))
+            return -1;
 
-       if (zip_error_code_zip(&ctx->stat_error) != 0) {
-           zip_error_set(&ctx->error, zip_error_code_zip(&ctx->stat_error), zip_error_code_system(&ctx->stat_error));
-           return -1;
-       }
+        if (zip_error_code_zip(&ctx->stat_error) != 0) {
+            zip_error_set(&ctx->error, zip_error_code_zip(&ctx->stat_error), zip_error_code_system(&ctx->stat_error));
+            return -1;
+        }
 
-       memcpy(data, &ctx->st, sizeof(ctx->st));
-       return sizeof(ctx->st);
+        memcpy(data, &ctx->st, sizeof(ctx->st));
+        return sizeof(ctx->st);
     }
 
     case ZIP_SOURCE_SUPPORTS:
-       return ctx->supports;
+        return ctx->supports;
 
     case ZIP_SOURCE_TELL:
-       return (zip_int64_t)ctx->offset;
+        return (zip_int64_t)ctx->offset;
 
     case ZIP_SOURCE_TELL_WRITE:
-       return ctx->ops->tell(ctx, ctx->fout);
+        return ctx->ops->tell(ctx, ctx->fout);
 
     case ZIP_SOURCE_WRITE:
-       return ctx->ops->write(ctx, data, len);
+        return ctx->ops->write(ctx, data, len);
 
     default:
-       zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
+        return -1;
     }
 }
index 4a22f78..1581771 100644 (file)
@@ -69,7 +69,7 @@ static zip_source_file_operations_t ops_stdio_read = {
 ZIP_EXTERN zip_source_t *
 zip_source_filep(zip_t *za, FILE *file, zip_uint64_t start, zip_int64_t len) {
     if (za == NULL) {
-       return NULL;
+        return NULL;
     }
 
     return zip_source_filep_create(file, start, len, &za->error);
@@ -79,8 +79,8 @@ zip_source_filep(zip_t *za, FILE *file, zip_uint64_t start, zip_int64_t len) {
 ZIP_EXTERN zip_source_t *
 zip_source_filep_create(FILE *file, zip_uint64_t start, zip_int64_t length, zip_error_t *error) {
     if (file == NULL || length < -1) {
-       zip_error_set(error, ZIP_ER_INVAL, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
 
     return zip_source_file_common_new(NULL, file, start, length, NULL, &ops_stdio_read, NULL, error);
@@ -97,14 +97,14 @@ zip_int64_t
 _zip_stdio_op_read(zip_source_file_context_t *ctx, void *buf, zip_uint64_t len) {
     size_t i;
     if (len > SIZE_MAX) {
-       len = SIZE_MAX;
+        len = SIZE_MAX;
     }
 
     if ((i = fread(buf, 1, (size_t)len, ctx->f)) == 0) {
-       if (ferror((FILE *)ctx->f)) {
-           zip_error_set(&ctx->error, ZIP_ER_READ, errno);
-           return -1;
-       }
+        if (ferror((FILE *)ctx->f)) {
+            zip_error_set(&ctx->error, ZIP_ER_READ, errno);
+            return -1;
+        }
     }
 
     return (zip_int64_t)i;
@@ -115,14 +115,14 @@ bool
 _zip_stdio_op_seek(zip_source_file_context_t *ctx, void *f, zip_int64_t offset, int whence) {
 #if ZIP_FSEEK_MAX > ZIP_INT64_MAX
     if (offset > ZIP_FSEEK_MAX || offset < ZIP_FSEEK_MIN) {
-       zip_error_set(&ctx->error, ZIP_ER_SEEK, EOVERFLOW);
-       return false;
+        zip_error_set(&ctx->error, ZIP_ER_SEEK, EOVERFLOW);
+        return false;
     }
 #endif
 
     if (fseeko((FILE *)f, (off_t)offset, whence) < 0) {
-       zip_error_set(&ctx->error, ZIP_ER_SEEK, errno);
-       return false;
+        zip_error_set(&ctx->error, ZIP_ER_SEEK, errno);
+        return false;
     }
     return true;
 }
@@ -135,10 +135,10 @@ _zip_stdio_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st) {
     int ret;
 
     if (ctx->fname) {
-       ret = stat(ctx->fname, &sb);
+        ret = stat(ctx->fname, &sb);
     }
     else {
-       ret = fstat(fileno((FILE *)ctx->f), &sb);
+        ret = fstat(fileno((FILE *)ctx->f), &sb);
     }
 
     if (ret < 0) {
@@ -146,8 +146,8 @@ _zip_stdio_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st) {
             st->exists = false;
             return true;
         }
-       zip_error_set(&ctx->error, ZIP_ER_READ, errno);
-       return false;
+        zip_error_set(&ctx->error, ZIP_ER_READ, errno);
+        return false;
     }
 
     st->size = (zip_uint64_t)sb.st_size;
@@ -171,7 +171,7 @@ _zip_stdio_op_tell(zip_source_file_context_t *ctx, void *f) {
     off_t offset = ftello((FILE *)f);
 
     if (offset < 0) {
-       zip_error_set(&ctx->error, ZIP_ER_SEEK, errno);
+        zip_error_set(&ctx->error, ZIP_ER_SEEK, errno);
     }
 
     return offset;
@@ -191,18 +191,18 @@ _zip_fopen_close_on_exec(const char *name, bool writeable) {
 
     flags = O_CLOEXEC;
     if (writeable) {
-       flags |= O_RDWR;
+        flags |= O_RDWR;
     }
     else {
-       flags |= O_RDONLY;
+        flags |= O_RDONLY;
     }
 
     /* mode argument needed on Windows */
     if ((fd = open(name, flags, 0666)) < 0) {
-       return NULL;
+        return NULL;
     }
     if ((fp = fdopen(fd, writeable ? "r+b" : "rb")) == NULL) {
-       return NULL;
+        return NULL;
     }
     return fp;
 }
index dae8177..5387c76 100644 (file)
@@ -89,7 +89,7 @@ static zip_source_file_operations_t ops_stdio_named = {
 ZIP_EXTERN zip_source_t *
 zip_source_file(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t len) {
     if (za == NULL)
-       return NULL;
+        return NULL;
 
     return zip_source_file_create(fname, start, len, &za->error);
 }
@@ -98,8 +98,8 @@ zip_source_file(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t le
 ZIP_EXTERN zip_source_t *
 zip_source_file_create(const char *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error) {
     if (fname == NULL || length < -1) {
-       zip_error_set(error, ZIP_ER_INVAL, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
 
     return zip_source_file_common_new(fname, NULL, start, length, NULL, &ops_stdio_named, NULL, error);
@@ -109,12 +109,12 @@ zip_source_file_create(const char *fname, zip_uint64_t start, zip_int64_t length
 static zip_int64_t
 _zip_stdio_op_commit_write(zip_source_file_context_t *ctx) {
     if (fclose(ctx->fout) < 0) {
-       zip_error_set(&ctx->error, ZIP_ER_WRITE, errno);
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_WRITE, errno);
+        return -1;
     }
     if (rename(ctx->tmpname, ctx->fname) < 0) {
-       zip_error_set(&ctx->error, ZIP_ER_RENAME, errno);
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_RENAME, errno);
+        return -1;
     }
 
     return 0;
@@ -130,31 +130,31 @@ _zip_stdio_op_create_temp_output(zip_source_file_context_t *ctx) {
     struct stat st;
 
     if ((temp = (char *)malloc(strlen(ctx->fname) + 8)) == NULL) {
-       zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
+        return -1;
     }
 
     if (stat(ctx->fname, &st) == 0) {
-       mode = st.st_mode;
+        mode = st.st_mode;
     }
     else {
-       mode = -1;
+        mode = -1;
     }
 
     sprintf(temp, "%s.XXXXXX", ctx->fname);
 
     if ((tfd = _zip_mkstempm(temp, mode)) == -1) {
-       zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
-       free(temp);
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
+        free(temp);
+        return -1;
     }
 
     if ((tfp = fdopen(tfd, "r+b")) == NULL) {
-       zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
-       close(tfd);
-       (void)remove(temp);
-       free(temp);
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
+        close(tfd);
+        (void)remove(temp);
+        free(temp);
+        return -1;
     }
 
     ctx->fout = tfp;
@@ -170,13 +170,13 @@ _zip_stdio_op_create_temp_output_cloning(zip_source_file_context_t *ctx, zip_uin
     FILE *tfp;
 
     if (offset > ZIP_OFF_MAX) {
-       zip_error_set(&ctx->error, ZIP_ER_SEEK, E2BIG);
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_SEEK, E2BIG);
+        return -1;
     }
 
     if ((temp = (char *)malloc(strlen(ctx->fname) + 8)) == NULL) {
-       zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
+        return -1;
     }
     sprintf(temp, "%s.XXXXXX", ctx->fname);
 
@@ -184,77 +184,77 @@ _zip_stdio_op_create_temp_output_cloning(zip_source_file_context_t *ctx, zip_uin
 #ifndef __clang_analyzer__
     /* we can't use mkstemp, since clonefile insists on creating the file */
     if (mktemp(temp) == NULL) {
-       zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
-       free(temp);
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
+        free(temp);
+        return -1;
     }
 #endif
 
     if (clonefile(ctx->fname, temp, 0) < 0) {
-       zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
-       free(temp);
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
+        free(temp);
+        return -1;
     }
     if ((tfp = _zip_fopen_close_on_exec(temp, true)) == NULL) {
-       zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
-       (void)remove(temp);
-       free(temp);
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
+        (void)remove(temp);
+        free(temp);
+        return -1;
     }
 #else
     {
-       int fd;
-       struct file_clone_range range;
-       struct stat st;
-
-       if (fstat(fileno(ctx->f), &st) < 0) {
-           zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
-           free(temp);
-           return -1;
-       }
-
-       if ((fd = mkstemp(temp)) < 0) {
-           zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
-           free(temp);
-           return -1;
-       }
-
-       range.src_fd = fileno(ctx->f);
-       range.src_offset = 0;
-       range.src_length = ((offset + st.st_blksize - 1) / st.st_blksize) * st.st_blksize;
-       if (range.src_length > st.st_size) {
-           range.src_length = 0;
-       }
-       range.dest_offset = 0;
-       if (ioctl(fd, FICLONERANGE, &range) < 0) {
-           zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
-           (void)close(fd);
-           (void)remove(temp);
-           free(temp);
-           return -1;
-       }
-
-       if ((tfp = fdopen(fd, "r+b")) == NULL) {
-           zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
-           (void)close(fd);
-           (void)remove(temp);
-           free(temp);
-           return -1;
-       }
+        int fd;
+        struct file_clone_range range;
+        struct stat st;
+
+        if (fstat(fileno(ctx->f), &st) < 0) {
+            zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
+            free(temp);
+            return -1;
+        }
+
+        if ((fd = mkstemp(temp)) < 0) {
+            zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
+            free(temp);
+            return -1;
+        }
+
+        range.src_fd = fileno(ctx->f);
+        range.src_offset = 0;
+        range.src_length = ((offset + st.st_blksize - 1) / st.st_blksize) * st.st_blksize;
+        if (range.src_length > st.st_size) {
+            range.src_length = 0;
+        }
+        range.dest_offset = 0;
+        if (ioctl(fd, FICLONERANGE, &range) < 0) {
+            zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
+            (void)close(fd);
+            (void)remove(temp);
+            free(temp);
+            return -1;
+        }
+
+        if ((tfp = fdopen(fd, "r+b")) == NULL) {
+            zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
+            (void)close(fd);
+            (void)remove(temp);
+            free(temp);
+            return -1;
+        }
     }
 #endif
 
     if (ftruncate(fileno(tfp), (off_t)offset) < 0) {
-       (void)fclose(tfp);
-       (void)remove(temp);
-       free(temp);
-       return -1;
+        (void)fclose(tfp);
+        (void)remove(temp);
+        free(temp);
+        return -1;
     }
     if (fseeko(tfp, (off_t)offset, SEEK_SET) < 0) {
-       (void)fclose(tfp);
-       (void)remove(temp);
-       free(temp);
-       zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
+        (void)fclose(tfp);
+        (void)remove(temp);
+        free(temp);
+        zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
     }
 
     ctx->fout = tfp;
@@ -267,8 +267,8 @@ _zip_stdio_op_create_temp_output_cloning(zip_source_file_context_t *ctx, zip_uin
 static bool
 _zip_stdio_op_open(zip_source_file_context_t *ctx) {
     if ((ctx->f = _zip_fopen_close_on_exec(ctx->fname, false)) == NULL) {
-       zip_error_set(&ctx->error, ZIP_ER_OPEN, errno);
-       return false;
+        zip_error_set(&ctx->error, ZIP_ER_OPEN, errno);
+        return false;
     }
     return true;
 }
@@ -277,8 +277,8 @@ _zip_stdio_op_open(zip_source_file_context_t *ctx) {
 static zip_int64_t
 _zip_stdio_op_remove(zip_source_file_context_t *ctx) {
     if (remove(ctx->fname) < 0) {
-       zip_error_set(&ctx->error, ZIP_ER_REMOVE, errno);
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_REMOVE, errno);
+        return -1;
     }
     return 0;
 }
@@ -287,7 +287,7 @@ _zip_stdio_op_remove(zip_source_file_context_t *ctx) {
 static void
 _zip_stdio_op_rollback_write(zip_source_file_context_t *ctx) {
     if (ctx->fout) {
-       fclose(ctx->fout);
+        fclose(ctx->fout);
     }
     (void)remove(ctx->tmpname);
 }
@@ -305,8 +305,8 @@ _zip_stdio_op_write(zip_source_file_context_t *ctx, const void *data, zip_uint64
     clearerr((FILE *)ctx->fout);
     ret = fwrite(data, 1, len, (FILE *)ctx->fout);
     if (ret != len || ferror((FILE *)ctx->fout)) {
-       zip_error_set(&ctx->error, ZIP_ER_WRITE, errno);
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_WRITE, errno);
+        return -1;
     }
 
     return (zip_int64_t)ret;
index 2fe838f..6547fc2 100644 (file)
@@ -37,6 +37,8 @@ static bool _zip_win32_op_stat(zip_source_file_context_t *ctx, zip_source_file_s
 
 static bool _zip_stat_win32(zip_source_file_context_t *ctx, zip_source_file_stat_t *st, HANDLE h);
 
+/* clang-format off */
+
 static zip_source_file_operations_t ops_win32_read = {
     _zip_win32_op_close,
     NULL,
@@ -53,13 +55,14 @@ static zip_source_file_operations_t ops_win32_read = {
     NULL
 };
 
+/* clang-format on */
 
 ZIP_EXTERN zip_source_t *
 zip_source_win32handle(zip_t *za, HANDLE h, zip_uint64_t start, zip_int64_t len) {
     if (za == NULL) {
         return NULL;
     }
-    
+
     return zip_source_win32handle_create(h, start, len, &za->error);
 }
 
@@ -90,7 +93,7 @@ _zip_win32_op_read(zip_source_file_context_t *ctx, void *buf, zip_uint64_t len)
         zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError()));
         return -1;
     }
-    
+
     return (zip_int64_t)i;
 }
 
@@ -135,13 +138,13 @@ zip_int64_t
 _zip_win32_op_tell(zip_source_file_context_t *ctx, void *f) {
     LARGE_INTEGER zero;
     LARGE_INTEGER new_offset;
-    
+
     zero.QuadPart = 0;
     if (!SetFilePointerEx((HANDLE)f, zero, &new_offset, FILE_CURRENT)) {
         zip_error_set(&ctx->error, ZIP_ER_SEEK, _zip_win32_error_to_errno(GetLastError()));
         return -1;
     }
-    
+
     return (zip_int64_t)new_offset.QuadPart;
 }
 
@@ -153,6 +156,7 @@ _zip_win32_error_to_errno(DWORD win32err) {
     case ERROR_INVALID_PARAMETER:
         return EINVAL;
     case ERROR_FILE_NOT_FOUND:
+    case ERROR_PATH_NOT_FOUND:
         return ENOENT;
     case ERROR_INVALID_HANDLE:
         return EBADF;
@@ -184,7 +188,7 @@ _zip_stat_win32(zip_source_file_context_t *ctx, zip_source_file_stat_t *st, HAND
         zip_error_set(&ctx->error, ZIP_ER_READ, ERANGE);
         return false;
     }
-    
+
     st->exists = true;
     st->mtime = mtime;
 
@@ -198,7 +202,7 @@ _zip_stat_win32(zip_source_file_context_t *ctx, zip_source_file_stat_t *st, HAND
 
         st->size = (zip_uint64_t)size.QuadPart;
     }
-    
+
     /* TODO: fill in ctx->attributes */
 
     return true;
index 5092e63..88e45b1 100644 (file)
 
 #include <aclapi.h>
 
+#include <stdlib.h>
+
 #include "zipint.h"
 
 #include "zip_source_file.h"
 
 struct zip_win32_file_operations {
     char *(*allocate_tempname)(const char *name, size_t extra_chars, size_t *lengthp);
-    HANDLE (__stdcall *create_file)(const void *name, DWORD access, DWORD share_mode, PSECURITY_ATTRIBUTES security_attributes, DWORD creation_disposition, DWORD file_attributes, HANDLE template_file);
-    BOOL (__stdcall *delete_file)(const void *name);
-    DWORD (__stdcall *get_file_attributes)(const void *name);
-    BOOL (__stdcall *get_file_attributes_ex)(const void *name, GET_FILEEX_INFO_LEVELS info_level, void *information);
+    HANDLE(__stdcall *create_file)(const void *name, DWORD access, DWORD share_mode, PSECURITY_ATTRIBUTES security_attributes, DWORD creation_disposition, DWORD file_attributes, HANDLE template_file);
+    BOOL(__stdcall *delete_file)(const void *name);
+    DWORD(__stdcall *get_file_attributes)(const void *name);
+    BOOL(__stdcall *get_file_attributes_ex)(const void *name, GET_FILEEX_INFO_LEVELS info_level, void *information);
     void (*make_tempname)(char *buf, size_t len, const char *name, zip_uint32_t i);
-    BOOL (__stdcall *move_file)(const void *from, const void *to, DWORD flags);
-    BOOL (__stdcall *set_file_attributes)(const void *name, DWORD attributes);
+    BOOL(__stdcall *move_file)(const void *from, const void *to, DWORD flags);
+    BOOL(__stdcall *set_file_attributes)(const void *name, DWORD attributes);
     char *(*string_duplicate)(const char *string);
 };
 
index 573b74e..f299692 100644 (file)
@@ -36,6 +36,8 @@
 static char *ansi_allocate_tempname(const char *name, size_t extra_chars, size_t *lengthp);
 static void ansi_make_tempname(char *buf, size_t len, const char *name, zip_uint32_t i);
 
+/* clang-format off */
+
 zip_win32_file_operations_t ops_ansi = {
     ansi_allocate_tempname,
     CreateFileA,
@@ -48,10 +50,12 @@ zip_win32_file_operations_t ops_ansi = {
     strdup
 };
 
+/* clang-format on */
+
 ZIP_EXTERN zip_source_t *
 zip_source_win32a(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t len) {
     if (za == NULL)
-    return NULL;
+        return NULL;
 
     return zip_source_win32a_create(fname, start, len, &za->error);
 }
@@ -60,8 +64,8 @@ zip_source_win32a(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t
 ZIP_EXTERN zip_source_t *
 zip_source_win32a_create(const char *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error) {
     if (fname == NULL || length < -1) {
-    zip_error_set(error, ZIP_ER_INVAL, 0);
-    return NULL;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
 
     return zip_source_file_common_new(fname, NULL, start, length, NULL, &_zip_source_file_win32_named_ops, &ops_ansi, error);
index 9591b26..1fe5591 100644 (file)
@@ -65,13 +65,14 @@ zip_source_file_operations_t _zip_source_file_win32_named_ops = {
 static zip_int64_t
 _zip_win32_named_op_commit_write(zip_source_file_context_t *ctx) {
     zip_win32_file_operations_t *file_ops = (zip_win32_file_operations_t *)ctx->ops_userdata;
-    
+    DWORD attributes;
+
     if (!CloseHandle((HANDLE)ctx->fout)) {
         zip_error_set(&ctx->error, ZIP_ER_WRITE, _zip_win32_error_to_errno(GetLastError()));
         return -1;
     }
-    
-    DWORD attributes = file_ops->get_file_attributes(ctx->tmpname);
+
+    attributes = file_ops->get_file_attributes(ctx->tmpname);
     if (attributes == INVALID_FILE_ATTRIBUTES) {
         zip_error_set(&ctx->error, ZIP_ER_RENAME, _zip_win32_error_to_errno(GetLastError()));
         return -1;
@@ -108,47 +109,47 @@ _zip_win32_named_op_create_temp_output(zip_source_file_context_t *ctx) {
     char *tempname = NULL;
     size_t tempname_size = 0;
 
-     if ((HANDLE)ctx->f != INVALID_HANDLE_VALUE && GetFileType((HANDLE)ctx->f) == FILE_TYPE_DISK) {
-         si = DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION;
-         success = GetSecurityInfo((HANDLE)ctx->f, SE_FILE_OBJECT, si, NULL, NULL, &dacl, NULL, &psd);
-         if (success == ERROR_SUCCESS) {
-             sa.nLength = sizeof(SECURITY_ATTRIBUTES);
-             sa.bInheritHandle = FALSE;
-             sa.lpSecurityDescriptor = psd;
-             psa = &sa;
-         }
-     }
-
- #ifndef MS_UWP
+    if ((HANDLE)ctx->f != INVALID_HANDLE_VALUE && GetFileType((HANDLE)ctx->f) == FILE_TYPE_DISK) {
+        si = DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION;
+        success = GetSecurityInfo((HANDLE)ctx->f, SE_FILE_OBJECT, si, NULL, NULL, &dacl, NULL, &psd);
+        if (success == ERROR_SUCCESS) {
+            sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+            sa.bInheritHandle = FALSE;
+            sa.lpSecurityDescriptor = psd;
+            psa = &sa;
+        }
+    }
+
+#ifndef MS_UWP
     value = GetTickCount();
 #else
     value = (zip_uint32_t)(GetTickCount64() & 0xffffffff);
 #endif
-    
+
     if ((tempname = file_ops->allocate_tempname(ctx->fname, 10, &tempname_size)) == NULL) {
         zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
         return -1;
     }
-        
+
     for (i = 0; i < 1024 && th == INVALID_HANDLE_VALUE; i++) {
         file_ops->make_tempname(tempname, tempname_size, ctx->fname, value + i);
-        
+
         th = win32_named_open(ctx, tempname, true, psa);
         if (th == INVALID_HANDLE_VALUE && GetLastError() != ERROR_FILE_EXISTS)
             break;
     }
-    
+
     if (th == INVALID_HANDLE_VALUE) {
         free(tempname);
         LocalFree(psd);
         zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, _zip_win32_error_to_errno(GetLastError()));
         return -1;
     }
-    
+
     LocalFree(psd);
     ctx->fout = th;
     ctx->tmpname = tempname;
-    
+
     return 0;
 }
 
@@ -156,11 +157,11 @@ _zip_win32_named_op_create_temp_output(zip_source_file_context_t *ctx) {
 static bool
 _zip_win32_named_op_open(zip_source_file_context_t *ctx) {
     HANDLE h = win32_named_open(ctx, ctx->fname, false, NULL);
-    
+
     if (h == INVALID_HANDLE_VALUE) {
         return false;
     }
-    
+
     ctx->f = h;
     return true;
 }
@@ -193,7 +194,7 @@ _zip_win32_named_op_rollback_write(zip_source_file_context_t *ctx) {
 static bool
 _zip_win32_named_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st) {
     zip_win32_file_operations_t *file_ops = (zip_win32_file_operations_t *)ctx->ops_userdata;
-    
+
     WIN32_FILE_ATTRIBUTE_DATA file_attributes;
 
     if (!file_ops->get_file_attributes_ex(ctx->fname, GetFileExInfoStandard, &file_attributes)) {
@@ -205,9 +206,16 @@ _zip_win32_named_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t
         zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(error));
         return false;
     }
-    
+
     st->exists = true;
-    st->regular_file = true; /* TODO: Is this always right? How to determine without a HANDLE? */
+    st->regular_file = false;
+
+    if (file_attributes.dwFileAttributes != INVALID_FILE_ATTRIBUTES) {
+        if ((file_attributes.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_REPARSE_POINT)) == 0) {
+            st->regular_file = true;
+        }
+    }
+
     if (!_zip_filetime_to_time_t(file_attributes.ftLastWriteTime, &st->mtime)) {
         zip_error_set(&ctx->error, ZIP_ER_READ, ERANGE);
         return false;
@@ -235,7 +243,7 @@ _zip_win32_named_op_write(zip_source_file_context_t *ctx, const void *data, zip_
         zip_error_set(&ctx->error, ZIP_ER_WRITE, _zip_win32_error_to_errno(GetLastError()));
         return -1;
     }
-    
+
     return (zip_int64_t)ret;
 }
 
@@ -248,7 +256,8 @@ win32_named_open(zip_source_file_context_t *ctx, const char *name, bool temporar
     DWORD share_mode = FILE_SHARE_READ | FILE_SHARE_WRITE;
     DWORD creation_disposition = OPEN_EXISTING;
     DWORD file_attributes = FILE_ATTRIBUTE_NORMAL;
-    
+    HANDLE h;
+
     if (temporary) {
         access = GENERIC_READ | GENERIC_WRITE;
         share_mode = FILE_SHARE_READ;
@@ -256,8 +265,8 @@ win32_named_open(zip_source_file_context_t *ctx, const char *name, bool temporar
         file_attributes = FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_TEMPORARY;
     }
 
-    HANDLE h = file_ops->create_file(name, access, share_mode, security_attributes, creation_disposition, file_attributes, NULL);
-    
+    h = file_ops->create_file(name, access, share_mode, security_attributes, creation_disposition, file_attributes, NULL);
+
     if (h == INVALID_HANDLE_VALUE) {
         zip_error_set(&ctx->error, ZIP_ER_OPEN, _zip_win32_error_to_errno(GetLastError()));
     }
index 3fa0aa1..6aef2bb 100644 (file)
@@ -38,6 +38,8 @@ static HANDLE __stdcall utf16_create_file(const char *name, DWORD access, DWORD
 static void utf16_make_tempname(char *buf, size_t len, const char *name, zip_uint32_t i);
 static char *utf16_strdup(const char *string);
 
+/* clang-format off */
+
 zip_win32_file_operations_t ops_utf16 = {
     utf16_allocate_tempname,
     utf16_create_file,
@@ -50,10 +52,12 @@ zip_win32_file_operations_t ops_utf16 = {
     utf16_strdup
 };
 
+/* clang-format on */
+
 ZIP_EXTERN zip_source_t *
 zip_source_win32w(zip_t *za, const wchar_t *fname, zip_uint64_t start, zip_int64_t len) {
     if (za == NULL)
-    return NULL;
+        return NULL;
 
     return zip_source_win32w_create(fname, start, len, &za->error);
 }
@@ -62,8 +66,8 @@ zip_source_win32w(zip_t *za, const wchar_t *fname, zip_uint64_t start, zip_int64
 ZIP_EXTERN zip_source_t *
 zip_source_win32w_create(const wchar_t *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error) {
     if (fname == NULL || length < -1) {
-    zip_error_set(error, ZIP_ER_INVAL, 0);
-    return NULL;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
 
 
@@ -78,8 +82,7 @@ utf16_allocate_tempname(const char *name, size_t extra_chars, size_t *lengthp) {
 }
 
 
-static HANDLE __stdcall
-utf16_create_file(const char *name, DWORD access, DWORD share_mode, PSECURITY_ATTRIBUTES security_attributes, DWORD creation_disposition, DWORD file_attributes, HANDLE template_file) {
+static HANDLE __stdcall utf16_create_file(const char *name, DWORD access, DWORD share_mode, PSECURITY_ATTRIBUTES security_attributes, DWORD creation_disposition, DWORD file_attributes, HANDLE template_file) {
 #ifdef MS_UWP
     CREATEFILE2_EXTENDED_PARAMETERS extParams = {0};
     extParams.dwFileAttributes = file_attributes;
@@ -88,7 +91,7 @@ utf16_create_file(const char *name, DWORD access, DWORD share_mode, PSECURITY_AT
     extParams.dwSize = sizeof(extParams);
     extParams.hTemplateFile = template_file;
     extParams.lpSecurityAttributes = security_attributes;
-    
+
     return CreateFile2((const wchar_t *)name, access, share_mode, creation_disposition, &extParams);
 #else
     return CreateFileW((const wchar_t *)name, access, share_mode, security_attributes, creation_disposition, file_attributes, template_file);
index 4f258bc..d6728e3 100644 (file)
@@ -38,7 +38,7 @@ zip_source_file(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t le
     if (za == NULL) {
         return NULL;
     }
-    
+
     return zip_source_file_create(fname, start, len, &za->error);
 }
 
@@ -67,7 +67,7 @@ zip_source_file_create(const char *fname, zip_uint64_t start, zip_int64_t length
     MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, fname, -1, wfname, size);
 
     source = zip_source_win32w_create(wfname, start, length, error);
-    
+
     free(wfname);
     return source;
 }
index 2f10ef8..2e6944e 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_free.c -- free zip data source
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 ZIP_EXTERN void
 zip_source_free(zip_source_t *src) {
     if (src == NULL)
-       return;
+        return;
 
     if (src->refcount > 0) {
-       src->refcount--;
+        src->refcount--;
     }
     if (src->refcount > 0) {
-       return;
+        return;
     }
 
     if (ZIP_SOURCE_IS_OPEN_READING(src)) {
-       src->open_count = 1; /* force close */
-       zip_source_close(src);
+        src->open_count = 1; /* force close */
+        zip_source_close(src);
     }
     if (ZIP_SOURCE_IS_OPEN_WRITING(src)) {
-       zip_source_rollback_write(src);
+        zip_source_rollback_write(src);
     }
 
     if (src->source_archive && !src->source_closed) {
-       _zip_deregister_source(src->source_archive, src);
+        _zip_deregister_source(src->source_archive, src);
     }
 
     (void)_zip_source_call(src, NULL, 0, ZIP_SOURCE_FREE);
 
     if (src->src) {
-       zip_source_free(src->src);
+        zip_source_free(src->src);
     }
 
     free(src);
index d5c1b5b..44db947 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_function.c -- create zip data source from callback function
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -40,7 +40,7 @@
 ZIP_EXTERN zip_source_t *
 zip_source_function(zip_t *za, zip_source_callback zcb, void *ud) {
     if (za == NULL) {
-       return NULL;
+        return NULL;
     }
 
     return zip_source_function_create(zcb, ud, &za->error);
@@ -52,14 +52,14 @@ zip_source_function_create(zip_source_callback zcb, void *ud, zip_error_t *error
     zip_source_t *zs;
 
     if ((zs = _zip_source_new(error)) == NULL)
-       return NULL;
+        return NULL;
 
     zs->cb.f = zcb;
     zs->ud = ud;
 
     zs->supports = zcb(ud, NULL, 0, ZIP_SOURCE_SUPPORTS);
     if (zs->supports < 0) {
-       zs->supports = ZIP_SOURCE_SUPPORTS_READABLE;
+        zs->supports = ZIP_SOURCE_SUPPORTS_READABLE;
     }
 
     return zs;
@@ -77,8 +77,8 @@ _zip_source_new(zip_error_t *error) {
     zip_source_t *src;
 
     if ((src = (zip_source_t *)malloc(sizeof(*src))) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     src->src = NULL;
@@ -92,6 +92,7 @@ _zip_source_new(zip_error_t *error) {
     zip_error_init(&src->error);
     src->eof = false;
     src->had_read_error = false;
+    src->bytes_read = 0;
 
     return src;
 }
index acbede1..734767a 100644 (file)
@@ -42,62 +42,64 @@ zip_file_attributes_init(zip_file_attributes_t *attributes) {
 int
 zip_source_get_file_attributes(zip_source_t *src, zip_file_attributes_t *attributes) {
     if (src->source_closed) {
-       return -1;
+        return -1;
     }
     if (attributes == NULL) {
-       zip_error_set(&src->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&src->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     zip_file_attributes_init(attributes);
 
     if (src->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_GET_FILE_ATTRIBUTES)) {
-       if (_zip_source_call(src, attributes, sizeof(*attributes), ZIP_SOURCE_GET_FILE_ATTRIBUTES) < 0) {
-           return -1;
-       }
+        if (_zip_source_call(src, attributes, sizeof(*attributes), ZIP_SOURCE_GET_FILE_ATTRIBUTES) < 0) {
+            return -1;
+        }
     }
 
     if (ZIP_SOURCE_IS_LAYERED(src)) {
-       zip_file_attributes_t lower_attributes;
+        zip_file_attributes_t lower_attributes;
 
-       if (zip_source_get_file_attributes(src->src, &lower_attributes) < 0) {
-           _zip_error_set_from_source(&src->error, src->src);
-           return -1;
-       }
+        if (zip_source_get_file_attributes(src->src, &lower_attributes) < 0) {
+            _zip_error_set_from_source(&src->error, src->src);
+            return -1;
+        }
 
-       if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM) && (attributes->valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM) == 0) {
-           attributes->host_system = lower_attributes.host_system;
-           attributes->valid |= ZIP_FILE_ATTRIBUTES_HOST_SYSTEM;
-       }
-       if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_ASCII) && (attributes->valid & ZIP_FILE_ATTRIBUTES_ASCII) == 0) {
-           attributes->ascii = lower_attributes.ascii;
-           attributes->valid |= ZIP_FILE_ATTRIBUTES_ASCII;
-       }
-       if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED)) {
-           if (attributes->valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED) {
-               attributes->version_needed = ZIP_MAX(lower_attributes.version_needed, attributes->version_needed);
-           }
-           else {
-               attributes->version_needed = lower_attributes.version_needed;
-               attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED;
-           }
-       }
-       if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES) && (attributes->valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES) == 0) {
-           attributes->external_file_attributes = lower_attributes.external_file_attributes;
-           attributes->valid |= ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES;
-       }
-       if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS)) {
-           if (attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) {
-               attributes->general_purpose_bit_flags &= ~lower_attributes.general_purpose_bit_mask;
-               attributes->general_purpose_bit_flags |= lower_attributes.general_purpose_bit_flags & lower_attributes.general_purpose_bit_mask;
-               attributes->general_purpose_bit_mask |= lower_attributes.general_purpose_bit_mask;
-           }
-           else {
-               attributes->valid |= ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS;
-               attributes->general_purpose_bit_flags = lower_attributes.general_purpose_bit_flags;
-               attributes->general_purpose_bit_mask = lower_attributes.general_purpose_bit_mask;
-           }
-       }
+        if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM) && (attributes->valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM) == 0) {
+            attributes->host_system = lower_attributes.host_system;
+            attributes->valid |= ZIP_FILE_ATTRIBUTES_HOST_SYSTEM;
+        }
+        if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_ASCII) && (attributes->valid & ZIP_FILE_ATTRIBUTES_ASCII) == 0) {
+            attributes->ascii = lower_attributes.ascii;
+            attributes->valid |= ZIP_FILE_ATTRIBUTES_ASCII;
+        }
+        if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED)) {
+            if (attributes->valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED) {
+                attributes->version_needed = ZIP_MAX(lower_attributes.version_needed, attributes->version_needed);
+            }
+            else {
+                attributes->version_needed = lower_attributes.version_needed;
+                attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED;
+            }
+        }
+        if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES) && (attributes->valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES) == 0) {
+            attributes->external_file_attributes = lower_attributes.external_file_attributes;
+            attributes->valid |= ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES;
+        }
+        if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS)) {
+            if (attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) {
+               /* only take from lower level what is not defined at current level */
+               lower_attributes.general_purpose_bit_mask &= ~attributes->general_purpose_bit_mask;
+
+                attributes->general_purpose_bit_flags |= lower_attributes.general_purpose_bit_flags & lower_attributes.general_purpose_bit_mask;
+                attributes->general_purpose_bit_mask |= lower_attributes.general_purpose_bit_mask;
+            }
+            else {
+                attributes->valid |= ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS;
+                attributes->general_purpose_bit_flags = lower_attributes.general_purpose_bit_flags;
+                attributes->general_purpose_bit_mask = lower_attributes.general_purpose_bit_mask;
+            }
+        }
     }
 
     return 0;
index edd10ca..c2c7eb5 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_is_deleted.c -- was archive was removed?
-  Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
index d02bc85..f6db2a7 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_layered.c -- create layered source
-  Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -40,7 +40,7 @@
 zip_source_t *
 zip_source_layered(zip_t *za, zip_source_t *src, zip_source_layered_callback cb, void *ud) {
     if (za == NULL)
-       return NULL;
+        return NULL;
 
     return zip_source_layered_create(src, cb, ud, &za->error);
 }
@@ -51,7 +51,7 @@ zip_source_layered_create(zip_source_t *src, zip_source_layered_callback cb, voi
     zip_source_t *zs;
 
     if ((zs = _zip_source_new(error)) == NULL)
-       return NULL;
+        return NULL;
 
     zip_source_keep(src);
     zs->src = src;
@@ -60,7 +60,7 @@ zip_source_layered_create(zip_source_t *src, zip_source_layered_callback cb, voi
 
     zs->supports = cb(src, ud, NULL, 0, ZIP_SOURCE_SUPPORTS);
     if (zs->supports < 0) {
-       zs->supports = ZIP_SOURCE_SUPPORTS_READABLE;
+        zs->supports = ZIP_SOURCE_SUPPORTS_READABLE;
     }
 
     return zs;
index 414c677..b12a4c2 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_open.c -- open zip_source (prepare for reading)
-  Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 ZIP_EXTERN int
 zip_source_open(zip_source_t *src) {
     if (src->source_closed) {
-       return -1;
+        return -1;
     }
     if (src->write_state == ZIP_SOURCE_WRITE_REMOVED) {
-       zip_error_set(&src->error, ZIP_ER_DELETED, 0);
-       return -1;
+        zip_error_set(&src->error, ZIP_ER_DELETED, 0);
+        return -1;
     }
 
     if (ZIP_SOURCE_IS_OPEN_READING(src)) {
-       if ((zip_source_supports(src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK)) == 0) {
-           zip_error_set(&src->error, ZIP_ER_INUSE, 0);
-           return -1;
-       }
+        if ((zip_source_supports(src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK)) == 0) {
+            zip_error_set(&src->error, ZIP_ER_INUSE, 0);
+            return -1;
+        }
     }
     else {
-       if (ZIP_SOURCE_IS_LAYERED(src)) {
-           if (zip_source_open(src->src) < 0) {
-               _zip_error_set_from_source(&src->error, src->src);
-               return -1;
-           }
-       }
+        if (ZIP_SOURCE_IS_LAYERED(src)) {
+            if (zip_source_open(src->src) < 0) {
+                _zip_error_set_from_source(&src->error, src->src);
+                return -1;
+            }
+        }
 
-       if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_OPEN) < 0) {
-           if (ZIP_SOURCE_IS_LAYERED(src)) {
-               zip_source_close(src->src);
-           }
-           return -1;
-       }
+        if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_OPEN) < 0) {
+            if (ZIP_SOURCE_IS_LAYERED(src)) {
+                zip_source_close(src->src);
+            }
+            return -1;
+        }
     }
 
     src->eof = false;
     src->had_read_error = false;
     _zip_error_clear(&src->error);
+    src->bytes_read = 0;
     src->open_count++;
 
     return 0;
index d5489a5..a1c9e3a 100644 (file)
@@ -56,21 +56,21 @@ zip_source_pkware_decode(zip_t *za, zip_source_t *src, zip_uint16_t em, int flag
     zip_source_t *s2;
 
     if (password == NULL || src == NULL || em != ZIP_EM_TRAD_PKWARE) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return NULL;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
     if (flags & ZIP_CODEC_ENCODE) {
-       zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
-       return NULL;
+        zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
+        return NULL;
     }
 
     if ((ctx = trad_pkware_new(password, &za->error)) == NULL) {
-       return NULL;
+        return NULL;
     }
 
     if ((s2 = zip_source_layered(za, src, pkware_decrypt, ctx)) == NULL) {
-       trad_pkware_free(ctx);
-       return NULL;
+        trad_pkware_free(ctx);
+        return NULL;
     }
 
     return s2;
@@ -82,22 +82,23 @@ decrypt_header(zip_source_t *src, struct trad_pkware *ctx) {
     zip_uint8_t header[ZIP_CRYPTO_PKWARE_HEADERLEN];
     struct zip_stat st;
     zip_int64_t n;
+    bool ok = false;
 
     if ((n = zip_source_read(src, header, ZIP_CRYPTO_PKWARE_HEADERLEN)) < 0) {
-       _zip_error_set_from_source(&ctx->error, src);
-       return -1;
+        _zip_error_set_from_source(&ctx->error, src);
+        return -1;
     }
 
     if (n != ZIP_CRYPTO_PKWARE_HEADERLEN) {
-       zip_error_set(&ctx->error, ZIP_ER_EOF, 0);
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_EOF, 0);
+        return -1;
     }
 
     _zip_pkware_decrypt(&ctx->keys, header, header, ZIP_CRYPTO_PKWARE_HEADERLEN);
 
     if (zip_source_stat(src, &st)) {
-       /* stat failed, skip password validation */
-       return 0;
+        /* stat failed, skip password validation */
+        return 0;
     }
 
     /* password verification - two ways:
@@ -105,25 +106,23 @@ decrypt_header(zip_source_t *src, struct trad_pkware *ctx) {
      *  CRC - old PKWare way
      */
 
-    bool ok = false;
-
     if (st.valid & ZIP_STAT_MTIME) {
-       unsigned short dostime, dosdate;
-       _zip_u2d_time(st.mtime, &dostime, &dosdate);
-       if (header[ZIP_CRYPTO_PKWARE_HEADERLEN - 1] == dostime >> 8) {
-           ok = true;
-       }
+        unsigned short dostime, dosdate;
+        _zip_u2d_time(st.mtime, &dostime, &dosdate);
+        if (header[ZIP_CRYPTO_PKWARE_HEADERLEN - 1] == dostime >> 8) {
+            ok = true;
+        }
     }
 
     if (st.valid & ZIP_STAT_CRC) {
-       if (header[ZIP_CRYPTO_PKWARE_HEADERLEN - 1] == st.crc >> 24) {
-           ok = true;
-       }
+        if (header[ZIP_CRYPTO_PKWARE_HEADERLEN - 1] == st.crc >> 24) {
+            ok = true;
+        }
     }
 
     if (!ok && ((st.valid & (ZIP_STAT_MTIME | ZIP_STAT_CRC)) != 0)) {
-       zip_error_set(&ctx->error, ZIP_ER_WRONGPASSWD, 0);
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_WRONGPASSWD, 0);
+        return -1;
     }
 
     return 0;
@@ -139,52 +138,52 @@ pkware_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_so
 
     switch (cmd) {
     case ZIP_SOURCE_OPEN:
-       _zip_pkware_keys_reset(&ctx->keys);
-       _zip_pkware_decrypt(&ctx->keys, NULL, (const zip_uint8_t *)ctx->password, strlen(ctx->password));
-       if (decrypt_header(src, ctx) < 0) {
-           return -1;
-       }
-       return 0;
+        _zip_pkware_keys_reset(&ctx->keys);
+        _zip_pkware_decrypt(&ctx->keys, NULL, (const zip_uint8_t *)ctx->password, strlen(ctx->password));
+        if (decrypt_header(src, ctx) < 0) {
+            return -1;
+        }
+        return 0;
 
     case ZIP_SOURCE_READ:
-       if ((n = zip_source_read(src, data, len)) < 0) {
-           _zip_error_set_from_source(&ctx->error, src);
-           return -1;
-       }
+        if ((n = zip_source_read(src, data, len)) < 0) {
+            _zip_error_set_from_source(&ctx->error, src);
+            return -1;
+        }
 
-       _zip_pkware_decrypt(&ctx->keys, (zip_uint8_t *)data, (zip_uint8_t *)data, (zip_uint64_t)n);
-       return n;
+        _zip_pkware_decrypt(&ctx->keys, (zip_uint8_t *)data, (zip_uint8_t *)data, (zip_uint64_t)n);
+        return n;
 
     case ZIP_SOURCE_CLOSE:
-       return 0;
+        return 0;
 
     case ZIP_SOURCE_STAT: {
-       zip_stat_t *st;
+        zip_stat_t *st;
 
-       st = (zip_stat_t *)data;
+        st = (zip_stat_t *)data;
 
-       st->encryption_method = ZIP_EM_NONE;
-       st->valid |= ZIP_STAT_ENCRYPTION_METHOD;
-       if (st->valid & ZIP_STAT_COMP_SIZE) {
-           st->comp_size -= ZIP_CRYPTO_PKWARE_HEADERLEN;
-       }
+        st->encryption_method = ZIP_EM_NONE;
+        st->valid |= ZIP_STAT_ENCRYPTION_METHOD;
+        if (st->valid & ZIP_STAT_COMP_SIZE) {
+            st->comp_size -= ZIP_CRYPTO_PKWARE_HEADERLEN;
+        }
 
-       return 0;
+        return 0;
     }
 
     case ZIP_SOURCE_SUPPORTS:
-       return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1);
+        return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1);
 
     case ZIP_SOURCE_ERROR:
-       return zip_error_to_data(&ctx->error, data, len);
+        return zip_error_to_data(&ctx->error, data, len);
 
     case ZIP_SOURCE_FREE:
-       trad_pkware_free(ctx);
-       return 0;
+        trad_pkware_free(ctx);
+        return 0;
 
     default:
-       zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 }
 
@@ -194,14 +193,14 @@ trad_pkware_new(const char *password, zip_error_t *error) {
     struct trad_pkware *ctx;
 
     if ((ctx = (struct trad_pkware *)malloc(sizeof(*ctx))) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     if ((ctx->password = strdup(password)) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       free(ctx);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        free(ctx);
+        return NULL;
     }
 
     zip_error_init(&ctx->error);
@@ -213,7 +212,7 @@ trad_pkware_new(const char *password, zip_error_t *error) {
 static void
 trad_pkware_free(struct trad_pkware *ctx) {
     if (ctx == NULL) {
-       return;
+        return;
     }
 
     free(ctx->password);
index 1e8f42c..7c77e1e 100644 (file)
@@ -58,21 +58,21 @@ zip_source_pkware_encode(zip_t *za, zip_source_t *src, zip_uint16_t em, int flag
     zip_source_t *s2;
 
     if (password == NULL || src == NULL || em != ZIP_EM_TRAD_PKWARE) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return NULL;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
     if (!(flags & ZIP_CODEC_ENCODE)) {
-       zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
-       return NULL;
+        zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
+        return NULL;
     }
 
     if ((ctx = trad_pkware_new(password, &za->error)) == NULL) {
-       return NULL;
+        return NULL;
     }
 
     if ((s2 = zip_source_layered(za, src, pkware_encrypt, ctx)) == NULL) {
-       trad_pkware_free(ctx);
-       return NULL;
+        trad_pkware_free(ctx);
+        return NULL;
     }
 
     return s2;
@@ -86,15 +86,15 @@ encrypt_header(zip_source_t *src, struct trad_pkware *ctx) {
     zip_uint8_t *header;
 
     if (zip_source_stat(src, &st) != 0) {
-       _zip_error_set_from_source(&ctx->error, src);
-       return -1;
+        _zip_error_set_from_source(&ctx->error, src);
+        return -1;
     }
 
     _zip_u2d_time(st.mtime, &dostime, &dosdate);
 
     if ((ctx->buffer = _zip_buffer_new(NULL, ZIP_CRYPTO_PKWARE_HEADERLEN)) == NULL) {
-       zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
+        return -1;
     }
 
     header = _zip_buffer_data(ctx->buffer);
@@ -102,10 +102,10 @@ encrypt_header(zip_source_t *src, struct trad_pkware *ctx) {
     /* generate header from random bytes and mtime
        see appnote.iz, XIII. Decryption, Step 2, last paragraph */
     if (!zip_secure_random(header, ZIP_CRYPTO_PKWARE_HEADERLEN - 1)) {
-       zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
-       _zip_buffer_free(ctx->buffer);
-       ctx->buffer = NULL;
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
+        _zip_buffer_free(ctx->buffer);
+        ctx->buffer = NULL;
+        return -1;
     }
     header[ZIP_CRYPTO_PKWARE_HEADERLEN - 1] = (zip_uint8_t)((dostime >> 8) & 0xff);
 
@@ -125,92 +125,92 @@ pkware_encrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t length, zip
 
     switch (cmd) {
     case ZIP_SOURCE_OPEN:
-       ctx->eof = false;
+        ctx->eof = false;
 
-       /* initialize keys */
-       _zip_pkware_keys_reset(&ctx->keys);
-       _zip_pkware_encrypt(&ctx->keys, NULL, (const zip_uint8_t *)ctx->password, strlen(ctx->password));
+        /* initialize keys */
+        _zip_pkware_keys_reset(&ctx->keys);
+        _zip_pkware_encrypt(&ctx->keys, NULL, (const zip_uint8_t *)ctx->password, strlen(ctx->password));
 
-       if (encrypt_header(src, ctx) < 0) {
-           return -1;
-       }
-       return 0;
+        if (encrypt_header(src, ctx) < 0) {
+            return -1;
+        }
+        return 0;
 
     case ZIP_SOURCE_READ:
-       buffer_n = 0;
+        buffer_n = 0;
 
-       if (ctx->buffer) {
-           /* write header values to data */
-           buffer_n = _zip_buffer_read(ctx->buffer, data, length);
-           data = (zip_uint8_t *)data + buffer_n;
-           length -= buffer_n;
+        if (ctx->buffer) {
+            /* write header values to data */
+            buffer_n = _zip_buffer_read(ctx->buffer, data, length);
+            data = (zip_uint8_t *)data + buffer_n;
+            length -= buffer_n;
 
-           if (_zip_buffer_eof(ctx->buffer)) {
-               _zip_buffer_free(ctx->buffer);
-               ctx->buffer = NULL;
-           }
-       }
+            if (_zip_buffer_eof(ctx->buffer)) {
+                _zip_buffer_free(ctx->buffer);
+                ctx->buffer = NULL;
+            }
+        }
 
-       if (ctx->eof) {
-           return (zip_int64_t)buffer_n;
-       }
+        if (ctx->eof) {
+            return (zip_int64_t)buffer_n;
+        }
 
-       if ((n = zip_source_read(src, data, length)) < 0) {
-           _zip_error_set_from_source(&ctx->error, src);
-           return -1;
-       }
+        if ((n = zip_source_read(src, data, length)) < 0) {
+            _zip_error_set_from_source(&ctx->error, src);
+            return -1;
+        }
 
-       _zip_pkware_encrypt(&ctx->keys, (zip_uint8_t *)data, (zip_uint8_t *)data, (zip_uint64_t)n);
+        _zip_pkware_encrypt(&ctx->keys, (zip_uint8_t *)data, (zip_uint8_t *)data, (zip_uint64_t)n);
 
-       if ((zip_uint64_t)n < length) {
-           ctx->eof = true;
-       }
+        if ((zip_uint64_t)n < length) {
+            ctx->eof = true;
+        }
 
-       return (zip_int64_t)buffer_n + n;
+        return (zip_int64_t)buffer_n + n;
 
     case ZIP_SOURCE_CLOSE:
-       _zip_buffer_free(ctx->buffer);
-       ctx->buffer = NULL;
-       return 0;
+        _zip_buffer_free(ctx->buffer);
+        ctx->buffer = NULL;
+        return 0;
 
     case ZIP_SOURCE_STAT: {
-       zip_stat_t *st;
+        zip_stat_t *st;
 
-       st = (zip_stat_t *)data;
-       st->encryption_method = ZIP_EM_TRAD_PKWARE;
-       st->valid |= ZIP_STAT_ENCRYPTION_METHOD;
-       if (st->valid & ZIP_STAT_COMP_SIZE) {
-           st->comp_size += ZIP_CRYPTO_PKWARE_HEADERLEN;
-       }
+        st = (zip_stat_t *)data;
+        st->encryption_method = ZIP_EM_TRAD_PKWARE;
+        st->valid |= ZIP_STAT_ENCRYPTION_METHOD;
+        if (st->valid & ZIP_STAT_COMP_SIZE) {
+            st->comp_size += ZIP_CRYPTO_PKWARE_HEADERLEN;
+        }
 
-       return 0;
+        return 0;
     }
 
     case ZIP_SOURCE_GET_FILE_ATTRIBUTES: {
-       zip_file_attributes_t *attributes = (zip_file_attributes_t *)data;
-       if (length < sizeof(*attributes)) {
-           zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
-           return -1;
-       }
-       attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED;
-       attributes->version_needed = 20;
-
-       return 0;
+        zip_file_attributes_t *attributes = (zip_file_attributes_t *)data;
+        if (length < sizeof(*attributes)) {
+            zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
+            return -1;
+        }
+        attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED;
+        attributes->version_needed = 20;
+
+        return 0;
     }
 
     case ZIP_SOURCE_SUPPORTS:
-       return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1);
+        return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1);
 
     case ZIP_SOURCE_ERROR:
-       return zip_error_to_data(&ctx->error, data, length);
+        return zip_error_to_data(&ctx->error, data, length);
 
     case ZIP_SOURCE_FREE:
-       trad_pkware_free(ctx);
-       return 0;
+        trad_pkware_free(ctx);
+        return 0;
 
     default:
-       zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 }
 
@@ -220,14 +220,14 @@ trad_pkware_new(const char *password, zip_error_t *error) {
     struct trad_pkware *ctx;
 
     if ((ctx = (struct trad_pkware *)malloc(sizeof(*ctx))) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     if ((ctx->password = strdup(password)) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       free(ctx);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        free(ctx);
+        return NULL;
     }
     ctx->buffer = NULL;
     zip_error_init(&ctx->error);
@@ -239,7 +239,7 @@ trad_pkware_new(const char *password, zip_error_t *error) {
 static void
 trad_pkware_free(struct trad_pkware *ctx) {
     if (ctx == NULL) {
-       return;
+        return;
     }
 
     free(ctx->password);
index 33088cb..ee7686a 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_read.c -- read data from zip_source
-  Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -41,45 +41,51 @@ zip_source_read(zip_source_t *src, void *data, zip_uint64_t len) {
     zip_int64_t n;
 
     if (src->source_closed) {
-       return -1;
+        return -1;
     }
     if (!ZIP_SOURCE_IS_OPEN_READING(src) || len > ZIP_INT64_MAX || (len > 0 && data == NULL)) {
-       zip_error_set(&src->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&src->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     if (src->had_read_error) {
-       return -1;
+        return -1;
     }
 
     if (_zip_source_eof(src)) {
-       return 0;
+        return 0;
     }
 
     if (len == 0) {
-       return 0;
+        return 0;
     }
 
     bytes_read = 0;
     while (bytes_read < len) {
-       if ((n = _zip_source_call(src, (zip_uint8_t *)data + bytes_read, len - bytes_read, ZIP_SOURCE_READ)) < 0) {
-           src->had_read_error = true;
-           if (bytes_read == 0) {
-               return -1;
-           }
-           else {
-               return (zip_int64_t)bytes_read;
-           }
-       }
-
-       if (n == 0) {
-           src->eof = 1;
-           break;
-       }
-
-       bytes_read += (zip_uint64_t)n;
+        if ((n = _zip_source_call(src, (zip_uint8_t *)data + bytes_read, len - bytes_read, ZIP_SOURCE_READ)) < 0) {
+            src->had_read_error = true;
+            if (bytes_read == 0) {
+                return -1;
+            }
+            else {
+                return (zip_int64_t)bytes_read;
+            }
+        }
+
+        if (n == 0) {
+            src->eof = 1;
+            break;
+        }
+
+        bytes_read += (zip_uint64_t)n;
     }
 
+    if (src->bytes_read + bytes_read < src->bytes_read) {
+        src->bytes_read = ZIP_UINT64_MAX;
+    }
+    else {
+        src->bytes_read += bytes_read;
+    }
     return (zip_int64_t)bytes_read;
 }
 
index 14eddb8..46230cd 100644 (file)
@@ -1,6 +1,6 @@
 /*
  zip_source_remove.c -- remove empty archive
- Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
+ Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
 
  This file is part of libzip, a library to manipulate ZIP archives.
  The authors can be contacted at <libzip@nih.at>
 int
 zip_source_remove(zip_source_t *src) {
     if (src->write_state == ZIP_SOURCE_WRITE_REMOVED) {
-       return 0;
+        return 0;
     }
 
     if (ZIP_SOURCE_IS_OPEN_READING(src)) {
-       if (zip_source_close(src) < 0) {
-           return -1;
-       }
+        if (zip_source_close(src) < 0) {
+            return -1;
+        }
     }
     if (src->write_state != ZIP_SOURCE_WRITE_CLOSED) {
-       zip_source_rollback_write(src);
+        zip_source_rollback_write(src);
     }
 
     if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_REMOVE) < 0) {
-       return -1;
+        return -1;
     }
 
     src->write_state = ZIP_SOURCE_WRITE_REMOVED;
index e8259bf..6f98c39 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_rollback_write.c -- discard changes
-  Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -38,7 +38,7 @@
 ZIP_EXTERN void
 zip_source_rollback_write(zip_source_t *src) {
     if (src->write_state != ZIP_SOURCE_WRITE_OPEN && src->write_state != ZIP_SOURCE_WRITE_FAILED) {
-       return;
+        return;
     }
 
     _zip_source_call(src, NULL, 0, ZIP_SOURCE_ROLLBACK_WRITE);
index 163daf1..1acd6d8 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_seek.c -- seek to offset
-  Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -40,18 +40,18 @@ zip_source_seek(zip_source_t *src, zip_int64_t offset, int whence) {
     zip_source_args_seek_t args;
 
     if (src->source_closed) {
-       return -1;
+        return -1;
     }
     if (!ZIP_SOURCE_IS_OPEN_READING(src) || (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END)) {
-       zip_error_set(&src->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&src->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     args.offset = offset;
     args.whence = whence;
 
     if (_zip_source_call(src, &args, sizeof(args), ZIP_SOURCE_SEEK) < 0) {
-       return -1;
+        return -1;
     }
 
     src->eof = 0;
@@ -65,30 +65,30 @@ zip_source_seek_compute_offset(zip_uint64_t offset, zip_uint64_t length, void *d
     zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, data_length, error);
 
     if (args == NULL) {
-       return -1;
+        return -1;
     }
 
     switch (args->whence) {
     case SEEK_CUR:
-       new_offset = (zip_int64_t)offset + args->offset;
-       break;
+        new_offset = (zip_int64_t)offset + args->offset;
+        break;
 
     case SEEK_END:
-       new_offset = (zip_int64_t)length + args->offset;
-       break;
+        new_offset = (zip_int64_t)length + args->offset;
+        break;
 
     case SEEK_SET:
-       new_offset = args->offset;
-       break;
+        new_offset = args->offset;
+        break;
 
     default:
-       zip_error_set(error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     if (new_offset < 0 || (zip_uint64_t)new_offset > length) {
-       zip_error_set(error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     return new_offset;
index 6b0aa78..5599bcb 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_seek_write.c -- seek to offset for writing
-  Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -40,8 +40,8 @@ zip_source_seek_write(zip_source_t *src, zip_int64_t offset, int whence) {
     zip_source_args_seek_t args;
 
     if (!ZIP_SOURCE_IS_OPEN_WRITING(src) || (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END)) {
-       zip_error_set(&src->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&src->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     args.offset = offset;
index 3421d2c..a9745e0 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_stat.c -- get meta information from zip_source
-  Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 ZIP_EXTERN int
 zip_source_stat(zip_source_t *src, zip_stat_t *st) {
     if (src->source_closed) {
-       return -1;
+        return -1;
     }
     if (st == NULL) {
-       zip_error_set(&src->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&src->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     zip_stat_init(st);
 
     if (ZIP_SOURCE_IS_LAYERED(src)) {
-       if (zip_source_stat(src->src, st) < 0) {
-           _zip_error_set_from_source(&src->error, src->src);
-           return -1;
-       }
+        if (zip_source_stat(src->src, st) < 0) {
+            _zip_error_set_from_source(&src->error, src->src);
+            return -1;
+        }
     }
 
     if (_zip_source_call(src, st, sizeof(*st), ZIP_SOURCE_STAT) < 0) {
-       return -1;
+        return -1;
     }
 
     return 0;
index 8471559..66a5303 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_supports.c -- check for supported functions
-  Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -53,11 +53,11 @@ zip_source_make_command_bitmap(zip_source_cmd_t cmd0, ...) {
 
     va_start(ap, cmd0);
     for (;;) {
-       int cmd = va_arg(ap, int);
-       if (cmd < 0) {
-           break;
-       }
-       bitmap |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd);
+        int cmd = va_arg(ap, int);
+        if (cmd < 0) {
+            break;
+        }
+        bitmap |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd);
     }
     va_end(ap);
 
index 772e252..8518739 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_tell.c -- report current offset
-  Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 ZIP_EXTERN zip_int64_t
 zip_source_tell(zip_source_t *src) {
     if (src->source_closed) {
-       return -1;
+        return -1;
     }
     if (!ZIP_SOURCE_IS_OPEN_READING(src)) {
-       zip_error_set(&src->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&src->error, ZIP_ER_INVAL, 0);
+        return -1;
+    }
+
+    if ((src->supports & (ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_TELL) | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK))) == 0) {
+        if (src->bytes_read > ZIP_INT64_MAX) {
+            zip_error_set(&src->error, ZIP_ER_TELL, EOVERFLOW);
+            return -1;
+        }
+        return (zip_int64_t)src->bytes_read;
     }
 
     return _zip_source_call(src, NULL, 0, ZIP_SOURCE_TELL);
index 96ad7e2..8edee67 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_tell_write.c -- report current offset for writing
-  Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -38,8 +38,8 @@
 ZIP_EXTERN zip_int64_t
 zip_source_tell_write(zip_source_t *src) {
     if (!ZIP_SOURCE_IS_OPEN_WRITING(src)) {
-       zip_error_set(&src->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&src->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     return _zip_source_call(src, NULL, 0, ZIP_SOURCE_TELL_WRITE);
index d996015..6f457b6 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_window.c -- return part of lower source
-  Copyright (C) 2012-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -40,6 +40,7 @@
 struct window {
     zip_uint64_t start; /* where in file we start reading */
     zip_uint64_t end;   /* where in file we stop reading */
+    bool end_valid;     /* whether end is set, otherwise read until EOF */
 
     /* if not NULL, read file data for this file */
     zip_t *source_archive;
@@ -57,34 +58,47 @@ struct window {
 static zip_int64_t window_read(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t);
 
 
-zip_source_t *
-zip_source_window(zip_t *za, zip_source_t *src, zip_uint64_t start, zip_uint64_t len) {
-    return _zip_source_window_new(src, start, len, NULL, 0, NULL, 0, &za->error);
+ZIP_EXTERN zip_source_t *
+zip_source_window_create(zip_source_t *src, zip_uint64_t start, zip_int64_t len, zip_error_t *error) {
+    return _zip_source_window_new(src, start, len, NULL, 0, NULL, 0, error);
 }
 
 
 zip_source_t *
-_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_file_attributes_t *attributes, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error) {
+_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_int64_t length, zip_stat_t *st, zip_file_attributes_t *attributes, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error) {
     struct window *ctx;
 
-    if (src == NULL || start + length < start || (source_archive == NULL && source_index != 0)) {
-       zip_error_set(error, ZIP_ER_INVAL, 0);
-       return NULL;
+    if (src == NULL || length < -1 || (source_archive == NULL && source_index != 0)) {
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return NULL;
+    }
+    
+    if (length >= 0) {
+        if (start + (zip_uint64_t)length < start) {
+            zip_error_set(error, ZIP_ER_INVAL, 0);
+            return NULL;
+        }
     }
 
     if ((ctx = (struct window *)malloc(sizeof(*ctx))) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     ctx->start = start;
-    ctx->end = start + length;
+    if (length == -1) {
+        ctx->end_valid = false;
+    }
+    else {
+        ctx->end = start + (zip_uint64_t)length;
+        ctx->end_valid = true;
+    }
     zip_stat_init(&ctx->stat);
     if (attributes != NULL) {
-       memcpy(&ctx->attributes, attributes, sizeof(ctx->attributes));
+        memcpy(&ctx->attributes, attributes, sizeof(ctx->attributes));
     }
     else {
-       zip_file_attributes_init(&ctx->attributes);
+        zip_file_attributes_init(&ctx->attributes);
     }
     ctx->source_archive = source_archive;
     ctx->source_index = source_index;
@@ -93,12 +107,12 @@ _zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t lengt
     ctx->needs_seek = (ctx->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK)) ? true : false;
 
     if (st) {
-       if (_zip_stat_merge(&ctx->stat, st, error) < 0) {
-           free(ctx);
-           return NULL;
-       }
+        if (_zip_stat_merge(&ctx->stat, st, error) < 0) {
+            free(ctx);
+            return NULL;
+        }
     }
-
+    
     return zip_source_layered_create(src, window_read, ctx, error);
 }
 
@@ -116,7 +130,7 @@ _zip_source_invalidate(zip_source_t *src) {
     src->source_closed = 1;
 
     if (zip_error_code_zip(&src->error) == ZIP_ER_OK) {
-       zip_error_set(&src->error, ZIP_ER_ZIPCLOSED, 0);
+        zip_error_set(&src->error, ZIP_ER_ZIPCLOSED, 0);
     }
 }
 
@@ -131,129 +145,159 @@ window_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_sou
 
     switch (cmd) {
     case ZIP_SOURCE_CLOSE:
-       return 0;
+        return 0;
 
     case ZIP_SOURCE_ERROR:
-       return zip_error_to_data(&ctx->error, data, len);
+        return zip_error_to_data(&ctx->error, data, len);
 
     case ZIP_SOURCE_FREE:
-       free(ctx);
-       return 0;
+        free(ctx);
+        return 0;
 
     case ZIP_SOURCE_OPEN:
-       if (ctx->source_archive) {
-           zip_uint64_t offset;
-
-           if ((offset = _zip_file_get_offset(ctx->source_archive, ctx->source_index, &ctx->error)) == 0) {
-               return -1;
-           }
-           if (ctx->end + offset < ctx->end) {
-               /* zip archive data claims end of data past zip64 limits */
-               zip_error_set(&ctx->error, ZIP_ER_INCONS, 0);
-               return -1;
-           }
-           ctx->start += offset;
-           ctx->end += offset;
-           ctx->source_archive = NULL;
-       }
-
-       if (!ctx->needs_seek) {
-           DEFINE_BYTE_ARRAY(b, BUFSIZE);
-
-           if (!byte_array_init(b, BUFSIZE)) {
-               zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
-               return -1;
-           }
-
-           for (n = 0; n < ctx->start; n += (zip_uint64_t)ret) {
-               i = (ctx->start - n > BUFSIZE ? BUFSIZE : ctx->start - n);
-               if ((ret = zip_source_read(src, b, i)) < 0) {
-                   _zip_error_set_from_source(&ctx->error, src);
-                   byte_array_fini(b);
-                   return -1;
-               }
-               if (ret == 0) {
-                   zip_error_set(&ctx->error, ZIP_ER_EOF, 0);
-                   byte_array_fini(b);
-                   return -1;
-               }
-           }
-
-           byte_array_fini(b);
-       }
-
-       ctx->offset = ctx->start;
-       return 0;
+        if (ctx->source_archive) {
+            zip_uint64_t offset;
+
+            if ((offset = _zip_file_get_offset(ctx->source_archive, ctx->source_index, &ctx->error)) == 0) {
+                return -1;
+            }
+            if (ctx->end + offset < ctx->end) {
+                /* zip archive data claims end of data past zip64 limits */
+                zip_error_set(&ctx->error, ZIP_ER_INCONS, MAKE_DETAIL_WITH_INDEX(ZIP_ER_DETAIL_CDIR_ENTRY_INVALID, ctx->source_index));
+                return -1;
+            }
+            ctx->start += offset;
+            ctx->end += offset;
+            ctx->source_archive = NULL;
+        }
+
+        if (!ctx->needs_seek) {
+            DEFINE_BYTE_ARRAY(b, BUFSIZE);
+
+            if (!byte_array_init(b, BUFSIZE)) {
+                zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
+                return -1;
+            }
+
+            for (n = 0; n < ctx->start; n += (zip_uint64_t)ret) {
+                i = (ctx->start - n > BUFSIZE ? BUFSIZE : ctx->start - n);
+                if ((ret = zip_source_read(src, b, i)) < 0) {
+                    _zip_error_set_from_source(&ctx->error, src);
+                    byte_array_fini(b);
+                    return -1;
+                }
+                if (ret == 0) {
+                    zip_error_set(&ctx->error, ZIP_ER_EOF, 0);
+                    byte_array_fini(b);
+                    return -1;
+                }
+            }
+
+            byte_array_fini(b);
+        }
+
+        ctx->offset = ctx->start;
+        return 0;
 
     case ZIP_SOURCE_READ:
-       if (len > ctx->end - ctx->offset)
-           len = ctx->end - ctx->offset;
-
-       if (len == 0)
-           return 0;
-
-       if (ctx->needs_seek) {
-           if (zip_source_seek(src, (zip_int64_t)ctx->offset, SEEK_SET) < 0) {
-               _zip_error_set_from_source(&ctx->error, src);
-               return -1;
-           }
-       }
-
-       if ((ret = zip_source_read(src, data, len)) < 0) {
-           zip_error_set(&ctx->error, ZIP_ER_EOF, 0);
-           return -1;
-       }
-
-       ctx->offset += (zip_uint64_t)ret;
-
-       if (ret == 0) {
-           if (ctx->offset < ctx->end) {
-               zip_error_set(&ctx->error, ZIP_ER_EOF, 0);
-               return -1;
-           }
-       }
-       return ret;
+        if (ctx->end_valid && len > ctx->end - ctx->offset) {
+            len = ctx->end - ctx->offset;
+        }
+
+        if (len == 0) {
+            return 0;
+        }
+
+        if (ctx->needs_seek) {
+            if (zip_source_seek(src, (zip_int64_t)ctx->offset, SEEK_SET) < 0) {
+                _zip_error_set_from_source(&ctx->error, src);
+                return -1;
+            }
+        }
+
+        if ((ret = zip_source_read(src, data, len)) < 0) {
+            zip_error_set(&ctx->error, ZIP_ER_EOF, 0);
+            return -1;
+        }
+
+        ctx->offset += (zip_uint64_t)ret;
+
+        if (ret == 0) {
+            if (ctx->end_valid && ctx->offset < ctx->end) {
+                zip_error_set(&ctx->error, ZIP_ER_EOF, 0);
+                return -1;
+            }
+        }
+        return ret;
 
     case ZIP_SOURCE_SEEK: {
-       zip_int64_t new_offset = zip_source_seek_compute_offset(ctx->offset - ctx->start, ctx->end - ctx->start, data, len, &ctx->error);
-
-       if (new_offset < 0) {
-           return -1;
-       }
-
-       ctx->offset = (zip_uint64_t)new_offset + ctx->start;
-       return 0;
+        zip_int64_t new_offset;
+        
+        if (!ctx->end_valid) {
+            zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);
+            
+            if (args == NULL) {
+                return -1;
+            }
+            if (args->whence == SEEK_END) {
+                if (zip_source_seek(src, args->offset, args->whence) < 0) {
+                    _zip_error_set_from_source(&ctx->error, src);
+                    return -1;
+                }
+                new_offset = zip_source_tell(src);
+                if (new_offset < 0) {
+                    _zip_error_set_from_source(&ctx->error, src);
+                    return -1;
+                }
+                if ((zip_uint64_t)new_offset < ctx->start) {
+                    zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
+                    (void)zip_source_seek(src, (zip_int64_t)ctx->offset, SEEK_SET);
+                    return -1;
+                }
+                ctx->offset = (zip_uint64_t)new_offset;
+                return 0;
+            }
+        }
+
+        new_offset = zip_source_seek_compute_offset(ctx->offset - ctx->start, ctx->end - ctx->start, data, len, &ctx->error);
+        
+        if (new_offset < 0) {
+            return -1;
+        }
+        
+        ctx->offset = (zip_uint64_t)new_offset + ctx->start;
+        return 0;
     }
 
     case ZIP_SOURCE_STAT: {
-       zip_stat_t *st;
+        zip_stat_t *st;
 
-       st = (zip_stat_t *)data;
+        st = (zip_stat_t *)data;
 
-       if (_zip_stat_merge(st, &ctx->stat, &ctx->error) < 0) {
-           return -1;
-       }
-       return 0;
+        if (_zip_stat_merge(st, &ctx->stat, &ctx->error) < 0) {
+            return -1;
+        }
+        return 0;
     }
 
     case ZIP_SOURCE_GET_FILE_ATTRIBUTES:
-       if (len < sizeof(ctx->attributes)) {
-           zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
-           return -1;
-       }
+        if (len < sizeof(ctx->attributes)) {
+            zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
+            return -1;
+        }
 
-       memcpy(data, &ctx->attributes, sizeof(ctx->attributes));
-       return sizeof(ctx->attributes);
+        memcpy(data, &ctx->attributes, sizeof(ctx->attributes));
+        return sizeof(ctx->attributes);
 
     case ZIP_SOURCE_SUPPORTS:
-       return ctx->supports;
+        return ctx->supports;
 
     case ZIP_SOURCE_TELL:
-       return (zip_int64_t)(ctx->offset - ctx->start);
+        return (zip_int64_t)(ctx->offset - ctx->start);
 
     default:
-       zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
+        return -1;
     }
 }
 
@@ -263,11 +307,11 @@ _zip_deregister_source(zip_t *za, zip_source_t *src) {
     unsigned int i;
 
     for (i = 0; i < za->nopen_source; i++) {
-       if (za->open_source[i] == src) {
-           za->open_source[i] = za->open_source[za->nopen_source - 1];
-           za->nopen_source--;
-           break;
-       }
+        if (za->open_source[i] == src) {
+            za->open_source[i] = za->open_source[za->nopen_source - 1];
+            za->nopen_source--;
+            break;
+        }
     }
 }
 
@@ -277,15 +321,15 @@ _zip_register_source(zip_t *za, zip_source_t *src) {
     zip_source_t **open_source;
 
     if (za->nopen_source + 1 >= za->nopen_source_alloc) {
-       unsigned int n;
-       n = za->nopen_source_alloc + 10;
-       open_source = (zip_source_t **)realloc(za->open_source, n * sizeof(zip_source_t *));
-       if (open_source == NULL) {
-           zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-           return -1;
-       }
-       za->nopen_source_alloc = n;
-       za->open_source = open_source;
+        unsigned int n;
+        n = za->nopen_source_alloc + 10;
+        open_source = (zip_source_t **)realloc(za->open_source, n * sizeof(zip_source_t *));
+        if (open_source == NULL) {
+            zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+            return -1;
+        }
+        za->nopen_source_alloc = n;
+        za->open_source = open_source;
     }
 
     za->open_source[za->nopen_source++] = src;
index 2ee626a..2999654 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_winzip_aes_decode.c -- Winzip AES decryption routines
-  Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -63,35 +63,35 @@ zip_source_winzip_aes_decode(zip_t *za, zip_source_t *src, zip_uint16_t encrypti
     struct winzip_aes *ctx;
 
     if ((encryption_method != ZIP_EM_AES_128 && encryption_method != ZIP_EM_AES_192 && encryption_method != ZIP_EM_AES_256) || password == NULL || src == NULL) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return NULL;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
     if (flags & ZIP_CODEC_ENCODE) {
-       zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
-       return NULL;
+        zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
+        return NULL;
     }
 
     if (zip_source_stat(src, &st) != 0) {
-       _zip_error_set_from_source(&za->error, src);
-       return NULL;
+        _zip_error_set_from_source(&za->error, src);
+        return NULL;
     }
 
     aux_length = WINZIP_AES_PASSWORD_VERIFY_LENGTH + SALT_LENGTH(encryption_method) + HMAC_LENGTH;
 
     if ((st.valid & ZIP_STAT_COMP_SIZE) == 0 || st.comp_size < aux_length) {
-       zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 0);
-       return NULL;
+        zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 0);
+        return NULL;
     }
 
     if ((ctx = winzip_aes_new(encryption_method, password, &za->error)) == NULL) {
-       return NULL;
+        return NULL;
     }
 
     ctx->data_length = st.comp_size - aux_length;
 
     if ((s2 = zip_source_layered(za, src, winzip_aes_decrypt, ctx)) == NULL) {
-       winzip_aes_free(ctx);
-       return NULL;
+        winzip_aes_free(ctx);
+        return NULL;
     }
 
     return s2;
@@ -107,23 +107,23 @@ decrypt_header(zip_source_t *src, struct winzip_aes *ctx) {
 
     headerlen = WINZIP_AES_PASSWORD_VERIFY_LENGTH + SALT_LENGTH(ctx->encryption_method);
     if ((n = zip_source_read(src, header, headerlen)) < 0) {
-       _zip_error_set_from_source(&ctx->error, src);
-       return -1;
+        _zip_error_set_from_source(&ctx->error, src);
+        return -1;
     }
 
     if (n != headerlen) {
-       zip_error_set(&ctx->error, ZIP_ER_EOF, 0);
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_EOF, 0);
+        return -1;
     }
 
     if ((ctx->aes_ctx = _zip_winzip_aes_new((zip_uint8_t *)ctx->password, strlen(ctx->password), header, ctx->encryption_method, password_verification, &ctx->error)) == NULL) {
-       return -1;
+        return -1;
     }
     if (memcmp(password_verification, header + SALT_LENGTH(ctx->encryption_method), WINZIP_AES_PASSWORD_VERIFY_LENGTH) != 0) {
-       _zip_winzip_aes_free(ctx->aes_ctx);
-       ctx->aes_ctx = NULL;
-       zip_error_set(&ctx->error, ZIP_ER_WRONGPASSWD, 0);
-       return -1;
+        _zip_winzip_aes_free(ctx->aes_ctx);
+        ctx->aes_ctx = NULL;
+        zip_error_set(&ctx->error, ZIP_ER_WRONGPASSWD, 0);
+        return -1;
     }
     return 0;
 }
@@ -133,20 +133,20 @@ static bool
 verify_hmac(zip_source_t *src, struct winzip_aes *ctx) {
     unsigned char computed[SHA1_LENGTH], from_file[HMAC_LENGTH];
     if (zip_source_read(src, from_file, HMAC_LENGTH) < HMAC_LENGTH) {
-       _zip_error_set_from_source(&ctx->error, src);
-       return false;
+        _zip_error_set_from_source(&ctx->error, src);
+        return false;
     }
 
     if (!_zip_winzip_aes_finish(ctx->aes_ctx, computed)) {
-       zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
-       return false;
+        zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
+        return false;
     }
     _zip_winzip_aes_free(ctx->aes_ctx);
     ctx->aes_ctx = NULL;
 
     if (memcmp(from_file, computed, HMAC_LENGTH) != 0) {
-       zip_error_set(&ctx->error, ZIP_ER_CRC, 0);
-       return false;
+        zip_error_set(&ctx->error, ZIP_ER_CRC, 0);
+        return false;
     }
 
     return true;
@@ -162,67 +162,67 @@ winzip_aes_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zi
 
     switch (cmd) {
     case ZIP_SOURCE_OPEN:
-       if (decrypt_header(src, ctx) < 0) {
-           return -1;
-       }
-       ctx->current_position = 0;
-       return 0;
+        if (decrypt_header(src, ctx) < 0) {
+            return -1;
+        }
+        ctx->current_position = 0;
+        return 0;
 
     case ZIP_SOURCE_READ:
-       if (len > ctx->data_length - ctx->current_position) {
-           len = ctx->data_length - ctx->current_position;
-       }
-
-       if (len == 0) {
-           if (!verify_hmac(src, ctx)) {
-               return -1;
-           }
-           return 0;
-       }
-
-       if ((n = zip_source_read(src, data, len)) < 0) {
-           _zip_error_set_from_source(&ctx->error, src);
-           return -1;
-       }
-       ctx->current_position += (zip_uint64_t)n;
-
-       if (!_zip_winzip_aes_decrypt(ctx->aes_ctx, (zip_uint8_t *)data, (zip_uint64_t)n)) {
-           zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
-           return -1;
-       }
-
-       return n;
+        if (len > ctx->data_length - ctx->current_position) {
+            len = ctx->data_length - ctx->current_position;
+        }
+
+        if (len == 0) {
+            if (!verify_hmac(src, ctx)) {
+                return -1;
+            }
+            return 0;
+        }
+
+        if ((n = zip_source_read(src, data, len)) < 0) {
+            _zip_error_set_from_source(&ctx->error, src);
+            return -1;
+        }
+        ctx->current_position += (zip_uint64_t)n;
+
+        if (!_zip_winzip_aes_decrypt(ctx->aes_ctx, (zip_uint8_t *)data, (zip_uint64_t)n)) {
+            zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
+            return -1;
+        }
+
+        return n;
 
     case ZIP_SOURCE_CLOSE:
-       return 0;
+        return 0;
 
     case ZIP_SOURCE_STAT: {
-       zip_stat_t *st;
+        zip_stat_t *st;
 
-       st = (zip_stat_t *)data;
+        st = (zip_stat_t *)data;
 
-       st->encryption_method = ZIP_EM_NONE;
-       st->valid |= ZIP_STAT_ENCRYPTION_METHOD;
-       if (st->valid & ZIP_STAT_COMP_SIZE) {
-           st->comp_size -= 12 + SALT_LENGTH(ctx->encryption_method);
-       }
+        st->encryption_method = ZIP_EM_NONE;
+        st->valid |= ZIP_STAT_ENCRYPTION_METHOD;
+        if (st->valid & ZIP_STAT_COMP_SIZE) {
+            st->comp_size -= 12 + SALT_LENGTH(ctx->encryption_method);
+        }
 
-       return 0;
+        return 0;
     }
 
     case ZIP_SOURCE_SUPPORTS:
-       return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1);
+        return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1);
 
     case ZIP_SOURCE_ERROR:
-       return zip_error_to_data(&ctx->error, data, len);
+        return zip_error_to_data(&ctx->error, data, len);
 
     case ZIP_SOURCE_FREE:
-       winzip_aes_free(ctx);
-       return 0;
+        winzip_aes_free(ctx);
+        return 0;
 
     default:
-       zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 }
 
@@ -230,7 +230,7 @@ winzip_aes_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zi
 static void
 winzip_aes_free(struct winzip_aes *ctx) {
     if (ctx == NULL) {
-       return;
+        return;
     }
 
     _zip_crypto_clear(ctx->password, strlen(ctx->password));
@@ -246,14 +246,14 @@ winzip_aes_new(zip_uint16_t encryption_method, const char *password, zip_error_t
     struct winzip_aes *ctx;
 
     if ((ctx = (struct winzip_aes *)malloc(sizeof(*ctx))) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     if ((ctx->password = strdup(password)) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       free(ctx);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        free(ctx);
+        return NULL;
     }
 
     ctx->encryption_method = encryption_method;
index f9ae555..44c4e4b 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_winzip_aes_encode.c -- Winzip AES encryption routines
-  Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -63,17 +63,17 @@ zip_source_winzip_aes_encode(zip_t *za, zip_source_t *src, zip_uint16_t encrypti
     struct winzip_aes *ctx;
 
     if ((encryption_method != ZIP_EM_AES_128 && encryption_method != ZIP_EM_AES_192 && encryption_method != ZIP_EM_AES_256) || password == NULL || src == NULL) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return NULL;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
 
     if ((ctx = winzip_aes_new(encryption_method, password, &za->error)) == NULL) {
-       return NULL;
+        return NULL;
     }
 
     if ((s2 = zip_source_layered(za, src, winzip_aes_encrypt, ctx)) == NULL) {
-       winzip_aes_free(ctx);
-       return NULL;
+        winzip_aes_free(ctx);
+        return NULL;
     }
 
     return s2;
@@ -84,19 +84,19 @@ static int
 encrypt_header(zip_source_t *src, struct winzip_aes *ctx) {
     zip_uint16_t salt_length = SALT_LENGTH(ctx->encryption_method);
     if (!zip_secure_random(ctx->data, salt_length)) {
-       zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
+        return -1;
     }
 
     if ((ctx->aes_ctx = _zip_winzip_aes_new((zip_uint8_t *)ctx->password, strlen(ctx->password), ctx->data, ctx->encryption_method, ctx->data + salt_length, &ctx->error)) == NULL) {
-       return -1;
+        return -1;
     }
 
     if ((ctx->buffer = _zip_buffer_new(ctx->data, salt_length + WINZIP_AES_PASSWORD_VERIFY_LENGTH)) == NULL) {
-       _zip_winzip_aes_free(ctx->aes_ctx);
-       ctx->aes_ctx = NULL;
-       zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
-       return -1;
+        _zip_winzip_aes_free(ctx->aes_ctx);
+        ctx->aes_ctx = NULL;
+        zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
+        return -1;
     }
 
     return 0;
@@ -113,102 +113,102 @@ winzip_aes_encrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t length,
 
     switch (cmd) {
     case ZIP_SOURCE_OPEN:
-       ctx->eof = false;
-       if (encrypt_header(src, ctx) < 0) {
-           return -1;
-       }
-       return 0;
+        ctx->eof = false;
+        if (encrypt_header(src, ctx) < 0) {
+            return -1;
+        }
+        return 0;
 
     case ZIP_SOURCE_READ:
-       buffer_n = 0;
-
-       if (ctx->buffer) {
-           buffer_n = _zip_buffer_read(ctx->buffer, data, length);
-
-           data = (zip_uint8_t *)data + buffer_n;
-           length -= buffer_n;
-
-           if (_zip_buffer_eof(ctx->buffer)) {
-               _zip_buffer_free(ctx->buffer);
-               ctx->buffer = NULL;
-           }
-       }
-
-       if (ctx->eof) {
-           return (zip_int64_t)buffer_n;
-       }
-
-       if ((ret = zip_source_read(src, data, length)) < 0) {
-           _zip_error_set_from_source(&ctx->error, src);
-           return -1;
-       }
-
-       if (!_zip_winzip_aes_encrypt(ctx->aes_ctx, data, (zip_uint64_t)ret)) {
-           zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
-           /* TODO: return partial read? */
-           return -1;
-       }
-
-       if ((zip_uint64_t)ret < length) {
-           ctx->eof = true;
-           if (!_zip_winzip_aes_finish(ctx->aes_ctx, ctx->data)) {
-               zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
-               /* TODO: return partial read? */
-               return -1;
-           }
-           _zip_winzip_aes_free(ctx->aes_ctx);
-           ctx->aes_ctx = NULL;
-           if ((ctx->buffer = _zip_buffer_new(ctx->data, HMAC_LENGTH)) == NULL) {
-               zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
-               /* TODO: return partial read? */
-               return -1;
-           }
-           buffer_n += _zip_buffer_read(ctx->buffer, (zip_uint8_t *)data + ret, length - (zip_uint64_t)ret);
-       }
-
-       return (zip_int64_t)(buffer_n + (zip_uint64_t)ret);
+        buffer_n = 0;
+
+        if (ctx->buffer) {
+            buffer_n = _zip_buffer_read(ctx->buffer, data, length);
+
+            data = (zip_uint8_t *)data + buffer_n;
+            length -= buffer_n;
+
+            if (_zip_buffer_eof(ctx->buffer)) {
+                _zip_buffer_free(ctx->buffer);
+                ctx->buffer = NULL;
+            }
+        }
+
+        if (ctx->eof) {
+            return (zip_int64_t)buffer_n;
+        }
+
+        if ((ret = zip_source_read(src, data, length)) < 0) {
+            _zip_error_set_from_source(&ctx->error, src);
+            return -1;
+        }
+
+        if (!_zip_winzip_aes_encrypt(ctx->aes_ctx, data, (zip_uint64_t)ret)) {
+            zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
+            /* TODO: return partial read? */
+            return -1;
+        }
+
+        if ((zip_uint64_t)ret < length) {
+            ctx->eof = true;
+            if (!_zip_winzip_aes_finish(ctx->aes_ctx, ctx->data)) {
+                zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
+                /* TODO: return partial read? */
+                return -1;
+            }
+            _zip_winzip_aes_free(ctx->aes_ctx);
+            ctx->aes_ctx = NULL;
+            if ((ctx->buffer = _zip_buffer_new(ctx->data, HMAC_LENGTH)) == NULL) {
+                zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
+                /* TODO: return partial read? */
+                return -1;
+            }
+            buffer_n += _zip_buffer_read(ctx->buffer, (zip_uint8_t *)data + ret, length - (zip_uint64_t)ret);
+        }
+
+        return (zip_int64_t)(buffer_n + (zip_uint64_t)ret);
 
     case ZIP_SOURCE_CLOSE:
-       return 0;
+        return 0;
 
     case ZIP_SOURCE_STAT: {
-       zip_stat_t *st;
+        zip_stat_t *st;
 
-       st = (zip_stat_t *)data;
-       st->encryption_method = ctx->encryption_method;
-       st->valid |= ZIP_STAT_ENCRYPTION_METHOD;
-       if (st->valid & ZIP_STAT_COMP_SIZE) {
-           st->comp_size += 12 + SALT_LENGTH(ctx->encryption_method);
-       }
+        st = (zip_stat_t *)data;
+        st->encryption_method = ctx->encryption_method;
+        st->valid |= ZIP_STAT_ENCRYPTION_METHOD;
+        if (st->valid & ZIP_STAT_COMP_SIZE) {
+            st->comp_size += 12 + SALT_LENGTH(ctx->encryption_method);
+        }
 
-       return 0;
+        return 0;
     }
 
     case ZIP_SOURCE_GET_FILE_ATTRIBUTES: {
-       zip_file_attributes_t *attributes = (zip_file_attributes_t *)data;
-       if (length < sizeof(*attributes)) {
-           zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
-           return -1;
-       }
-       attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED;
-       attributes->version_needed = 51;
-
-       return 0;
+        zip_file_attributes_t *attributes = (zip_file_attributes_t *)data;
+        if (length < sizeof(*attributes)) {
+            zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
+            return -1;
+        }
+        attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED;
+        attributes->version_needed = 51;
+
+        return 0;
     }
 
     case ZIP_SOURCE_SUPPORTS:
-       return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1);
+        return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1);
 
     case ZIP_SOURCE_ERROR:
-       return zip_error_to_data(&ctx->error, data, length);
+        return zip_error_to_data(&ctx->error, data, length);
 
     case ZIP_SOURCE_FREE:
-       winzip_aes_free(ctx);
-       return 0;
+        winzip_aes_free(ctx);
+        return 0;
 
     default:
-       zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 }
 
@@ -216,7 +216,7 @@ winzip_aes_encrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t length,
 static void
 winzip_aes_free(struct winzip_aes *ctx) {
     if (ctx == NULL) {
-       return;
+        return;
     }
 
     _zip_crypto_clear(ctx->password, strlen(ctx->password));
@@ -233,14 +233,14 @@ winzip_aes_new(zip_uint16_t encryption_method, const char *password, zip_error_t
     struct winzip_aes *ctx;
 
     if ((ctx = (struct winzip_aes *)malloc(sizeof(*ctx))) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     if ((ctx->password = strdup(password)) == NULL) {
-       free(ctx);
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        free(ctx);
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     ctx->encryption_method = encryption_method;
index 73fc3a3..bb72b14 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_write.c -- start a new file for writing
-  Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -38,8 +38,8 @@
 ZIP_EXTERN zip_int64_t
 zip_source_write(zip_source_t *src, const void *data, zip_uint64_t length) {
     if (!ZIP_SOURCE_IS_OPEN_WRITING(src) || length > ZIP_INT64_MAX) {
-       zip_error_set(&src->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&src->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     return _zip_source_call(src, (void *)data, length, ZIP_SOURCE_WRITE);
index 8a7feaa..e6cedaf 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_zip.c -- create data source from zip file
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 
 #include "zipint.h"
 
-
-ZIP_EXTERN zip_source_t *
-zip_source_zip(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_int64_t len) {
+ZIP_EXTERN zip_source_t *zip_source_zip_create(zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_int64_t len, zip_error_t *error) {
     if (len < -1) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
-
+    
     if (len == -1)
-       len = 0;
-
+        len = 0;
+    
     if (start == 0 && len == 0)
-       flags |= ZIP_FL_COMPRESSED;
+        flags |= ZIP_FL_COMPRESSED;
     else
-       flags &= ~ZIP_FL_COMPRESSED;
+        flags &= ~ZIP_FL_COMPRESSED;
+    
+    return _zip_source_zip_new(srcza, srcidx, flags, start, (zip_uint64_t)len, NULL, error);
+}
+
 
-    return _zip_source_zip_new(za, srcza, srcidx, flags, start, (zip_uint64_t)len, NULL);
+ZIP_EXTERN zip_source_t *zip_source_zip(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_int64_t len) {
+    return zip_source_zip_create(srcza, srcidx, flags, start, len, &za->error);
 }
index 6d547f0..cf3d267 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_zip_new.c -- prepare data structures for zip_fopen/zip_source_zip
-  Copyright (C) 2012-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 
 static void _zip_file_attributes_from_dirent(zip_file_attributes_t *attributes, zip_dirent_t *de);
 
-zip_source_t *
-_zip_source_zip_new(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_uint64_t len, const char *password) {
+zip_source_t *_zip_source_zip_new(zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_uint64_t len, const char *password, zip_error_t *error) {
     zip_source_t *src, *s2;
     zip_stat_t st;
     zip_file_attributes_t attributes;
     zip_dirent_t *de;
     bool partial_data, needs_crc, needs_decrypt, needs_decompress;
 
-    if (za == NULL) {
-       return NULL;
-    }
-
-    if (srcza == NULL || srcidx >= srcza->nentry) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return NULL;
+    if (srcza == NULL || srcidx >= srcza->nentry || len > ZIP_INT64_MAX) {
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
 
     if ((flags & ZIP_FL_UNCHANGED) == 0 && (ZIP_ENTRY_DATA_CHANGED(srcza->entry + srcidx) || srcza->entry[srcidx].deleted)) {
-       zip_error_set(&za->error, ZIP_ER_CHANGED, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_CHANGED, 0);
+        return NULL;
     }
 
     if (zip_stat_index(srcza, srcidx, flags | ZIP_FL_UNCHANGED, &st) < 0) {
-       zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INTERNAL, 0);
+        return NULL;
     }
 
     if (flags & ZIP_FL_ENCRYPTED) {
-       flags |= ZIP_FL_COMPRESSED;
+        flags |= ZIP_FL_COMPRESSED;
     }
 
     if ((start > 0 || len > 0) && (flags & ZIP_FL_COMPRESSED)) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
 
     /* overflow or past end of file */
     if ((start > 0 || len > 0) && (start + len < start || start + len > st.size)) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
 
     if (len == 0) {
-       len = st.size - start;
+        len = st.size - start;
     }
 
     partial_data = len < st.size;
@@ -91,89 +86,93 @@ _zip_source_zip_new(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t fl
     needs_crc = ((flags & ZIP_FL_COMPRESSED) == 0 || st.comp_method == ZIP_CM_STORE) && !partial_data;
 
     if (needs_decrypt) {
-       if (password == NULL) {
-           password = za->default_password;
-       }
-       if (password == NULL) {
-           zip_error_set(&za->error, ZIP_ER_NOPASSWD, 0);
-           return NULL;
-       }
+        if (password == NULL) {
+            password = srcza->default_password;
+        }
+        if (password == NULL) {
+            zip_error_set(error, ZIP_ER_NOPASSWD, 0);
+            return NULL;
+        }
     }
 
-    if ((de = _zip_get_dirent(srcza, srcidx, flags, &za->error)) == NULL) {
-       return NULL;
+    if ((de = _zip_get_dirent(srcza, srcidx, flags, error)) == NULL) {
+        return NULL;
     }
     _zip_file_attributes_from_dirent(&attributes, de);
 
     if (st.comp_size == 0) {
-       return zip_source_buffer_with_attributes(za, NULL, 0, 0, &attributes);
+        return zip_source_buffer_with_attributes_create(NULL, 0, 0, &attributes, error);
     }
 
     if (partial_data && !needs_decrypt && !needs_decompress) {
-       struct zip_stat st2;
+        struct zip_stat st2;
 
-       st2.size = len;
-       st2.comp_size = len;
-       st2.comp_method = ZIP_CM_STORE;
-       st2.mtime = st.mtime;
-       st2.valid = ZIP_STAT_SIZE | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_MTIME;
+        st2.size = len;
+        st2.comp_size = len;
+        st2.comp_method = ZIP_CM_STORE;
+        st2.mtime = st.mtime;
+        st2.valid = ZIP_STAT_SIZE | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_MTIME;
 
-       if ((src = _zip_source_window_new(srcza->src, start, len, &st2, &attributes, srcza, srcidx, &za->error)) == NULL) {
-           return NULL;
-       }
+        if ((src = _zip_source_window_new(srcza->src, start, (zip_int64_t)len, &st2, &attributes, srcza, srcidx, error)) == NULL) {
+            return NULL;
+        }
     }
     else {
-       if ((src = _zip_source_window_new(srcza->src, 0, st.comp_size, &st, &attributes, srcza, srcidx, &za->error)) == NULL) {
-           return NULL;
-       }
+        if (st.comp_size > ZIP_INT64_MAX) {
+            zip_error_set(error, ZIP_ER_INVAL, 0);
+            return NULL;
+        }
+        if ((src =  _zip_source_window_new(srcza->src, 0, (zip_int64_t)st.comp_size, &st, &attributes, srcza, srcidx, error)) == NULL) {
+            return NULL;
+        }
     }
 
     if (_zip_source_set_source_archive(src, srcza) < 0) {
-       zip_source_free(src);
-       return NULL;
+        zip_source_free(src);
+        return NULL;
     }
 
     /* creating a layered source calls zip_keep() on the lower layer, so we free it */
 
     if (needs_decrypt) {
-       zip_encryption_implementation enc_impl;
+        zip_encryption_implementation enc_impl;
 
-       if ((enc_impl = _zip_get_encryption_implementation(st.encryption_method, ZIP_CODEC_DECODE)) == NULL) {
-           zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
-           return NULL;
-       }
+        if ((enc_impl = _zip_get_encryption_implementation(st.encryption_method, ZIP_CODEC_DECODE)) == NULL) {
+            zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
+            return NULL;
+        }
 
-       s2 = enc_impl(za, src, st.encryption_method, 0, password);
-       zip_source_free(src);
-       if (s2 == NULL) {
-           return NULL;
-       }
-       src = s2;
+        s2 = enc_impl(srcza, src, st.encryption_method, 0, password);
+        zip_source_free(src);
+        if (s2 == NULL) {
+            return NULL;
+        }
+        src = s2;
     }
     if (needs_decompress) {
-       s2 = zip_source_decompress(za, src, st.comp_method);
-       zip_source_free(src);
-       if (s2 == NULL) {
-           return NULL;
-       }
-       src = s2;
+        s2 = zip_source_decompress(srcza, src, st.comp_method);
+        zip_source_free(src);
+        if (s2 == NULL) {
+            return NULL;
+        }
+        src = s2;
     }
     if (needs_crc) {
-       s2 = zip_source_crc(za, src, 1);
-       zip_source_free(src);
-       if (s2 == NULL) {
-           return NULL;
-       }
-       src = s2;
+        s2 = zip_source_crc_create(src, 1, error);
+        zip_source_free(src);
+        if (s2 == NULL) {
+            return NULL;
+        }
+        src = s2;
     }
 
     if (partial_data && (needs_decrypt || needs_decompress)) {
-       s2 = zip_source_window(za, src, start, len);
-       zip_source_free(src);
-       if (s2 == NULL) {
-           return NULL;
-       }
-       src = s2;
+        s2 = zip_source_window_create(src, start, (zip_int64_t)len, error);
+        zip_source_free(src);
+        if (s2 == NULL) {
+            return NULL;
+        }
+        src = s2;
     }
 
     return src;
index 341c6f7..4b7c495 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_stat.c -- get information about file by name
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -40,7 +40,7 @@ zip_stat(zip_t *za, const char *fname, zip_flags_t flags, zip_stat_t *st) {
     zip_int64_t idx;
 
     if ((idx = zip_name_locate(za, fname, flags)) < 0)
-       return -1;
+        return -1;
 
     return zip_stat_index(za, (zip_uint64_t)idx, flags, st);
 }
index 7799325..62dc045 100644 (file)
@@ -41,35 +41,35 @@ zip_stat_index(zip_t *za, zip_uint64_t index, zip_flags_t flags, zip_stat_t *st)
     zip_dirent_t *de;
 
     if ((de = _zip_get_dirent(za, index, flags, NULL)) == NULL)
-       return -1;
+        return -1;
 
     if ((name = zip_get_name(za, index, flags)) == NULL)
-       return -1;
+        return -1;
 
 
     if ((flags & ZIP_FL_UNCHANGED) == 0 && ZIP_ENTRY_DATA_CHANGED(za->entry + index)) {
-       zip_entry_t *entry = za->entry + index;
+        zip_entry_t *entry = za->entry + index;
 
-       if (zip_source_stat(entry->source, st) < 0) {
-           zip_error_set(&za->error, ZIP_ER_CHANGED, 0);
-           return -1;
-       }
+        if (zip_source_stat(entry->source, st) < 0) {
+            zip_error_set(&za->error, ZIP_ER_CHANGED, 0);
+            return -1;
+        }
 
-       if (entry->changes->changed & ZIP_DIRENT_LAST_MOD) {
-           st->mtime = de->last_mod;
-           st->valid |= ZIP_STAT_MTIME;
-       }
+        if (entry->changes != NULL && entry->changes->changed & ZIP_DIRENT_LAST_MOD) {
+            st->mtime = de->last_mod;
+            st->valid |= ZIP_STAT_MTIME;
+        }
     }
     else {
-       zip_stat_init(st);
-
-       st->crc = de->crc;
-       st->size = de->uncomp_size;
-       st->mtime = de->last_mod;
-       st->comp_size = de->comp_size;
-       st->comp_method = (zip_uint16_t)de->comp_method;
-       st->encryption_method = de->encryption_method;
-       st->valid = (de->crc_valid ? ZIP_STAT_CRC : 0) | ZIP_STAT_SIZE | ZIP_STAT_MTIME | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_ENCRYPTION_METHOD;
+        zip_stat_init(st);
+
+        st->crc = de->crc;
+        st->size = de->uncomp_size;
+        st->mtime = de->last_mod;
+        st->comp_size = de->comp_size;
+        st->comp_method = (zip_uint16_t)de->comp_method;
+        st->encryption_method = de->encryption_method;
+        st->valid = (de->crc_valid ? ZIP_STAT_CRC : 0) | ZIP_STAT_SIZE | ZIP_STAT_MTIME | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_ENCRYPTION_METHOD;
     }
 
     st->index = index;
index 6d0903d..f513bde 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_stat_init.c -- initialize struct zip_stat.
-  Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -54,28 +54,28 @@ int
 _zip_stat_merge(zip_stat_t *dst, const zip_stat_t *src, zip_error_t *error) {
     /* name is not merged, since zip_stat_t doesn't own it, and src may not be valid as long as dst */
     if (src->valid & ZIP_STAT_INDEX) {
-       dst->index = src->index;
+        dst->index = src->index;
     }
     if (src->valid & ZIP_STAT_SIZE) {
-       dst->size = src->size;
+        dst->size = src->size;
     }
     if (src->valid & ZIP_STAT_COMP_SIZE) {
-       dst->comp_size = src->comp_size;
+        dst->comp_size = src->comp_size;
     }
     if (src->valid & ZIP_STAT_MTIME) {
-       dst->mtime = src->mtime;
+        dst->mtime = src->mtime;
     }
     if (src->valid & ZIP_STAT_CRC) {
-       dst->crc = src->crc;
+        dst->crc = src->crc;
     }
     if (src->valid & ZIP_STAT_COMP_METHOD) {
-       dst->comp_method = src->comp_method;
+        dst->comp_method = src->comp_method;
     }
     if (src->valid & ZIP_STAT_ENCRYPTION_METHOD) {
-       dst->encryption_method = src->encryption_method;
+        dst->encryption_method = src->encryption_method;
     }
     if (src->valid & ZIP_STAT_FLAGS) {
-       dst->flags = src->flags;
+        dst->flags = src->flags;
     }
     dst->valid |= src->valid;
 
index 906c7f7..e22db65 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_sterror.c -- get string representation of zip error
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
index 122721d..7013315 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_string.c -- string handling (with encoding)
-  Copyright (C) 2012-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -45,7 +45,7 @@ _zip_string_crc32(const zip_string_t *s) {
     crc = (zip_uint32_t)crc32(0L, Z_NULL, 0);
 
     if (s != NULL)
-       crc = (zip_uint32_t)crc32(crc, s->raw, s->length);
+        crc = (zip_uint32_t)crc32(crc, s->raw, s->length);
 
     return crc;
 }
@@ -54,10 +54,10 @@ _zip_string_crc32(const zip_string_t *s) {
 int
 _zip_string_equal(const zip_string_t *a, const zip_string_t *b) {
     if (a == NULL || b == NULL)
-       return a == b;
+        return a == b;
 
     if (a->length != b->length)
-       return 0;
+        return 0;
 
     /* TODO: encoding */
 
@@ -68,7 +68,7 @@ _zip_string_equal(const zip_string_t *a, const zip_string_t *b) {
 void
 _zip_string_free(zip_string_t *s) {
     if (s == NULL)
-       return;
+        return;
 
     free(s->raw);
     free(s->converted);
@@ -81,29 +81,29 @@ _zip_string_get(zip_string_t *string, zip_uint32_t *lenp, zip_flags_t flags, zip
     static const zip_uint8_t empty[1] = "";
 
     if (string == NULL) {
-       if (lenp)
-           *lenp = 0;
-       return empty;
+        if (lenp)
+            *lenp = 0;
+        return empty;
     }
 
     if ((flags & ZIP_FL_ENC_RAW) == 0) {
-       /* start guessing */
-       if (string->encoding == ZIP_ENCODING_UNKNOWN)
-           _zip_guess_encoding(string, ZIP_ENCODING_UNKNOWN);
-
-       if (((flags & ZIP_FL_ENC_STRICT) && string->encoding != ZIP_ENCODING_ASCII && string->encoding != ZIP_ENCODING_UTF8_KNOWN) || (string->encoding == ZIP_ENCODING_CP437)) {
-           if (string->converted == NULL) {
-               if ((string->converted = _zip_cp437_to_utf8(string->raw, string->length, &string->converted_length, error)) == NULL)
-                   return NULL;
-           }
-           if (lenp)
-               *lenp = string->converted_length;
-           return string->converted;
-       }
+        /* start guessing */
+        if (string->encoding == ZIP_ENCODING_UNKNOWN)
+            _zip_guess_encoding(string, ZIP_ENCODING_UNKNOWN);
+
+        if (((flags & ZIP_FL_ENC_STRICT) && string->encoding != ZIP_ENCODING_ASCII && string->encoding != ZIP_ENCODING_UTF8_KNOWN) || (string->encoding == ZIP_ENCODING_CP437)) {
+            if (string->converted == NULL) {
+                if ((string->converted = _zip_cp437_to_utf8(string->raw, string->length, &string->converted_length, error)) == NULL)
+                    return NULL;
+            }
+            if (lenp)
+                *lenp = string->converted_length;
+            return string->converted;
+        }
     }
 
     if (lenp)
-       *lenp = string->length;
+        *lenp = string->length;
     return string->raw;
 }
 
@@ -111,7 +111,7 @@ _zip_string_get(zip_string_t *string, zip_uint32_t *lenp, zip_flags_t flags, zip
 zip_uint16_t
 _zip_string_length(const zip_string_t *s) {
     if (s == NULL)
-       return 0;
+        return 0;
 
     return s->length;
 }
@@ -123,31 +123,31 @@ _zip_string_new(const zip_uint8_t *raw, zip_uint16_t length, zip_flags_t flags,
     zip_encoding_type_t expected_encoding;
 
     if (length == 0)
-       return NULL;
+        return NULL;
 
     switch (flags & ZIP_FL_ENCODING_ALL) {
     case ZIP_FL_ENC_GUESS:
-       expected_encoding = ZIP_ENCODING_UNKNOWN;
-       break;
+        expected_encoding = ZIP_ENCODING_UNKNOWN;
+        break;
     case ZIP_FL_ENC_UTF_8:
-       expected_encoding = ZIP_ENCODING_UTF8_KNOWN;
-       break;
+        expected_encoding = ZIP_ENCODING_UTF8_KNOWN;
+        break;
     case ZIP_FL_ENC_CP437:
-       expected_encoding = ZIP_ENCODING_CP437;
-       break;
+        expected_encoding = ZIP_ENCODING_CP437;
+        break;
     default:
-       zip_error_set(error, ZIP_ER_INVAL, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
 
     if ((s = (zip_string_t *)malloc(sizeof(*s))) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     if ((s->raw = (zip_uint8_t *)malloc((size_t)length + 1)) == NULL) {
-       free(s);
-       return NULL;
+        free(s);
+        return NULL;
     }
 
     memcpy(s->raw, raw, length);
@@ -158,11 +158,11 @@ _zip_string_new(const zip_uint8_t *raw, zip_uint16_t length, zip_flags_t flags,
     s->converted_length = 0;
 
     if (expected_encoding != ZIP_ENCODING_UNKNOWN) {
-       if (_zip_guess_encoding(s, expected_encoding) == ZIP_ENCODING_ERROR) {
-           _zip_string_free(s);
-           zip_error_set(error, ZIP_ER_INVAL, 0);
-           return NULL;
-       }
+        if (_zip_guess_encoding(s, expected_encoding) == ZIP_ENCODING_ERROR) {
+            _zip_string_free(s);
+            zip_error_set(error, ZIP_ER_INVAL, 0);
+            return NULL;
+        }
     }
 
     return s;
@@ -172,7 +172,7 @@ _zip_string_new(const zip_uint8_t *raw, zip_uint16_t length, zip_flags_t flags,
 int
 _zip_string_write(zip_t *za, const zip_string_t *s) {
     if (s == NULL)
-       return 0;
+        return 0;
 
     return _zip_write(za, s->raw, s->length);
 }
index 1a78e2c..d80a6ad 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_unchange.c -- undo changes to file in zip archive
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -49,39 +49,39 @@ _zip_unchange(zip_t *za, zip_uint64_t idx, int allow_duplicates) {
     const char *orig_name, *changed_name;
 
     if (idx >= za->nentry) {
-       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
 
     if (!allow_duplicates && za->entry[idx].changes && (za->entry[idx].changes->changed & ZIP_DIRENT_FILENAME)) {
-       if (za->entry[idx].orig != NULL) {
-           if ((orig_name = _zip_get_name(za, idx, ZIP_FL_UNCHANGED, &za->error)) == NULL) {
-               return -1;
-           }
-
-           i = _zip_name_locate(za, orig_name, 0, NULL);
-           if (i >= 0 && (zip_uint64_t)i != idx) {
-               zip_error_set(&za->error, ZIP_ER_EXISTS, 0);
-               return -1;
-           }
-       }
-       else {
-           orig_name = NULL;
-       }
-
-       if ((changed_name = _zip_get_name(za, idx, 0, &za->error)) == NULL) {
-           return -1;
-       }
-
-       if (orig_name) {
-           if (_zip_hash_add(za->names, (const zip_uint8_t *)orig_name, idx, 0, &za->error) == false) {
-               return -1;
-           }
-       }
-       if (_zip_hash_delete(za->names, (const zip_uint8_t *)changed_name, &za->error) == false) {
-           _zip_hash_delete(za->names, (const zip_uint8_t *)orig_name, NULL);
-           return -1;
-       }
+        if (za->entry[idx].orig != NULL) {
+            if ((orig_name = _zip_get_name(za, idx, ZIP_FL_UNCHANGED, &za->error)) == NULL) {
+                return -1;
+            }
+
+            i = _zip_name_locate(za, orig_name, 0, NULL);
+            if (i >= 0 && (zip_uint64_t)i != idx) {
+                zip_error_set(&za->error, ZIP_ER_EXISTS, 0);
+                return -1;
+            }
+        }
+        else {
+            orig_name = NULL;
+        }
+
+        if ((changed_name = _zip_get_name(za, idx, 0, &za->error)) == NULL) {
+            return -1;
+        }
+
+        if (orig_name) {
+            if (_zip_hash_add(za->names, (const zip_uint8_t *)orig_name, idx, 0, &za->error) == false) {
+                return -1;
+            }
+        }
+        if (_zip_hash_delete(za->names, (const zip_uint8_t *)changed_name, &za->error) == false) {
+            _zip_hash_delete(za->names, (const zip_uint8_t *)orig_name, NULL);
+            return -1;
+        }
     }
 
     _zip_dirent_free(za->entry[idx].changes);
index 2ae742f..7b0a4c0 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_unchange.c -- undo changes to all files in zip archive
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -41,12 +41,12 @@ zip_unchange_all(zip_t *za) {
     zip_uint64_t i;
 
     if (!_zip_hash_revert(za->names, &za->error)) {
-       return -1;
+        return -1;
     }
 
     ret = 0;
     for (i = 0; i < za->nentry; i++)
-       ret |= _zip_unchange(za, i, 1);
+        ret |= _zip_unchange(za, i, 1);
 
     ret |= zip_unchange_archive(za);
 
index bd223ef..a0616cc 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_unchange_archive.c -- undo global changes to ZIP archive
-  Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -40,9 +40,9 @@
 ZIP_EXTERN int
 zip_unchange_archive(zip_t *za) {
     if (za->comment_changed) {
-       _zip_string_free(za->comment_changes);
-       za->comment_changes = NULL;
-       za->comment_changed = 0;
+        _zip_string_free(za->comment_changes);
+        za->comment_changes = NULL;
+        za->comment_changed = 0;
     }
 
     za->ch_flags = za->flags;
index 74a429c..153c839 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_unchange_data.c -- undo helper function
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 void
 _zip_unchange_data(zip_entry_t *ze) {
     if (ze->source) {
-       zip_source_free(ze->source);
-       ze->source = NULL;
+        zip_source_free(ze->source);
+        ze->source = NULL;
     }
 
     if (ze->changes != NULL && (ze->changes->changed & ZIP_DIRENT_COMP_METHOD) && ze->changes->comp_method == ZIP_CM_REPLACED_DEFAULT) {
-       ze->changes->changed &= ~ZIP_DIRENT_COMP_METHOD;
-       if (ze->changes->changed == 0) {
-           _zip_dirent_free(ze->changes);
-           ze->changes = NULL;
-       }
+        ze->changes->changed &= ~ZIP_DIRENT_COMP_METHOD;
+        if (ze->changes->changed == 0) {
+            _zip_dirent_free(ze->changes);
+            ze->changes = NULL;
+        }
     }
 
     ze->deleted = 0;
index 099db9b..ebf67fa 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_utf-8.c -- UTF-8 support functions for libzip
-  Copyright (C) 2011-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2011-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -103,54 +103,54 @@ _zip_guess_encoding(zip_string_t *str, zip_encoding_type_t expected_encoding) {
     zip_uint32_t i, j, ulen;
 
     if (str == NULL)
-       return ZIP_ENCODING_ASCII;
+        return ZIP_ENCODING_ASCII;
 
     name = str->raw;
 
     if (str->encoding != ZIP_ENCODING_UNKNOWN)
-       enc = str->encoding;
+        enc = str->encoding;
     else {
-       enc = ZIP_ENCODING_ASCII;
-       for (i = 0; i < str->length; i++) {
-           if ((name[i] > 31 && name[i] < 128) || name[i] == '\r' || name[i] == '\n' || name[i] == '\t')
-               continue;
-
-           enc = ZIP_ENCODING_UTF8_GUESSED;
-           if ((name[i] & UTF_8_LEN_2_MASK) == UTF_8_LEN_2_MATCH)
-               ulen = 1;
-           else if ((name[i] & UTF_8_LEN_3_MASK) == UTF_8_LEN_3_MATCH)
-               ulen = 2;
-           else if ((name[i] & UTF_8_LEN_4_MASK) == UTF_8_LEN_4_MATCH)
-               ulen = 3;
-           else {
-               enc = ZIP_ENCODING_CP437;
-               break;
-           }
-
-           if (i + ulen >= str->length) {
-               enc = ZIP_ENCODING_CP437;
-               break;
-           }
-
-           for (j = 1; j <= ulen; j++) {
-               if ((name[i + j] & UTF_8_CONTINUE_MASK) != UTF_8_CONTINUE_MATCH) {
-                   enc = ZIP_ENCODING_CP437;
-                   goto done;
-               }
-           }
-           i += ulen;
-       }
+        enc = ZIP_ENCODING_ASCII;
+        for (i = 0; i < str->length; i++) {
+            if ((name[i] > 31 && name[i] < 128) || name[i] == '\r' || name[i] == '\n' || name[i] == '\t')
+                continue;
+
+            enc = ZIP_ENCODING_UTF8_GUESSED;
+            if ((name[i] & UTF_8_LEN_2_MASK) == UTF_8_LEN_2_MATCH)
+                ulen = 1;
+            else if ((name[i] & UTF_8_LEN_3_MASK) == UTF_8_LEN_3_MATCH)
+                ulen = 2;
+            else if ((name[i] & UTF_8_LEN_4_MASK) == UTF_8_LEN_4_MATCH)
+                ulen = 3;
+            else {
+                enc = ZIP_ENCODING_CP437;
+                break;
+            }
+
+            if (i + ulen >= str->length) {
+                enc = ZIP_ENCODING_CP437;
+                break;
+            }
+
+            for (j = 1; j <= ulen; j++) {
+                if ((name[i + j] & UTF_8_CONTINUE_MASK) != UTF_8_CONTINUE_MATCH) {
+                    enc = ZIP_ENCODING_CP437;
+                    goto done;
+                }
+            }
+            i += ulen;
+        }
     }
 
 done:
     str->encoding = enc;
 
     if (expected_encoding != ZIP_ENCODING_UNKNOWN) {
-       if (expected_encoding == ZIP_ENCODING_UTF8_KNOWN && enc == ZIP_ENCODING_UTF8_GUESSED)
-           str->encoding = enc = ZIP_ENCODING_UTF8_KNOWN;
+        if (expected_encoding == ZIP_ENCODING_UTF8_KNOWN && enc == ZIP_ENCODING_UTF8_GUESSED)
+            str->encoding = enc = ZIP_ENCODING_UTF8_KNOWN;
 
-       if (expected_encoding != enc && enc != ZIP_ENCODING_ASCII)
-           return ZIP_ENCODING_ERROR;
+        if (expected_encoding != enc && enc != ZIP_ENCODING_ASCII)
+            return ZIP_ENCODING_ERROR;
     }
 
     return enc;
@@ -160,11 +160,11 @@ done:
 static zip_uint32_t
 _zip_unicode_to_utf8_len(zip_uint32_t codepoint) {
     if (codepoint < 0x0080)
-       return 1;
+        return 1;
     if (codepoint < 0x0800)
-       return 2;
+        return 2;
     if (codepoint < 0x10000)
-       return 3;
+        return 3;
     return 4;
 }
 
@@ -172,19 +172,19 @@ _zip_unicode_to_utf8_len(zip_uint32_t codepoint) {
 static zip_uint32_t
 _zip_unicode_to_utf8(zip_uint32_t codepoint, zip_uint8_t *buf) {
     if (codepoint < 0x0080) {
-       buf[0] = codepoint & 0xff;
-       return 1;
+        buf[0] = codepoint & 0xff;
+        return 1;
     }
     if (codepoint < 0x0800) {
-       buf[0] = (zip_uint8_t)(UTF_8_LEN_2_MATCH | ((codepoint >> 6) & 0x1f));
-       buf[1] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | (codepoint & 0x3f));
-       return 2;
+        buf[0] = (zip_uint8_t)(UTF_8_LEN_2_MATCH | ((codepoint >> 6) & 0x1f));
+        buf[1] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | (codepoint & 0x3f));
+        return 2;
     }
     if (codepoint < 0x10000) {
-       buf[0] = (zip_uint8_t)(UTF_8_LEN_3_MATCH | ((codepoint >> 12) & 0x0f));
-       buf[1] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | ((codepoint >> 6) & 0x3f));
-       buf[2] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | (codepoint & 0x3f));
-       return 3;
+        buf[0] = (zip_uint8_t)(UTF_8_LEN_3_MATCH | ((codepoint >> 12) & 0x0f));
+        buf[1] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | ((codepoint >> 6) & 0x3f));
+        buf[2] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | (codepoint & 0x3f));
+        return 3;
     }
     buf[0] = (zip_uint8_t)(UTF_8_LEN_4_MATCH | ((codepoint >> 18) & 0x07));
     buf[1] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | ((codepoint >> 12) & 0x3f));
@@ -201,26 +201,26 @@ _zip_cp437_to_utf8(const zip_uint8_t *const _cp437buf, zip_uint32_t len, zip_uin
     zip_uint32_t buflen, i, offset;
 
     if (len == 0) {
-       if (utf8_lenp)
-           *utf8_lenp = 0;
-       return NULL;
+        if (utf8_lenp)
+            *utf8_lenp = 0;
+        return NULL;
     }
 
     buflen = 1;
     for (i = 0; i < len; i++)
-       buflen += _zip_unicode_to_utf8_len(_cp437_to_unicode[cp437buf[i]]);
+        buflen += _zip_unicode_to_utf8_len(_cp437_to_unicode[cp437buf[i]]);
 
     if ((utf8buf = (zip_uint8_t *)malloc(buflen)) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     offset = 0;
     for (i = 0; i < len; i++)
-       offset += _zip_unicode_to_utf8(_cp437_to_unicode[cp437buf[i]], utf8buf + offset);
+        offset += _zip_unicode_to_utf8(_cp437_to_unicode[cp437buf[i]], utf8buf + offset);
 
     utf8buf[buflen - 1] = 0;
     if (utf8_lenp)
-       *utf8_lenp = buflen - 1;
+        *utf8_lenp = buflen - 1;
     return utf8buf;
 }
index c86ef88..b36e46c 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_winzip_aes.c -- Winzip AES de/encryption backend routines
-  Copyright (C) 2017-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -55,19 +55,19 @@ aes_crypt(zip_winzip_aes_t *ctx, zip_uint8_t *data, zip_uint64_t length) {
     zip_uint64_t i, j;
 
     for (i = 0; i < length; i++) {
-       if (ctx->pad_offset == AES_BLOCK_SIZE) {
-           for (j = 0; j < 8; j++) {
-               ctx->counter[j]++;
-               if (ctx->counter[j] != 0) {
-                   break;
-               }
-           }
-           if (!_zip_crypto_aes_encrypt_block(ctx->aes, ctx->counter, ctx->pad)) {
-               return false;
-           }
-           ctx->pad_offset = 0;
-       }
-       data[i] ^= ctx->pad[ctx->pad_offset++];
+        if (ctx->pad_offset == AES_BLOCK_SIZE) {
+            for (j = 0; j < 8; j++) {
+                ctx->counter[j]++;
+                if (ctx->counter[j] != 0) {
+                    break;
+                }
+            }
+            if (!_zip_crypto_aes_encrypt_block(ctx->aes, ctx->counter, ctx->pad)) {
+                return false;
+            }
+            ctx->pad_offset = 0;
+        }
+        data[i] ^= ctx->pad[ctx->pad_offset++];
     }
 
     return true;
@@ -83,49 +83,49 @@ _zip_winzip_aes_new(const zip_uint8_t *password, zip_uint64_t password_length, c
 
     switch (encryption_method) {
     case ZIP_EM_AES_128:
-       key_size = 128;
-       break;
+        key_size = 128;
+        break;
     case ZIP_EM_AES_192:
-       key_size = 192;
-       break;
+        key_size = 192;
+        break;
     case ZIP_EM_AES_256:
-       key_size = 256;
-       break;
+        key_size = 256;
+        break;
     }
 
     if (key_size == 0 || salt == NULL || password == NULL || password_length == 0) {
-       zip_error_set(error, ZIP_ER_INVAL, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
 
     key_length = key_size / 8;
 
     if ((ctx = (zip_winzip_aes_t *)malloc(sizeof(*ctx))) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     memset(ctx->counter, 0, sizeof(ctx->counter));
     ctx->pad_offset = ZIP_CRYPTO_AES_BLOCK_LENGTH;
 
     if (!_zip_crypto_pbkdf2(password, password_length, salt, key_length / 2, PBKDF2_ITERATIONS, buffer, 2 * key_length + WINZIP_AES_PASSWORD_VERIFY_LENGTH)) {
-       free(ctx);
-       return NULL;
+        free(ctx);
+        return NULL;
     }
 
     if ((ctx->aes = _zip_crypto_aes_new(buffer, key_size, error)) == NULL) {
-       _zip_crypto_clear(ctx, sizeof(*ctx));
-       free(ctx);
-       return NULL;
+        _zip_crypto_clear(ctx, sizeof(*ctx));
+        free(ctx);
+        return NULL;
     }
     if ((ctx->hmac = _zip_crypto_hmac_new(buffer + key_length, key_length, error)) == NULL) {
-       _zip_crypto_aes_free(ctx->aes);
-       free(ctx);
-       return NULL;
+        _zip_crypto_aes_free(ctx->aes);
+        free(ctx);
+        return NULL;
     }
 
     if (password_verify) {
-       memcpy(password_verify, buffer + (2 * key_size / 8), WINZIP_AES_PASSWORD_VERIFY_LENGTH);
+        memcpy(password_verify, buffer + (2 * key_size / 8), WINZIP_AES_PASSWORD_VERIFY_LENGTH);
     }
 
     return ctx;
@@ -153,7 +153,7 @@ _zip_winzip_aes_finish(zip_winzip_aes_t *ctx, zip_uint8_t *hmac) {
 void
 _zip_winzip_aes_free(zip_winzip_aes_t *ctx) {
     if (ctx == NULL) {
-       return;
+        return;
     }
 
     _zip_crypto_aes_free(ctx->aes);
index 99c1806..eab1e3a 100644 (file)
@@ -3,7 +3,7 @@
 
 /*
   zipint.h -- internal declarations.
-  Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -35,6 +35,7 @@
 */
 
 #include "config.h"
+
 #include "compat.h"
 
 #ifdef ZIP_ALLOCATE_BUFFER
@@ -121,6 +122,9 @@ enum zip_compression_status {
 typedef enum zip_compression_status zip_compression_status_t;
 
 struct zip_compression_algorithm {
+    /* Return maxiumum compressed size for uncompressed data of given size. */
+    zip_uint64_t (*maximum_compressed_size)(zip_uint64_t uncompressed_size);
+
     /* called once to create new context */
     void *(*allocate)(zip_uint16_t method, int compression_flags, zip_error_t *error);
     /* called once to free context */
@@ -132,7 +136,7 @@ struct zip_compression_algorithm {
     zip_uint8_t version_needed;
 
     /* start processing */
-    bool (*start)(void *ctx);
+    bool (*start)(void *ctx, zip_stat_t *st, zip_file_attributes_t *attributes);
     /* stop processing */
     bool (*end)(void *ctx);
 
@@ -153,7 +157,10 @@ extern zip_compression_algorithm_t zip_algorithm_deflate_compress;
 extern zip_compression_algorithm_t zip_algorithm_deflate_decompress;
 extern zip_compression_algorithm_t zip_algorithm_xz_compress;
 extern zip_compression_algorithm_t zip_algorithm_xz_decompress;
+extern zip_compression_algorithm_t zip_algorithm_zstd_compress;
+extern zip_compression_algorithm_t zip_algorithm_zstd_decompress;
 
+zip_compression_algorithm_t *_zip_get_compression_algorithm(zip_int32_t method, bool compress);
 
 /* This API is not final yet, but we need it internally, so it's private for now. */
 
@@ -165,7 +172,7 @@ const zip_uint8_t *zip_get_extra_field_by_id(zip_t *, int, int, zip_uint16_t, in
 
 typedef zip_int64_t (*zip_source_layered_callback)(zip_source_t *, void *, void *, zip_uint64_t, enum zip_source_cmd);
 zip_source_t *zip_source_compress(zip_t *za, zip_source_t *src, zip_int32_t cm, int compression_flags);
-zip_source_t *zip_source_crc(zip_t *, zip_source_t *, int);
+zip_source_t *zip_source_crc_create(zip_source_t *, int, zip_error_t *error);
 zip_source_t *zip_source_decompress(zip_t *za, zip_source_t *src, zip_int32_t cm);
 zip_source_t *zip_source_layered(zip_t *, zip_source_t *, zip_source_layered_callback, void *);
 zip_source_t *zip_source_layered_create(zip_source_t *src, zip_source_layered_callback cb, void *ud, zip_error_t *error);
@@ -173,15 +180,57 @@ zip_source_t *zip_source_pkware_decode(zip_t *, zip_source_t *, zip_uint16_t, in
 zip_source_t *zip_source_pkware_encode(zip_t *, zip_source_t *, zip_uint16_t, int, const char *);
 int zip_source_remove(zip_source_t *);
 zip_int64_t zip_source_supports(zip_source_t *src);
-zip_source_t *zip_source_window(zip_t *, zip_source_t *, zip_uint64_t, zip_uint64_t);
 zip_source_t *zip_source_winzip_aes_decode(zip_t *, zip_source_t *, zip_uint16_t, int, const char *);
 zip_source_t *zip_source_winzip_aes_encode(zip_t *, zip_source_t *, zip_uint16_t, int, const char *);
 zip_source_t *zip_source_buffer_with_attributes(zip_t *za, const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes);
+zip_source_t *zip_source_buffer_with_attributes_create(const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes, zip_error_t *error);
 
 /* error source for layered sources */
 
 enum zip_les { ZIP_LES_NONE, ZIP_LES_UPPER, ZIP_LES_LOWER, ZIP_LES_INVAL };
 
+#define ZIP_DETAIL_ET_GLOBAL 0
+#define ZIP_DETAIL_ET_ENTRY  1
+
+struct _zip_err_info {
+    int type;
+    const char *description;
+};
+
+extern const struct _zip_err_info _zip_err_str[];
+extern const int _zip_err_str_count;
+extern const struct _zip_err_info _zip_err_details[];
+extern const int _zip_err_details_count;
+
+/* macros for libzip-internal errors */
+#define MAX_DETAIL_INDEX 0x7fffff
+#define MAKE_DETAIL_WITH_INDEX(error, index) ((((index) > MAX_DETAIL_INDEX) ? MAX_DETAIL_INDEX : (int)(index)) << 8 | (error))
+#define GET_INDEX_FROM_DETAIL(error) (((error) >> 8) & MAX_DETAIL_INDEX)
+#define GET_ERROR_FROM_DETAIL(error) ((error) & 0xff)
+#define ADD_INDEX_TO_DETAIL(error, index) MAKE_DETAIL_WITH_INDEX(GET_ERROR_FROM_DETAIL(error), (index))
+
+/* error code for libzip-internal errors */
+#define ZIP_ER_DETAIL_NO_DETAIL 0   /* G no detail */
+#define ZIP_ER_DETAIL_CDIR_OVERLAPS_EOCD 1  /* G central directory overlaps EOCD, or there is space between them */
+#define ZIP_ER_DETAIL_COMMENT_LENGTH_INVALID 2  /* G archive comment length incorrect */
+#define ZIP_ER_DETAIL_CDIR_LENGTH_INVALID 3  /* G central directory length invalid */
+#define ZIP_ER_DETAIL_CDIR_ENTRY_INVALID 4  /* E central header invalid */
+#define ZIP_ER_DETAIL_CDIR_WRONG_ENTRIES_COUNT 5  /* G central directory count of entries is incorrect */
+#define ZIP_ER_DETAIL_ENTRY_HEADER_MISMATCH 6  /* E local and central headers do not match */
+#define ZIP_ER_DETAIL_EOCD_LENGTH_INVALID 7  /* G wrong EOCD length */
+#define ZIP_ER_DETAIL_EOCD64_OVERLAPS_EOCD 8  /* G EOCD64 overlaps EOCD, or there is space between them */
+#define ZIP_ER_DETAIL_EOCD64_WRONG_MAGIC 9  /* G EOCD64 magic incorrect */
+#define ZIP_ER_DETAIL_EOCD64_MISMATCH 10  /* G EOCD64 and EOCD do not match */
+#define ZIP_ER_DETAIL_CDIR_INVALID 11  /* G invalid value in central directory */
+#define ZIP_ER_DETAIL_VARIABLE_SIZE_OVERFLOW 12 /* E variable size fields overflow header */
+#define ZIP_ER_DETAIL_INVALID_UTF8_IN_FILENAME 13 /* E invalid UTF-8 in filename */
+#define ZIP_ER_DETAIL_INVALID_UTF8_IN_COMMENT 13 /* E invalid UTF-8 in comment */
+#define ZIP_ER_DETAIL_INVALID_ZIP64_EF 14 /* E invalid Zip64 extra field */
+#define ZIP_ER_DETAIL_INVALID_WINZIPAES_EF 14 /* E invalid WinZip AES extra field */
+#define ZIP_ER_DETAIL_EF_TRAILING_GARBAGE 15 /* E garbage at end of extra fields */
+#define ZIP_ER_DETAIL_INVALID_EF_LENGTH 16 /* E extra field length is invalid */
+#define ZIP_ER_DETAIL_INVALID_FILE_LENGTH 17 /* E file length in header doesn't match actual file length */
+
 /* directory entry: general purpose bit flags */
 
 #define ZIP_GPBF_ENCRYPTED 0x0001u         /* is encrypted */
@@ -334,8 +383,8 @@ typedef enum zip_source_write_state zip_source_write_state_t;
 struct zip_source {
     zip_source_t *src;
     union {
-       zip_source_callback f;
-       zip_source_layered_callback l;
+        zip_source_callback f;
+        zip_source_layered_callback l;
     } cb;
     void *ud;
     zip_error_t error;
@@ -345,8 +394,9 @@ struct zip_source {
     bool source_closed;                   /* set if source archive is closed */
     zip_t *source_archive;                /* zip archive we're reading from, NULL if not from archive */
     unsigned int refcount;
-    bool eof;            /* EOF reached */
-    bool had_read_error; /* a previous ZIP_SOURCE_READ reported an error */
+    bool eof;                /* EOF reached */
+    bool had_read_error;     /* a previous ZIP_SOURCE_READ reported an error */
+    zip_uint64_t bytes_read; /* for sources that don't support ZIP_SOURCE_TELL. */
 };
 
 #define ZIP_SOURCE_IS_OPEN_READING(src) ((src)->open_count > 0)
@@ -419,10 +469,6 @@ struct _zip_pkware_keys {
 };
 typedef struct _zip_pkware_keys zip_pkware_keys_t;
 
-extern const char *const _zip_err_str[];
-extern const int _zip_nerr_str;
-extern const int _zip_err_type[];
-
 #define ZIP_MAX(a, b) ((a) > (b) ? (a) : (b))
 #define ZIP_MIN(a, b) ((a) < (b) ? (a) : (b))
 
@@ -561,8 +607,8 @@ bool _zip_source_had_error(zip_source_t *);
 void _zip_source_invalidate(zip_source_t *src);
 zip_source_t *_zip_source_new(zip_error_t *error);
 int _zip_source_set_source_archive(zip_source_t *, zip_t *);
-zip_source_t *_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_file_attributes_t *attributes, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error);
-zip_source_t *_zip_source_zip_new(zip_t *, zip_t *, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_uint64_t, const char *);
+zip_source_t *_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_int64_t length, zip_stat_t *st, zip_file_attributes_t *attributes, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error);
+zip_source_t *_zip_source_zip_new(zip_t *, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_uint64_t, const char *, zip_error_t *error);
 
 int _zip_stat_merge(zip_stat_t *dst, const zip_stat_t *src, zip_error_t *error);
 int _zip_string_equal(const zip_string_t *, const zip_string_t *);
index 90d462a..7f4b0ec 100644 (file)
@@ -54,6 +54,7 @@ set(MAN_PAGES
   zip_libzip_version.3
   zip_name_locate.3
   zip_open.3
+  zip_register_cancel_callback_with_state.3
   zip_register_progress_callback.3
   zip_register_progress_callback_with_state.3
   zip_rename.3
@@ -88,6 +89,7 @@ set(MAN_PAGES
   zip_source_win32a.3
   zip_source_win32handle.3
   zip_source_win32w.3
+  zip_source_window.3
   zip_source_write.3
   zip_source_zip.3
   zip_stat.3
@@ -114,7 +116,7 @@ foreach(MAN_PAGE ${MAN_PAGES})
   #configure_file(${SOURCE_FILE} ${MAN_PAGE} COPYONLY)
   add_custom_command(OUTPUT ${MAN_PAGE}
     DEPENDS ${SOURCE_FILE}
-    COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PROJECT_SOURCE_DIR}/man/${SOURCE_FILE} ${PROJECT_BINARY_DIR}/man/${MAN_PAGE}
+    COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE_FILE} ${CMAKE_CURRENT_BINARY_DIR}/${MAN_PAGE}
     COMMENT "Preparing ${MAN_PAGE}"
     )
 
@@ -123,18 +125,20 @@ foreach(MAN_PAGE ${MAN_PAGES})
   string(REGEX REPLACE "[1-9]$" "mdoc" MDOC_FILE ${MAN_PAGE})
 
   # html re-generation
-  add_custom_command(OUTPUT ${PROJECT_SOURCE_DIR}/man/${HTML_FILE}
+  add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${HTML_FILE}
     DEPENDS ${MDOC_FILE}
-    COMMAND ${CMAKE_COMMAND} -DIN=${MDOC_FILE} -DOUT=${HTML_FILE} -DDIR=${PROJECT_SOURCE_DIR}/man -P ${PROJECT_SOURCE_DIR}/man/update-html.cmake
+    COMMAND ${CMAKE_COMMAND} -DIN=${CMAKE_CURRENT_SOURCE_DIR}/${MDOC_FILE} -DOUT=${CMAKE_CURRENT_BINARY_DIR}/${HTML_FILE} -P ${CMAKE_CURRENT_SOURCE_DIR}/update-html.cmake
+    COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/${HTML_FILE} ${CMAKE_CURRENT_SOURCE_DIR}/${HTML_FILE}
     )
-  list(APPEND UPDATEHTML ${PROJECT_SOURCE_DIR}/man/${HTML_FILE})
+  list(APPEND UPDATEHTML ${CMAKE_CURRENT_BINARY_DIR}/${HTML_FILE})
 
   # man re-generation
-  add_custom_command(OUTPUT ${PROJECT_SOURCE_DIR}/man/${MAN_FILE}
+  add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${MAN_FILE}
     DEPENDS ${MDOC_FILE}
-    COMMAND ${CMAKE_COMMAND} -DIN=${MDOC_FILE} -DOUT=${MAN_FILE} -DDIR=${PROJECT_SOURCE_DIR}/man -P ${PROJECT_SOURCE_DIR}/man/update-man.cmake
+     COMMAND ${CMAKE_COMMAND} -DIN=${CMAKE_CURRENT_SOURCE_DIR}/${MDOC_FILE} -DOUT=${CMAKE_CURRENT_BINARY_DIR}/${MAN_FILE} -P ${CMAKE_CURRENT_SOURCE_DIR}/update-man.cmake
+    COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/${MAN_FILE} ${CMAKE_CURRENT_SOURCE_DIR}/${MAN_FILE}
     )
-  list(APPEND UPDATEMAN ${PROJECT_SOURCE_DIR}/man/${MAN_FILE})
+  list(APPEND UPDATEMAN ${CMAKE_CURRENT_BINARY_DIR}/${MAN_FILE})
 endforeach()
 add_custom_target(man ALL DEPENDS ${MAN_PAGES})
 add_custom_target(update-man DEPENDS ${UPDATEMAN})
index ecaf340..fabeff0 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    libzip.mdoc -- general overview of available functions
-   Copyright (C) 2005-2020 Dieter Baron and Thomas Klausner
+   Copyright (C) 2005-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
@@ -75,6 +75,18 @@ libzip (-lzip)
     original zip archive atomically.</p>
 <p class="Pp">Below there are two sections listing functions: one for how to
     read from zip archives and one for how to create/modify them.</p>
+<section class="Ss">
+<h2 class="Ss" id="THREAD_SAFETY"><a class="permalink" href="#THREAD_SAFETY">THREAD
+  SAFETY</a></h2>
+In general, different zip archives opened by <code class="Nm">libzip</code> are
+  independent of each other and can be used by parallel-running threads without
+  locking. If you want to use an archive from multiple threads, you have to
+  synchronize access to it yourself. If you use an archive as a source for
+  <a class="Xr" href="zip_file_add.html">zip_file_add(3)</a> or
+  <a class="Xr" href="zip_file_replace.html">zip_file_replace(3)</a>, access to
+  the target archive must be synchronized with access to the source archive as
+  well.
+</section>
 </section>
 <section class="Sh">
 <h1 class="Sh" id="READING_ZIP_ARCHIVES"><a class="permalink" href="#READING_ZIP_ARCHIVES">READING
@@ -214,6 +226,7 @@ libzip (-lzip)
 <ul class="Bl-bullet Bl-compact">
   <li><a class="Xr" href="zip_file_attributes_init.html">zip_file_attributes_init(3)</a></li>
   <li><a class="Xr" href="zip_libzip_version.html">zip_libzip_version(3)</a></li>
+  <li><a class="Xr" href="zip_register_cancel_callback_with_state.html">zip_register_cancel_callback_with_state(3)</a></li>
   <li><a class="Xr" href="zip_register_progress_callback_with_state.html">zip_register_progress_callback_with_state(3)</a></li>
   <li><a class="Xr" href="zip_set_archive_comment.html">zip_set_archive_comment(3)</a></li>
   <li><a class="Xr" href="zip_set_archive_flag.html">zip_set_archive_flag(3)</a></li>
@@ -228,6 +241,7 @@ libzip (-lzip)
   <li><a class="Xr" href="zip_error_strerror.html">zip_error_strerror(3)</a></li>
   <li><a class="Xr" href="zip_strerror.html">zip_strerror(3)</a></li>
   <li><a class="Xr" href="zip_file_strerror.html">zip_file_strerror(3)</a></li>
+  <li><a class="Xr" href="zip_file_get_error.html">zip_file_get_error(3)</a></li>
   <li><a class="Xr" href="zip_get_error.html">zip_get_error(3)</a></li>
   <li><a class="Xr" href="zip_error_init_with_code.html">zip_error_init_with_code(3)</a></li>
   <li><a class="Xr" href="zip_error_system_type.html">zip_error_system_type(3)</a></li>
@@ -244,7 +258,7 @@ libzip (-lzip)
 </div>
 <table class="foot">
   <tr>
-    <td class="foot-date">April 17, 2020</td>
+    <td class="foot-date">April 6, 2021</td>
     <td class="foot-os">NiH</td>
   </tr>
 </table>
index b3a2bb6..62c6bbf 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" libzip.mdoc -- general overview of available functions
-.\" Copyright (C) 2005-2020 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2005-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -30,7 +30,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.TH "LIBZIP" "3" "April 17, 2020" "NiH" "Library Functions Manual"
+.TH "LIBZIP" "3" "April 6, 2021" "NiH" "Library Functions Manual"
 .nh
 .if n .ad l
 .SH "NAME"
@@ -66,6 +66,19 @@ zip archive atomically.
 .PP
 Below there are two sections listing functions: one for how to read
 from zip archives and one for how to create/modify them.
+.SS "THREAD SAFETY"
+In general, different zip archives opened by
+\fBlibzip\fR
+are independent of each other and can be used by parallel-running
+threads without locking.
+If you want to use an archive from multiple threads, you have to
+synchronize access to it yourself.
+If you use an archive as a source for
+zip_file_add(3)
+or
+zip_file_replace(3),
+access to the target archive must be synchronized with access to the
+source archive as well.
 .SH "READING ZIP ARCHIVES"
 .SS "open archive"
 .TP 4n
@@ -262,6 +275,9 @@ zip_file_attributes_init(3)
 zip_libzip_version(3)
 .TP 4n
 \fB\(bu\fR
+zip_register_cancel_callback_with_state(3)
+.TP 4n
+\fB\(bu\fR
 zip_register_progress_callback_with_state(3)
 .TP 4n
 \fB\(bu\fR
@@ -286,6 +302,9 @@ zip_strerror(3)
 zip_file_strerror(3)
 .TP 4n
 \fB\(bu\fR
+zip_file_get_error(3)
+.TP 4n
+\fB\(bu\fR
 zip_get_error(3)
 .TP 4n
 \fB\(bu\fR
index ec2fd6c..8799d30 100644 (file)
@@ -1,5 +1,5 @@
 .\" libzip.mdoc -- general overview of available functions
-.\" Copyright (C) 2005-2020 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2005-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -29,7 +29,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd April 17, 2020
+.Dd April 6, 2021
 .Dt LIBZIP 3
 .Os
 .Sh NAME
@@ -62,6 +62,19 @@ zip archive atomically.
 .Pp
 Below there are two sections listing functions: one for how to read
 from zip archives and one for how to create/modify them.
+.Ss THREAD SAFETY
+In general, different zip archives opened by
+.Nm
+are independent of each other and can be used by parallel-running
+threads without locking.
+If you want to use an archive from multiple threads, you have to
+synchronize access to it yourself.
+If you use an archive as a source for
+.Xr zip_file_add 3
+or
+.Xr zip_file_replace 3 ,
+access to the target archive must be synchronized with access to the
+source archive as well.
 .Sh READING ZIP ARCHIVES
 .Ss open archive
 .Bl -bullet -compact
@@ -213,6 +226,8 @@ from zip archives and one for how to create/modify them.
 .It
 .Xr zip_libzip_version 3
 .It
+.Xr zip_register_cancel_callback_with_state 3
+.It
 .Xr zip_register_progress_callback_with_state 3
 .It
 .Xr zip_set_archive_comment 3
@@ -230,6 +245,8 @@ from zip archives and one for how to create/modify them.
 .It
 .Xr zip_file_strerror 3
 .It
+.Xr zip_file_get_error 3
+.It
 .Xr zip_get_error 3
 .It
 .Xr zip_error_init_with_code 3
index 82cacce..4bc469b 100644 (file)
@@ -1,12 +1,12 @@
-# expect variables IN, OUT, and DIR
-EXECUTE_PROCESS(COMMAND mandoc -T html -Oman=%N.html,style=../nih-man.css ${DIR}/${IN}
+# expect variables IN and OUT
+EXECUTE_PROCESS(COMMAND mandoc -T html -Oman=%N.html,style=../nih-man.css ${IN}
   OUTPUT_VARIABLE HTML)
 SET(LINKBASE "http://pubs.opengroup.org/onlinepubs/9699919799/functions/")
 STRING(REGEX REPLACE "(<a class=\"Xr\" href=\")([^\"]*)(\">)" "\\1${LINKBASE}\\2\\3" HTML "${HTML}")
 STRING(REGEX REPLACE "${LINKBASE}(libzip|zip)" "\\1" HTML "${HTML}")
 STRING(REGEX REPLACE "NetBSD [0-9.]*" "NiH" HTML "${HTML}")
-FILE(WRITE ${DIR}/${OUT}.new "${HTML}")
-CONFIGURE_FILE(${DIR}/${OUT}.new ${DIR}/${OUT} COPYONLY)
-FILE(REMOVE ${DIR}/${OUT}.new)
+FILE(WRITE ${OUT}.new "${HTML}")
+CONFIGURE_FILE(${OUT}.new ${OUT} COPYONLY)
+FILE(REMOVE ${OUT}.new)
 
 
index 4254711..3f915d6 100644 (file)
@@ -1,7 +1,7 @@
-# expect variables IN, OUT, and DIR
-EXECUTE_PROCESS(COMMAND mandoc -T man ${DIR}/${IN} OUTPUT_VARIABLE MAN)
+# expect variables IN and OUT
+EXECUTE_PROCESS(COMMAND mandoc -T man ${IN} OUTPUT_VARIABLE MAN)
 STRING(REGEX REPLACE "NetBSD [0-9.]*" "NiH" MAN "${MAN}")
-FILE(WRITE ${DIR}/${OUT}.new "${MAN}")
-CONFIGURE_FILE(${DIR}/${OUT}.new ${DIR}/${OUT} COPYONLY)
-FILE(REMOVE ${DIR}/${OUT}.new)
+FILE(WRITE ${OUT}.new "${MAN}")
+CONFIGURE_FILE(${OUT}.new ${OUT} COPYONLY)
+FILE(REMOVE ${OUT}.new)
 
index d8c1858..585ccbe 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_close.mdoc -- close zip archive
-   Copyright (C) 2003-2019 Dieter Baron and Thomas Klausner
+   Copyright (C) 2003-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
@@ -72,6 +72,11 @@ The <code class="Fn">zip_close</code>() function writes any changes made to
   <var class="Ar">archive</var> is left unchanged and must still be freed.
 <p class="Pp">To close and free a zip archive without saving changes, use
     <a class="Xr" href="zip_discard.html">zip_discard(3)</a>.</p>
+<p class="Pp">Progress updates for GUIs can be implemented using
+    <a class="Xr" href="zip_register_progress_callback_with_state.html">zip_register_progress_callback_with_state(3)</a>.
+    Cancelling the write of an archive during <code class="Nm">zip_close</code>
+    can be implemented using
+    <a class="Xr" href="zip_register_cancel_callback_with_state.html">zip_register_cancel_callback_with_state(3)</a>.</p>
 </section>
 <section class="Sh">
 <h1 class="Sh" id="RETURN_VALUES"><a class="permalink" href="#RETURN_VALUES">RETURN
@@ -120,6 +125,7 @@ Additionally, any errors returned by the callback function for added or replaced
   <a class="Xr" href="zip_fdopen.html">zip_fdopen(3)</a>,
   <a class="Xr" href="zip_get_error.html">zip_get_error(3)</a>,
   <a class="Xr" href="zip_open.html">zip_open(3)</a>,
+  <a class="Xr" href="zip_register_cancel_callback_with_state.html">zip_register_cancel_callback_with_state(3)</a>,
   <a class="Xr" href="zip_register_progress_callback_with_state.html">zip_register_progress_callback_with_state(3)</a>,
   <a class="Xr" href="zip_strerror.html">zip_strerror(3)</a>
 </section>
@@ -137,7 +143,7 @@ Additionally, any errors returned by the callback function for added or replaced
 </div>
 <table class="foot">
   <tr>
-    <td class="foot-date">September 17, 2019</td>
+    <td class="foot-date">April 6, 2021</td>
     <td class="foot-os">NiH</td>
   </tr>
 </table>
index a5264eb..7bccb20 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_close.mdoc -- close zip archive
-.\" Copyright (C) 2003-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2003-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -30,7 +30,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.TH "ZIP_CLOSE" "3" "September 17, 2019" "NiH" "Library Functions Manual"
+.TH "ZIP_CLOSE" "3" "April 6, 2021" "NiH" "Library Functions Manual"
 .nh
 .if n .ad l
 .SH "NAME"
@@ -66,6 +66,13 @@ is left unchanged and must still be freed.
 .PP
 To close and free a zip archive without saving changes, use
 zip_discard(3).
+.PP
+Progress updates for GUIs can be implemented using
+zip_register_progress_callback_with_state(3).
+Cancelling the write of an archive during
+\fBzip_close\fR
+can be implemented using
+zip_register_cancel_callback_with_state(3).
 .SH "RETURN VALUES"
 Upon successful completion 0 is returned.
 Otherwise, \-1 is returned and the error code in
@@ -123,6 +130,7 @@ zip_discard(3),
 zip_fdopen(3),
 zip_get_error(3),
 zip_open(3),
+zip_register_cancel_callback_with_state(3),
 zip_register_progress_callback_with_state(3),
 zip_strerror(3)
 .SH "HISTORY"
index b5bfd21..c6239c0 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_close.mdoc -- close zip archive
-.\" Copyright (C) 2003-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2003-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -29,7 +29,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd September 17, 2019
+.Dd April 6, 2021
 .Dt ZIP_CLOSE 3
 .Os
 .Sh NAME
@@ -60,6 +60,13 @@ is left unchanged and must still be freed.
 .Pp
 To close and free a zip archive without saving changes, use
 .Xr zip_discard 3 .
+.Pp
+Progress updates for GUIs can be implemented using
+.Xr zip_register_progress_callback_with_state 3 .
+Cancelling the write of an archive during
+.Nm
+can be implemented using
+.Xr zip_register_cancel_callback_with_state 3 .
 .Sh RETURN VALUES
 Upon successful completion 0 is returned.
 Otherwise, \-1 is returned and the error code in
@@ -105,6 +112,7 @@ for added or replaced files will be passed back.
 .Xr zip_fdopen 3 ,
 .Xr zip_get_error 3 ,
 .Xr zip_open 3 ,
+.Xr zip_register_cancel_callback_with_state 3 ,
 .Xr zip_register_progress_callback_with_state 3 ,
 .Xr zip_strerror 3
 .Sh HISTORY
index fb2b0e4..e297326 100644 (file)
@@ -77,7 +77,8 @@ The function <code class="Fn">zip_dir_add</code>() adds a directory to a zip
     any of:</p>
 <dl class="Bl-tag">
   <dt><a class="permalink" href="#ZIP_FL_ENC_GUESS"><code class="Dv" id="ZIP_FL_ENC_GUESS">ZIP_FL_ENC_GUESS</code></a></dt>
-  <dd>Guess encoding of <var class="Ar">name</var> (default).</dd>
+  <dd>Guess encoding of <var class="Ar">name</var> (default). (Only CP-437 and
+      UTF-8 are recognized.)</dd>
   <dt><a class="permalink" href="#ZIP_FL_ENC_UTF_8"><code class="Dv" id="ZIP_FL_ENC_UTF_8">ZIP_FL_ENC_UTF_8</code></a></dt>
   <dd>Interpret <var class="Ar">name</var> as UTF-8.</dd>
   <dt><a class="permalink" href="#ZIP_FL_ENC_CP437"><code class="Dv" id="ZIP_FL_ENC_CP437">ZIP_FL_ENC_CP437</code></a></dt>
@@ -125,7 +126,7 @@ Upon successful completion, the index of the new entry in the archive is
 </div>
 <table class="foot">
   <tr>
-    <td class="foot-date">April 25, 2020</td>
+    <td class="foot-date">September 20, 2020</td>
     <td class="foot-os">NiH</td>
   </tr>
 </table>
index d6a3d5a..4c863fe 100644 (file)
@@ -30,7 +30,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.TH "ZIP_DIR_ADD" "3" "April 25, 2020" "NiH" "Library Functions Manual"
+.TH "ZIP_DIR_ADD" "3" "September 20, 2020" "NiH" "Library Functions Manual"
 .nh
 .if n .ad l
 .SH "NAME"
@@ -68,6 +68,7 @@ argument can be any of:
 Guess encoding of
 \fIname\fR
 (default).
+(Only CP-437 and UTF-8 are recognized.)
 .TP 22n
 \fRZIP_FL_ENC_UTF_8\fR
 Interpret
index 023ace9..01e0a22 100644 (file)
@@ -29,7 +29,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd April 25, 2020
+.Dd September 20, 2020
 .Dt ZIP_DIR_ADD 3
 .Os
 .Sh NAME
@@ -62,6 +62,7 @@ argument can be any of:
 Guess encoding of
 .Ar name
 (default).
+(Only CP-437 and UTF-8 are recognized.)
 .It Dv ZIP_FL_ENC_UTF_8
 Interpret
 .Ar name
index 8d91d62..7f9350c 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_error_clear.mdoc -- clear error state for archive or file
-   Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
+   Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
index 5ccda3f..650a36b 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_error_clear.mdoc -- clear error state for archive or file
-.\" Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index ebb157a..c322630 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_error_clear.mdoc -- clear error state for archive or file
-.\" Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index b9bd08f..b1d87e7 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_error_set.mdoc -- set zip_error
-   Copyright (C) 2014-2017 Dieter Baron and Thomas Klausner
+   Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
index 9bc4cb8..0908d1e 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_error_set.mdoc -- set zip_error
-.\" Copyright (C) 2014-2017 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index 6a6833e..68e81f3 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_error_set.mdoc -- set zip_error
-.\" Copyright (C) 2014-2017 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index e7ad240..d7c25d2 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_errors.mdoc -- list of all libzip error codes
-   Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+   Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
index ba9ae9b..353c23b 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_errors.mdoc -- list of all libzip error codes
-.\" Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index a35890c..5c1d8fd 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_errors.mdoc -- list of all libzip error codes
-.\" Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index 7cbb6ad..f3b84eb 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_fdopen.mdoc -- open zip archive using existing file descriptor
-   Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
+   Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
index 359e5ce..075a649 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_fdopen.mdoc -- open zip archive using existing file descriptor
-.\" Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index 8921125..0db086e 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_fdopen.mdoc -- open zip archive using existing file descriptor
-.\" Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index 2078332..c702ac2 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_file_add.mdoc -- add files to zip archive
-   Copyright (C) 2004-2019 Dieter Baron and Thomas Klausner
+   Copyright (C) 2004-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
@@ -91,7 +91,8 @@ The function <code class="Fn">zip_file_add</code>() adds a file to a zip
   <dd>Overwrite any existing file of the same name. For
       <code class="Nm">zip_file_add</code> only.</dd>
   <dt><a class="permalink" href="#ZIP_FL_ENC_GUESS"><code class="Dv" id="ZIP_FL_ENC_GUESS">ZIP_FL_ENC_GUESS</code></a></dt>
-  <dd>Guess encoding of <var class="Ar">name</var> (default).</dd>
+  <dd>Guess encoding of <var class="Ar">name</var> (default). (Only CP-437 and
+      UTF-8 are recognized.)</dd>
   <dt><a class="permalink" href="#ZIP_FL_ENC_UTF_8"><code class="Dv" id="ZIP_FL_ENC_UTF_8">ZIP_FL_ENC_UTF_8</code></a></dt>
   <dd>Interpret <var class="Ar">name</var> as UTF-8.</dd>
   <dt><a class="permalink" href="#ZIP_FL_ENC_CP437"><code class="Dv" id="ZIP_FL_ENC_CP437">ZIP_FL_ENC_CP437</code></a></dt>
@@ -119,7 +120,7 @@ Upon successful completion, <code class="Fn">zip_file_add</code>() returns the
 <div class="Bd Bd-indent">
 <pre>
 zip_source_t *s;
-const char *buf=&quot;teststring&quot;;
+const char buf[]=&quot;teststring&quot;;
 
 if ((s=zip_source_buffer(archive, buf, sizeof(buf), 0)) == NULL ||
     zip_file_add(archive, name, s, ZIP_FL_ENC_UTF_8) &lt; 0) {
@@ -169,7 +170,7 @@ if ((s=zip_source_buffer(archive, buf, sizeof(buf), 0)) == NULL ||
 </div>
 <table class="foot">
   <tr>
-    <td class="foot-date">December 18, 2017</td>
+    <td class="foot-date">September 22, 2020</td>
     <td class="foot-os">NiH</td>
   </tr>
 </table>
index 4a59589..c27f3cd 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_file_add.mdoc -- add files to zip archive
-.\" Copyright (C) 2004-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2004-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -30,7 +30,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.TH "ZIP_FILE_ADD" "3" "December 18, 2017" "NiH" "Library Functions Manual"
+.TH "ZIP_FILE_ADD" "3" "September 22, 2020" "NiH" "Library Functions Manual"
 .nh
 .if n .ad l
 .SH "NAME"
@@ -88,6 +88,7 @@ only.
 Guess encoding of
 \fIname\fR
 (default).
+(Only CP-437 and UTF-8 are recognized.)
 .TP 22n
 \fRZIP_FL_ENC_UTF_8\fR
 Interpret
@@ -128,7 +129,7 @@ is set to indicate the error.
 .nf
 .RS 6n
 zip_source_t *s;
-const char *buf="teststring";
+const char buf[]="teststring";
 
 if ((s=zip_source_buffer(archive, buf, sizeof(buf), 0)) == NULL ||
     zip_file_add(archive, name, s, ZIP_FL_ENC_UTF_8) < 0) {
index 4a3e3b0..4c29e27 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_file_add.mdoc -- add files to zip archive
-.\" Copyright (C) 2004-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2004-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -29,7 +29,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd December 18, 2017
+.Dd September 22, 2020
 .Dt ZIP_FILE_ADD 3
 .Os
 .Sh NAME
@@ -76,6 +76,7 @@ only.
 Guess encoding of
 .Ar name
 (default).
+(Only CP-437 and UTF-8 are recognized.)
 .It Dv ZIP_FL_ENC_UTF_8
 Interpret
 .Ar name
@@ -111,7 +112,7 @@ is set to indicate the error.
 .Sh EXAMPLES
 .Bd -literal -offset indent
 zip_source_t *s;
-const char *buf="teststring";
+const char buf[]="teststring";
 
 if ((s=zip_source_buffer(archive, buf, sizeof(buf), 0)) == NULL ||
     zip_file_add(archive, name, s, ZIP_FL_ENC_UTF_8) < 0) {
index 59fdad6..4b95548 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_file_get_comment.mdoc -- get comment for file in zip
-   Copyright (C) 2006-2017 Dieter Baron and Thomas Klausner
+   Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP files.
    The authors can be contacted at <libzip@nih.at>
@@ -86,7 +86,8 @@ The <code class="Fn">zip_file_get_comment</code>() function returns the comment
   <dd>Return the unmodified comment as it is in the ZIP archive.</dd>
   <dt><a class="permalink" href="#ZIP_FL_ENC_GUESS"><code class="Dv" id="ZIP_FL_ENC_GUESS">ZIP_FL_ENC_GUESS</code></a></dt>
   <dd>(Default.) Guess the encoding of the comment in the ZIP archive and
-      convert it to UTF-8, if necessary.</dd>
+      convert it to UTF-8, if necessary. (Only CP-437 and UTF-8 are
+    recognized.)</dd>
   <dt><a class="permalink" href="#ZIP_FL_ENC_STRICT"><code class="Dv" id="ZIP_FL_ENC_STRICT">ZIP_FL_ENC_STRICT</code></a></dt>
   <dd>Follow the ZIP specification for file names and extend it to file
       comments, expecting them to be encoded in CP-437 in the ZIP archive
@@ -134,7 +135,7 @@ Upon successful completion, a pointer to the comment is returned, or
 </div>
 <table class="foot">
   <tr>
-    <td class="foot-date">December 18, 2017</td>
+    <td class="foot-date">September 22, 2020</td>
     <td class="foot-os">NiH</td>
   </tr>
 </table>
index 248f4f6..cdaa5c6 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_file_get_comment.mdoc -- get comment for file in zip
-.\" Copyright (C) 2006-2017 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP files.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -30,7 +30,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.TH "ZIP_FILE_GET_COMMENT" "3" "December 18, 2017" "NiH" "Library Functions Manual"
+.TH "ZIP_FILE_GET_COMMENT" "3" "September 22, 2020" "NiH" "Library Functions Manual"
 .nh
 .if n .ad l
 .SH "NAME"
@@ -85,6 +85,7 @@ Return the unmodified comment as it is in the ZIP archive.
 (Default.)
 Guess the encoding of the comment in the ZIP archive and convert it
 to UTF-8, if necessary.
+(Only CP-437 and UTF-8 are recognized.)
 .TP 21n
 \fRZIP_FL_ENC_STRICT\fR
 Follow the ZIP specification for file names and extend it to file
index 7243282..a554f13 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_file_get_comment.mdoc -- get comment for file in zip
-.\" Copyright (C) 2006-2017 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP files.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -29,7 +29,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd December 18, 2017
+.Dd September 22, 2020
 .Dt ZIP_FILE_GET_COMMENT 3
 .Os
 .Sh NAME
@@ -77,6 +77,7 @@ Return the unmodified comment as it is in the ZIP archive.
 (Default.)
 Guess the encoding of the comment in the ZIP archive and convert it
 to UTF-8, if necessary.
+(Only CP-437 and UTF-8 are recognized.)
 .It Dv ZIP_FL_ENC_STRICT
 Follow the ZIP specification for file names and extend it to file
 comments, expecting them to be encoded in CP-437 in the ZIP archive
index 804e71c..c4d2aa9 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_file_rename.mdoc -- rename file in zip archive
-   Copyright (C) 2003-2019 Dieter Baron and Thomas Klausner
+   Copyright (C) 2003-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
@@ -73,7 +73,8 @@ The file at position <var class="Ar">index</var> in the zip archive
   <var class="Ar">flags</var> argument can be any of:
 <dl class="Bl-tag">
   <dt><a class="permalink" href="#ZIP_FL_ENC_GUESS"><code class="Dv" id="ZIP_FL_ENC_GUESS">ZIP_FL_ENC_GUESS</code></a></dt>
-  <dd>Guess encoding of <var class="Ar">name</var> (default).</dd>
+  <dd>Guess encoding of <var class="Ar">name</var> (default). (Only CP-437 and
+      UTF-8 are recognized.)</dd>
   <dt><a class="permalink" href="#ZIP_FL_ENC_UTF_8"><code class="Dv" id="ZIP_FL_ENC_UTF_8">ZIP_FL_ENC_UTF_8</code></a></dt>
   <dd>Interpret <var class="Ar">name</var> as UTF-8.</dd>
   <dt><a class="permalink" href="#ZIP_FL_ENC_CP437"><code class="Dv" id="ZIP_FL_ENC_CP437">ZIP_FL_ENC_CP437</code></a></dt>
@@ -123,7 +124,7 @@ Upon successful completion 0 is returned. Otherwise, -1 is returned and the
 </div>
 <table class="foot">
   <tr>
-    <td class="foot-date">December 18, 2017</td>
+    <td class="foot-date">September 22, 2020</td>
     <td class="foot-os">NiH</td>
   </tr>
 </table>
index 92a3771..4dc57f0 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_file_rename.mdoc -- rename file in zip archive
-.\" Copyright (C) 2003-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2003-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -30,7 +30,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.TH "ZIP_FILE_RENAME" "3" "December 18, 2017" "NiH" "Library Functions Manual"
+.TH "ZIP_FILE_RENAME" "3" "September 22, 2020" "NiH" "Library Functions Manual"
 .nh
 .if n .ad l
 .SH "NAME"
@@ -62,6 +62,7 @@ argument can be any of:
 Guess encoding of
 \fIname\fR
 (default).
+(Only CP-437 and UTF-8 are recognized.)
 .TP 22n
 \fRZIP_FL_ENC_UTF_8\fR
 Interpret
index d1a23d1..a14fe66 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_file_rename.mdoc -- rename file in zip archive
-.\" Copyright (C) 2003-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2003-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -29,7 +29,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd December 18, 2017
+.Dd September 22, 2020
 .Dt ZIP_FILE_RENAME 3
 .Os
 .Sh NAME
@@ -56,6 +56,7 @@ argument can be any of:
 Guess encoding of
 .Ar name
 (default).
+(Only CP-437 and UTF-8 are recognized.)
 .It Dv ZIP_FL_ENC_UTF_8
 Interpret
 .Ar name
index 844ca04..5277baa 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_file_set_comment.mdoc -- set comment for file in zip
-   Copyright (C) 2006-2017 Dieter Baron and Thomas Klausner
+   Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP files.
    The authors can be contacted at <libzip@nih.at>
@@ -77,7 +77,8 @@ The <code class="Fn">zip_file_set_comment</code>() function sets the comment for
   <var class="Ar">flags</var> argument can be any of:
 <dl class="Bl-tag">
   <dt><a class="permalink" href="#ZIP_FL_ENC_GUESS"><code class="Dv" id="ZIP_FL_ENC_GUESS">ZIP_FL_ENC_GUESS</code></a></dt>
-  <dd>Guess encoding of <var class="Ar">comment</var> (default).</dd>
+  <dd>Guess encoding of <var class="Ar">comment</var> (default). (Only CP-437
+      and UTF-8 are recognized.)</dd>
   <dt><a class="permalink" href="#ZIP_FL_ENC_UTF_8"><code class="Dv" id="ZIP_FL_ENC_UTF_8">ZIP_FL_ENC_UTF_8</code></a></dt>
   <dd>Interpret <var class="Ar">comment</var> as UTF-8.</dd>
   <dt><a class="permalink" href="#ZIP_FL_ENC_CP437"><code class="Dv" id="ZIP_FL_ENC_CP437">ZIP_FL_ENC_CP437</code></a></dt>
@@ -128,7 +129,7 @@ Upon successful completion 0 is returned. Otherwise, -1 is returned and the
 </div>
 <table class="foot">
   <tr>
-    <td class="foot-date">December 18, 2017</td>
+    <td class="foot-date">September 22, 2020</td>
     <td class="foot-os">NiH</td>
   </tr>
 </table>
index b1425ca..2b019c4 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_file_set_comment.mdoc -- set comment for file in zip
-.\" Copyright (C) 2006-2017 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP files.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -30,7 +30,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.TH "ZIP_FILE_SET_COMMENT" "3" "December 18, 2017" "NiH" "Library Functions Manual"
+.TH "ZIP_FILE_SET_COMMENT" "3" "September 22, 2020" "NiH" "Library Functions Manual"
 .nh
 .if n .ad l
 .SH "NAME"
@@ -71,6 +71,7 @@ argument can be any of:
 Guess encoding of
 \fIcomment\fR
 (default).
+(Only CP-437 and UTF-8 are recognized.)
 .TP 22n
 \fRZIP_FL_ENC_UTF_8\fR
 Interpret
index 1e596cf..4328aac 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_file_set_comment.mdoc -- set comment for file in zip
-.\" Copyright (C) 2006-2017 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP files.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -29,7 +29,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd December 18, 2017
+.Dd September 22, 2020
 .Dt ZIP_FILE_SET_COMMENT 3
 .Os
 .Sh NAME
@@ -65,6 +65,7 @@ argument can be any of:
 Guess encoding of
 .Ar comment
 (default).
+(Only CP-437 and UTF-8 are recognized.)
 .It Dv ZIP_FL_ENC_UTF_8
 Interpret
 .Ar comment
index a64d5e0..bcf453a 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_file_set_encryption.mdoc -- set encryption method for file
-   Copyright (C) 2016-2017 Dieter Baron and Thomas Klausner
+   Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP files.
    The authors can be contacted at <libzip@nih.at>
index da983f9..a6414e4 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_file_set_encryption.mdoc -- set encryption method for file
-.\" Copyright (C) 2016-2017 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP files.
 .\" The authors can be contacted at <libzip@nih.at>
index afc1168..2bfd971 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_file_set_encryption.mdoc -- set encryption method for file
-.\" Copyright (C) 2016-2017 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP files.
 .\" The authors can be contacted at <libzip@nih.at>
index f20a35b..c7b479d 100644 (file)
@@ -88,22 +88,22 @@ The <code class="Fn">zip_file_set_mtime</code>() function sets the last
 <div class="Bd-indent">
 <dl class="Bl-tag">
   <dt>0-4</dt>
-  <dd>day of the month (1-31)</dd>
-  <dt>5-8</dt>
-  <dd>month (January = 1, February = 2, ...)</dd>
-  <dt>9-15</dt>
-  <dd>year offset from 1980 (1980 = 0, 1981 = 1, ...)</dd>
+  <dd>seconds divided by two (1-2 = 1, 3-4 = 2, ...)</dd>
+  <dt>5-10</dt>
+  <dd>minute (0-59)</dd>
+  <dt>11-15</dt>
+  <dd>hour (0-23)</dd>
 </dl>
 </div>
 <p class="Pp">The values of the date bytes are defined as follows:</p>
 <div class="Bd-indent">
 <dl class="Bl-tag">
   <dt>0-4</dt>
-  <dd>seconds divided by two (1-2 = 1, 3-4 = 2, ...)</dd>
-  <dt>5-10</dt>
-  <dd>minute (0-59)</dd>
-  <dt>11-15</dt>
-  <dd>hour (0-23)</dd>
+  <dd>day of the month (1-31)</dd>
+  <dt>5-8</dt>
+  <dd>month (January = 1, February = 2, ...)</dd>
+  <dt>9-15</dt>
+  <dd>year offset from 1980 (1980 = 0, 1981 = 1, ...)</dd>
 </dl>
 </div>
 </section>
@@ -156,7 +156,7 @@ Following historical practice, the <code class="Fn">zip_file_set_mtime</code>()
 </div>
 <table class="foot">
   <tr>
-    <td class="foot-date">January 7, 2020</td>
+    <td class="foot-date">August 24, 2020</td>
     <td class="foot-os">NiH</td>
   </tr>
 </table>
index 48dc132..d3928bc 100644 (file)
@@ -30,7 +30,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.TH "ZIP_FILE_SET_MTIME" "3" "January 7, 2020" "NiH" "Library Functions Manual"
+.TH "ZIP_FILE_SET_MTIME" "3" "August 24, 2020" "NiH" "Library Functions Manual"
 .nh
 .if n .ad l
 .SH "NAME"
@@ -75,26 +75,26 @@ The values of the time bytes are defined as follows:
 .RS 6n
 .TP 7n
 0-4
-day of the month (1-31)
+seconds divided by two (1-2 = 1, 3-4 = 2, ...)
 .TP 7n
-5-8
-month (January = 1, February = 2, ...)
+5-10
+minute (0-59)
 .TP 7n
-9-15
-year offset from 1980 (1980 = 0, 1981 = 1, ...)
+11-15
+hour (0-23)
 .RE
 .PP
 The values of the date bytes are defined as follows:
 .RS 6n
 .TP 7n
 0-4
-seconds divided by two (1-2 = 1, 3-4 = 2, ...)
+day of the month (1-31)
 .TP 7n
-5-10
-minute (0-59)
+5-8
+month (January = 1, February = 2, ...)
 .TP 7n
-11-15
-hour (0-23)
+9-15
+year offset from 1980 (1980 = 0, 1981 = 1, ...)
 .RE
 .SH "RETURN VALUES"
 Upon successful completion 0 is returned.
index e024e24..f47c6b1 100644 (file)
@@ -29,7 +29,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd January 7, 2020
+.Dd August 24, 2020
 .Dt ZIP_FILE_SET_MTIME 3
 .Os
 .Sh NAME
@@ -63,22 +63,22 @@ function.
 The values of the time bytes are defined as follows:
 .Bl -tag -width 5n -offset indent
 .It 0-4
-day of the month (1-31)
-.It 5-8
-month (January = 1, February = 2, ...)
-.It 9-15
-year offset from 1980 (1980 = 0, 1981 = 1, ...)
-.El
-.Pp
-The values of the date bytes are defined as follows:
-.Bl -tag -width 5n -offset indent
-.It 0-4
 seconds divided by two (1-2 = 1, 3-4 = 2, ...)
 .It 5-10
 minute (0-59)
 .It 11-15
 hour (0-23)
 .El
+.Pp
+The values of the date bytes are defined as follows:
+.Bl -tag -width 5n -offset indent
+.It 0-4
+day of the month (1-31)
+.It 5-8
+month (January = 1, February = 2, ...)
+.It 9-15
+year offset from 1980 (1980 = 0, 1981 = 1, ...)
+.El
 .Sh RETURN VALUES
 Upon successful completion 0 is returned.
 Otherwise, \-1 is returned and the error information in
index 019efe0..d9db6ac 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_file_strerror.mdoc -- get string representation for a zip error
-   Copyright (C) 2003-2019 Dieter Baron and Thomas Klausner
+   Copyright (C) 2003-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
index db2b16d..8ee81a1 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_file_strerror.mdoc -- get string representation for a zip error
-.\" Copyright (C) 2003-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2003-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index 7ce929d..f10073b 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_file_strerror.mdoc -- get string representation for a zip error
-.\" Copyright (C) 2003-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2003-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index 495b580..f80a3ed 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_fopen_encrypted.mdoc -- open encrypted file in zip archive for reading
-   Copyright (C) 2011-2017 Dieter Baron and Thomas Klausner
+   Copyright (C) 2011-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
@@ -78,8 +78,11 @@ libzip (-lzip)
 <h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
 The <code class="Fn">zip_fopen_encrypted</code>() function opens the encrypted
   file name <var class="Ar">fname</var> in <var class="Ar">archive</var> using
-  the password given in the <var class="Ar">password</var> argument. The
-  <var class="Ar">flags</var> argument are the same as for
+  the password given in the <var class="Ar">password</var> argument. If
+  <var class="Ar">password</var> is <code class="Dv">NULL</code> or the empty
+  string, the default password is used (see
+  <a class="Xr" href="zip_set_default_password.html">zip_set_default_password(3)</a>).
+  The <var class="Ar">flags</var> argument are the same as for
   <a class="Xr" href="zip_fopen.html">zip_fopen(3)</a>.
 <p class="Pp">The <code class="Fn">zip_fopen_index_encrypted</code>() function
     opens the file at position <var class="Ar">index</var>, see
@@ -133,10 +136,21 @@ Upon successful completion, a <var class="Ft">struct zip_file</var> pointer is
   <span class="An">Thomas Klausner</span>
   &lt;<a class="Mt" href="mailto:tk@giga.or.at">tk@giga.or.at</a>&gt;
 </section>
+<section class="Sh">
+<h1 class="Sh" id="CAVEATS"><a class="permalink" href="#CAVEATS">CAVEATS</a></h1>
+The zip file format provides very limited possibility for password verification
+  (a short hash of is compared against one byte in the zip archive). For this
+  reason, reading a file while using an incorrect password may immediately fail
+  with <code class="Er">ZIP_ER_WRONGPASSWD</code>, but if the mismatch is not
+  detected, a zlib error may be returned later instead. Since zlib errors can
+  also be caused by broken compressed data, there is no way to make sure if the
+  password was incorrect or if it was correct, but the compressed data was
+  invalid.
+</section>
 </div>
 <table class="foot">
   <tr>
-    <td class="foot-date">December 18, 2017</td>
+    <td class="foot-date">September 15, 2020</td>
     <td class="foot-os">NiH</td>
   </tr>
 </table>
index 872a3c8..8bf4e0c 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_fopen_encrypted.mdoc -- open encrypted file in zip archive for reading
-.\" Copyright (C) 2011-2017 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2011-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -30,7 +30,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.TH "ZIP_FOPEN_ENCRYPTED" "3" "December 18, 2017" "NiH" "Library Functions Manual"
+.TH "ZIP_FOPEN_ENCRYPTED" "3" "September 15, 2020" "NiH" "Library Functions Manual"
 .nh
 .if n .ad l
 .SH "NAME"
@@ -65,6 +65,12 @@ in
 using the password given in the
 \fIpassword\fR
 argument.
+If
+\fIpassword\fR
+is
+\fRNULL\fR
+or the empty string, the default password is used (see
+zip_set_default_password(3)).
 The
 \fIflags\fR
 argument are the same as for
@@ -124,3 +130,15 @@ were added in libzip 1.0.
 Dieter Baron <\fIdillo@nih.at\fR>
 and
 Thomas Klausner <\fItk@giga.or.at\fR>
+.SH "CAVEATS"
+The zip file format provides very limited possibility for password
+verification (a short hash of is compared against one byte in the zip
+archive).
+For this reason, reading a file while using an incorrect password may
+immediately fail with
+\fRZIP_ER_WRONGPASSWD\fR,
+but if the mismatch is not detected, a zlib error may be returned
+later instead.
+Since zlib errors can also be caused by broken compressed data, there
+is no way to make sure if the password was incorrect or if it was
+correct, but the compressed data was invalid.
index fb159ce..80fd4b7 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_fopen_encrypted.mdoc -- open encrypted file in zip archive for reading
-.\" Copyright (C) 2011-2017 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2011-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -29,7 +29,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd December 18, 2017
+.Dd September 15, 2020
 .Dt ZIP_FOPEN_ENCRYPTED 3
 .Os
 .Sh NAME
@@ -54,6 +54,12 @@ in
 using the password given in the
 .Ar password
 argument.
+If
+.Ar password
+is
+.Dv NULL
+or the empty string, the default password is used (see
+.Xr zip_set_default_password 3 ) .
 The
 .Ar flags
 argument are the same as for
@@ -115,3 +121,15 @@ were added in libzip 1.0.
 .An Dieter Baron Aq Mt dillo@nih.at
 and
 .An Thomas Klausner Aq Mt tk@giga.or.at
+.Sh CAVEATS
+The zip file format provides very limited possibility for password
+verification (a short hash of is compared against one byte in the zip
+archive).
+For this reason, reading a file while using an incorrect password may
+immediately fail with
+.Er ZIP_ER_WRONGPASSWD ,
+but if the mismatch is not detected, a zlib error may be returned
+later instead.
+Since zlib errors can also be caused by broken compressed data, there
+is no way to make sure if the password was incorrect or if it was
+correct, but the compressed data was invalid.
index 48faf64..cd74df9 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_ftell.mdoc -- tell position in file
-   Copyright (C) 2016-2017 Dieter Baron and Thomas Klausner
+   Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
@@ -67,8 +67,6 @@ libzip (-lzip)
 <h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
 The <code class="Fn">zip_ftell</code>() function reports the current offset in
   the file.
-<p class="Pp"><code class="Nm">zip_ftell</code> only works on uncompressed
-    (stored) data. When called on compressed data it will return an error.</p>
 </section>
 <section class="Sh">
 <h1 class="Sh" id="RETURN_VALUES"><a class="permalink" href="#RETURN_VALUES">RETURN
@@ -99,7 +97,7 @@ If successful, <code class="Nm">zip_ftell</code> returns the current file
 </div>
 <table class="foot">
   <tr>
-    <td class="foot-date">December 18, 2017</td>
+    <td class="foot-date">July 21, 2020</td>
     <td class="foot-os">NiH</td>
   </tr>
 </table>
index 9f87de8..2a441c6 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_ftell.mdoc -- tell position in file
-.\" Copyright (C) 2016-2017 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -30,7 +30,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.TH "ZIP_FTELL" "3" "December 18, 2017" "NiH" "Library Functions Manual"
+.TH "ZIP_FTELL" "3" "July 21, 2020" "NiH" "Library Functions Manual"
 .nh
 .if n .ad l
 .SH "NAME"
@@ -51,10 +51,6 @@ libzip (-lzip)
 The
 \fBzip_ftell\fR()
 function reports the current offset in the file.
-.PP
-\fBzip_ftell\fR
-only works on uncompressed (stored) data.
-When called on compressed data it will return an error.
 .SH "RETURN VALUES"
 If successful,
 \fBzip_ftell\fR
index 2638d5d..dff0eff 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_ftell.mdoc -- tell position in file
-.\" Copyright (C) 2016-2017 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -29,7 +29,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd December 18, 2017
+.Dd July 21, 2020
 .Dt ZIP_FTELL 3
 .Os
 .Sh NAME
@@ -45,10 +45,6 @@ libzip (-lzip)
 The
 .Fn zip_ftell
 function reports the current offset in the file.
-.Pp
-.Nm
-only works on uncompressed (stored) data.
-When called on compressed data it will return an error.
 .Sh RETURN VALUES
 If successful,
 .Nm
index b0fb97f..19f0596 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_get_archive_comment.mdoc -- get zip archive comment
-   Copyright (C) 2006-2018 Dieter Baron and Thomas Klausner
+   Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
@@ -85,7 +85,8 @@ The <code class="Fn">zip_get_archive_comment</code>() function returns the
   <dd>Return the unmodified archive comment as it is in the ZIP archive.</dd>
   <dt><a class="permalink" href="#ZIP_FL_ENC_GUESS"><code class="Dv" id="ZIP_FL_ENC_GUESS">ZIP_FL_ENC_GUESS</code></a></dt>
   <dd>(Default.) Guess the encoding of the archive comment in the ZIP archive
-      and convert it to UTF-8, if necessary.</dd>
+      and convert it to UTF-8, if necessary. (Only CP-437 and UTF-8 are
+      recognized.)</dd>
   <dt><a class="permalink" href="#ZIP_FL_ENC_STRICT"><code class="Dv" id="ZIP_FL_ENC_STRICT">ZIP_FL_ENC_STRICT</code></a></dt>
   <dd>Follow the ZIP specification for file names and extend it to the archive
       comment, thus also expecting it in CP-437 encoding. Convert it to
@@ -122,7 +123,7 @@ Upon successful completion, a pointer to the comment is returned, or
 </div>
 <table class="foot">
   <tr>
-    <td class="foot-date">July 22, 2018</td>
+    <td class="foot-date">September 22, 2020</td>
     <td class="foot-os">NiH</td>
   </tr>
 </table>
index 8cdfa30..6c2d99c 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_get_archive_comment.mdoc -- get zip archive comment
-.\" Copyright (C) 2006-2018 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -30,7 +30,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.TH "ZIP_GET_ARCHIVE_COMMENT" "3" "July 22, 2018" "NiH" "Library Functions Manual"
+.TH "ZIP_GET_ARCHIVE_COMMENT" "3" "September 22, 2020" "NiH" "Library Functions Manual"
 .nh
 .if n .ad l
 .SH "NAME"
@@ -83,6 +83,7 @@ Return the unmodified archive comment as it is in the ZIP archive.
 (Default.)
 Guess the encoding of the archive comment in the ZIP archive and convert it
 to UTF-8, if necessary.
+(Only CP-437 and UTF-8 are recognized.)
 .TP 21n
 \fRZIP_FL_ENC_STRICT\fR
 Follow the ZIP specification for file names and extend it to the
index ce9a01b..1e2eb7e 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_get_archive_comment.mdoc -- get zip archive comment
-.\" Copyright (C) 2006-2018 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -29,7 +29,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd July 22, 2018
+.Dd September 22, 2020
 .Dt ZIP_GET_ARCHIVE_COMMENT 3
 .Os
 .Sh NAME
@@ -75,6 +75,7 @@ Return the unmodified archive comment as it is in the ZIP archive.
 (Default.)
 Guess the encoding of the archive comment in the ZIP archive and convert it
 to UTF-8, if necessary.
+(Only CP-437 and UTF-8 are recognized.)
 .It Dv ZIP_FL_ENC_STRICT
 Follow the ZIP specification for file names and extend it to the
 archive comment, thus also expecting it in CP-437 encoding.
index e41222f..d3e747e 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_get_name.mdoc -- get name of file by index
-   Copyright (C) 2003-2017 Dieter Baron and Thomas Klausner
+   Copyright (C) 2003-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
@@ -83,7 +83,7 @@ The <code class="Fn">zip_get_name</code>() function returns the name of the file
   <dd>Return the unmodified names as it is in the ZIP archive.</dd>
   <dt><a class="permalink" href="#ZIP_FL_ENC_GUESS"><code class="Dv" id="ZIP_FL_ENC_GUESS">ZIP_FL_ENC_GUESS</code></a></dt>
   <dd>(Default.) Guess the encoding of the name in the ZIP archive and convert
-      it to UTF-8, if necessary.</dd>
+      it to UTF-8, if necessary. (Only CP-437 and UTF-8 are recognized.)</dd>
   <dt><a class="permalink" href="#ZIP_FL_ENC_STRICT"><code class="Dv" id="ZIP_FL_ENC_STRICT">ZIP_FL_ENC_STRICT</code></a></dt>
   <dd>Follow the ZIP specification and expect CP-437 encoded names in the ZIP
       archive (except if they are explicitly marked as UTF-8). Convert it to
@@ -138,7 +138,7 @@ Upon successful completion, a pointer to the name is returned. Otherwise,
 </div>
 <table class="foot">
   <tr>
-    <td class="foot-date">December 18, 2017</td>
+    <td class="foot-date">September 22, 2020</td>
     <td class="foot-os">NiH</td>
   </tr>
 </table>
index a83ca8e..9a6351e 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_get_name.mdoc -- get name of file by index
-.\" Copyright (C) 2003-2017 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2003-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -30,7 +30,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.TH "ZIP_GET_NAME" "3" "December 18, 2017" "NiH" "Library Functions Manual"
+.TH "ZIP_GET_NAME" "3" "September 22, 2020" "NiH" "Library Functions Manual"
 .nh
 .if n .ad l
 .SH "NAME"
@@ -79,6 +79,7 @@ Return the unmodified names as it is in the ZIP archive.
 (Default.)
 Guess the encoding of the name in the ZIP archive and convert it
 to UTF-8, if necessary.
+(Only CP-437 and UTF-8 are recognized.)
 .TP 21n
 \fRZIP_FL_ENC_STRICT\fR
 Follow the ZIP specification and expect CP-437 encoded names in
index 27084f4..bb1ea0a 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_get_name.mdoc -- get name of file by index
-.\" Copyright (C) 2003-2017 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2003-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -29,7 +29,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd December 18, 2017
+.Dd September 22, 2020
 .Dt ZIP_GET_NAME 3
 .Os
 .Sh NAME
@@ -71,6 +71,7 @@ Return the unmodified names as it is in the ZIP archive.
 (Default.)
 Guess the encoding of the name in the ZIP archive and convert it
 to UTF-8, if necessary.
+(Only CP-437 and UTF-8 are recognized.)
 .It Dv ZIP_FL_ENC_STRICT
 Follow the ZIP specification and expect CP-437 encoded names in
 the ZIP archive (except if they are explicitly marked as UTF-8).
index f5d38f7..5d5dba6 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_name_locate.mdoc -- get index of file by name
-   Copyright (C) 2003-2017 Dieter Baron and Thomas Klausner
+   Copyright (C) 2003-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
@@ -87,7 +87,8 @@ The <code class="Fn">zip_name_locate</code>() function returns the index of the
   <dd>Compare against the unmodified names as it is in the ZIP archive.</dd>
   <dt><a class="permalink" href="#ZIP_FL_ENC_GUESS"><code class="Dv" id="ZIP_FL_ENC_GUESS">ZIP_FL_ENC_GUESS</code></a></dt>
   <dd>(Default.) Guess the encoding of the name in the ZIP archive and convert
-      it to UTF-8, if necessary, before comparing.</dd>
+      it to UTF-8, if necessary, before comparing. (Only CP-437 and UTF-8 are
+      recognized.)</dd>
   <dt><a class="permalink" href="#ZIP_FL_ENC_STRICT"><code class="Dv" id="ZIP_FL_ENC_STRICT">ZIP_FL_ENC_STRICT</code></a></dt>
   <dd>Follow the ZIP specification and expect CP-437 encoded names in the ZIP
       archive (except if they are explicitly marked as UTF-8). Convert it to
@@ -140,7 +141,7 @@ The <code class="Fn">zip_name_locate</code>() function returns the index of the
 </div>
 <table class="foot">
   <tr>
-    <td class="foot-date">December 18, 2017</td>
+    <td class="foot-date">September 22, 2020</td>
     <td class="foot-os">NiH</td>
   </tr>
 </table>
index c8acfae..1b910b0 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_name_locate.mdoc -- get index of file by name
-.\" Copyright (C) 2003-2017 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2003-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -30,7 +30,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.TH "ZIP_NAME_LOCATE" "3" "December 18, 2017" "NiH" "Library Functions Manual"
+.TH "ZIP_NAME_LOCATE" "3" "September 22, 2020" "NiH" "Library Functions Manual"
 .nh
 .if n .ad l
 .SH "NAME"
@@ -85,6 +85,7 @@ Compare against the unmodified names as it is in the ZIP archive.
 (Default.)
 Guess the encoding of the name in the ZIP archive and convert it
 to UTF-8, if necessary, before comparing.
+(Only CP-437 and UTF-8 are recognized.)
 .TP 15n
 \fRZIP_FL_ENC_STRICT\fR
 Follow the ZIP specification and expect CP-437 encoded names in
index d16402d..6ffe5c3 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_name_locate.mdoc -- get index of file by name
-.\" Copyright (C) 2003-2017 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2003-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -29,7 +29,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd December 18, 2017
+.Dd September 22, 2020
 .Dt ZIP_NAME_LOCATE 3
 .Os
 .Sh NAME
@@ -74,6 +74,7 @@ Compare against the unmodified names as it is in the ZIP archive.
 (Default.)
 Guess the encoding of the name in the ZIP archive and convert it
 to UTF-8, if necessary, before comparing.
+(Only CP-437 and UTF-8 are recognized.)
 .It Dv ZIP_FL_ENC_STRICT
 Follow the ZIP specification and expect CP-437 encoded names in
 the ZIP archive (except if they are explicitly marked as UTF-8).
index 6670737..4edad5f 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_open.mdoc -- open zip archive
-   Copyright (C) 2003-2019 Dieter Baron and Thomas Klausner
+   Copyright (C) 2003-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
index 5bf7cb3..bdc9a9c 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_open.mdoc -- open zip archive
-.\" Copyright (C) 2003-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2003-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index 586af78..946eea3 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_open.mdoc -- open zip archive
-.\" Copyright (C) 2003-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2003-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
diff --git a/man/zip_register_cancel_callback_with_state.html b/man/zip_register_cancel_callback_with_state.html
new file mode 100644 (file)
index 0000000..5872b43
--- /dev/null
@@ -0,0 +1,121 @@
+<!DOCTYPE html>
+<html>
+<!-- This is an automatically generated file.  Do not edit.
+   zip_register_cancel_callback_with_state.mdoc -- allow cancelling during zip_close
+   Copyright (C) 2021 Dieter Baron and Thomas Klausner
+  
+   This file is part of libzip, a library to manipulate ZIP archives.
+   The authors can be contacted at <libzip@nih.at>
+  
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+   1. Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+   2. Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in
+      the documentation and/or other materials provided with the
+      distribution.
+   3. The names of the authors may not be used to endorse or promote
+      products derived from this software without specific prior
+      written permission.
+  
+   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+   IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   -->
+<head>
+  <meta charset="utf-8"/>
+  <link rel="stylesheet" href="../nih-man.css" type="text/css" media="all"/>
+  <title>ZIP_REGISTER_CANCEL_CALLBACK_WITH_STATE(3)</title>
+</head>
+<body>
+<table class="head">
+  <tr>
+    <td class="head-ltitle">ZIP_REGISTER_CANCEL_CALLBACK_WITH_STATE(3)</td>
+    <td class="head-vol">Library Functions Manual</td>
+    <td class="head-rtitle">ZIP_REGISTER_CANCEL_CALLBACK_WITH_STATE(3)</td>
+  </tr>
+</table>
+<div class="manual-text">
+<section class="Sh">
+<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
+<code class="Nm">zip_register_cancel_callback_with_state</code> &#x2014;
+<div class="Nd">allow cancelling during zip_close</div>
+</section>
+<section class="Sh">
+<h1 class="Sh" id="LIBRARY"><a class="permalink" href="#LIBRARY">LIBRARY</a></h1>
+libzip (-lzip)
+</section>
+<section class="Sh">
+<h1 class="Sh" id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">SYNOPSIS</a></h1>
+<code class="In">#include &lt;<a class="In">zip.h</a>&gt;</code>
+<p class="Pp"><var class="Vt">typedef void (*zip_cancel_callback)(zip_t *,
+    double, void *);</var></p>
+<p class="Pp"><var class="Ft">void</var>
+  <br/>
+  <code class="Fn">zip_register_cancel_callback_with_state</code>(<var class="Fa" style="white-space: nowrap;">zip_t
+    *archive</var>,
+    <var class="Fa" style="white-space: nowrap;">zip_cancel_callback
+    callback</var>, <var class="Fa" style="white-space: nowrap;">void
+    (*ud_free)(void *)</var>, <var class="Fa" style="white-space: nowrap;">void
+    *ud</var>);</p>
+</section>
+<section class="Sh">
+<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
+This function can be used to cancel writing of a zip archive during
+  <a class="Xr" href="zip_close.html">zip_close(3)</a>.
+<p class="Pp">The
+    <code class="Fn">zip_register_cancel_callback_with_state</code>() function
+    registers a callback function <var class="Ar">callback</var> for the zip
+    archive <var class="Ar">archive</var>. The <var class="Ar">ud_free</var>
+    function is called during cleanup for deleting the userdata supplied in
+    <var class="Ar">ud</var>.</p>
+<p class="Pp">The callback function is called during
+    <a class="Xr" href="zip_close.html">zip_close(3)</a> in regular intervals
+    (after every zip archive entry that's completely written to disk, and while
+    writing data for entries) with zip archive <var class="Ar">archive</var>,
+    the current progress state (see
+    <a class="Xr" href="zip_register_progress_callback_with_state.html">zip_register_progress_callback_with_state(3)</a>)
+    as a <var class="Vt">double</var>, and the user-provided user-data
+    <var class="Ar">ud</var> as arguments. The progress state is a
+    <var class="Vt">double</var> in the range from 0.0 to 1.0.</p>
+<p class="Pp">The callback function should be fast, since it will be called
+    often.</p>
+</section>
+<section class="Sh">
+<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE
+  ALSO</a></h1>
+<a class="Xr" href="libzip.html">libzip(3)</a>,
+  <a class="Xr" href="zip_close.html">zip_close(3)</a>,
+  <a class="Xr" href="zip_register_progress_callback_with_state.html">zip_register_progress_callback_with_state(3)</a>
+</section>
+<section class="Sh">
+<h1 class="Sh" id="HISTORY"><a class="permalink" href="#HISTORY">HISTORY</a></h1>
+<code class="Fn">zip_register_cancel_callback_with_state</code>() was added in
+  libzip 1.6.0.
+</section>
+<section class="Sh">
+<h1 class="Sh" id="AUTHORS"><a class="permalink" href="#AUTHORS">AUTHORS</a></h1>
+<span class="An">Dieter Baron</span>
+  &lt;<a class="Mt" href="mailto:dillo@nih.at">dillo@nih.at</a>&gt; and
+  <span class="An">Thomas Klausner</span>
+  &lt;<a class="Mt" href="mailto:tk@giga.or.at">tk@giga.or.at</a>&gt;
+</section>
+</div>
+<table class="foot">
+  <tr>
+    <td class="foot-date">April 6, 2021</td>
+    <td class="foot-os">NiH</td>
+  </tr>
+</table>
+</body>
+</html>
diff --git a/man/zip_register_cancel_callback_with_state.man b/man/zip_register_cancel_callback_with_state.man
new file mode 100644 (file)
index 0000000..7ddf69c
--- /dev/null
@@ -0,0 +1,94 @@
+.\" Automatically generated from an mdoc input file.  Do not edit.
+.\" zip_register_cancel_callback_with_state.mdoc -- allow cancelling during zip_close
+.\" Copyright (C) 2021 Dieter Baron and Thomas Klausner
+.\"
+.\" This file is part of libzip, a library to manipulate ZIP archives.
+.\" The authors can be contacted at <libzip@nih.at>
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in
+.\"    the documentation and/or other materials provided with the
+.\"    distribution.
+.\" 3. The names of the authors may not be used to endorse or promote
+.\"    products derived from this software without specific prior
+.\"    written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.TH "ZIP_REGISTER_CANCEL_CALLBACK_WITH_STATE" "3" "April 6, 2021" "NiH" "Library Functions Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBzip_register_cancel_callback_with_state\fR
+\- allow cancelling during zip_close
+.SH "LIBRARY"
+libzip (-lzip)
+.SH "SYNOPSIS"
+\fB#include <zip.h>\fR
+.sp
+\fItypedef void (*zip_cancel_callback)(zip_t *, double, void *);\fR
+.sp
+\fIvoid\fR
+.br
+.PD 0
+.HP 4n
+\fBzip_register_cancel_callback_with_state\fR(\fIzip_t\ *archive\fR, \fIzip_cancel_callback\ callback\fR, \fIvoid\ (*ud_free)(void\ *)\fR, \fIvoid\ *ud\fR);
+.PD
+.SH "DESCRIPTION"
+This function can be used to cancel writing of a zip archive during
+zip_close(3).
+.PP
+The
+\fBzip_register_cancel_callback_with_state\fR()
+function registers a callback function
+\fIcallback\fR
+for the zip archive
+\fIarchive\fR.
+The
+\fIud_free\fR
+function is called during cleanup for deleting the userdata supplied in
+\fIud\fR.
+.PP
+The callback function is called during
+zip_close(3)
+in regular intervals (after every zip archive entry that's completely
+written to disk, and while writing data for entries) with zip archive
+\fIarchive\fR,
+the current progress state (see
+zip_register_progress_callback_with_state(3))
+as a
+\fIdouble\fR,
+and the user-provided user-data
+\fIud\fR
+as arguments.
+The progress state is a
+\fIdouble\fR
+in the range from 0.0 to 1.0.
+.PP
+The callback function should be fast, since it will be called often.
+.SH "SEE ALSO"
+libzip(3),
+zip_close(3),
+zip_register_progress_callback_with_state(3)
+.SH "HISTORY"
+\fBzip_register_cancel_callback_with_state\fR()
+was added in libzip 1.6.0.
+.SH "AUTHORS"
+Dieter Baron <\fIdillo@nih.at\fR>
+and
+Thomas Klausner <\fItk@giga.or.at\fR>
diff --git a/man/zip_register_cancel_callback_with_state.mdoc b/man/zip_register_cancel_callback_with_state.mdoc
new file mode 100644 (file)
index 0000000..58fdc59
--- /dev/null
@@ -0,0 +1,88 @@
+.\" zip_register_cancel_callback_with_state.mdoc -- allow cancelling during zip_close
+.\" Copyright (C) 2021 Dieter Baron and Thomas Klausner
+.\"
+.\" This file is part of libzip, a library to manipulate ZIP archives.
+.\" The authors can be contacted at <libzip@nih.at>
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in
+.\"    the documentation and/or other materials provided with the
+.\"    distribution.
+.\" 3. The names of the authors may not be used to endorse or promote
+.\"    products derived from this software without specific prior
+.\"    written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd April 6, 2021
+.Dt ZIP_REGISTER_CANCEL_CALLBACK_WITH_STATE 3
+.Os
+.Sh NAME
+.Nm zip_register_cancel_callback_with_state
+.Nd allow cancelling during zip_close
+.Sh LIBRARY
+libzip (-lzip)
+.Sh SYNOPSIS
+.In zip.h
+.Vt typedef void (*zip_cancel_callback)(zip_t *, double, void *);
+.Ft void
+.Fn zip_register_cancel_callback_with_state "zip_t *archive" "zip_cancel_callback callback" "void (*ud_free)(void *)" "void *ud"
+.Sh DESCRIPTION
+This function can be used to cancel writing of a zip archive during
+.Xr zip_close 3 .
+.Pp
+The
+.Fn zip_register_cancel_callback_with_state
+function registers a callback function
+.Ar callback
+for the zip archive
+.Ar archive .
+The
+.Ar ud_free
+function is called during cleanup for deleting the userdata supplied in
+.Ar ud .
+.Pp
+The callback function is called during
+.Xr zip_close 3
+in regular intervals (after every zip archive entry that's completely
+written to disk, and while writing data for entries) with zip archive
+.Ar archive ,
+the current progress state (see
+.Xr zip_register_progress_callback_with_state 3 )
+as a
+.Vt double ,
+and the user-provided user-data
+.Ar ud
+as arguments.
+The progress state is a
+.Vt double
+in the range from 0.0 to 1.0.
+.Pp
+The callback function should be fast, since it will be called often.
+.Sh SEE ALSO
+.Xr libzip 3 ,
+.Xr zip_close 3 ,
+.Xr zip_register_progress_callback_with_state 3
+.Sh HISTORY
+.Fn zip_register_cancel_callback_with_state
+was added in libzip 1.6.0.
+.Sh AUTHORS
+.An -nosplit
+.An Dieter Baron Aq Mt dillo@nih.at
+and
+.An Thomas Klausner Aq Mt tk@giga.or.at
index 4faf331..b2f2bfd 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_register_progress_callback_with_state.mdoc -- provide updates during zip_close
-   Copyright (C) 2017 Dieter Baron and Thomas Klausner
+   Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
@@ -93,7 +93,8 @@ The <code class="Fn">zip_register_progress_callback_with_state</code>() function
 <h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE
   ALSO</a></h1>
 <a class="Xr" href="libzip.html">libzip(3)</a>,
-  <a class="Xr" href="zip_close.html">zip_close(3)</a>
+  <a class="Xr" href="zip_close.html">zip_close(3)</a>,
+  <a class="Xr" href="zip_register_cancel_callback_with_state.html">zip_register_cancel_callback_with_state(3)</a>
 </section>
 <section class="Sh">
 <h1 class="Sh" id="HISTORY"><a class="permalink" href="#HISTORY">HISTORY</a></h1>
index f24905b..56c912d 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_register_progress_callback_with_state.mdoc -- provide updates during zip_close
-.\" Copyright (C) 2017 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -82,7 +82,8 @@ in the range from 0.0 to 1.0.
 This can be used to provide progress indicators for user interfaces.
 .SH "SEE ALSO"
 libzip(3),
-zip_close(3)
+zip_close(3),
+zip_register_cancel_callback_with_state(3)
 .SH "HISTORY"
 \fBzip_register_progress_callback_with_state\fR()
 was added in libzip 1.3.0.
index 7eea3d6..5d881b6 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_register_progress_callback_with_state.mdoc -- provide updates during zip_close
-.\" Copyright (C) 2017 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -75,7 +75,8 @@ in the range from 0.0 to 1.0.
 This can be used to provide progress indicators for user interfaces.
 .Sh SEE ALSO
 .Xr libzip 3 ,
-.Xr zip_close 3
+.Xr zip_close 3 ,
+.Xr zip_register_cancel_callback_with_state 3
 .Sh HISTORY
 .Fn zip_register_progress_callback_with_state
 was added in libzip 1.3.0.
index 4f9b113..6e0e740 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_set_archive_comment.mdoc -- set zip archive comment
-   Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
+   Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
index 2b5d9d2..2833cc0 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_set_archive_comment.mdoc -- set zip archive comment
-.\" Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index f4bfad0..4fe8a25 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_set_archive_comment.mdoc -- set zip archive comment
-.\" Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index bb2940e..2f39f2a 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_set_default_password.mdoc -- set default password for zip
-   Copyright (C) 2011-2017 Dieter Baron and Thomas Klausner
+   Copyright (C) 2011-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP files.
    The authors can be contacted at <libzip@nih.at>
@@ -68,12 +68,16 @@ libzip (-lzip)
 <h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
 The <code class="Fn">zip_set_default_password</code>() function sets the default
   password used when accessing encrypted files. If
-  <var class="Ar">password</var> is <code class="Dv">NULL</code>, the default
-  password is unset.
+  <var class="Ar">password</var> is <code class="Dv">NULL</code> or the empty
+  string, the default password is unset.
 <p class="Pp">If you prefer a different password for single files, use
     <a class="Xr" href="zip_fopen_encrypted.html">zip_fopen_encrypted(3)</a>
     instead of <a class="Xr" href="zip_fopen.html">zip_fopen(3)</a>. Usually,
     however, the same password is used for every file in an zip archive.</p>
+<p class="Pp">The password is not verified when calling this function. See the
+    <a class="Sx" href="#CAVEATS">CAVEATS</a> section in
+    <a class="Xr" href="zip_fopen_encrypted.html">zip_fopen_encrypted(3)</a> for
+    more details about password handling.</p>
 </section>
 <section class="Sh">
 <h1 class="Sh" id="RETURN_VALUES"><a class="permalink" href="#RETURN_VALUES">RETURN
@@ -111,7 +115,7 @@ Upon successful completion 0 is returned. Otherwise, -1 is returned and the
 </div>
 <table class="foot">
   <tr>
-    <td class="foot-date">December 18, 2017</td>
+    <td class="foot-date">September 15, 2020</td>
     <td class="foot-os">NiH</td>
   </tr>
 </table>
index 7104bb3..f2265e5 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_set_default_password.mdoc -- set default password for zip
-.\" Copyright (C) 2011-2017 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2011-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP files.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -30,7 +30,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.TH "ZIP_SET_DEFAULT_PASSWORD" "3" "December 18, 2017" "NiH" "Library Functions Manual"
+.TH "ZIP_SET_DEFAULT_PASSWORD" "3" "September 15, 2020" "NiH" "Library Functions Manual"
 .nh
 .if n .ad l
 .SH "NAME"
@@ -54,8 +54,8 @@ function sets the default password used when accessing encrypted files.
 If
 \fIpassword\fR
 is
-\fRNULL\fR,
-the default password is unset.
+\fRNULL\fR
+or the empty string, the default password is unset.
 .PP
 If you prefer a different password for single files, use
 zip_fopen_encrypted(3)
@@ -63,6 +63,13 @@ instead of
 zip_fopen(3).
 Usually, however, the same password is used for every file in an
 zip archive.
+.PP
+The password is not verified when calling this function.
+See the
+\fICAVEATS\fR
+section in
+zip_fopen_encrypted(3)
+for more details about password handling.
 .SH "RETURN VALUES"
 Upon successful completion 0 is returned.
 Otherwise, \-1 is returned and the error information in
index 792176c..a1f1335 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_set_default_password.mdoc -- set default password for zip
-.\" Copyright (C) 2011-2017 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2011-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP files.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -29,7 +29,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd December 18, 2017
+.Dd September 15, 2020
 .Dt ZIP_SET_DEFAULT_PASSWORD 3
 .Os
 .Sh NAME
@@ -48,8 +48,8 @@ function sets the default password used when accessing encrypted files.
 If
 .Ar password
 is
-.Dv NULL ,
-the default password is unset.
+.Dv NULL
+or the empty string, the default password is unset.
 .Pp
 If you prefer a different password for single files, use
 .Xr zip_fopen_encrypted 3
@@ -57,6 +57,13 @@ instead of
 .Xr zip_fopen 3 .
 Usually, however, the same password is used for every file in an
 zip archive.
+.Pp
+The password is not verified when calling this function.
+See the
+.Sx CAVEATS
+section in
+.Xr zip_fopen_encrypted 3
+for more details about password handling.
 .Sh RETURN VALUES
 Upon successful completion 0 is returned.
 Otherwise, \-1 is returned and the error information in
index 887c35c..40db4e4 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_set_file_compression.mdoc -- set compression method and its flags
-   Copyright (C) 2012-2019 Dieter Baron and Thomas Klausner
+   Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP files.
    The authors can be contacted at <libzip@nih.at>
@@ -88,14 +88,27 @@ The <code class="Fn">zip_set_file_compression</code>() function sets the
   <dt><a class="permalink" href="#ZIP_CM_DEFLATE"><code class="Dv" id="ZIP_CM_DEFLATE">ZIP_CM_DEFLATE</code></a></dt>
   <dd>Deflate the file with the <a class="Xr" href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/zlib.html">zlib(3)</a>
       algorithm and default options.</dd>
+  <dt><a class="permalink" href="#ZIP_CM_XZ"><code class="Dv" id="ZIP_CM_XZ">ZIP_CM_XZ</code></a></dt>
+  <dd>Use the <a class="Xr" href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/xz.html">xz(1)</a> algorithm for
+    compression</dd>
+  <dt><a class="permalink" href="#ZIP_CM_ZSTD"><code class="Dv" id="ZIP_CM_ZSTD">ZIP_CM_ZSTD</code></a></dt>
+  <dd>Use the <a class="Xr" href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/zstd.html">zstd(1)</a> algorithm for
+      compression</dd>
 </dl>
 <p class="Pp"><i class="Em">NOTE</i>: Only the deflate and store methods can be
     assumed to be universally supported.</p>
 <p class="Pp">The <var class="Ar">comp_flags</var> argument defines the
-    compression level, 1 being fastest compression and 9 highest. Allowed values
-    are 0 (which uses the default compression for the algorithm) and 1-9, other
-    values are undefined. Further compression method specific flags might be
-    added over time.</p>
+    compression level. This value is dependent on the compression algorithm. In
+    general, lower numbers mean faster de/compression and higher numbers mean
+    slower de/compression. For <code class="Dv">ZIP_CM_BZIP</code>,
+    <code class="Dv">ZIP_CM_DEFLATE</code>, and
+    <code class="Dv">ZIP_CM_XZ</code> 1 is the fastest compression and 9 the
+    best, 0 chooses the default. For <code class="Dv">ZIP_CM_ZSTD</code>
+    possible values are
+    <a class="Xr" href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/ZSTD_minCLevel.html">ZSTD_minCLevel(3)</a> to
+    <a class="Xr" href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/ZSTD_maxCLevel.html">ZSTD_maxCLevel(3)</a>.</p>
+<p class="Pp">Further compression method specific flags might be added over
+    time.</p>
 <p class="Pp">The current compression method for a file in a zip archive can be
     determined using <a class="Xr" href="zip_stat.html">zip_stat(3)</a>.</p>
 </section>
@@ -141,7 +154,7 @@ Upon successful completion 0 is returned. Otherwise, -1 is returned and the
 </div>
 <table class="foot">
   <tr>
-    <td class="foot-date">April 2, 2020</td>
+    <td class="foot-date">June 18, 2021</td>
     <td class="foot-os">NiH</td>
   </tr>
 </table>
index 15bacde..7f6630a 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_set_file_compression.mdoc -- set compression method and its flags
-.\" Copyright (C) 2012-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP files.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -30,7 +30,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.TH "ZIP_SET_FILE_COMPRESSION" "3" "April 2, 2020" "NiH" "Library Functions Manual"
+.TH "ZIP_SET_FILE_COMPRESSION" "3" "June 18, 2021" "NiH" "Library Functions Manual"
 .nh
 .if n .ad l
 .SH "NAME"
@@ -83,6 +83,16 @@ algorithm.
 Deflate the file with the
 zlib(3)
 algorithm and default options.
+.TP 19n
+\fRZIP_CM_XZ\fR
+Use the
+xz(1)
+algorithm for compression
+.TP 19n
+\fRZIP_CM_ZSTD\fR
+Use the
+zstd(1)
+algorithm for compression
 .PP
 \fINOTE\fR:
 Only the deflate and store methods can be assumed to be universally
@@ -90,10 +100,23 @@ supported.
 .PP
 The
 \fIcomp_flags\fR
-argument defines the compression level, 1 being fastest compression
-and 9 highest.
-Allowed values are 0 (which uses the default compression for the
-algorithm) and 1-9, other values are undefined.
+argument defines the compression level.
+This value is dependent on the compression algorithm.
+In general, lower numbers mean faster de/compression and higher
+numbers mean slower de/compression.
+For
+\fRZIP_CM_BZIP\fR,
+\fRZIP_CM_DEFLATE\fR,
+and
+\fRZIP_CM_XZ\fR
+1 is the fastest compression and 9 the best, 0 chooses the default.
+For
+\fRZIP_CM_ZSTD\fR
+possible values are
+ZSTD_minCLevel(3)
+to
+ZSTD_maxCLevel(3).
+.PP
 Further compression method specific flags might be added over time.
 .PP
 The current compression method for a file in a zip archive can be
index db7c10e..53a3614 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_set_file_compression.mdoc -- set compression method and its flags
-.\" Copyright (C) 2012-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP files.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -29,7 +29,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd April 2, 2020
+.Dd June 18, 2021
 .Dt ZIP_SET_FILE_COMPRESSION 3
 .Os
 .Sh NAME
@@ -74,6 +74,14 @@ algorithm.
 Deflate the file with the
 .Xr zlib 3
 algorithm and default options.
+.It Dv ZIP_CM_XZ
+Use the
+.Xr xz 1
+algorithm for compression
+.It Dv ZIP_CM_ZSTD
+Use the
+.Xr zstd 1
+algorithm for compression
 .El
 .Pp
 .Em NOTE :
@@ -82,10 +90,23 @@ supported.
 .Pp
 The
 .Ar comp_flags
-argument defines the compression level, 1 being fastest compression
-and 9 highest.
-Allowed values are 0 (which uses the default compression for the
-algorithm) and 1-9, other values are undefined.
+argument defines the compression level.
+This value is dependent on the compression algorithm.
+In general, lower numbers mean faster de/compression and higher
+numbers mean slower de/compression.
+For
+.Dv ZIP_CM_BZIP ,
+.Dv ZIP_CM_DEFLATE ,
+and
+.Dv ZIP_CM_XZ
+1 is the fastest compression and 9 the best, 0 chooses the default.
+For
+.Dv ZIP_CM_ZSTD
+possible values are
+.Xr ZSTD_minCLevel 3
+to
+.Xr ZSTD_maxCLevel 3 .
+.Pp
 Further compression method specific flags might be added over time.
 .Pp
 The current compression method for a file in a zip archive can be
index 2877ed3..571040e 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_source.mdoc -- description of zip data source
-   Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
+   Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
@@ -74,7 +74,8 @@ A <var class="Vt">struct zip_source</var> is a data source used by
   <a class="Xr" href="zip_source_filep_create.html">zip_source_filep_create(3)</a>,
   <a class="Xr" href="zip_source_function.html">zip_source_function(3)</a>,
   <a class="Xr" href="zip_source_function_create.html">zip_source_function_create(3)</a>,
-  or <a class="Xr" href="zip_source_zip.html">zip_source_zip(3)</a>.
+  <a class="Xr" href="zip_source_window.html">zip_source_window(3)</a>, or
+  <a class="Xr" href="zip_source_zip.html">zip_source_zip(3)</a>.
   <var class="Vt">zip_source_t</var> is reference counted, and created with a
   reference count of 1.
   <a class="Xr" href="zip_open_from_source.html">zip_open_from_source(3)</a>,
@@ -97,6 +98,7 @@ A <var class="Vt">struct zip_source</var> is a data source used by
   <a class="Xr" href="zip_source_filep.html">zip_source_filep(3)</a>,
   <a class="Xr" href="zip_source_free.html">zip_source_free(3)</a>,
   <a class="Xr" href="zip_source_function.html">zip_source_function(3)</a>,
+  <a class="Xr" href="zip_source_window.html">zip_source_window(3)</a>,
   <a class="Xr" href="zip_source_zip.html">zip_source_zip(3)</a>
 </section>
 <section class="Sh">
index 6b3098d..b683b56 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_source.mdoc -- description of zip data source
-.\" Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -58,6 +58,7 @@ zip_source_filep(3),
 zip_source_filep_create(3),
 zip_source_function(3),
 zip_source_function_create(3),
+zip_source_window(3),
 or
 zip_source_zip(3).
 \fIzip_source_t\fR
@@ -82,6 +83,7 @@ zip_source_file(3),
 zip_source_filep(3),
 zip_source_free(3),
 zip_source_function(3),
+zip_source_window(3),
 zip_source_zip(3)
 .SH "AUTHORS"
 Dieter Baron <\fIdillo@nih.at\fR>
index 9f3398c..0b3cafa 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_source.mdoc -- description of zip data source
-.\" Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -56,6 +56,7 @@ It is created by calling one of
 .Xr zip_source_filep_create 3 ,
 .Xr zip_source_function 3 ,
 .Xr zip_source_function_create 3 ,
+.Xr zip_source_window 3 ,
 or
 .Xr zip_source_zip 3 .
 .Vt zip_source_t
@@ -80,6 +81,7 @@ to increase the reference count, for example if you need the source after
 .Xr zip_source_filep 3 ,
 .Xr zip_source_free 3 ,
 .Xr zip_source_function 3 ,
+.Xr zip_source_window 3 ,
 .Xr zip_source_zip 3
 .Sh AUTHORS
 .An -nosplit
index b491747..6681cf2 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_source_buffer.mdoc -- create zip data source from buffer
-   Copyright (C) 2004-2019 Dieter Baron and Thomas Klausner
+   Copyright (C) 2004-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
index 2d6909c..4a368d9 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_source_buffer.mdoc -- create zip data source from buffer
-.\" Copyright (C) 2004-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2004-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index b8f0b19..081e7e2 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_source_buffer.mdoc -- create zip data source from buffer
-.\" Copyright (C) 2004-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2004-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index 7464560..a40c259 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_source_buffer_fragment.mdoc -- create zip data source from multiple buffers
-   Copyright (C) 2004-2019 Dieter Baron and Thomas Klausner
+   Copyright (C) 2004-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
index 772df19..f066977 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_source_buffer_fragment.mdoc -- create zip data source from multiple buffers
-.\" Copyright (C) 2004-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2004-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index 6ac35e0..8965528 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_source_buffer_fragment.mdoc -- create zip data source from multiple buffers
-.\" Copyright (C) 2004-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2004-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index 375c5cf..efe3375 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_source_close.mdoc -- close zip source (open for reading)
-   Copyright (C) 2014-2017 Dieter Baron and Thomas Klausner
+   Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
@@ -49,7 +49,7 @@
 <section class="Sh">
 <h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
 <code class="Nm">zip_source_close</code> &#x2014;
-<div class="Nd">open zip_source (which was open for reading)</div>
+<div class="Nd">close zip_source (which was open for reading)</div>
 </section>
 <section class="Sh">
 <h1 class="Sh" id="LIBRARY"><a class="permalink" href="#LIBRARY">LIBRARY</a></h1>
index 283e93b..cd886e8 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_source_close.mdoc -- close zip source (open for reading)
-.\" Copyright (C) 2014-2017 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -35,7 +35,7 @@
 .if n .ad l
 .SH "NAME"
 \fBzip_source_close\fR
-\- open zip_source (which was open for reading)
+\- close zip_source (which was open for reading)
 .SH "LIBRARY"
 libzip (-lzip)
 .SH "SYNOPSIS"
index 4220861..197695d 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_source_close.mdoc -- close zip source (open for reading)
-.\" Copyright (C) 2014-2017 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -34,7 +34,7 @@
 .Os
 .Sh NAME
 .Nm zip_source_close
-.Nd open zip_source (which was open for reading)
+.Nd close zip_source (which was open for reading)
 .Sh LIBRARY
 libzip (-lzip)
 .Sh SYNOPSIS
index e6643f9..6cb7a9f 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_source_file.mdoc -- create data source from a file
-   Copyright (C) 2004-2019 Dieter Baron and Thomas Klausner
+   Copyright (C) 2004-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
index 307c2a7..56471f9 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_source_file.mdoc -- create data source from a file
-.\" Copyright (C) 2004-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2004-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index 9f2ed4b..cffd493 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_source_file.mdoc -- create data source from a file
-.\" Copyright (C) 2004-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2004-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index f7d91e9..96a3584 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_source_filep.mdoc -- create data source from a file stream
-   Copyright (C) 2004-2019 Dieter Baron and Thomas Klausner
+   Copyright (C) 2004-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
index c9d1853..f7c96f9 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_source_filep.mdoc -- create data source from a file stream
-.\" Copyright (C) 2004-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2004-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index fc3f085..088c750 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_source_filep.mdoc -- create data source from a file stream
-.\" Copyright (C) 2004-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2004-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index 814085e..b0f05b8 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_source_function.mdoc -- create data source from function
-   Copyright (C) 2004-2019 Dieter Baron and Thomas Klausner
+   Copyright (C) 2004-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
index 4d43f99..4fc01d9 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_source_function.mdoc -- create data source from function
-.\" Copyright (C) 2004-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2004-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index aeb31f5..8272ea1 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_source_function.mdoc -- create data source from function
-.\" Copyright (C) 2004-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2004-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index 91ae69c..9e1cb4f 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_source_stat.mdoc -- get information about zip source
-   Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
+   Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
index cb8443b..598b22f 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_source_stat.mdoc -- get information about zip source
-.\" Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index c501daa..b5916a8 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_source_stat.mdoc -- get information about zip source
-.\" Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index 5461b7e..44dd02b 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_source_win32a.mdoc -- create data source using a win32 ANSI name
-   Copyright (C) 2015-2019 Dieter Baron and Thomas Klausner
+   Copyright (C) 2015-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
index a6f279c..c6144d3 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_source_win32a.mdoc -- create data source using a win32 ANSI name
-.\" Copyright (C) 2015-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2015-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index 5761caf..557ae7d 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_source_win32a.mdoc -- create data source using a win32 ANSI name
-.\" Copyright (C) 2015-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2015-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index 5eeb48d..41c8f2c 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_source_handle.mdoc -- create data source from a Windows file handle
-   Copyright (C) 2015-2019 Dieter Baron and Thomas Klausner
+   Copyright (C) 2015-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
index e7462cd..b014a7b 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_source_handle.mdoc -- create data source from a Windows file handle
-.\" Copyright (C) 2015-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2015-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index a1bf934..ab01543 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_source_handle.mdoc -- create data source from a Windows file handle
-.\" Copyright (C) 2015-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2015-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index 4e616f0..f2e1189 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_source_win32w.mdoc -- create data source using a win32 Unicode name
-   Copyright (C) 2015-2019 Dieter Baron and Thomas Klausner
+   Copyright (C) 2015-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
index 557a628..e1241fc 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_source_win32w.mdoc -- create data source using a win32 Unicode name
-.\" Copyright (C) 2015-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2015-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
index aa1265d..904760b 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_source_win32w.mdoc -- create data source using a win32 Unicode name
-.\" Copyright (C) 2015-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2015-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
diff --git a/man/zip_source_window.html b/man/zip_source_window.html
new file mode 100644 (file)
index 0000000..aa38ca7
--- /dev/null
@@ -0,0 +1,123 @@
+<!DOCTYPE html>
+<html>
+<!-- This is an automatically generated file.  Do not edit.
+   zip_source_window.mdoc -- create zip data source overlay
+   Copyright (C) 2021 Dieter Baron and Thomas Klausner
+  
+   This file is part of libzip, a library to manipulate ZIP archives.
+   The authors can be contacted at <libzip@nih.at>
+  
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+   1. Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+   2. Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in
+      the documentation and/or other materials provided with the
+      distribution.
+   3. The names of the authors may not be used to endorse or promote
+      products derived from this software without specific prior
+      written permission.
+  
+   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+   IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   -->
+<head>
+  <meta charset="utf-8"/>
+  <link rel="stylesheet" href="../nih-man.css" type="text/css" media="all"/>
+  <title>ZIP_SOURCE_WINDOW(3)</title>
+</head>
+<body>
+<table class="head">
+  <tr>
+    <td class="head-ltitle">ZIP_SOURCE_WINDOW(3)</td>
+    <td class="head-vol">Library Functions Manual</td>
+    <td class="head-rtitle">ZIP_SOURCE_WINDOW(3)</td>
+  </tr>
+</table>
+<div class="manual-text">
+<section class="Sh">
+<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
+<code class="Nm">zip_source_window_create</code> &#x2014;
+<div class="Nd">create zip data source overlay</div>
+</section>
+<section class="Sh">
+<h1 class="Sh" id="LIBRARY"><a class="permalink" href="#LIBRARY">LIBRARY</a></h1>
+libzip (-lzip)
+</section>
+<section class="Sh">
+<h1 class="Sh" id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">SYNOPSIS</a></h1>
+<code class="In">#include &lt;<a class="In">zip.h</a>&gt;</code>
+<p class="Pp"><var class="Ft">zip_source_t *</var>
+  <br/>
+  <code class="Fn">zip_source_window_create</code>(<var class="Fa" style="white-space: nowrap;">zip_source_t
+    *source</var>, <var class="Fa" style="white-space: nowrap;">zip_uint64_t
+    start</var>, <var class="Fa" style="white-space: nowrap;">zip_int64_t
+    len</var>, <var class="Fa" style="white-space: nowrap;">zip_error_t
+    *error</var>);</p>
+</section>
+<section class="Sh">
+<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
+The <code class="Fn">zip_source_window_create</code>() function create a zip
+  source from an underlying zip source, restricting access to a particular
+  window starting at byte <var class="Ar">start</var> and having size
+  <var class="Ar">len</var>. If <var class="Ar">len</var> is -1, the window
+  spans to the end of the underlying source.
+</section>
+<section class="Sh">
+<h1 class="Sh" id="RETURN_VALUES"><a class="permalink" href="#RETURN_VALUES">RETURN
+  VALUES</a></h1>
+Upon successful completion, the created source is returned. Otherwise,
+  <code class="Dv">NULL</code> is returned and the error code in
+  <var class="Ar">error</var> is set to indicate the error.
+</section>
+<section class="Sh">
+<h1 class="Sh" id="ERRORS"><a class="permalink" href="#ERRORS">ERRORS</a></h1>
+<code class="Fn">zip_source_window_create</code>() fails if:
+<dl class="Bl-tag">
+  <dt>[<a class="permalink" href="#ZIP_ER_INVAL"><code class="Er" id="ZIP_ER_INVAL">ZIP_ER_INVAL</code></a>]</dt>
+  <dd><var class="Ar">src</var> is <code class="Dv">NULL</code>; there is an
+      integer overflow adding <var class="Ar">start</var> and
+      <var class="Ar">len</var>; or <var class="Ar">len</var> is less than
+    -1.</dd>
+  <dt>[<a class="permalink" href="#ZIP_ER_MEMORY"><code class="Er" id="ZIP_ER_MEMORY">ZIP_ER_MEMORY</code></a>]</dt>
+  <dd>Required memory could not be allocated.</dd>
+</dl>
+</section>
+<section class="Sh">
+<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE
+  ALSO</a></h1>
+<a class="Xr" href="libzip.html">libzip(3)</a>,
+  <a class="Xr" href="zip_source.html">zip_source(3)</a>
+  <a class="Xr" href="zip_source.html">zip_source(3)</a>
+</section>
+<section class="Sh">
+<h1 class="Sh" id="HISTORY"><a class="permalink" href="#HISTORY">HISTORY</a></h1>
+<code class="Fn">zip_source_window_create</code>() was added in libzip 1.8.0.
+</section>
+<section class="Sh">
+<h1 class="Sh" id="AUTHORS"><a class="permalink" href="#AUTHORS">AUTHORS</a></h1>
+<span class="An">Dieter Baron</span>
+  &lt;<a class="Mt" href="mailto:dillo@nih.at">dillo@nih.at</a>&gt; and
+  <span class="An">Thomas Klausner</span>
+  &lt;<a class="Mt" href="mailto:tk@giga.or.at">tk@giga.or.at</a>&gt;
+</section>
+</div>
+<table class="foot">
+  <tr>
+    <td class="foot-date">April 29, 2021</td>
+    <td class="foot-os">NiH</td>
+  </tr>
+</table>
+</body>
+</html>
diff --git a/man/zip_source_window.man b/man/zip_source_window.man
new file mode 100644 (file)
index 0000000..8b53ac8
--- /dev/null
@@ -0,0 +1,96 @@
+.\" Automatically generated from an mdoc input file.  Do not edit.
+.\" zip_source_window.mdoc -- create zip data source overlay
+.\" Copyright (C) 2021 Dieter Baron and Thomas Klausner
+.\"
+.\" This file is part of libzip, a library to manipulate ZIP archives.
+.\" The authors can be contacted at <libzip@nih.at>
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in
+.\"    the documentation and/or other materials provided with the
+.\"    distribution.
+.\" 3. The names of the authors may not be used to endorse or promote
+.\"    products derived from this software without specific prior
+.\"    written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.TH "ZIP_SOURCE_WINDOW" "3" "April 29, 2021" "NiH" "Library Functions Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBzip_source_window_create\fR
+\- create zip data source overlay
+.SH "LIBRARY"
+libzip (-lzip)
+.SH "SYNOPSIS"
+\fB#include <zip.h>\fR
+.sp
+\fIzip_source_t *\fR
+.br
+.PD 0
+.HP 4n
+\fBzip_source_window_create\fR(\fIzip_source_t\ *source\fR, \fIzip_uint64_t\ start\fR, \fIzip_int64_t\ len\fR, \fIzip_error_t\ *error\fR);
+.PD
+.SH "DESCRIPTION"
+The
+\fBzip_source_window_create\fR()
+function create a zip source from an underlying zip source,
+restricting access to a particular window starting at byte
+\fIstart\fR
+and having size
+\fIlen\fR.
+If
+\fIlen\fR
+is \-1, the window spans to the end of the underlying source.
+.SH "RETURN VALUES"
+Upon successful completion, the created source is returned.
+Otherwise,
+\fRNULL\fR
+is returned and the error code in
+\fIerror\fR
+is set to indicate the error.
+.SH "ERRORS"
+\fBzip_source_window_create\fR()
+fails if:
+.TP 19n
+[\fRZIP_ER_INVAL\fR]
+\fIsrc\fR
+is
+\fRNULL\fR;
+there is an integer overflow adding
+\fIstart\fR
+and
+\fIlen\fR;
+or
+\fIlen\fR
+is less than \-1.
+.TP 19n
+[\fRZIP_ER_MEMORY\fR]
+Required memory could not be allocated.
+.SH "SEE ALSO"
+libzip(3),
+zip_source(3)
+zip_source(3)
+.SH "HISTORY"
+\fBzip_source_window_create\fR()
+was added in libzip 1.8.0.
+.SH "AUTHORS"
+Dieter Baron <\fIdillo@nih.at\fR>
+and
+Thomas Klausner <\fItk@giga.or.at\fR>
diff --git a/man/zip_source_window.mdoc b/man/zip_source_window.mdoc
new file mode 100644 (file)
index 0000000..a6c9524
--- /dev/null
@@ -0,0 +1,91 @@
+.\" zip_source_window.mdoc -- create zip data source overlay
+.\" Copyright (C) 2021 Dieter Baron and Thomas Klausner
+.\"
+.\" This file is part of libzip, a library to manipulate ZIP archives.
+.\" The authors can be contacted at <libzip@nih.at>
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in
+.\"    the documentation and/or other materials provided with the
+.\"    distribution.
+.\" 3. The names of the authors may not be used to endorse or promote
+.\"    products derived from this software without specific prior
+.\"    written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd April 29, 2021
+.Dt ZIP_SOURCE_WINDOW 3
+.Os
+.Sh NAME
+.Nm zip_source_window_create
+.Nd create zip data source overlay
+.Sh LIBRARY
+libzip (-lzip)
+.Sh SYNOPSIS
+.In zip.h
+.Ft zip_source_t *
+.Fn zip_source_window_create "zip_source_t *source" "zip_uint64_t start" "zip_int64_t len" "zip_error_t *error"
+.Sh DESCRIPTION
+The
+.Fn zip_source_window_create
+function create a zip source from an underlying zip source,
+restricting access to a particular window starting at byte
+.Ar start
+and having size
+.Ar len .
+If
+.Ar len
+is \-1, the window spans to the end of the underlying source.
+.Sh RETURN VALUES
+Upon successful completion, the created source is returned.
+Otherwise,
+.Dv NULL
+is returned and the error code in
+.Ar error
+is set to indicate the error.
+.Sh ERRORS
+.Fn zip_source_window_create
+fails if:
+.Bl -tag -width Er
+.It Bq Er ZIP_ER_INVAL
+.Ar src
+is
+.Dv NULL ;
+there is an integer overflow adding
+.Ar start
+and
+.Ar len ;
+or
+.Ar len
+is less than \-1.
+.It Bq Er ZIP_ER_MEMORY
+Required memory could not be allocated.
+.El
+.Sh SEE ALSO
+.Xr libzip 3 ,
+.Xr zip_source 3
+.Xr zip_source 3
+.Sh HISTORY
+.Fn zip_source_window_create
+was added in libzip 1.8.0.
+.Sh AUTHORS
+.An -nosplit
+.An Dieter Baron Aq Mt dillo@nih.at
+and
+.An Thomas Klausner Aq Mt tk@giga.or.at
index ec8dd75..067e725 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zip_source_zip.mdoc -- create data source from zip file
-   Copyright (C) 2004-2019 Dieter Baron and Thomas Klausner
+   Copyright (C) 2004-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
@@ -48,7 +48,8 @@
 <div class="manual-text">
 <section class="Sh">
 <h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
-<code class="Nm">zip_source_zip</code> &#x2014;
+<code class="Nm">zip_source_zip</code>,
+  <code class="Nm">zip_source_zip_create</code> &#x2014;
 <div class="Nd">create data source from zip file</div>
 </section>
 <section class="Sh">
@@ -67,11 +68,21 @@ libzip (-lzip)
     flags</var>, <var class="Fa" style="white-space: nowrap;">zip_uint64_t
     start</var>, <var class="Fa" style="white-space: nowrap;">zip_int64_t
     len</var>);</p>
+<p class="Pp"><var class="Ft">zip_source_t *</var>
+  <br/>
+  <code class="Fn">zip_source_zip_create</code>(<var class="Fa" style="white-space: nowrap;">zip_t
+    *srcarchive</var>, <var class="Fa" style="white-space: nowrap;">zip_uint64_t
+    srcidx</var>, <var class="Fa" style="white-space: nowrap;">zip_flags_t
+    flags</var>, <var class="Fa" style="white-space: nowrap;">zip_uint64_t
+    start</var>, <var class="Fa" style="white-space: nowrap;">zip_int64_t
+    len</var>, <var class="Fa" style="white-space: nowrap;">zip_error_t
+    *error</var>);</p>
 </section>
 <section class="Sh">
 <h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
-The function <code class="Fn">zip_source_zip</code>() creates a zip source from
-  a file in a zip archive. The <var class="Ar">srcarchive</var> argument is the
+The functions <code class="Fn">zip_source_zip</code>() and
+  <code class="Fn">zip_source_zip_create</code>() create a zip source from a
+  file in a zip archive. The <var class="Ar">srcarchive</var> argument is the
   (open) zip archive containing the source zip file at index
   <var class="Ar">srcidx</var>. <var class="Ar">len</var> bytes from offset
   <var class="Ar">start</var> will be used in the zip_source. If
@@ -94,11 +105,13 @@ The function <code class="Fn">zip_source_zip</code>() creates a zip source from
   VALUES</a></h1>
 Upon successful completion, the created source is returned. Otherwise,
   <code class="Dv">NULL</code> is returned and the error code in
-  <var class="Ar">archive</var> is set to indicate the error.
+  <var class="Ar">archive</var> or <var class="Ar">error</var> is set to
+  indicate the error.
 </section>
 <section class="Sh">
 <h1 class="Sh" id="ERRORS"><a class="permalink" href="#ERRORS">ERRORS</a></h1>
-<code class="Fn">zip_source_zip</code>() fails if:
+<code class="Fn">zip_source_zip</code>() and
+  <code class="Fn">zip_source_zip_create</code>() fail if:
 <dl class="Bl-tag">
   <dt>[<a class="permalink" href="#ZIP_ER_CHANGED"><code class="Er" id="ZIP_ER_CHANGED">ZIP_ER_CHANGED</code></a>]</dt>
   <dd>Unchanged data was requested, but it is not available.</dd>
@@ -124,6 +137,7 @@ Additionally, it can return all error codes from
 <section class="Sh">
 <h1 class="Sh" id="HISTORY"><a class="permalink" href="#HISTORY">HISTORY</a></h1>
 <code class="Fn">zip_source_zip</code>() was added in libzip 1.0.
+  <code class="Fn">zip_source_zip_create</code>() was added in libzip 1.8.0.
 </section>
 <section class="Sh">
 <h1 class="Sh" id="AUTHORS"><a class="permalink" href="#AUTHORS">AUTHORS</a></h1>
@@ -135,7 +149,7 @@ Additionally, it can return all error codes from
 </div>
 <table class="foot">
   <tr>
-    <td class="foot-date">December 18, 2017</td>
+    <td class="foot-date">April 4, 2021</td>
     <td class="foot-os">NiH</td>
   </tr>
 </table>
index 9719115..14f1b24 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zip_source_zip.mdoc -- create data source from zip file
-.\" Copyright (C) 2004-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2004-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.TH "ZIP_SOURCE_ZIP" "3" "December 18, 2017" "NiH" "Library Functions Manual"
+.TH "ZIP_SOURCE_ZIP" "3" "April 4, 2021" "NiH" "Library Functions Manual"
 .nh
 .if n .ad l
 .SH "NAME"
-\fBzip_source_zip\fR
+\fBzip_source_zip\fR,
+\fBzip_source_zip_create\fR
 \- create data source from zip file
 .SH "LIBRARY"
 libzip (-lzip)
@@ -47,10 +48,19 @@ libzip (-lzip)
 .HP 4n
 \fBzip_source_zip\fR(\fIzip_t\ *archive\fR, \fIzip_t\ *srcarchive\fR, \fIzip_uint64_t\ srcidx\fR, \fIzip_flags_t\ flags\fR, \fIzip_uint64_t\ start\fR, \fIzip_int64_t\ len\fR);
 .PD
+.PP
+\fIzip_source_t *\fR
+.br
+.PD 0
+.HP 4n
+\fBzip_source_zip_create\fR(\fIzip_t\ *srcarchive\fR, \fIzip_uint64_t\ srcidx\fR, \fIzip_flags_t\ flags\fR, \fIzip_uint64_t\ start\fR, \fIzip_int64_t\ len\fR, \fIzip_error_t\ *error\fR);
+.PD
 .SH "DESCRIPTION"
-The function
+The functions
 \fBzip_source_zip\fR()
-creates a zip source from a file in a zip archive.
+and
+\fBzip_source_zip_create\fR()
+create a zip source from a file in a zip archive.
 The
 \fIsrcarchive\fR
 argument is the (open) zip archive containing the source zip file
@@ -90,10 +100,14 @@ Otherwise,
 \fRNULL\fR
 is returned and the error code in
 \fIarchive\fR
+or
+\fIerror\fR
 is set to indicate the error.
 .SH "ERRORS"
 \fBzip_source_zip\fR()
-fails if:
+and
+\fBzip_source_zip_create\fR()
+fail if:
 .TP 19n
 [\fRZIP_ER_CHANGED\fR]
 Unchanged data was requested, but it is not available.
@@ -123,6 +137,8 @@ zip_source(3)
 .SH "HISTORY"
 \fBzip_source_zip\fR()
 was added in libzip 1.0.
+\fBzip_source_zip_create\fR()
+was added in libzip 1.8.0.
 .SH "AUTHORS"
 Dieter Baron <\fIdillo@nih.at\fR>
 and
index 943ceef..27f3345 100644 (file)
@@ -1,5 +1,5 @@
 .\" zip_source_zip.mdoc -- create data source from zip file
-.\" Copyright (C) 2004-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2004-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd December 18, 2017
+.Dd April 4, 2021
 .Dt ZIP_SOURCE_ZIP 3
 .Os
 .Sh NAME
-.Nm zip_source_zip
+.Nm zip_source_zip ,
+.Nm zip_source_zip_create
 .Nd create data source from zip file
 .Sh LIBRARY
 libzip (-lzip)
@@ -41,10 +42,14 @@ libzip (-lzip)
 .In zip.h
 .Ft zip_source_t *
 .Fn zip_source_zip "zip_t *archive" "zip_t *srcarchive" "zip_uint64_t srcidx" "zip_flags_t flags" "zip_uint64_t start" "zip_int64_t len"
+.Ft zip_source_t *
+.Fn zip_source_zip_create "zip_t *srcarchive" "zip_uint64_t srcidx" "zip_flags_t flags" "zip_uint64_t start" "zip_int64_t len" "zip_error_t *error"
 .Sh DESCRIPTION
-The function
+The functions
 .Fn zip_source_zip
-creates a zip source from a file in a zip archive.
+and
+.Fn zip_source_zip_create
+create a zip source from a file in a zip archive.
 The
 .Ar srcarchive
 argument is the (open) zip archive containing the source zip file
@@ -84,10 +89,14 @@ Otherwise,
 .Dv NULL
 is returned and the error code in
 .Ar archive
+or
+.Ar error
 is set to indicate the error.
 .Sh ERRORS
 .Fn zip_source_zip
-fails if:
+and
+.Fn zip_source_zip_create
+fail if:
 .Bl -tag -width Er
 .It Bq Er ZIP_ER_CHANGED
 Unchanged data was requested, but it is not available.
@@ -113,6 +122,8 @@ and
 .Sh HISTORY
 .Fn zip_source_zip
 was added in libzip 1.0.
+.Fn zip_source_zip_create
+was added in libzip 1.8.0.
 .Sh AUTHORS
 .An -nosplit
 .An Dieter Baron Aq Mt dillo@nih.at
index ddb397e..9c341da 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zipcmp.mdoc -- compare zip archives
-   Copyright (C) 2003-2019 Dieter Baron and Thomas Klausner
+   Copyright (C) 2003-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
@@ -56,7 +56,7 @@
 <table class="Nm">
   <tr>
     <td><code class="Nm">zipcmp</code></td>
-    <td>[<code class="Fl">-hipqtVv</code>] <var class="Ar">archive1
+    <td>[<code class="Fl">-ChipqtVv</code>] <var class="Ar">archive1
       archive2</var></td>
   </tr>
 </table>
   CRCs. File order and compressed size differences are ignored.
 <p class="Pp">Supported options:</p>
 <dl class="Bl-tag">
+  <dt><a class="permalink" href="#C"><code class="Fl" id="C">-C</code></a></dt>
+  <dd>Check consistency of archives. Results in an error if archive is
+      inconsistent or not valid according to the zip specification.</dd>
   <dt><a class="permalink" href="#h"><code class="Fl" id="h">-h</code></a></dt>
   <dd>Display a short help message and exit.</dd>
   <dt><a class="permalink" href="#i"><code class="Fl" id="i">-i</code></a></dt>
   <dd>Compare names ignoring case distinctions.</dd>
   <dt><a class="permalink" href="#p"><code class="Fl" id="p">-p</code></a></dt>
-  <dd>Enable paranoid checks. Compares extra fields and other meta data.
-      (Automatically disabled if one of the archives is a directory.)</dd>
+  <dd>Enable paranoid checks. Compares extra fields, comments, and other meta
+      data. (Automatically disabled if one of the archives is a directory.)
+      These checks are skipped for files where the data differs.</dd>
   <dt><a class="permalink" href="#q"><code class="Fl" id="q">-q</code></a></dt>
   <dd>Quiet mode. Compare <code class="Fl">-v</code>.</dd>
   <dt><a class="permalink" href="#t"><code class="Fl" id="t">-t</code></a></dt>
 </div>
 <table class="foot">
   <tr>
-    <td class="foot-date">December 18, 2017</td>
+    <td class="foot-date">March 17, 2021</td>
     <td class="foot-os">NiH</td>
   </tr>
 </table>
index fe84821..a5a8b1b 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zipcmp.mdoc -- compare zip archives
-.\" Copyright (C) 2003-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2003-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -30,7 +30,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.TH "ZIPCMP" "1" "December 18, 2017" "NiH" "General Commands Manual"
+.TH "ZIPCMP" "1" "March 17, 2021" "NiH" "General Commands Manual"
 .nh
 .if n .ad l
 .SH "NAME"
@@ -39,7 +39,7 @@
 .SH "SYNOPSIS"
 .HP 7n
 \fBzipcmp\fR
-[\fB\-hipqtVv\fR]
+[\fB\-ChipqtVv\fR]
 \fIarchive1\ archive2\fR
 .SH "DESCRIPTION"
 \fBzipcmp\fR
@@ -53,6 +53,11 @@ File order and compressed size differences are ignored.
 .PP
 Supported options:
 .TP 5n
+\fB\-C\fR
+Check consistency of archives.
+Results in an error if archive is inconsistent or not valid
+according to the zip specification.
+.TP 5n
 \fB\-h\fR
 Display a short help message and exit.
 .TP 5n
@@ -61,8 +66,9 @@ Compare names ignoring case distinctions.
 .TP 5n
 \fB\-p\fR
 Enable paranoid checks.
-Compares extra fields and other meta data.
+Compares extra fields, comments, and other meta data.
 (Automatically disabled if one of the archives is a directory.)
+These checks are skipped for files where the data differs.
 .TP 5n
 \fB\-q\fR
 Quiet mode.
index 5311abf..d1b1513 100644 (file)
@@ -1,5 +1,5 @@
 .\" zipcmp.mdoc -- compare zip archives
-.\" Copyright (C) 2003-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2003-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -29,7 +29,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd December 18, 2017
+.Dd March 17, 2021
 .Dt ZIPCMP 1
 .Os
 .Sh NAME
@@ -37,7 +37,7 @@
 .Nd compare contents of zip archives
 .Sh SYNOPSIS
 .Nm
-.Op Fl hipqtVv
+.Op Fl ChipqtVv
 .Ar archive1 archive2
 .Sh DESCRIPTION
 .Nm
@@ -51,14 +51,19 @@ File order and compressed size differences are ignored.
 .Pp
 Supported options:
 .Bl -tag -width MMM
+.It Fl C
+Check consistency of archives.
+Results in an error if archive is inconsistent or not valid
+according to the zip specification.
 .It Fl h
 Display a short help message and exit.
 .It Fl i
 Compare names ignoring case distinctions.
 .It Fl p
 Enable paranoid checks.
-Compares extra fields and other meta data.
+Compares extra fields, comments, and other meta data.
 (Automatically disabled if one of the archives is a directory.)
+These checks are skipped for files where the data differs.
 .It Fl q
 Quiet mode.
 Compare
index e81d8c3..86651b3 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- This is an automatically generated file.  Do not edit.
    zipmerge.mdoc -- merge zip archives
-   Copyright (C) 2004-2019 Dieter Baron and Thomas Klausner
+   Copyright (C) 2004-2021 Dieter Baron and Thomas Klausner
   
    This file is part of libzip, a library to manipulate ZIP archives.
    The authors can be contacted at <libzip@nih.at>
   <span class="An">Thomas Klausner</span>
   &lt;<a class="Mt" href="mailto:tk@giga.or.at">tk@giga.or.at</a>&gt;
 </section>
+<section class="Sh">
+<h1 class="Sh" id="CAVEATS"><a class="permalink" href="#CAVEATS">CAVEATS</a></h1>
+<code class="Nm">zipmerge</code> uses one open file descriptor per zip archive.
+  If you need to merge a lot of zip archives, check your shell's file descriptor
+  ulimit and either increase it or run <code class="Nm">zipmerge</code> multiple
+  times with e.g. 1000 source zip archives each time.
+</section>
 </div>
 <table class="foot">
   <tr>
-    <td class="foot-date">December 18, 2017</td>
+    <td class="foot-date">March 17, 2021</td>
     <td class="foot-os">NiH</td>
   </tr>
 </table>
index 088b346..31f8e58 100644 (file)
@@ -1,6 +1,6 @@
 .\" Automatically generated from an mdoc input file.  Do not edit.
 .\" zipmerge.mdoc -- merge zip archives
-.\" Copyright (C) 2004-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2004-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -30,7 +30,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.TH "ZIPMERGE" "1" "December 18, 2017" "NiH" "General Commands Manual"
+.TH "ZIPMERGE" "1" "March 17, 2021" "NiH" "General Commands Manual"
 .nh
 .if n .ad l
 .SH "NAME"
@@ -95,3 +95,10 @@ was added in libzip 0.6.
 Dieter Baron <\fIdillo@nih.at\fR>
 and
 Thomas Klausner <\fItk@giga.or.at\fR>
+.SH "CAVEATS"
+\fBzipmerge\fR
+uses one open file descriptor per zip archive.
+If you need to merge a lot of zip archives, check your shell's
+file descriptor ulimit and either increase it or run
+\fBzipmerge\fR
+multiple times with e.g. 1000 source zip archives each time.
index bf0b869..1325f8c 100644 (file)
@@ -1,5 +1,5 @@
 .\" zipmerge.mdoc -- merge zip archives
-.\" Copyright (C) 2004-2019 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2004-2021 Dieter Baron and Thomas Klausner
 .\"
 .\" This file is part of libzip, a library to manipulate ZIP archives.
 .\" The authors can be contacted at <libzip@nih.at>
@@ -29,7 +29,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd December 18, 2017
+.Dd March 17, 2021
 .Dt ZIPMERGE 1
 .Os
 .Sh NAME
@@ -89,3 +89,10 @@ was added in libzip 0.6.
 .An Dieter Baron Aq Mt dillo@nih.at
 and
 .An Thomas Klausner Aq Mt tk@giga.or.at
+.Sh CAVEATS
+.Nm
+uses one open file descriptor per zip archive.
+If you need to merge a lot of zip archives, check your shell's
+file descriptor ulimit and either increase it or run
+.Nm
+multiple times with e.g. 1000 source zip archives each time.
index e7ec59d..8f0bd29 100644 (file)
@@ -7,6 +7,7 @@ set(TEST_PROGRAMS
   fseek
   fuzz_main
   nonrandomopentest
+  liboverride-test
 )
 
 set(GETOPT_USERS
@@ -45,11 +46,11 @@ target_include_directories(ziptool_regress PRIVATE BEFORE ${PROJECT_SOURCE_DIR}/
 set(DL_USERS
   # malloc
   nonrandomopen
+  liboverride
 )
 
 foreach(PROGRAM IN LISTS DL_USERS)
   add_library(${PROGRAM} MODULE ${PROGRAM}.c)
-  target_link_libraries(${PROGRAM} ${CMAKE_DL_LIBS})
   target_include_directories(${PROGRAM} PRIVATE BEFORE ${PROJECT_SOURCE_DIR}/lib ${PROJECT_BINARY_DIR})
 endforeach()
 
@@ -76,144 +77,6 @@ set_property(DIRECTORY PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
   manyfiles.zip
 )
 
-set(EXTRA_TESTS
-       add_dir.test
-       add_from_buffer.test
-       add_from_file.test
-       add_from_file_duplicate.test
-       add_from_file_twice_duplicate.test
-       add_from_filep.test
-       add_from_stdin.test
-       add_from_zip_closed.test
-       add_from_zip_deflated.test
-       add_from_zip_deflated2.test
-       add_from_zip_partial_deflated.test
-       add_from_zip_partial_stored.test
-       add_from_zip_stored.test
-       add_stored.test
-       add_stored_in_memory.test
-       buffer-fragment-read.test
-       buffer-fragment-write.test
-       cancel_45.test
-       cancel_90.test
-       clone-buffer-add.test
-       clone-buffer-delete.test
-       clone-buffer-replace.test
-       clone-fs-add.test
-       clone-fs-delete.test
-       clone-fs-replace.test
-       cm-default.test
-       count_entries.test
-       decrypt-correct-password-aes128.test
-       decrypt-correct-password-aes192.test
-       decrypt-correct-password-aes256.test
-       decrypt-correct-password-pkware.test
-       decrypt-no-password-aes256.test
-       decrypt-wrong-password-aes128.test
-       decrypt-wrong-password-aes192.test
-       decrypt-wrong-password-aes256.test
-       decrypt-wrong-password-pkware.test
-       delete_add_same.test
-       delete_invalid.test
-       delete_last.test
-       delete_multiple_last.test
-       delete_multiple_partial.test
-       delete_renamed_rename.test
-       encrypt.test
-       encryption-nonrandom-aes128.test
-       encryption-nonrandom-aes192.test
-       encryption-nonrandom-aes256.test
-       encryption-nonrandom-pkware.test
-       encryption-remove.test
-       extra_add.test
-       extra_add_multiple.test
-       extra_count.test
-       extra_count_by_id.test
-       extra_count_ignore_zip64.test
-       extra_delete.test
-       extra_delete_by_id.test
-       extra_field_align.test
-       extra_get.test
-       extra_get_by_id.test
-       extra_set.test
-       extra_set_modify_c.test
-       extra_set_modify_l.test
-       fdopen_ok.test
-       file_comment_encmismatch.test
-       fopen_unchanged.test
-       fread.test
-       fseek_deflated.test
-       fseek_fail.test
-       fseek_ok.test
-       get_comment.test
-       junk_at_end.test
-       junk_at_start.test
-       name_locate.test
-       open_cons_extrabytes.test
-       open_empty.test
-       open_empty_2.test
-       open_extrabytes.test
-       open_file_count.test
-       open_filename_duplicate.test
-       open_filename_duplicate_consistency.test
-       open_filename_duplicate_empty.test
-       open_filename_duplicate_empty_consistency.test
-       open_filename_empty.test
-       open_incons.test
-       open_many_fail.test
-       open_many_ok.test
-       open_multidisk.test
-       open_new_but_exists.test
-       open_new_ok.test
-       open_nonarchive.test
-       open_nosuchfile.test
-       open_ok.test
-       open_too_short.test
-       open_truncate.test
-       open_zip64_3mf.test
-       open_zip64_ok.test
-       preload.test
-       progress.test
-       rename_ascii.test
-       rename_cp437.test
-       rename_deleted.test
-       rename_fail.test
-       rename_ok.test
-       rename_utf8.test
-       rename_utf8_encmismatch.test
-       set_comment_all.test
-       set_comment_localonly.test
-       set_comment_removeglobal.test
-       set_comment_revert.test
-       set_compression_bzip2_to_deflate.test
-       set_compression_deflate_to_bzip2.test
-       set_compression_deflate_to_deflate.test
-       set_compression_deflate_to_store.test
-       set_compression_store_to_bzip2.test
-       set_compression_store_to_deflate.test
-       set_compression_store_to_store.test
-       set_compression_store_to_xz.test
-       set_compression_unknown.test
-       set_compression_xz_to_store.test
-       set_file_dostime.test
-       stat_index_cp437_guess.test
-       stat_index_cp437_raw.test
-       stat_index_cp437_strict.test
-       stat_index_fileorder.test
-       stat_index_streamed.test
-       stat_index_streamed_zip64.test
-       stat_index_utf8_guess.test
-       stat_index_utf8_raw.test
-       stat_index_utf8_strict.test
-       stat_index_utf8_unmarked_strict.test
-       stat_index_zip64.test
-       utf-8-standardization.test
-       zip-in-archive-comment.test
-       zip64_creation.test
-       zip64_stored_creation.test
-)
-
-
 set(path "$<TARGET_FILE_DIR:zip>;$ENV{PATH}")
 if (TARGET zlib)
   set(path "$<TARGET_FILE_DIR:zlib>;${path}")
@@ -222,8 +85,10 @@ string(REPLACE ";" "\\;" path "${path}")
 
 set(ENV{srcdir} ${PROJECT_SOURCE_DIR}/regress)
 
-foreach(CASE IN LISTS EXTRA_TESTS)
-  add_test(NAME ${CASE} COMMAND ${PERL_EXECUTABLE} ${PROJECT_BINARY_DIR}/regress/runtest --bin-sub-directory $<CONFIG> ${PROJECT_SOURCE_DIR}/regress/${CASE})
+file(GLOB EXTRA_TESTS ${CMAKE_CURRENT_SOURCE_DIR}/*.test)
+foreach(FULL_CASE IN LISTS EXTRA_TESTS)
+  get_filename_component(CASE ${FULL_CASE} NAME)
+  add_test(NAME ${CASE} COMMAND ${PERL_EXECUTABLE} ${PROJECT_BINARY_DIR}/regress/runtest -v --bin-sub-directory $<CONFIG> ${PROJECT_SOURCE_DIR}/regress/${CASE})
   set_tests_properties(${CASE} PROPERTIES SKIP_RETURN_CODE 77)
   set_tests_properties(${CASE} PROPERTIES ENVIRONMENT "PATH=${path}")
 endforeach()
diff --git a/regress/add_from_file_unchange.test b/regress/add_from_file_unchange.test
new file mode 100644 (file)
index 0000000..dff1c2f
--- /dev/null
@@ -0,0 +1,4 @@
+# add file to zip, but revert before closing
+return 0
+args -- testfile.zip   add_file testfile.txt testfile.txt 0 -1  unchange 0
+file testfile.txt testfile.txt testfile.txt
index da0b98c..53aec85 100644 (file)
@@ -1,6 +1,6 @@
 /*
   add_from_filep.c -- test case for adding file to archive
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -53,43 +53,43 @@ main(int argc, char *argv[]) {
     prg = argv[0];
 
     if (argc != 3) {
-       fprintf(stderr, "usage: %s archive file\n", prg);
-       return 1;
+        fprintf(stderr, "usage: %s archive file\n", prg);
+        return 1;
     }
 
     archive = argv[1];
     file = argv[2];
 
     if ((za = zip_open(archive, ZIP_CREATE, &err)) == NULL) {
-       zip_error_t error;
-       zip_error_init_with_code(&error, err);
-       fprintf(stderr, "%s: can't open zip archive '%s': %s\n", prg, archive, zip_error_strerror(&error));
-       zip_error_fini(&error);
-       return 1;
+        zip_error_t error;
+        zip_error_init_with_code(&error, err);
+        fprintf(stderr, "%s: can't open zip archive '%s': %s\n", prg, archive, zip_error_strerror(&error));
+        zip_error_fini(&error);
+        return 1;
     }
 
     if ((fp = fopen(file, "rb")) == NULL) {
-       fprintf(stderr, "%s: can't open input file '%s': %s\n", prg, file, strerror(errno));
-       return 1;
+        fprintf(stderr, "%s: can't open input file '%s': %s\n", prg, file, strerror(errno));
+        return 1;
     }
 
     if ((zs = zip_source_filep(za, fp, 0, -1)) == NULL) {
-       fprintf(stderr, "%s: error creating file source for '%s': %s\n", prg, file, zip_strerror(za));
-       return 1;
+        fprintf(stderr, "%s: error creating file source for '%s': %s\n", prg, file, zip_strerror(za));
+        return 1;
     }
 
     if ((name = strrchr(file, '/')) == NULL)
-       name = file;
+        name = file;
 
     if (zip_add(za, name, zs) == -1) {
-       zip_source_free(zs);
-       fprintf(stderr, "%s: can't add file '%s': %s\n", prg, file, zip_strerror(za));
-       return 1;
+        zip_source_free(zs);
+        fprintf(stderr, "%s: can't add file '%s': %s\n", prg, file, zip_strerror(za));
+        return 1;
     }
 
     if (zip_close(za) == -1) {
-       fprintf(stderr, "%s: can't close zip archive '%s': %s\n", prg, archive, zip_strerror(za));
-       return 1;
+        fprintf(stderr, "%s: can't close zip archive '%s': %s\n", prg, archive, zip_strerror(za));
+        return 1;
     }
 
     return 0;
index 33cc1a9..887947d 100644 (file)
@@ -1,6 +1,6 @@
 /*
  can_clone_file.c -- does the current filesystem support cloning
- Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
  This file is part of libzip, a library to manipulate ZIP archives.
  The authors can be contacted at <libzip@nih.at>
 #include "config.h"
 
 #ifdef HAVE_CLONEFILE
-#include <sys/attr.h>
-#include <sys/mount.h>
-#include <sys/param.h>
 #include <errno.h>
 #include <stdio.h>
 #include <string.h>
+#include <sys/attr.h>
+#include <sys/mount.h>
+#include <sys/param.h>
 #include <unistd.h>
 #elif defined(HAVE_FICLONERANGE)
-#include <linux/fs.h>
-#include <sys/ioctl.h>
 #include <errno.h>
+#include <linux/fs.h>
 #include <stdio.h>
 #include <string.h>
+#include <sys/ioctl.h>
 #include <unistd.h>
 #endif
 
@@ -58,13 +58,13 @@ main(int argc, char *argv[]) {
     struct statfs fs;
     struct attrlist attribute_list;
     struct {
-       uint32_t size;
-       vol_capabilities_attr_t capabilities;
+        uint32_t size;
+        vol_capabilities_attr_t capabilities;
     } volume_attributes;
 
     if (statfs(".", &fs) < 0) {
-       fprintf(stderr, "%s: can't get mount point of current directory: %s\n", argv[0], strerror(errno));
-       exit(1);
+        fprintf(stderr, "%s: can't get mount point of current directory: %s\n", argv[0], strerror(errno));
+        exit(1);
     }
 
     /* Not all volumes support clonefile().  A volume can be tested for
@@ -78,12 +78,12 @@ main(int argc, char *argv[]) {
     memset(&volume_attributes, 0, sizeof(volume_attributes));
 
     if (getattrlist(fs.f_mntonname, &attribute_list, &volume_attributes, sizeof(volume_attributes), 0) < 0) {
-       fprintf(stderr, "%s: can't get volume capabilities of '%s': %s\n", argv[0], fs.f_mntonname, strerror(errno));
-       exit(1);
+        fprintf(stderr, "%s: can't get volume capabilities of '%s': %s\n", argv[0], fs.f_mntonname, strerror(errno));
+        exit(1);
     }
 
     if (volume_attributes.capabilities.capabilities[VOL_CAPABILITIES_INTERFACES] & VOL_CAP_INT_CLONE) {
-       exit(0);
+        exit(0);
     }
 #elif defined(HAVE_FICLONERANGE)
     char namea[32] = "a.fioclone.XXXXXX";
@@ -92,22 +92,22 @@ main(int argc, char *argv[]) {
     struct file_clone_range range;
 
     if ((fda = mkstemp(namea)) < 0) {
-       fprintf(stderr, "can't create temp file a: %s\n", strerror(errno));
-       exit(1);
+        fprintf(stderr, "can't create temp file a: %s\n", strerror(errno));
+        exit(1);
     }
     if ((fdb = mkstemp(nameb)) < 0) {
-       fprintf(stderr, "can't create temp file b: %s\n", strerror(errno));
-       (void)close(fda);
-       (void)remove(namea);
-       exit(1);
+        fprintf(stderr, "can't create temp file b: %s\n", strerror(errno));
+        (void)close(fda);
+        (void)remove(namea);
+        exit(1);
     }
     if (write(fda, "test\n", 5) < 0) {
-       fprintf(stderr, "can't write temp file a: %s\n", strerror(errno));
-       (void)close(fda);
-       (void)remove(namea);
-       close(fdb);
-       (void)remove(nameb);
-       exit(1);
+        fprintf(stderr, "can't write temp file a: %s\n", strerror(errno));
+        (void)close(fda);
+        (void)remove(namea);
+        close(fdb);
+        (void)remove(nameb);
+        exit(1);
     }
     range.src_fd = fda;
     range.src_offset = 0;
@@ -119,7 +119,7 @@ main(int argc, char *argv[]) {
     (void)remove(namea);
     (void)remove(nameb);
     if (ret >= 0) {
-       exit(0);
+        exit(0);
     }
 #endif
 
diff --git a/regress/decrypt-correct-password-pkware-2.test b/regress/decrypt-correct-password-pkware-2.test
new file mode 100644 (file)
index 0000000..24f43b5
--- /dev/null
@@ -0,0 +1,9 @@
+# test decryption support, extract file using correct password
+return 0
+args encrypt.zzip  set_password 1234  cat 0
+file encrypt.zzip encrypt-1234.zip encrypt-1234.zip
+stdout I would love to try or hear the sample audio your app can produce. I do not want to purchase, because I've purchased so many apps that say they do something and do not deliver.  
+stdout
+stdout Can you please add audio samples with text you've converted? I'd love to see the end results.
+stdout
+stdout Thanks!
diff --git a/regress/decrypt-wrong-password-pkware-2.test b/regress/decrypt-wrong-password-pkware-2.test
new file mode 100644 (file)
index 0000000..fb1e66c
--- /dev/null
@@ -0,0 +1,7 @@
+# test decryption support, extract file using wrong password (correct: "1234")
+# In some cases, like this one, the password, even if incorrect, passes the
+# minimal verification that's possible due to the zip file format specification.
+return 1
+args encrypt.zzip  set_password sample  cat 0
+file encrypt.zzip encrypt-1234.zip encrypt-1234.zip
+stderr can't read file at index '0': Zlib error: data error
diff --git a/regress/encrypt-1234.zip b/regress/encrypt-1234.zip
new file mode 100644 (file)
index 0000000..09ef679
Binary files /dev/null and b/regress/encrypt-1234.zip differ
index fa21efe..4fae471 100644 (file)
@@ -1,4 +1,5 @@
 features CRYPTO
+precheck ./liboverride-test
 description encrypt file without entropy, to make results repeatable
 return 0
 preload nonrandomopen.so
index bd0ebc4..7f0335a 100644 (file)
@@ -1,4 +1,5 @@
 features CRYPTO
+precheck ./liboverride-test
 description encrypt file without entropy, to make results repeatable
 return 0
 preload nonrandomopen.so
index ee6be9f..9d8d6ac 100644 (file)
@@ -1,4 +1,5 @@
 features CRYPTO
+precheck ./liboverride-test
 description encrypt file without entropy, to make results repeatable
 return 0
 preload nonrandomopen.so
index a01b168..2d14e40 100644 (file)
@@ -1,4 +1,5 @@
 features CRYPTO
+precheck ./liboverride-test
 description encrypt file by Traditional PKWARE
 return 0
 preload nonrandomopen.so
diff --git a/regress/encryption-stat.test b/regress/encryption-stat.test
new file mode 100644 (file)
index 0000000..d84d8fc
--- /dev/null
@@ -0,0 +1,23 @@
+features CRYPTO
+description encrypt file, look at stat before commit
+return 0
+args encrypt.zzip  stat 1  set_file_encryption 1 AES-128 no-entropy  stat 1  unchange_all
+file encrypt.zzip encrypt-none.zip encrypt-none.zip
+stdout name: 'encrypted'
+stdout index: '1'
+stdout size: '10'
+stdout compressed size: '10'
+stdout mtime: 'Sat Jan 14 2017 21:27:26'
+stdout crc: 'fb8c5e55'
+stdout compression method: '0'
+stdout encryption method: '0'
+stdout 
+stdout name: 'encrypted'
+stdout index: '1'
+stdout size: '10'
+stdout compressed size: '10'
+stdout mtime: 'Sat Jan 14 2017 21:27:26'
+stdout crc: 'fb8c5e55'
+stdout compression method: '0'
+stdout encryption method: '257'
+stdout 
index fe42977..3bb51c9 100644 (file)
@@ -17,16 +17,16 @@ file extra_field_align_3-ef_ff.zzip extra_field_align_3-ef_ff.zip extra_field_al
 args -c extra_field_align_1-0.zzip extra_field_align_1-ff.zzip extra_field_align_2-0.zzip extra_field_align_2-ff.zzip extra_field_align_3-0.zzip extra_field_align_3-ff.zzip extra_field_align_4-ff.zzip extra_field_align_1-ef_00.zzip extra_field_align_1-ef_ff.zzip extra_field_align_2-ef_00.zzip extra_field_align_2-ef_ff.zzip extra_field_align_3-ef_00.zzip extra_field_align_3-ef_ff.zzip
 return 1
 stdout opening 'extra_field_align_1-0.zzip' succeeded, 1 entries
-stdout opening 'extra_field_align_1-ff.zzip' returned error 21
+stdout opening 'extra_field_align_1-ff.zzip' returned error 21/15
 stdout opening 'extra_field_align_2-0.zzip' succeeded, 1 entries
-stdout opening 'extra_field_align_2-ff.zzip' returned error 21
+stdout opening 'extra_field_align_2-ff.zzip' returned error 21/15
 stdout opening 'extra_field_align_3-0.zzip' succeeded, 1 entries
-stdout opening 'extra_field_align_3-ff.zzip' returned error 21
+stdout opening 'extra_field_align_3-ff.zzip' returned error 21/15
 stdout opening 'extra_field_align_4-ff.zzip' succeeded, 1 entries
 stdout opening 'extra_field_align_1-ef_00.zzip' succeeded, 1 entries
-stdout opening 'extra_field_align_1-ef_ff.zzip' returned error 21
+stdout opening 'extra_field_align_1-ef_ff.zzip' returned error 21/15
 stdout opening 'extra_field_align_2-ef_00.zzip' succeeded, 1 entries
-stdout opening 'extra_field_align_2-ef_ff.zzip' returned error 21
+stdout opening 'extra_field_align_2-ef_ff.zzip' returned error 21/15
 stdout opening 'extra_field_align_3-ef_00.zzip' succeeded, 1 entries
-stdout opening 'extra_field_align_3-ef_ff.zzip' returned error 21
+stdout opening 'extra_field_align_3-ef_ff.zzip' returned error 21/15
 stderr 6 errors
index 3c9da84..8e2ee26 100644 (file)
@@ -1,6 +1,6 @@
 /*
   fopen_unchanged.c -- test case for adding file and reading from unchanged
-  Copyright (C) 2012-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -49,41 +49,41 @@ main(int argc, char *argv[]) {
     int err;
 
     if (argc != 2) {
-       fprintf(stderr, "usage: %s archive\n", argv[0]);
-       return 1;
+        fprintf(stderr, "usage: %s archive\n", argv[0]);
+        return 1;
     }
 
     archive = argv[1];
 
     if ((za = zip_open(archive, ZIP_CREATE, &err)) == NULL) {
-       zip_error_t error;
-       zip_error_init_with_code(&error, err);
-       fprintf(stderr, "can't open zip archive '%s': %s\n", archive, zip_error_strerror(&error));
-       zip_error_fini(&error);
-       return 1;
+        zip_error_t error;
+        zip_error_init_with_code(&error, err);
+        fprintf(stderr, "can't open zip archive '%s': %s\n", archive, zip_error_strerror(&error));
+        zip_error_fini(&error);
+        return 1;
     }
 
     if ((zs = zip_source_buffer(za, teststr, strlen(teststr), 0)) == NULL) {
-       fprintf(stderr, "can't create zip_source from buffer: %s\n", zip_strerror(za));
-       exit(1);
+        fprintf(stderr, "can't create zip_source from buffer: %s\n", zip_strerror(za));
+        exit(1);
     }
 
     if (zip_add(za, file, zs) == -1) {
-       fprintf(stderr, "can't add file '%s': %s\n", file, zip_strerror(za));
-       (void)zip_source_free(zs);
-       (void)zip_close(za);
-       return 1;
+        fprintf(stderr, "can't add file '%s': %s\n", file, zip_strerror(za));
+        (void)zip_source_free(zs);
+        (void)zip_close(za);
+        return 1;
     }
 
     if (zip_fopen(za, file, ZIP_FL_UNCHANGED) == NULL) {
-       fprintf(stderr, "can't zip_fopen file '%s': %s\n", file, zip_strerror(za));
-       (void)zip_discard(za);
-       return 1;
+        fprintf(stderr, "can't zip_fopen file '%s': %s\n", file, zip_strerror(za));
+        (void)zip_discard(za);
+        return 1;
     }
 
     if (zip_close(za) == -1) {
-       fprintf(stderr, "can't close zip archive '%s': %s\n", archive, zip_strerror(za));
-       return 1;
+        fprintf(stderr, "can't close zip archive '%s': %s\n", archive, zip_strerror(za));
+        return 1;
     }
 
     return 0;
index 8545e9e..f644282 100644 (file)
@@ -1,6 +1,6 @@
 /*
   fread.c -- test cases for reading from zip archives
-  Copyright (C) 2004-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2004-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -68,31 +68,31 @@ main(int argc, char *argv[]) {
     progname = argv[0];
 
     while ((c = getopt(argc, argv, "v")) != -1) {
-       switch (c) {
-       case 'v':
-           verbose = 1;
-           break;
-
-       default:
-           fprintf(stderr, USAGE, progname);
-           return 1;
-       }
+        switch (c) {
+        case 'v':
+            verbose = 1;
+            break;
+
+        default:
+            fprintf(stderr, USAGE, progname);
+            return 1;
+        }
     }
 
 
     if (argc - optind != 1) {
-       fprintf(stderr, USAGE, progname);
-       return 1;
+        fprintf(stderr, USAGE, progname);
+        return 1;
     }
 
     archive = argv[optind];
 
     if ((z = zip_open(archive, 0, &ze)) == NULL) {
-       zip_error_t error;
-       zip_error_init_with_code(&error, ze);
-       fprintf(stderr, "%s: can't open zip archive '%s': %s\n", progname, archive, zip_error_strerror(&error));
-       zip_error_fini(&error);
-       return 1;
+        zip_error_t error;
+        zip_error_init_with_code(&error, ze);
+        fprintf(stderr, "%s: can't open zip archive '%s': %s\n", progname, archive, zip_error_strerror(&error));
+        zip_error_fini(&error);
+        return 1;
     }
 
     fail += do_read(z, "storedok", 0, WHEN_NEVER, 0, 0);
@@ -118,46 +118,46 @@ main(int argc, char *argv[]) {
 
     zs = zip_source_buffer(z, "asdf", 4, 0);
     if ((idx = zip_name_locate(z, "storedok", 0)) < 0) {
-       fprintf(stderr, "%s: can't locate 'storedok' in zip archive '%s': %s\n", progname, archive, zip_strerror(z));
-       fail++;
+        fprintf(stderr, "%s: can't locate 'storedok' in zip archive '%s': %s\n", progname, archive, zip_strerror(z));
+        fail++;
     }
     else {
-       if (zip_replace(z, (zip_uint64_t)idx, zs) < 0) {
-           fprintf(stderr, "%s: can't replace 'storedok' in zip archive '%s': %s\n", progname, archive, zip_strerror(z));
-           fail++;
-       }
-       else {
-           fail += do_read(z, "storedok", 0, WHEN_OPEN, ZIP_ER_CHANGED, 0);
-           fail += do_read(z, "storedok", ZIP_FL_UNCHANGED, WHEN_NEVER, 0, 0);
-       }
+        if (zip_replace(z, (zip_uint64_t)idx, zs) < 0) {
+            fprintf(stderr, "%s: can't replace 'storedok' in zip archive '%s': %s\n", progname, archive, zip_strerror(z));
+            fail++;
+        }
+        else {
+            fail += do_read(z, "storedok", 0, WHEN_OPEN, ZIP_ER_CHANGED, 0);
+            fail += do_read(z, "storedok", ZIP_FL_UNCHANGED, WHEN_NEVER, 0, 0);
+        }
     }
     if ((idx = zip_name_locate(z, "storedok", 0)) < 0) {
-       fprintf(stderr, "%s: can't locate 'storedok' in zip archive '%s': %s\n", progname, archive, zip_strerror(z));
-       fail++;
+        fprintf(stderr, "%s: can't locate 'storedok' in zip archive '%s': %s\n", progname, archive, zip_strerror(z));
+        fail++;
     }
     else {
-       if (zip_delete(z, (zip_uint64_t)idx) < 0) {
-           fprintf(stderr, "%s: can't replace 'storedok' in zip archive '%s': %s\n", progname, archive, zip_strerror(z));
-           fail++;
-       }
-       else {
-           fail += do_read(z, "storedok", 0, WHEN_OPEN, ZIP_ER_NOENT, 0);
-           fail += do_read(z, "storedok", ZIP_FL_UNCHANGED, WHEN_NEVER, 0, 0);
-       }
+        if (zip_delete(z, (zip_uint64_t)idx) < 0) {
+            fprintf(stderr, "%s: can't replace 'storedok' in zip archive '%s': %s\n", progname, archive, zip_strerror(z));
+            fail++;
+        }
+        else {
+            fail += do_read(z, "storedok", 0, WHEN_OPEN, ZIP_ER_NOENT, 0);
+            fail += do_read(z, "storedok", ZIP_FL_UNCHANGED, WHEN_NEVER, 0, 0);
+        }
     }
     zs = zip_source_buffer(z, "asdf", 4, 0);
     if (zip_file_add(z, "new_file", zs, 0) < 0) {
-       fprintf(stderr, "%s: can't add file to zip archive '%s': %s\n", progname, archive, zip_strerror(z));
-       fail++;
+        fprintf(stderr, "%s: can't add file to zip archive '%s': %s\n", progname, archive, zip_strerror(z));
+        fail++;
     }
     else {
-       fail += do_read(z, "new_file", 0, WHEN_OPEN, ZIP_ER_CHANGED, 0);
+        fail += do_read(z, "new_file", 0, WHEN_OPEN, ZIP_ER_CHANGED, 0);
     }
 
     zip_unchange_all(z);
     if (zip_close(z) == -1) {
-       fprintf(stderr, "%s: can't close zip archive '%s': %s\n", progname, archive, zip_strerror(z));
-       return 1;
+        fprintf(stderr, "%s: can't close zip archive '%s': %s\n", progname, archive, zip_strerror(z));
+        return 1;
     }
 
     exit(fail ? 1 : 0);
@@ -180,33 +180,33 @@ do_read(zip_t *z, const char *name, zip_flags_t flags, enum when when_ex, int ze
     zip_error_set(&error_ex, ze_ex, se_ex);
 
     if ((zf = zip_fopen(z, name, flags)) == NULL) {
-       when_got = WHEN_OPEN;
-       zf_error = zip_get_error(z);
-       zip_error_set(&error_got, zip_error_code_zip(zf_error), zip_error_code_system(zf_error));
+        when_got = WHEN_OPEN;
+        zf_error = zip_get_error(z);
+        zip_error_set(&error_got, zip_error_code_zip(zf_error), zip_error_code_system(zf_error));
     }
     else {
-       while ((n = zip_fread(zf, b, sizeof(b))) > 0)
-           ;
-       if (n < 0) {
-           when_got = WHEN_READ;
-           zf_error = zip_file_get_error(zf);
-           zip_error_set(&error_got, zip_error_code_zip(zf_error), zip_error_code_system(zf_error));
-       }
-       err = zip_fclose(zf);
-       if (when_got == WHEN_NEVER && err != 0) {
-           when_got = WHEN_CLOSE;
-           zip_error_init_with_code(&error_got, err);
-       }
+        while ((n = zip_fread(zf, b, sizeof(b))) > 0)
+            ;
+        if (n < 0) {
+            when_got = WHEN_READ;
+            zf_error = zip_file_get_error(zf);
+            zip_error_set(&error_got, zip_error_code_zip(zf_error), zip_error_code_system(zf_error));
+        }
+        err = zip_fclose(zf);
+        if (when_got == WHEN_NEVER && err != 0) {
+            when_got = WHEN_CLOSE;
+            zip_error_init_with_code(&error_got, err);
+        }
     }
 
     if (when_got != when_ex || zip_error_code_zip(&error_got) != zip_error_code_zip(&error_ex) || zip_error_code_system(&error_got) != zip_error_code_system(&error_ex)) {
-       printf("%s: %s: got %s error (%s), expected %s error (%s)\n", progname, name, when_name[when_got], zip_error_strerror(&error_got), when_name[when_ex], zip_error_strerror(&error_ex));
-       zip_error_fini(&error_got);
-       zip_error_fini(&error_ex);
-       return 1;
+        printf("%s: %s: got %s error (%s), expected %s error (%s)\n", progname, name, when_name[when_got], zip_error_strerror(&error_got), when_name[when_ex], zip_error_strerror(&error_ex));
+        zip_error_fini(&error_got);
+        zip_error_fini(&error_ex);
+        return 1;
     }
     else if (verbose)
-       printf("%s: %s: passed\n", progname, name);
+        printf("%s: %s: passed\n", progname, name);
 
     return 0;
 }
index 28474be..41b7c3f 100644 (file)
@@ -1,6 +1,6 @@
 /*
   fseek.c -- test tool for seeking in zip archives
-  Copyright (C) 2016-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -51,8 +51,8 @@ main(int argc, char *argv[]) {
     progname = argv[0];
 
     if (argc != 4) {
-       fprintf(stderr, USAGE, progname);
-       return 1;
+        fprintf(stderr, USAGE, progname);
+        return 1;
     }
 
     archive = argv[1];
@@ -60,44 +60,44 @@ main(int argc, char *argv[]) {
     offset = (zip_int64_t)strtoull(argv[3], NULL, 10);
 
     if ((z = zip_open(archive, 0, &ze)) == NULL) {
-       zip_error_t error;
-       zip_error_init_with_code(&error, ze);
-       fprintf(stderr, "%s: can't open zip archive '%s': %s\n", progname, archive, zip_error_strerror(&error));
-       zip_error_fini(&error);
-       return 1;
+        zip_error_t error;
+        zip_error_init_with_code(&error, ze);
+        fprintf(stderr, "%s: can't open zip archive '%s': %s\n", progname, archive, zip_error_strerror(&error));
+        zip_error_fini(&error);
+        return 1;
     }
 
     if ((zf = zip_fopen_index(z, index, 0)) == NULL) {
-       fprintf(stderr, "%s: can't open file in archive '%s': %s\n", progname, archive, zip_error_strerror(zip_file_get_error(zf)));
-       zip_close(z);
-       return 1;
+        fprintf(stderr, "%s: can't open file in archive '%s': %s\n", progname, archive, zip_error_strerror(zip_file_get_error(zf)));
+        zip_close(z);
+        return 1;
     }
 
     if (zip_fseek(zf, offset, SEEK_SET) < 0) {
-       fprintf(stderr, "%s: zip_fseek failed: %s\n", progname, zip_error_strerror(zip_file_get_error(zf)));
-       zip_fclose(zf);
-       zip_close(z);
-       return 1;
+        fprintf(stderr, "%s: zip_fseek failed: %s\n", progname, zip_error_strerror(zip_file_get_error(zf)));
+        zip_fclose(zf);
+        zip_close(z);
+        return 1;
     }
 
     while ((n = zip_fread(zf, b, sizeof(b))) > 0) {
-       printf("%.*s", (int)n, b);
+        printf("%.*s", (int)n, b);
     }
     if (n < 0) {
-       fprintf(stderr, "%s: zip_fread failed: %s\n", progname, zip_error_strerror(zip_file_get_error(zf)));
-       zip_fclose(zf);
-       zip_close(z);
-       return 1;
+        fprintf(stderr, "%s: zip_fread failed: %s\n", progname, zip_error_strerror(zip_file_get_error(zf)));
+        zip_fclose(zf);
+        zip_close(z);
+        return 1;
     }
 
     if (zip_fclose(zf) == -1) {
-       fprintf(stderr, "%s: can't close zip archive entry %" PRIu64 " in '%s': %s\n", progname, index, archive, zip_strerror(z));
-       return 1;
+        fprintf(stderr, "%s: can't close zip archive entry %" PRIu64 " in '%s': %s\n", progname, index, archive, zip_strerror(z));
+        return 1;
     }
 
     if (zip_close(z) == -1) {
-       fprintf(stderr, "%s: can't close zip archive '%s': %s\n", progname, archive, zip_strerror(z));
-       return 1;
+        fprintf(stderr, "%s: can't close zip archive '%s': %s\n", progname, archive, zip_strerror(z));
+        return 1;
     }
 
     return 0;
index a0859e0..0a99d33 100644 (file)
@@ -4,8 +4,8 @@
 
 /* fuzz target entry point, works without libFuzzer */
 
-int main(int argc, char **argv)
-{
+int
+main(int argc, char **argv) {
     FILE *f;
     char *buf = NULL;
     long siz_buf;
@@ -27,10 +27,10 @@ int main(int argc, char **argv)
     rewind(f);
 
     if (siz_buf < 1) {
-       goto err;
+        goto err;
     }
 
-    buf = (char*)malloc(siz_buf);
+    buf = (char *)malloc(siz_buf);
     if (buf == NULL) {
         fprintf(stderr, "malloc() failed\n");
         goto err;
@@ -41,7 +41,7 @@ int main(int argc, char **argv)
         goto err;
     }
 
-    (void)LLVMFuzzerTestOneInput((uint8_t*)buf, siz_buf);
+    (void)LLVMFuzzerTestOneInput((uint8_t *)buf, siz_buf);
 
 err:
     free(buf);
index 0222bab..e15033c 100644 (file)
@@ -1,6 +1,6 @@
 /*
  hole.c -- convert huge files with mostly NULs to/from source_hole
- Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
+ Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
 
  This file is part of libzip, a library to manipulate ZIP archives.
  The authors can be contacted at <libzip@nih.at>
@@ -55,38 +55,38 @@ copy_source(zip_source_t *from, zip_source_t *to) {
     zip_int64_t n;
 
     if (zip_source_open(from) < 0) {
-       fprintf(stderr, "%s: can't open source for reading: %s\n", progname, zip_error_strerror(zip_source_error(from)));
-       return -1;
+        fprintf(stderr, "%s: can't open source for reading: %s\n", progname, zip_error_strerror(zip_source_error(from)));
+        return -1;
     }
 
     if (zip_source_begin_write(to) < 0) {
-       fprintf(stderr, "%s: can't open source for writing: %s\n", progname, zip_error_strerror(zip_source_error(to)));
-       zip_source_close(from);
-       return -1;
+        fprintf(stderr, "%s: can't open source for writing: %s\n", progname, zip_error_strerror(zip_source_error(to)));
+        zip_source_close(from);
+        return -1;
     }
 
     while ((n = zip_source_read(from, buf, sizeof(buf))) > 0) {
-       if (zip_source_write(to, buf, (zip_uint64_t)n) != n) {
-           fprintf(stderr, "%s: can't write to source: %s\n", progname, zip_error_strerror(zip_source_error(to)));
-           zip_source_close(from);
-           zip_source_rollback_write(to);
-           return -1;
-       }
+        if (zip_source_write(to, buf, (zip_uint64_t)n) != n) {
+            fprintf(stderr, "%s: can't write to source: %s\n", progname, zip_error_strerror(zip_source_error(to)));
+            zip_source_close(from);
+            zip_source_rollback_write(to);
+            return -1;
+        }
     }
 
     if (n < 0) {
-       fprintf(stderr, "%s: can't read from source: %s\n", progname, zip_error_strerror(zip_source_error(from)));
-       zip_source_close(from);
-       zip_source_rollback_write(to);
-       return -1;
+        fprintf(stderr, "%s: can't read from source: %s\n", progname, zip_error_strerror(zip_source_error(from)));
+        zip_source_close(from);
+        zip_source_rollback_write(to);
+        return -1;
     }
 
     zip_source_close(from);
 
     if (zip_source_commit_write(to) < 0) {
-       fprintf(stderr, "%s: can't commit source: %s\n", progname, zip_error_strerror(zip_source_error(to)));
-       zip_source_rollback_write(to);
-       return -1;
+        fprintf(stderr, "%s: can't commit source: %s\n", progname, zip_error_strerror(zip_source_error(to)));
+        zip_source_rollback_write(to);
+        return -1;
     }
 
     return 0;
@@ -101,9 +101,9 @@ open_compressed(const char *fname, int flags) {
     zip_error_init(&error);
 
     if ((src = source_hole_create(fname, flags, &error)) == NULL) {
-       fprintf(stderr, "%s: can't open compressed file %s: %s\n", progname, fname, zip_error_strerror(&error));
-       zip_error_fini(&error);
-       exit(1);
+        fprintf(stderr, "%s: can't open compressed file %s: %s\n", progname, fname, zip_error_strerror(&error));
+        zip_error_fini(&error);
+        exit(1);
     }
 
     return src;
@@ -118,9 +118,9 @@ open_file(const char *fname) {
     zip_error_init(&error);
 
     if ((src = zip_source_file_create(fname, 0, 0, &error)) == NULL) {
-       fprintf(stderr, "%s: can't open file %s: %s\n", progname, fname, zip_error_strerror(&error));
-       zip_error_fini(&error);
-       exit(1);
+        fprintf(stderr, "%s: can't open file %s: %s\n", progname, fname, zip_error_strerror(&error));
+        zip_error_fini(&error);
+        exit(1);
     }
 
     return src;
@@ -146,39 +146,39 @@ main(int argc, char **argv) {
     progname = argv[0];
 
     while ((c = getopt(argc, argv, "du")) != -1) {
-       switch (c) {
-       case 'd':
-           compress = 0;
-           decompress = 1;
-           break;
-
-       case 'u':
-           compress = 1;
-           decompress = 1;
-           break;
-
-       default:
-           usage();
-           break;
-       }
+        switch (c) {
+        case 'd':
+            compress = 0;
+            decompress = 1;
+            break;
+
+        case 'u':
+            compress = 1;
+            decompress = 1;
+            break;
+
+        default:
+            usage();
+            break;
+        }
     }
 
     if (optind + 2 != argc) {
-       usage();
+        usage();
     }
 
     if (decompress) {
-       from = open_compressed(argv[optind], 0);
+        from = open_compressed(argv[optind], 0);
     }
     else {
-       from = open_file(argv[optind]);
+        from = open_file(argv[optind]);
     }
 
     if (compress) {
-       to = open_compressed(argv[optind + 1], ZIP_CREATE);
+        to = open_compressed(argv[optind + 1], ZIP_CREATE);
     }
     else {
-       to = open_file(argv[optind + 1]);
+        to = open_file(argv[optind + 1]);
     }
 
     err = copy_source(from, to);
diff --git a/regress/liboverride-test.c b/regress/liboverride-test.c
new file mode 100644 (file)
index 0000000..29e4780
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+  liboverride.c -- override function called by zip_open()
+
+  Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
+
+  This file is part of ckmame, a program to check rom sets for MAME.
+  The authors can be contacted at <ckmame@nih.at>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+  3. The name of the author may not be used to endorse or promote
+     products derived from this software without specific prior
+     written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef _WIN32
+int main(int argc, const char *argv[]) {
+    /* Symbol override is not supported on Windows. */
+    if (argc > 1 && strcmp(argv[1], "-v") == 0) {
+        printf("not supported on Windows\n");
+    }
+    exit(1);
+}
+#else
+
+#include <errno.h>
+#include <unistd.h>
+
+#include "zip.h"
+
+/*
+ Some systems bind functions called and defined within a shared library, so the override doesn't work. This program calls zip_open and checks whether the override worked.
+ */
+
+int
+main(int argc, const char *argv[]) {
+    int verbose = 0;
+    int error_code;
+    
+    if (argc > 1 && strcmp(argv[1], "-v") == 0) {
+        verbose = 1;
+    }
+    
+    if (getenv("LIBOVERRIDE_SET") == NULL) {
+        char *cwd = getcwd(NULL, 0);
+        char *so = (char *)malloc(strlen(cwd) + 64);
+        sprintf(so, "%s/libliboverride.so", cwd);
+        setenv("LIBOVERRIDE_SET", "1", 1);
+        setenv("LD_PRELOAD", so, 1);
+        execv(argv[0], (void *)argv);
+        if (verbose) {
+            printf("exec failed: %s\n", strerror(errno));
+        }
+        exit(2);
+    }
+    
+    if (zip_open("nosuchfile", 0, &error_code) != NULL) {
+        /* We expect failure. */
+        if (verbose) {
+            printf("open succeded\n");
+        }
+        exit(1);
+    }
+    if (error_code != 32000) {
+        /* Override didn't take, we didn't get its magic error code. */
+        if (verbose) {
+            printf("got unexpected error %d\n", error_code);
+        }
+        exit(1);
+    }
+    
+    if (verbose) {
+        printf("success\n");
+    }
+    exit(0);
+}
+
+#endif /* not Windows */
diff --git a/regress/liboverride.c b/regress/liboverride.c
new file mode 100644 (file)
index 0000000..200f712
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+  liboverride.c -- override function called by zip_open()
+
+  Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
+
+  This file is part of ckmame, a program to check rom sets for MAME.
+  The authors can be contacted at <ckmame@nih.at>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+  3. The name of the author may not be used to endorse or promote
+     products derived from this software without specific prior
+     written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "zipint.h"
+
+/*
+ Some systems bind functions called and defined within a shared library, so the override doesn't work. This overrides a function called by zip_open to return an invalid error code so we can check whether the override works.
+ */
+
+zip_source_t *
+zip_source_file_create(const char *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error) {
+    if (error != NULL) {
+        error->zip_err = 32000;
+    }
+    
+    return NULL;
+}
diff --git a/regress/lzma-no-eos.zip b/regress/lzma-no-eos.zip
new file mode 100644 (file)
index 0000000..883d851
Binary files /dev/null and b/regress/lzma-no-eos.zip differ
index 0032c71..1141104 100644 (file)
@@ -1,6 +1,6 @@
 /*
   malloc.c -- override *alloc() to allow testing special cases
-  Copyright (C) 2015-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2015-2021 Dieter Baron and Thomas Klausner
 
   This file is part of ckmame, a program to check rom sets for MAME.
   The authors can be contacted at <ckmame@nih.at>
@@ -81,20 +81,20 @@ init(void) {
     char *foo;
     myname = getprogname();
     if (!myname)
-       myname = "(unknown)";
+        myname = "(unknown)";
     if ((foo = getenv("MALLOC_MAX_COUNT")) != NULL)
-       max_count = strtoul(foo, NULL, 0);
+        max_count = strtoul(foo, NULL, 0);
     if ((foo = getenv("MALLOC_MIN_SIZE")) != NULL)
-       min_size = strtoul(foo, NULL, 0);
+        min_size = strtoul(foo, NULL, 0);
     real_calloc = dlsym(RTLD_NEXT, "calloc");
     if (!real_calloc)
-       abort();
+        abort();
     real_malloc = dlsym(RTLD_NEXT, "malloc");
     if (!real_malloc)
-       abort();
+        abort();
     real_realloc = dlsym(RTLD_NEXT, "realloc");
     if (!real_realloc)
-       abort();
+        abort();
     inited = 1;
 }
 
@@ -103,17 +103,17 @@ calloc(size_t number, size_t size) {
     void *ret;
 
     if (!inited) {
-       init();
+        init();
     }
 
     if (number >= min_size / size && count >= max_count) {
-       errno = ENOMEM;
-       return NULL;
+        errno = ENOMEM;
+        return NULL;
     }
 
     ret = real_calloc(number, size);
     if (size >= min_size) {
-       count++;
+        count++;
     }
 
     return ret;
@@ -124,17 +124,17 @@ malloc(size_t size) {
     void *ret;
 
     if (!inited) {
-       init();
+        init();
     }
 
     if (size >= min_size && count >= max_count) {
-       errno = ENOMEM;
-       return NULL;
+        errno = ENOMEM;
+        return NULL;
     }
 
     ret = real_malloc(size);
     if (size >= min_size) {
-       count++;
+        count++;
     }
 
     return ret;
@@ -145,17 +145,17 @@ realloc(void *ptr, size_t size) {
     void *ret;
 
     if (!inited) {
-       init();
+        init();
     }
 
     if (size >= min_size && count >= max_count) {
-       errno = ENOMEM;
-       return NULL;
+        errno = ENOMEM;
+        return NULL;
     }
 
     ret = real_realloc(ptr, size);
     if (size >= min_size) {
-       count++;
+        count++;
     }
 
     return ret;
index eb20037..4523f03 100644 (file)
@@ -1,7 +1,7 @@
 /*
   nonrandomopen.c -- override zip_secure_random
 
-  Copyright (C) 2017-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
 
   This file is part of ckmame, a program to check rom sets for MAME.
   The authors can be contacted at <ckmame@nih.at>
index be585ee..e4585a4 100644 (file)
@@ -1,6 +1,6 @@
 /*
   nonrandomopentest.c -- test nonrandomopen.so
-  Copyright (C) 2017-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
 
   This file is part of ckmame, a program to check rom sets for MAME.
   The authors can be contacted at <ckmame@nih.at>
@@ -43,14 +43,14 @@ main(int argc, const char *argv[]) {
 
 #ifdef HAVE_CRYPTO
     if (!zip_secure_random(buf, sizeof(buf))) {
-       fprintf(stderr, "zip_secure_random returned false\n");
-       exit(1);
+        fprintf(stderr, "zip_secure_random returned false\n");
+        exit(1);
     }
     for (i = 0; i < sizeof(buf); i++) {
-       if (buf[i] != 0) {
-           fprintf(stderr, "non-zero byte found\n");
-           exit(1);
-       }
+        if (buf[i] != 0) {
+            fprintf(stderr, "non-zero byte found\n");
+            exit(1);
+        }
     }
 #endif
     exit(0);
index beeb90e..ab6b018 100644 (file)
@@ -3,5 +3,5 @@ program tryopen
 file testextrabytes.zzip testextrabytes.zip testextrabytes.zip
 args -c testextrabytes.zzip
 return 1
-stdout opening 'testextrabytes.zzip' returned error 21
+stdout opening 'testextrabytes.zzip' returned error 21/2
 stderr 1 errors
index 5078978..1f18deb 100644 (file)
@@ -6,7 +6,7 @@ file incons-file-count-low.zzip incons-file-count-low.zip incons-file-count-low.
 file incons-file-count-overflow.zzip incons-file-count-overflow.zip incons-file-count-overflow.zip
 args incons-file-count-high.zzip incons-file-count-low.zzip incons-file-count-overflow.zzip
 return 1
-stdout opening 'incons-file-count-high.zzip' returned error 21
-stdout opening 'incons-file-count-low.zzip' returned error 21
-stdout opening 'incons-file-count-overflow.zzip' returned error 21
+stdout opening 'incons-file-count-high.zzip' returned error 21/5
+stdout opening 'incons-file-count-low.zzip' returned error 21/5
+stdout opening 'incons-file-count-overflow.zzip' returned error 21/11
 stderr 3 errors
index cda6afb..c0e63a0 100644 (file)
@@ -36,39 +36,39 @@ file incons-local-magic-bad.zzip incons-local-magic-bad.zip incons-local-magic-b
 file incons-local-size-larger.zzip incons-local-size-larger.zip incons-local-size-larger.zip
 args -c incons-archive-comment-longer.zzip incons-archive-comment-shorter.zzip incons-cdoffset.zzip incons-central-compression-method.zzip incons-central-compsize-larger-toolarge.zzip incons-central-compsize-larger.zzip incons-central-compsize-smaller.zzip incons-central-crc.zzip incons-central-date.zzip incons-central-file-comment-longer.zzip incons-central-file-comment-shorter.zzip incons-central-magic-bad.zzip incons-central-magic-bad2.zzip incons-central-size-larger.zzip incons-data.zzip incons-ef-central-size-wrong.zzip incons-ef-local-id-size.zzip incons-ef-local-id.zzip incons-ef-local-size.zzip incons-eocd-magic-bad.zzip incons-file-count-high.zzip incons-file-count-low.zzip incons-file-count-overflow.zzip incons-local-compression-method.zzip incons-local-compsize-larger.zzip incons-local-compsize-smaller.zzip incons-local-crc.zzip incons-local-filename-long.zzip incons-local-filename-missing.zzip incons-local-filename-short.zzip incons-local-filename.zzip incons-local-magic-bad.zzip incons-local-size-larger.zzip
 return 1
-stdout opening 'incons-archive-comment-longer.zzip' returned error 21
-stdout opening 'incons-archive-comment-shorter.zzip' returned error 21
-stdout opening 'incons-cdoffset.zzip' returned error 21
-stdout opening 'incons-central-compression-method.zzip' returned error 21
+stdout opening 'incons-archive-comment-longer.zzip' returned error 21/2
+stdout opening 'incons-archive-comment-shorter.zzip' returned error 21/2
+stdout opening 'incons-cdoffset.zzip' returned error 21/1
+stdout opening 'incons-central-compression-method.zzip' returned error 21/6
 stdout opening 'incons-central-compsize-larger-toolarge.zzip' returned error 19
-stdout opening 'incons-central-compsize-larger.zzip' returned error 21
-stdout opening 'incons-central-compsize-smaller.zzip' returned error 21
-stdout opening 'incons-central-crc.zzip' returned error 21
-stdout opening 'incons-central-date.zzip' returned error 21
-stdout opening 'incons-central-file-comment-longer.zzip' returned error 21
-stdout opening 'incons-central-file-comment-shorter.zzip' returned error 21
+stdout opening 'incons-central-compsize-larger.zzip' returned error 21/6
+stdout opening 'incons-central-compsize-smaller.zzip' returned error 21/6
+stdout opening 'incons-central-crc.zzip' returned error 21/6
+stdout opening 'incons-central-date.zzip' returned error 21/6
+stdout opening 'incons-central-file-comment-longer.zzip' returned error 21/12
+stdout opening 'incons-central-file-comment-shorter.zzip' returned error 21/260
 stdout opening 'incons-central-magic-bad.zzip' returned error 19
 stdout opening 'incons-central-magic-bad2.zzip' returned error 19
-stdout opening 'incons-central-size-larger.zzip' returned error 21
+stdout opening 'incons-central-size-larger.zzip' returned error 21/6
 # tryopen does not test checksums, so this is fine.
 stdout opening 'incons-data.zzip' succeeded, 1 entries
-stdout opening 'incons-ef-central-size-wrong.zzip' returned error 21
-stdout opening 'incons-ef-local-id-size.zzip' returned error 21
+stdout opening 'incons-ef-central-size-wrong.zzip' returned error 21/16
+stdout opening 'incons-ef-local-id-size.zzip' returned error 21/16
 # different extra fields local vs. central is fine
 stdout opening 'incons-ef-local-id.zzip' succeeded, 1 entries
-stdout opening 'incons-ef-local-size.zzip' returned error 21
+stdout opening 'incons-ef-local-size.zzip' returned error 21/16
 stdout opening 'incons-eocd-magic-bad.zzip' returned error 19
-stdout opening 'incons-file-count-high.zzip' returned error 21
-stdout opening 'incons-file-count-low.zzip' returned error 21
-stdout opening 'incons-file-count-overflow.zzip' returned error 21
-stdout opening 'incons-local-compression-method.zzip' returned error 21
-stdout opening 'incons-local-compsize-larger.zzip' returned error 21
-stdout opening 'incons-local-compsize-smaller.zzip' returned error 21
-stdout opening 'incons-local-crc.zzip' returned error 21
+stdout opening 'incons-file-count-high.zzip' returned error 21/5
+stdout opening 'incons-file-count-low.zzip' returned error 21/5
+stdout opening 'incons-file-count-overflow.zzip' returned error 21/11
+stdout opening 'incons-local-compression-method.zzip' returned error 21/6
+stdout opening 'incons-local-compsize-larger.zzip' returned error 21/6
+stdout opening 'incons-local-compsize-smaller.zzip' returned error 21/6
+stdout opening 'incons-local-crc.zzip' returned error 21/6
 stdout opening 'incons-local-filename-long.zzip' returned error 17
-stdout opening 'incons-local-filename-missing.zzip' returned error 21
-stdout opening 'incons-local-filename-short.zzip' returned error 21
-stdout opening 'incons-local-filename.zzip' returned error 21
+stdout opening 'incons-local-filename-missing.zzip' returned error 21/6
+stdout opening 'incons-local-filename-short.zzip' returned error 21/16
+stdout opening 'incons-local-filename.zzip' returned error 21/6
 stdout opening 'incons-local-magic-bad.zzip' returned error 19
-stdout opening 'incons-local-size-larger.zzip' returned error 21
+stdout opening 'incons-local-size-larger.zzip' returned error 21/6
 stderr 31 errors
index d0c154d..2b57e15 100644 (file)
@@ -5,7 +5,7 @@ return 1
 file manyfiles-zip64-modulo.zzip manyfiles-zip64-modulo.zip manyfiles-zip64-modulo.zip
 file manyfiles-fewer.zzip manyfiles-fewer.zip manyfiles-fewer.zip
 file manyfiles-more.zzip manyfiles-more.zip manyfiles-more.zip
-stdout opening 'manyfiles-zip64-modulo.zzip' returned error 21
-stdout opening 'manyfiles-fewer.zzip' returned error 21
-stdout opening 'manyfiles-more.zzip' returned error 21
-stderr 3 errors
\ No newline at end of file
+stdout opening 'manyfiles-zip64-modulo.zzip' returned error 21/5
+stdout opening 'manyfiles-fewer.zzip' returned error 21/5
+stdout opening 'manyfiles-more.zzip' returned error 21/5
+stderr 3 errors
diff --git a/regress/set_compression_lzma_no_eos_to_store.test b/regress/set_compression_lzma_no_eos_to_store.test
new file mode 100644 (file)
index 0000000..793b843
--- /dev/null
@@ -0,0 +1,5 @@
+# change method from lzma-compressed (id 14) without EOS/EOPM marker to stored
+features LIBLZMA
+return 0
+args test.zip  set_file_compression 0 store 0
+file test.zip lzma-no-eos.zip stored-no-eos.zip
diff --git a/regress/set_compression_lzma_to_store.test b/regress/set_compression_lzma_to_store.test
new file mode 100644 (file)
index 0000000..67fc290
--- /dev/null
@@ -0,0 +1,5 @@
+# change method from lzma-compressed (id 14) to stored
+features LIBLZMA
+return 0
+args test.zip  set_file_compression 0 store 0
+file test.zip testfile-lzma.zip testfile-stored-dos.zip
diff --git a/regress/set_compression_store_to_lzma.test b/regress/set_compression_store_to_lzma.test
new file mode 100644 (file)
index 0000000..f5ff530
--- /dev/null
@@ -0,0 +1,5 @@
+# change method from stored to lzma-compressed (Id 14)
+features LIBLZMA
+return 0
+args test.zip  set_file_compression 0 lzma 0
+file test.zip testfile-stored-dos.zip testfile-lzma.zip
diff --git a/regress/set_compression_store_to_zstd.test b/regress/set_compression_store_to_zstd.test
new file mode 100644 (file)
index 0000000..898a3d8
--- /dev/null
@@ -0,0 +1,5 @@
+# change method from stored to zstd-compressed
+features LIBZSTD
+return 0
+args test.zip  set_file_compression 0 zstd 0
+file test.zip testfile-stored-dos.zip testfile-zstd.zip
diff --git a/regress/set_compression_zstd_to_store.test b/regress/set_compression_zstd_to_store.test
new file mode 100644 (file)
index 0000000..6f8cd7e
--- /dev/null
@@ -0,0 +1,5 @@
+# change method from zstd-compressed to stored
+features LIBZSTD
+return 0
+args test.zip  set_file_compression 0 store 0
+file test.zip testfile-zstd.zip testfile-stored-dos.zip
index a4a0ff3..0352114 100644 (file)
@@ -1,6 +1,6 @@
 /*
  source_hole.c -- source for handling huge files that are mostly NULs
- Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
+ Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
 
  This file is part of libzip, a library to manipulate ZIP archives.
  The authors can be contacted at <libzip@nih.at>
@@ -95,7 +95,7 @@ source_hole_create(const char *fname, int flags, zip_error_t *error) {
     hole_t *ud = hole_new(fname, flags, error);
 
     if (ud == NULL) {
-       return NULL;
+        return NULL;
     }
     return zip_source_function_create(source_hole_cb, ud, error);
 }
@@ -106,14 +106,14 @@ buffer_free(buffer_t *buffer) {
     zip_uint64_t i;
 
     if (buffer == NULL) {
-       return;
+        return;
     }
 
     if (buffer->fragment) {
-       for (i = 0; i < buffer->nfragments; i++) {
-           free(buffer->fragment[i]);
-       }
-       free(buffer->fragment);
+        for (i = 0; i < buffer->nfragments; i++) {
+            free(buffer->fragment[i]);
+        }
+        free(buffer->fragment);
     }
     free(buffer);
 }
@@ -125,25 +125,25 @@ buffer_from_file(const char *fname, int flags, zip_error_t *error) {
     FILE *f;
 
     if ((buffer = buffer_new()) == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     if ((flags & ZIP_TRUNCATE) == 0) {
-       if ((f = fopen(fname, "rb")) == NULL) {
-           if (!(errno == ENOENT && (flags & ZIP_CREATE))) {
-               buffer_free(buffer);
-               return NULL;
-           }
-       }
-       else {
-           if (buffer_read_file(buffer, f, error) < 0) {
-               buffer_free(buffer);
-               fclose(f);
-               return NULL;
-           }
-           fclose(f);
-       }
+        if ((f = fopen(fname, "rb")) == NULL) {
+            if (!(errno == ENOENT && (flags & ZIP_CREATE))) {
+                buffer_free(buffer);
+                return NULL;
+            }
+        }
+        else {
+            if (buffer_read_file(buffer, f, error) < 0) {
+                buffer_free(buffer);
+                fclose(f);
+                return NULL;
+            }
+            fclose(f);
+        }
     }
 
     return buffer;
@@ -155,7 +155,7 @@ buffer_new(void) {
     buffer_t *buffer;
 
     if ((buffer = (buffer_t *)malloc(sizeof(*buffer))) == NULL) {
-       return NULL;
+        return NULL;
     }
 
     buffer->fragment = NULL;
@@ -175,28 +175,28 @@ buffer_read(buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length, zip_error_
     length = MY_MIN(length, buffer->size - buffer->offset);
 
     if (length == 0) {
-       return 0;
+        return 0;
     }
     if (length > ZIP_INT64_MAX) {
-       return -1;
+        return -1;
     }
 
     i = buffer->offset / buffer->fragment_size;
     fragment_offset = buffer->offset % buffer->fragment_size;
     n = 0;
     while (n < length) {
-       zip_uint64_t left = MY_MIN(length - n, buffer->fragment_size - fragment_offset);
-
-       if (buffer->fragment[i]) {
-           memcpy(data + n, buffer->fragment[i] + fragment_offset, left);
-       }
-       else {
-           memset(data + n, 0, left);
-       }
-
-       n += left;
-       i++;
-       fragment_offset = 0;
+        zip_uint64_t left = MY_MIN(length - n, buffer->fragment_size - fragment_offset);
+
+        if (buffer->fragment[i]) {
+            memcpy(data + n, buffer->fragment[i] + fragment_offset, left);
+        }
+        else {
+            memset(data + n, 0, left);
+        }
+
+        n += left;
+        i++;
+        fragment_offset = 0;
     }
 
     buffer->offset += n;
@@ -210,65 +210,70 @@ buffer_read_file(buffer_t *buffer, FILE *f, zip_error_t *error) {
     zip_uint64_t i;
 
     if (fread(b, 20, 1, f) != 1) {
-       zip_error_set(error, ZIP_ER_READ, errno);
-       return -1;
+        zip_error_set(error, ZIP_ER_READ, errno);
+        return -1;
     }
 
     if (memcmp(b, MARK_BEGIN, 4) != 0) {
-       zip_error_set(error, ZIP_ER_READ, EFTYPE);
-       return -1;
+        zip_error_set(error, ZIP_ER_READ, EFTYPE);
+        return -1;
     }
 
     buffer->fragment_size = get_u64(b + 4);
     buffer->size = get_u64(b + 12);
+    
+    if (buffer->fragment_size == 0) {
+        zip_error_set(error, ZIP_ER_INCONS, 0);
+        return -1;
+    }
 
-    if (buffer->size + buffer->fragment_size < buffer->size) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return -1;
+    buffer->nfragments = buffer->size / buffer->fragment_size;
+    if (buffer->size % buffer->fragment_size != 0) {
+        buffer->nfragments += 1;
     }
-    buffer->nfragments = (buffer->size + buffer->fragment_size - 1) / buffer->fragment_size;
+    
     if ((buffer->nfragments > SIZE_MAX / sizeof(buffer->fragment[0])) || ((buffer->fragment = (zip_uint8_t **)malloc(sizeof(buffer->fragment[0]) * buffer->nfragments)) == NULL)) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return -1;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return -1;
     }
 
     for (i = 0; i < buffer->nfragments; i++) {
-       buffer->fragment[i] = NULL;
+        buffer->fragment[i] = NULL;
     }
 
     i = 0;
     while (i < buffer->nfragments) {
-       if (fread(b, 4, 1, f) != 1) {
-           zip_error_set(error, ZIP_ER_READ, errno);
-           return -1;
-       }
-
-       if (memcmp(b, MARK_DATA, 4) == 0) {
-           if (buffer->fragment_size > SIZE_MAX) {
-               zip_error_set(error, ZIP_ER_MEMORY, 0);
-               return -1;
-           }
-           if ((buffer->fragment[i] = (zip_uint8_t *)malloc(buffer->fragment_size)) == NULL) {
-               zip_error_set(error, ZIP_ER_MEMORY, 0);
-               return -1;
-           }
-           if (fread(buffer->fragment[i], buffer->fragment_size, 1, f) != 1) {
-               zip_error_set(error, ZIP_ER_READ, errno);
-               return -1;
-           }
-           i++;
-       }
-       else if (memcmp(b, MARK_NUL, 4) == 0) {
-           if (fread(b, 8, 1, f) != 1) {
-               zip_error_set(error, ZIP_ER_READ, errno);
-               return -1;
-           }
-           i += get_u64(b);
-       }
-       else {
-           zip_error_set(error, ZIP_ER_READ, EFTYPE);
-           return -1;
-       }
+        if (fread(b, 4, 1, f) != 1) {
+            zip_error_set(error, ZIP_ER_READ, errno);
+            return -1;
+        }
+
+        if (memcmp(b, MARK_DATA, 4) == 0) {
+            if (buffer->fragment_size > SIZE_MAX) {
+                zip_error_set(error, ZIP_ER_MEMORY, 0);
+                return -1;
+            }
+            if ((buffer->fragment[i] = (zip_uint8_t *)malloc(buffer->fragment_size)) == NULL) {
+                zip_error_set(error, ZIP_ER_MEMORY, 0);
+                return -1;
+            }
+            if (fread(buffer->fragment[i], buffer->fragment_size, 1, f) != 1) {
+                zip_error_set(error, ZIP_ER_READ, errno);
+                return -1;
+            }
+            i++;
+        }
+        else if (memcmp(b, MARK_NUL, 4) == 0) {
+            if (fread(b, 8, 1, f) != 1) {
+                zip_error_set(error, ZIP_ER_READ, errno);
+                return -1;
+            }
+            i += get_u64(b);
+        }
+        else {
+            zip_error_set(error, ZIP_ER_READ, EFTYPE);
+            return -1;
+        }
     }
 
     return 0;
@@ -279,7 +284,7 @@ buffer_seek(buffer_t *buffer, void *data, zip_uint64_t length, zip_error_t *erro
     zip_int64_t new_offset = zip_source_seek_compute_offset(buffer->offset, buffer->size, data, length, error);
 
     if (new_offset < 0) {
-       return -1;
+        return -1;
     }
 
     buffer->offset = (zip_uint64_t)new_offset;
@@ -294,8 +299,8 @@ buffer_to_file(buffer_t *buffer, const char *fname, zip_error_t *error) {
     zip_uint64_t nul_run;
 
     if (f == NULL) {
-       zip_error_set(error, ZIP_ER_OPEN, errno);
-       return -1;
+        zip_error_set(error, ZIP_ER_OPEN, errno);
+        return -1;
     }
 
     fwrite(MARK_BEGIN, 4, 1, f);
@@ -304,27 +309,27 @@ buffer_to_file(buffer_t *buffer, const char *fname, zip_error_t *error) {
 
     nul_run = 0;
     for (i = 0; i * buffer->fragment_size < buffer->size; i++) {
-       if (buffer->fragment[i] == NULL || only_nul(buffer->fragment[i], buffer->fragment_size)) {
-           nul_run++;
-       }
-       else {
-           if (nul_run > 0) {
-               write_nuls(nul_run, f);
-               nul_run = 0;
-           }
-           fwrite(MARK_DATA, 4, 1, f);
-
-           fwrite(buffer->fragment[i], 1, buffer->fragment_size, f);
-       }
+        if (buffer->fragment[i] == NULL || only_nul(buffer->fragment[i], buffer->fragment_size)) {
+            nul_run++;
+        }
+        else {
+            if (nul_run > 0) {
+                write_nuls(nul_run, f);
+                nul_run = 0;
+            }
+            fwrite(MARK_DATA, 4, 1, f);
+
+            fwrite(buffer->fragment[i], 1, buffer->fragment_size, f);
+        }
     }
 
     if (nul_run > 0) {
-       write_nuls(nul_run, f);
+        write_nuls(nul_run, f);
     }
 
     if (fclose(f) != 0) {
-       zip_error_set(error, ZIP_ER_WRITE, errno);
-       return -1;
+        zip_error_set(error, ZIP_ER_WRITE, errno);
+        return -1;
     }
 
     return 0;
@@ -335,60 +340,60 @@ static zip_int64_t
 buffer_write(buffer_t *buffer, const zip_uint8_t *data, zip_uint64_t length, zip_error_t *error) {
     zip_uint8_t **fragment;
     if (buffer->offset + length > buffer->nfragments * buffer->fragment_size) {
-       zip_uint64_t needed_fragments = (buffer->offset + length + buffer->fragment_size - 1) / buffer->fragment_size;
-       zip_uint64_t new_capacity = buffer->nfragments;
-       zip_uint64_t i;
-
-       if (new_capacity == 0) {
-           new_capacity = 4;
-       }
-       while (new_capacity < needed_fragments) {
-           new_capacity *= 2;
-       }
-
-       fragment = realloc(buffer->fragment, new_capacity * sizeof(*fragment));
-
-       if (fragment == NULL) {
-           zip_error_set(error, ZIP_ER_MEMORY, 0);
-           return -1;
-       }
-
-       for (i = buffer->nfragments; i < new_capacity; i++) {
-           fragment[i] = NULL;
-       }
-
-       buffer->fragment = fragment;
-       buffer->nfragments = new_capacity;
+        zip_uint64_t needed_fragments = (buffer->offset + length + buffer->fragment_size - 1) / buffer->fragment_size;
+        zip_uint64_t new_capacity = buffer->nfragments;
+        zip_uint64_t i;
+
+        if (new_capacity == 0) {
+            new_capacity = 4;
+        }
+        while (new_capacity < needed_fragments) {
+            new_capacity *= 2;
+        }
+
+        fragment = realloc(buffer->fragment, new_capacity * sizeof(*fragment));
+
+        if (fragment == NULL) {
+            zip_error_set(error, ZIP_ER_MEMORY, 0);
+            return -1;
+        }
+
+        for (i = buffer->nfragments; i < new_capacity; i++) {
+            fragment[i] = NULL;
+        }
+
+        buffer->fragment = fragment;
+        buffer->nfragments = new_capacity;
     }
 
     if (!only_nul(data, length)) {
-       zip_uint64_t idx, n, fragment_offset;
-
-       idx = buffer->offset / buffer->fragment_size;
-       fragment_offset = buffer->offset % buffer->fragment_size;
-       n = 0;
-
-       while (n < length) {
-           zip_uint64_t left = MY_MIN(length - n, buffer->fragment_size - fragment_offset);
-
-           if (buffer->fragment[idx] == NULL) {
-               if ((buffer->fragment[idx] = (zip_uint8_t *)malloc(buffer->fragment_size)) == NULL) {
-                   zip_error_set(error, ZIP_ER_MEMORY, 0);
-                   return -1;
-               }
-               memset(buffer->fragment[idx], 0, buffer->fragment_size);
-           }
-           memcpy(buffer->fragment[idx] + fragment_offset, data + n, left);
-
-           n += left;
-           idx++;
-           fragment_offset = 0;
-       }
+        zip_uint64_t idx, n, fragment_offset;
+
+        idx = buffer->offset / buffer->fragment_size;
+        fragment_offset = buffer->offset % buffer->fragment_size;
+        n = 0;
+
+        while (n < length) {
+            zip_uint64_t left = MY_MIN(length - n, buffer->fragment_size - fragment_offset);
+
+            if (buffer->fragment[idx] == NULL) {
+                if ((buffer->fragment[idx] = (zip_uint8_t *)malloc(buffer->fragment_size)) == NULL) {
+                    zip_error_set(error, ZIP_ER_MEMORY, 0);
+                    return -1;
+                }
+                memset(buffer->fragment[idx], 0, buffer->fragment_size);
+            }
+            memcpy(buffer->fragment[idx] + fragment_offset, data + n, left);
+
+            n += left;
+            idx++;
+            fragment_offset = 0;
+        }
     }
 
     buffer->offset += length;
     if (buffer->offset > buffer->size) {
-       buffer->size = buffer->offset;
+        buffer->size = buffer->offset;
     }
 
     return (zip_int64_t)length;
@@ -410,9 +415,9 @@ only_nul(const zip_uint8_t *data, zip_uint64_t length) {
     zip_uint64_t i;
 
     for (i = 0; i < length; i++) {
-       if (data[i] != '\0') {
-           return 0;
-       }
+        if (data[i] != '\0') {
+            return 0;
+        }
     }
 
     return 1;
@@ -422,7 +427,7 @@ only_nul(const zip_uint8_t *data, zip_uint64_t length) {
 static int
 write_nuls(zip_uint64_t n, FILE *f) {
     if (fwrite(MARK_NUL, 4, 1, f) != 1) {
-       return -1;
+        return -1;
     }
     return write_u64(n, f);
 }
@@ -448,7 +453,7 @@ write_u64(zip_uint64_t u64, FILE *f) {
 static void
 hole_free(hole_t *hole) {
     if (hole == NULL) {
-       return;
+        return;
     }
     zip_error_fini(&hole->error);
     buffer_free(hole->in);
@@ -463,19 +468,19 @@ hole_new(const char *fname, int flags, zip_error_t *error) {
     hole_t *ctx = (hole_t *)malloc(sizeof(*ctx));
 
     if (ctx == NULL) {
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     if ((ctx->fname = strdup(fname)) == NULL) {
-       free(ctx);
-       zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return NULL;
+        free(ctx);
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     if ((ctx->in = buffer_from_file(fname, flags, error)) == NULL) {
-       free(ctx);
-       return NULL;
+        free(ctx);
+        return NULL;
     }
 
     zip_error_init(&ctx->error);
@@ -491,82 +496,82 @@ source_hole_cb(void *ud, void *data, zip_uint64_t length, zip_source_cmd_t comma
 
     switch (command) {
     case ZIP_SOURCE_BEGIN_WRITE:
-       ctx->out = buffer_new();
-       return 0;
+        ctx->out = buffer_new();
+        return 0;
 
     case ZIP_SOURCE_CLOSE:
-       return 0;
+        return 0;
 
     case ZIP_SOURCE_COMMIT_WRITE:
-       if (buffer_to_file(ctx->out, ctx->fname, &ctx->error) < 0) {
-           return -1;
-       }
-       buffer_free(ctx->in);
-       ctx->in = ctx->out;
-       ctx->out = NULL;
-       return 0;
+        if (buffer_to_file(ctx->out, ctx->fname, &ctx->error) < 0) {
+            return -1;
+        }
+        buffer_free(ctx->in);
+        ctx->in = ctx->out;
+        ctx->out = NULL;
+        return 0;
 
     case ZIP_SOURCE_ERROR:
-       return zip_error_to_data(&ctx->error, data, length);
+        return zip_error_to_data(&ctx->error, data, length);
 
     case ZIP_SOURCE_FREE:
-       hole_free(ctx);
-       return 0;
+        hole_free(ctx);
+        return 0;
 
     case ZIP_SOURCE_OPEN:
-       ctx->in->offset = 0;
-       return 0;
+        ctx->in->offset = 0;
+        return 0;
 
     case ZIP_SOURCE_READ:
-       return buffer_read(ctx->in, data, length, &ctx->error);
+        return buffer_read(ctx->in, data, length, &ctx->error);
 
     case ZIP_SOURCE_REMOVE:
-       buffer_free(ctx->in);
-       ctx->in = buffer_new();
-       buffer_free(ctx->out);
-       ctx->out = NULL;
-       (void)remove(ctx->fname);
-       return 0;
+        buffer_free(ctx->in);
+        ctx->in = buffer_new();
+        buffer_free(ctx->out);
+        ctx->out = NULL;
+        (void)remove(ctx->fname);
+        return 0;
 
     case ZIP_SOURCE_ROLLBACK_WRITE:
-       buffer_free(ctx->out);
-       ctx->out = NULL;
-       return 0;
+        buffer_free(ctx->out);
+        ctx->out = NULL;
+        return 0;
 
     case ZIP_SOURCE_SEEK:
-       return buffer_seek(ctx->in, data, length, &ctx->error);
+        return buffer_seek(ctx->in, data, length, &ctx->error);
 
     case ZIP_SOURCE_SEEK_WRITE:
-       return buffer_seek(ctx->out, data, length, &ctx->error);
+        return buffer_seek(ctx->out, data, length, &ctx->error);
 
     case ZIP_SOURCE_STAT: {
-       zip_stat_t *st = ZIP_SOURCE_GET_ARGS(zip_stat_t, data, length, &ctx->error);
+        zip_stat_t *st = ZIP_SOURCE_GET_ARGS(zip_stat_t, data, length, &ctx->error);
 
-       if (st == NULL) {
-           return -1;
-       }
+        if (st == NULL) {
+            return -1;
+        }
 
-       /* TODO: return ENOENT if fname doesn't exist */
+        /* TODO: return ENOENT if fname doesn't exist */
 
-       st->valid |= ZIP_STAT_SIZE;
-       st->size = ctx->in->size;
-       return 0;
+        st->valid |= ZIP_STAT_SIZE;
+        st->size = ctx->in->size;
+        return 0;
     }
 
     case ZIP_SOURCE_TELL:
-       return (zip_int64_t)ctx->in->offset;
+        return (zip_int64_t)ctx->in->offset;
 
     case ZIP_SOURCE_TELL_WRITE:
-       return (zip_int64_t)ctx->out->offset;
+        return (zip_int64_t)ctx->out->offset;
 
     case ZIP_SOURCE_WRITE:
-       return buffer_write(ctx->out, data, length, &ctx->error);
+        return buffer_write(ctx->out, data, length, &ctx->error);
 
     case ZIP_SOURCE_SUPPORTS:
-       return zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_CLOSE, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_REMOVE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_STAT, ZIP_SOURCE_TELL, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_WRITE, -1);
+        return zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_CLOSE, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_REMOVE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_STAT, ZIP_SOURCE_TELL, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_WRITE, -1);
 
     default:
-       zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
+        return -1;
     }
 }
diff --git a/regress/stored-no-eos.zip b/regress/stored-no-eos.zip
new file mode 100644 (file)
index 0000000..4a7745f
Binary files /dev/null and b/regress/stored-no-eos.zip differ
index 59abb07..f855b2a 100644 (file)
Binary files a/regress/testfile-lzma.zip and b/regress/testfile-lzma.zip differ
index beb6bdf..1adf554 100644 (file)
Binary files a/regress/testfile-stored-dos.zip and b/regress/testfile-stored-dos.zip differ
diff --git a/regress/testfile-zstd.zip b/regress/testfile-zstd.zip
new file mode 100755 (executable)
index 0000000..bf42d3e
Binary files /dev/null and b/regress/testfile-zstd.zip differ
index d143b0a..54058f2 100644 (file)
@@ -1,6 +1,6 @@
 /*
   tryopen.c -- tool for tests that try opening zip archives
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 #endif
 
 #include "zip.h"
-#define TRYOPEN_USAGE "usage: %s [-cent] file\n\n" \
-                     "\t-c\tcheck consistency\n" \
-                     "\t-e\texclusively open archive\n" \
-                     "\t-n\tcreate new file\n" \
-                     "\t-t\ttruncate file to size 0\n"
+#define TRYOPEN_USAGE                  \
+    "usage: %s [-cent] file\n\n"       \
+    "\t-c\tcheck consistency\n"        \
+    "\t-e\texclusively open archive\n" \
+    "\t-n\tcreate new file\n"          \
+    "\t-t\ttruncate file to size 0\n"
 
 
 int
@@ -59,47 +60,54 @@ main(int argc, char *argv[]) {
     flags = 0;
 
     while ((c = getopt(argc, argv, "cent")) != -1) {
-       switch (c) {
-       case 'c':
-           flags |= ZIP_CHECKCONS;
-           break;
-       case 'e':
-           flags |= ZIP_EXCL;
-           break;
-       case 'n':
-           flags |= ZIP_CREATE;
-           break;
-       case 't':
-           flags |= ZIP_TRUNCATE;
-           break;
-
-       default:
-           fprintf(stderr, TRYOPEN_USAGE, argv[0]);
-           return 1;
-       }
+        switch (c) {
+        case 'c':
+            flags |= ZIP_CHECKCONS;
+            break;
+        case 'e':
+            flags |= ZIP_EXCL;
+            break;
+        case 'n':
+            flags |= ZIP_CREATE;
+            break;
+        case 't':
+            flags |= ZIP_TRUNCATE;
+            break;
+
+        default:
+            fprintf(stderr, TRYOPEN_USAGE, argv[0]);
+            return 1;
+        }
     }
 
     error = 0;
     for (; optind < argc; optind++) {
-       fname = argv[optind];
-       errno = 0;
-
-       if ((z = zip_open(fname, flags, &ze)) != NULL) {
-           count = zip_get_num_entries(z, 0);
-           printf("opening '%s' succeeded, %" PRIu64 " entries\n", fname, count);
-           zip_close(z);
-           continue;
-       }
-
-       printf("opening '%s' returned error %d", fname, ze);
-       if (zip_error_get_sys_type(ze) == ZIP_ET_SYS)
-           printf("/%d", errno);
-       printf("\n");
-       error++;
+        fname = argv[optind];
+        errno = 0;
+
+        if ((z = zip_open(fname, flags, &ze)) != NULL) {
+            count = zip_get_num_entries(z, 0);
+            printf("opening '%s' succeeded, %" PRIu64 " entries\n", fname, count);
+            zip_close(z);
+            continue;
+        }
+
+        printf("opening '%s' returned error %d", fname, ze);
+        switch (zip_error_get_sys_type(ze)) {
+            case ZIP_ET_SYS:
+            case ZIP_ET_LIBZIP:
+                printf("/%d", errno);
+                break;
+                
+            default:
+                break;
+        }
+        printf("\n");
+        error++;
     }
 
     if (error > 0)
-       fprintf(stderr, "%d errors\n", error);
+        fprintf(stderr, "%d errors\n", error);
 
     return error ? 1 : 0;
 }
diff --git a/regress/zipcmp_zip_dir.test b/regress/zipcmp_zip_dir.test
new file mode 100644 (file)
index 0000000..c44d83b
--- /dev/null
@@ -0,0 +1,15 @@
+# compare zip with directory
+features FTS_H
+program zipcmp
+mkdir 0777 a
+mkdir 0777 a/dir-with-file
+mkdir 0777 a/empty-dir-in-dir
+args zipcmp_zip_dir.zip  a
+file zipcmp_zip_dir.zip zipcmp_zip_dir.zip zipcmp_zip_dir.zip
+return 1
+stdout --- zipcmp_zip_dir.zip
+stdout +++ a
+stdout - directory '00-empty-dir/'
+stdout - file 'dir-with-file/a', size 1, crc e8b7be43
+stdout + directory 'empty-dir-in-dir/'
+stdout - directory 'empty-dir/'
diff --git a/regress/zipcmp_zip_dir.zip b/regress/zipcmp_zip_dir.zip
new file mode 100644 (file)
index 0000000..8f47f21
Binary files /dev/null and b/regress/zipcmp_zip_dir.zip differ
index ce51fbd..ee440d2 100644 (file)
@@ -13,6 +13,7 @@ zip_uint64_t fragment_size = 0;
 
 static int add_nul(int argc, char *argv[]);
 static int cancel(int argc, char *argv[]);
+static int unchange_one(int argc, char *argv[]);
 static int unchange_all(int argc, char *argv[]);
 static int zin_close(int argc, char *argv[]);
 
@@ -22,21 +23,26 @@ static int zin_close(int argc, char *argv[]);
 
 #define GETOPT_REGRESS                              \
     case 'H':                                       \
-       source_type = SOURCE_TYPE_HOLE;             \
-       break;                                      \
+        source_type = SOURCE_TYPE_HOLE;             \
+        break;                                      \
     case 'm':                                       \
-       source_type = SOURCE_TYPE_IN_MEMORY;        \
-       break;                                      \
+        source_type = SOURCE_TYPE_IN_MEMORY;        \
+        break;                                      \
     case 'F':                                       \
-       fragment_size = strtoull(optarg, NULL, 10); \
-       break;
+        fragment_size = strtoull(optarg, NULL, 10); \
+        break;
+
+/* clang-format off */
 
 #define DISPATCH_REGRESS \
     {"add_nul", 2, "name length", "add NUL bytes", add_nul}, \
     {"cancel", 1, "limit", "cancel writing archive when limit% have been written (calls print_progress)", cancel}, \
+    {"unchange", 1, "index", "revert changes for entry", unchange_one}, \
     {"unchange_all", 0, "", "revert all changes", unchange_all}, \
     { "zin_close", 1, "index", "close input zip_source (for internal tests)", zin_close }
 
+/* clang-format on */
+
 
 zip_t *ziptool_open(const char *archive, int flags, zip_error_t *error, zip_uint64_t offset, zip_uint64_t len);
 
@@ -58,14 +64,14 @@ add_nul(int argc, char *argv[]) {
     zip_uint64_t length = strtoull(argv[1], NULL, 10);
 
     if ((zs = source_nul(za, length)) == NULL) {
-       fprintf(stderr, "can't create zip_source for length: %s\n", zip_strerror(za));
-       return -1;
+        fprintf(stderr, "can't create zip_source for length: %s\n", zip_strerror(za));
+        return -1;
     }
 
     if (zip_add(za, argv[0], zs) == -1) {
-       zip_source_free(zs);
-       fprintf(stderr, "can't add file '%s': %s\n", argv[0], zip_strerror(za));
-       return -1;
+        zip_source_free(zs);
+        fprintf(stderr, "can't add file '%s': %s\n", argv[0], zip_strerror(za));
+        return -1;
     }
     return 0;
 }
@@ -73,16 +79,32 @@ add_nul(int argc, char *argv[]) {
 static int
 unchange_all(int argc, char *argv[]) {
     if (zip_unchange_all(za) < 0) {
-       fprintf(stderr, "can't revert changes to archive: %s\n", zip_strerror(za));
+        fprintf(stderr, "can't revert changes to archive: %s\n", zip_strerror(za));
+        return -1;
+    }
+    return 0;
+}
+
+
+static int
+unchange_one(int argc, char *argv[]) {
+    zip_uint64_t idx;
+
+    idx = strtoull(argv[0], NULL, 10);
+
+    if (zip_unchange(za, idx) < 0) {
+       fprintf(stderr, "can't revert changes for entry %" PRIu64 ": %s", idx, zip_strerror(za));
        return -1;
     }
+
     return 0;
 }
 
+
 static int
 cancel_callback(zip_t *archive, void *ud) {
     if (progress_userdata.percentage >= progress_userdata.limit) {
-       return -1;
+        return -1;
     }
     return 0;
 }
@@ -92,10 +114,10 @@ cancel(int argc, char *argv[]) {
     zip_int64_t percent;
     percent = strtoll(argv[0], NULL, 10);
     if (percent > 100 || percent < 0) {
-       fprintf(stderr, "invalid percentage '%" PRId64 "' for cancel (valid: 0 <= x <= 100)\n", percent);
-       return -1;
+        fprintf(stderr, "invalid percentage '%" PRId64 "' for cancel (valid: 0 <= x <= 100)\n", percent);
+        return -1;
     }
-    progress_userdata.limit = ((double)percent)/100;
+    progress_userdata.limit = ((double)percent) / 100;
 
     zip_register_cancel_callback_with_state(za, cancel_callback, NULL, NULL);
 
@@ -110,12 +132,12 @@ zin_close(int argc, char *argv[]) {
 
     idx = strtoull(argv[0], NULL, 10);
     if (idx >= z_in_count) {
-       fprintf(stderr, "invalid argument '%" PRIu64 "', only %u zip sources open\n", idx, z_in_count);
-       return -1;
+        fprintf(stderr, "invalid argument '%" PRIu64 "', only %u zip sources open\n", idx, z_in_count);
+        return -1;
     }
     if (zip_close(z_in[idx]) < 0) {
-       fprintf(stderr, "can't close source archive: %s\n", zip_strerror(z_in[idx]));
-       return -1;
+        fprintf(stderr, "can't close source archive: %s\n", zip_strerror(z_in[idx]));
+        return -1;
     }
     z_in[idx] = z_in[z_in_count];
     z_in_count--;
@@ -130,12 +152,12 @@ read_hole(const char *archive, int flags, zip_error_t *error) {
     zip_t *zs = NULL;
 
     if (strcmp(archive, "/dev/stdin") == 0) {
-       zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
+        return NULL;
     }
 
     if ((src = source_hole_create(archive, flags, error)) == NULL || (zs = zip_open_from_source(src, flags, error)) == NULL) {
-       zip_source_free(src);
+        zip_source_free(src);
     }
 
     return zs;
@@ -149,103 +171,103 @@ read_to_memory(const char *archive, int flags, zip_error_t *error, zip_source_t
     FILE *fp;
 
     if (strcmp(archive, "/dev/stdin") == 0) {
-       zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
-       return NULL;
+        zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
+        return NULL;
     }
 
     if ((fp = fopen(archive, "rb")) == NULL) {
-       if (errno == ENOENT) {
-           src = zip_source_buffer_create(NULL, 0, 0, error);
-       }
-       else {
-           zip_error_set(error, ZIP_ER_OPEN, errno);
-           return NULL;
-       }
+        if (errno == ENOENT) {
+            src = zip_source_buffer_create(NULL, 0, 0, error);
+        }
+        else {
+            zip_error_set(error, ZIP_ER_OPEN, errno);
+            return NULL;
+        }
     }
     else {
-       struct stat st;
-
-       if (fstat(fileno(fp), &st) < 0) {
-           fclose(fp);
-           zip_error_set(error, ZIP_ER_OPEN, errno);
-           return NULL;
-       }
-       if (fragment_size == 0) {
-           char *buf;
-           if ((buf = malloc((size_t)st.st_size)) == NULL) {
-               fclose(fp);
-               zip_error_set(error, ZIP_ER_MEMORY, 0);
-               return NULL;
-           }
-           if (fread(buf, (size_t)st.st_size, 1, fp) < 1) {
-               free(buf);
-               fclose(fp);
-               zip_error_set(error, ZIP_ER_READ, errno);
-               return NULL;
-           }
-           src = zip_source_buffer_create(buf, (zip_uint64_t)st.st_size, 1, error);
-           if (src == NULL) {
-               free(buf);
-           }
-       }
-       else {
-           zip_uint64_t nfragments, i, left;
-           zip_buffer_fragment_t *fragments;
-
-           nfragments = ((size_t)st.st_size + fragment_size - 1) / fragment_size;
-           if ((fragments = malloc(sizeof(fragments[0]) * nfragments)) == NULL) {
-               fclose(fp);
-               zip_error_set(error, ZIP_ER_MEMORY, 0);
-               return NULL;
-           }
-           for (i = 0; i < nfragments; i++) {
-               left = ZIP_MIN(fragment_size, (size_t)st.st_size - i * fragment_size);
-               if ((fragments[i].data = malloc(left)) == NULL) {
+        struct stat st;
+
+        if (fstat(fileno(fp), &st) < 0) {
+            fclose(fp);
+            zip_error_set(error, ZIP_ER_OPEN, errno);
+            return NULL;
+        }
+        if (fragment_size == 0) {
+            char *buf;
+            if ((buf = malloc((size_t)st.st_size)) == NULL) {
+                fclose(fp);
+                zip_error_set(error, ZIP_ER_MEMORY, 0);
+                return NULL;
+            }
+            if (fread(buf, (size_t)st.st_size, 1, fp) < 1) {
+                free(buf);
+                fclose(fp);
+                zip_error_set(error, ZIP_ER_READ, errno);
+                return NULL;
+            }
+            src = zip_source_buffer_create(buf, (zip_uint64_t)st.st_size, 1, error);
+            if (src == NULL) {
+                free(buf);
+            }
+        }
+        else {
+            zip_uint64_t nfragments, i, left;
+            zip_buffer_fragment_t *fragments;
+
+            nfragments = ((size_t)st.st_size + fragment_size - 1) / fragment_size;
+            if ((fragments = malloc(sizeof(fragments[0]) * nfragments)) == NULL) {
+                fclose(fp);
+                zip_error_set(error, ZIP_ER_MEMORY, 0);
+                return NULL;
+            }
+            for (i = 0; i < nfragments; i++) {
+                left = ZIP_MIN(fragment_size, (size_t)st.st_size - i * fragment_size);
+                if ((fragments[i].data = malloc(left)) == NULL) {
 #ifndef __clang_analyzer__
                     /* fragments is initialized up to i - 1*/
-                   while (--i > 0) {
-                       free(fragments[i].data);
+                    while (--i > 0) {
+                        free(fragments[i].data);
                     }
 #endif
-                   free(fragments);
-                   fclose(fp);
-                   zip_error_set(error, ZIP_ER_MEMORY, 0);
-                   return NULL;
-               }
-               fragments[i].length = left;
-               if (fread(fragments[i].data, left, 1, fp) < 1) {
+                    free(fragments);
+                    fclose(fp);
+                    zip_error_set(error, ZIP_ER_MEMORY, 0);
+                    return NULL;
+                }
+                fragments[i].length = left;
+                if (fread(fragments[i].data, left, 1, fp) < 1) {
 #ifndef __clang_analyzer__
                     /* fragments is initialized up to i - 1*/
-                   while (--i > 0) {
-                       free(fragments[i].data);
-                   }
+                    while (--i > 0) {
+                        free(fragments[i].data);
+                    }
 #endif
-                   free(fragments);
-                   fclose(fp);
-                   zip_error_set(error, ZIP_ER_READ, errno);
-                   return NULL;
-               }
-           }
-           src = zip_source_buffer_fragment_create(fragments, nfragments, 1, error);
-           if (src == NULL) {
-               for (i = 0; i < nfragments; i++) {
-                   free(fragments[i].data);
-               }
-               free(fragments);
-               fclose(fp);
-               return NULL;
-           }
+                    free(fragments);
+                    fclose(fp);
+                    zip_error_set(error, ZIP_ER_READ, errno);
+                    return NULL;
+                }
+            }
+            src = zip_source_buffer_fragment_create(fragments, nfragments, 1, error);
+            if (src == NULL) {
+                for (i = 0; i < nfragments; i++) {
+                    free(fragments[i].data);
+                }
+                free(fragments);
+                fclose(fp);
+                return NULL;
+            }
             free(fragments);
-       }
-       fclose(fp);
+        }
+        fclose(fp);
     }
     if (src == NULL) {
-       return NULL;
+        return NULL;
     }
     zb = zip_open_from_source(src, flags, error);
     if (zb == NULL) {
-       zip_source_free(src);
-       return NULL;
+        zip_source_free(src);
+        return NULL;
     }
     zip_source_keep(src);
     *srcp = src;
@@ -265,52 +287,52 @@ source_nul_cb(void *ud, void *data, zip_uint64_t length, zip_source_cmd_t comman
 
     switch (command) {
     case ZIP_SOURCE_CLOSE:
-       return 0;
+        return 0;
 
     case ZIP_SOURCE_ERROR:
-       return zip_error_to_data(&ctx->error, data, length);
+        return zip_error_to_data(&ctx->error, data, length);
 
     case ZIP_SOURCE_FREE:
-       free(ctx);
-       return 0;
+        free(ctx);
+        return 0;
 
     case ZIP_SOURCE_OPEN:
-       ctx->offset = 0;
-       return 0;
+        ctx->offset = 0;
+        return 0;
 
     case ZIP_SOURCE_READ:
-       if (length > ZIP_INT64_MAX) {
-           zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
-           return -1;
-       }
+        if (length > ZIP_INT64_MAX) {
+            zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
+            return -1;
+        }
 
-       if (length > ctx->length - ctx->offset) {
-           length = ctx->length - ctx->offset;
-       }
+        if (length > ctx->length - ctx->offset) {
+            length = ctx->length - ctx->offset;
+        }
 
-       memset(data, 0, length);
-       ctx->offset += length;
-       return (zip_int64_t)length;
+        memset(data, 0, length);
+        ctx->offset += length;
+        return (zip_int64_t)length;
 
     case ZIP_SOURCE_STAT: {
-       zip_stat_t *st = ZIP_SOURCE_GET_ARGS(zip_stat_t, data, length, &ctx->error);
+        zip_stat_t *st = ZIP_SOURCE_GET_ARGS(zip_stat_t, data, length, &ctx->error);
 
-       if (st == NULL) {
-           return -1;
-       }
+        if (st == NULL) {
+            return -1;
+        }
 
-       st->valid |= ZIP_STAT_SIZE;
-       st->size = ctx->length;
+        st->valid |= ZIP_STAT_SIZE;
+        st->size = ctx->length;
 
-       return 0;
+        return 0;
     }
 
     case ZIP_SOURCE_SUPPORTS:
-       return zip_source_make_command_bitmap(ZIP_SOURCE_CLOSE, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_STAT, -1);
+        return zip_source_make_command_bitmap(ZIP_SOURCE_CLOSE, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_STAT, -1);
 
     default:
-       zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
-       return -1;
+        zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
+        return -1;
     }
 }
 
@@ -320,8 +342,8 @@ source_nul(zip_t *zs, zip_uint64_t length) {
     zip_source_t *src;
 
     if ((ctx = (source_nul_t *)malloc(sizeof(*ctx))) == NULL) {
-       zip_error_set(zip_get_error(zs), ZIP_ER_MEMORY, 0);
-       return NULL;
+        zip_error_set(zip_get_error(zs), ZIP_ER_MEMORY, 0);
+        return NULL;
     }
 
     zip_error_init(&ctx->error);
@@ -329,8 +351,8 @@ source_nul(zip_t *zs, zip_uint64_t length) {
     ctx->offset = 0;
 
     if ((src = zip_source_function(zs, source_nul_cb, ctx)) == NULL) {
-       free(ctx);
-       return NULL;
+        free(ctx);
+        return NULL;
     }
 
     return src;
@@ -344,47 +366,47 @@ write_memory_src_to_file(const char *archive, zip_source_t *src) {
     FILE *fp;
 
     if (zip_source_stat(src, &zst) < 0) {
-       fprintf(stderr, "zip_source_stat on buffer failed: %s\n", zip_error_strerror(zip_source_error(src)));
-       return -1;
+        fprintf(stderr, "zip_source_stat on buffer failed: %s\n", zip_error_strerror(zip_source_error(src)));
+        return -1;
     }
     if (zip_source_open(src) < 0) {
-       if (zip_error_code_zip(zip_source_error(src)) == ZIP_ER_DELETED) {
-           if (unlink(archive) < 0 && errno != ENOENT) {
-               fprintf(stderr, "unlink failed: %s\n", strerror(errno));
-               return -1;
-           }
-           return 0;
-       }
-       fprintf(stderr, "zip_source_open on buffer failed: %s\n", zip_error_strerror(zip_source_error(src)));
-       return -1;
+        if (zip_error_code_zip(zip_source_error(src)) == ZIP_ER_DELETED) {
+            if (unlink(archive) < 0 && errno != ENOENT) {
+                fprintf(stderr, "unlink failed: %s\n", strerror(errno));
+                return -1;
+            }
+            return 0;
+        }
+        fprintf(stderr, "zip_source_open on buffer failed: %s\n", zip_error_strerror(zip_source_error(src)));
+        return -1;
     }
     if ((buf = malloc(zst.size)) == NULL) {
-       fprintf(stderr, "malloc failed: %s\n", strerror(errno));
-       zip_source_close(src);
-       return -1;
+        fprintf(stderr, "malloc failed: %s\n", strerror(errno));
+        zip_source_close(src);
+        return -1;
     }
     if (zip_source_read(src, buf, zst.size) < (zip_int64_t)zst.size) {
-       fprintf(stderr, "zip_source_read on buffer failed: %s\n", zip_error_strerror(zip_source_error(src)));
-       zip_source_close(src);
-       free(buf);
-       return -1;
+        fprintf(stderr, "zip_source_read on buffer failed: %s\n", zip_error_strerror(zip_source_error(src)));
+        zip_source_close(src);
+        free(buf);
+        return -1;
     }
     zip_source_close(src);
     if ((fp = fopen(archive, "wb")) == NULL) {
-       fprintf(stderr, "fopen failed: %s\n", strerror(errno));
-       free(buf);
-       return -1;
+        fprintf(stderr, "fopen failed: %s\n", strerror(errno));
+        free(buf);
+        return -1;
     }
     if (fwrite(buf, zst.size, 1, fp) < 1) {
-       fprintf(stderr, "fwrite failed: %s\n", strerror(errno));
-       free(buf);
-       fclose(fp);
-       return -1;
+        fprintf(stderr, "fwrite failed: %s\n", strerror(errno));
+        free(buf);
+        fclose(fp);
+        return -1;
     }
     free(buf);
     if (fclose(fp) != 0) {
-       fprintf(stderr, "fclose failed: %s\n", strerror(errno));
-       return -1;
+        fprintf(stderr, "fclose failed: %s\n", strerror(errno));
+        return -1;
     }
     return 0;
 }
@@ -394,16 +416,16 @@ zip_t *
 ziptool_open(const char *archive, int flags, zip_error_t *error, zip_uint64_t offset, zip_uint64_t len) {
     switch (source_type) {
     case SOURCE_TYPE_NONE:
-       za = read_from_file(archive, flags, error, offset, len);
-       break;
+        za = read_from_file(archive, flags, error, offset, len);
+        break;
 
     case SOURCE_TYPE_IN_MEMORY:
-       za = read_to_memory(archive, flags, error, &memory_src);
-       break;
+        za = read_to_memory(archive, flags, error, &memory_src);
+        break;
 
     case SOURCE_TYPE_HOLE:
-       za = read_hole(archive, flags, error);
-       break;
+        za = read_hole(archive, flags, error);
+        break;
     }
 
     return za;
@@ -413,10 +435,10 @@ ziptool_open(const char *archive, int flags, zip_error_t *error, zip_uint64_t of
 int
 ziptool_post_close(const char *archive) {
     if (source_type == SOURCE_TYPE_IN_MEMORY) {
-       if (write_memory_src_to_file(archive, memory_src) < 0) {
-           return -1;
-       }
-       zip_source_free(memory_src);
+        if (write_memory_src_to_file(archive, memory_src) < 0) {
+            return -1;
+        }
+        zip_source_free(memory_src);
     }
 
     return 0;
index b6eb0b1..5d75b8a 100644 (file)
@@ -10,4 +10,5 @@ foreach(PROGRAM zipcmp zipmerge ziptool)
     target_sources(${PROGRAM} PRIVATE getopt.c)
   endif(NOT HAVE_GETOPT)
 endforeach()
+target_sources(zipcmp PRIVATE diff_output.c)
 target_link_libraries(zipcmp ${FTS_LIB} ZLIB::ZLIB)
diff --git a/src/diff_output.c b/src/diff_output.c
new file mode 100644 (file)
index 0000000..2a53f03
--- /dev/null
@@ -0,0 +1,106 @@
+#include "diff_output.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "compat.h"
+
+static void ensure_header(diff_output_t *output) {
+    if (output->archive_names[0] != NULL) {
+        printf("--- %s\n", output->archive_names[0]);
+        printf("+++ %s\n", output->archive_names[1]);
+        output->archive_names[0] = NULL;
+        output->archive_names[1] = NULL;
+    }
+}
+
+void diff_output_init(diff_output_t *output, int verbose, char *const archive_names[]) {
+    output->archive_names[0] = archive_names[0];
+    output->archive_names[1] = archive_names[1];
+    output->verbose = verbose;
+    output->file_name = NULL;
+    output->file_size = 0;
+    output->file_crc = 0;
+}
+
+void diff_output_start_file(diff_output_t *output, const char *name, zip_uint64_t size, zip_uint32_t crc) {
+    output->file_name = name;
+    output->file_size = size;
+    output->file_crc = crc;
+}
+
+void diff_output_end_file(diff_output_t *output) {
+    output->file_name = NULL;
+}
+
+void diff_output(diff_output_t *output, int side, const char *fmt, ...) {
+    va_list ap;
+
+    if (!output->verbose) {
+        return;
+    }
+
+    ensure_header(output);
+    
+    if (output->file_name != NULL) {
+        diff_output_file(output, ' ', output->file_name, output->file_size, output->file_crc);
+        output->file_name = NULL;
+    }
+    
+    printf("%c ", side);
+    va_start(ap, fmt);
+    vprintf(fmt, ap);
+    va_end(ap);
+    printf("\n");
+}
+
+void diff_output_file(diff_output_t *output, char side, const char *name, zip_uint64_t size, zip_uint32_t crc) {
+    if (!output->verbose) {
+        return;
+    }
+    
+    ensure_header(output);
+    
+    if (size == 0 && crc == 0 && name[0] != '\0' && name[strlen(name) - 1] == '/') {
+        printf("%c directory '%s'\n", side, name);
+    }
+    else {
+        printf("%c file '%s', size %" PRIu64 ", crc %08x\n", side, name, size, crc);
+    }
+}
+
+#define MAX_BYTES 64
+void diff_output_data(diff_output_t *output, int side, const zip_uint8_t *data, zip_uint64_t data_length, const char *fmt, ...) {
+    char prefix[1024];
+    char hexdata[MAX_BYTES * 3 + 6];
+    size_t i, offset;
+    va_list ap;
+
+    if (!output->verbose) {
+        return;
+    }
+    
+    offset = 0;
+    for (i = 0; i < data_length; i++) {
+        hexdata[offset++] = (i == 0 ? '<' : ' ');
+
+        if (i >= MAX_BYTES) {
+            sprintf(hexdata + offset, "...");
+            break;
+        }
+        sprintf(hexdata + offset, "%02x", data[i]);
+        offset += 2;
+    }
+
+    hexdata[offset++] = '>';
+    hexdata[offset] = '\0';
+    
+    va_start(ap, fmt);
+    vsnprintf(prefix, sizeof(prefix), fmt, ap);
+    va_end(ap);
+    prefix[sizeof(prefix) - 1] = '\0';
+    
+    diff_output(output, side, "%s, length %" PRIu64 ", data %s", prefix, data_length, hexdata);
+}
diff --git a/src/diff_output.h b/src/diff_output.h
new file mode 100644 (file)
index 0000000..8ac12b8
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef HAD_DIFF_OUTPUT_H
+#define HAD_DIFF_OUTPUT_H
+
+#include <zip.h>
+
+typedef struct {
+    const char *archive_names[2];
+    const char *file_name;
+    zip_uint64_t file_size;
+    zip_uint32_t file_crc;
+    int verbose;
+} diff_output_t;
+
+#if defined(__GNUC__) && __GNUC__ >= 4
+#define PRINTF_LIKE(n, m) __attribute__((__format__(__printf__, n, m)))
+#else
+#define PRINTF_LIKE(n, m)
+#endif
+
+void diff_output_init(diff_output_t *output, int verbose, char *const archive_names[]);
+void diff_output_start_file(diff_output_t *output, const char *name, zip_uint64_t size, zip_uint32_t crc);
+void diff_output_end_file(diff_output_t *output);
+
+void diff_output(diff_output_t *output, int side, const char *fmt, ...) PRINTF_LIKE(3, 4);
+void diff_output_data(diff_output_t *output, int side, const zip_uint8_t *data, zip_uint64_t data_length, const char *fmt, ...) PRINTF_LIKE(5, 6);
+void diff_output_file(diff_output_t *output, char side, const char *name, zip_uint64_t size, zip_uint32_t crc);
+
+#endif /* HAD_DIFF_OUTPUT_H */
index befd672..a9879c4 100644 (file)
@@ -61,50 +61,50 @@ getopt(int nargc, char *const *nargv, const char *ostr) {
     char *oli;                 /* option letter list index */
 
     if (optreset || !*place) { /* update scanning pointer */
-       optreset = 0;
-       if (optind >= nargc || *(place = nargv[optind]) != '-') {
-           place = EMSG;
-           return (EOF);
-       }
-       if (place[1] && *++place == '-') { /* found "--" */
-           ++optind;
-           place = EMSG;
-           return (EOF);
-       }
+        optreset = 0;
+        if (optind >= nargc || *(place = nargv[optind]) != '-') {
+            place = EMSG;
+            return (EOF);
+        }
+        if (place[1] && *++place == '-') { /* found "--" */
+            ++optind;
+            place = EMSG;
+            return (EOF);
+        }
     } /* option letter okay? */
     if ((optopt = (int)*place++) == (int)':' || !(oli = (char *)strchr(ostr, optopt))) {
-       /*
-        * if the user didn't specify '-' as an option,
-        * assume it means EOF.
-        */
-       if (optopt == (int)'-')
-           return (EOF);
-       if (!*place)
-           ++optind;
-       if (opterr && *ostr != ':')
-           (void)fprintf(stderr, "illegal option -- %c\n", optopt);
-       return (BADCH);
+        /*
+         * if the user didn't specify '-' as an option,
+         * assume it means EOF.
+         */
+        if (optopt == (int)'-')
+            return (EOF);
+        if (!*place)
+            ++optind;
+        if (opterr && *ostr != ':')
+            (void)fprintf(stderr, "illegal option -- %c\n", optopt);
+        return (BADCH);
     }
     if (*++oli != ':') { /* don't need argument */
-       optarg = NULL;
-       if (!*place)
-           ++optind;
+        optarg = NULL;
+        if (!*place)
+            ++optind;
     }
     else {          /* need an argument */
-       if (*place) /* no white space */
-           optarg = place;
-       else if (nargc <= ++optind) { /* no arg */
-           place = EMSG;
-           if (*ostr == ':')
-               return (BADARG);
-           if (opterr)
-               (void)fprintf(stderr, "option requires an argument -- %c\n", optopt);
-           return (BADCH);
-       }
-       else /* white space */
-           optarg = nargv[optind];
-       place = EMSG;
-       ++optind;
+        if (*place) /* no white space */
+            optarg = place;
+        else if (nargc <= ++optind) { /* no arg */
+            place = EMSG;
+            if (*ostr == ':')
+                return (BADARG);
+            if (opterr)
+                (void)fprintf(stderr, "option requires an argument -- %c\n", optopt);
+            return (BADCH);
+        }
+        else /* white space */
+            optarg = nargv[optind];
+        place = EMSG;
+        ++optind;
     }
     return (optopt); /* dump back option letter */
 }
index 05669aa..bb09497 100644 (file)
@@ -3,7 +3,7 @@
 
 /*
   getopt.h -- header for getopt() replacement function
-  Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
index 83b70fd..6a1e741 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zipcmp.c -- compare zip files
-  Copyright (C) 2003-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2003-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -55,6 +55,8 @@
 
 #include "compat.h"
 
+#include "diff_output.h"
+
 struct archive {
     const char *name;
     zip_t *za;
@@ -84,6 +86,100 @@ struct entry {
 };
 
 
+typedef struct {
+    uint32_t value;
+    const char * const name;
+} enum_map_t;
+
+const enum_map_t comp_methods[] = {
+    { 0, "Stored (no compression)" },
+    { 1, "Shrunk" },
+    { 2, "Reduced with compression factor 1" },
+    { 3, "Reduced with compression factor 2" },
+    { 4, "Reduced with compression factor 3" },
+    { 5, "Reduced with compression factor 4" },
+    { 6, "Imploded" },
+    { 7, "Reserved for Tokenizing compression algorithm" },
+    { 8, "Deflated" },
+    { 9, "Enhanced Deflating using Deflate64(tm)" },
+    { 10, "PKWARE Data Compression Library Imploding (old IBM TERSE)" },
+    { 11, "11 (Reserved by PKWARE)" },
+    { 12, "BZIP2" },
+    { 13, "13 (Reserved by PKWARE)" },
+    { 14, "LZMA (EFS)" },
+    { 15, "15 (Reserved by PKWARE)" },
+    { 16, "16 (Reserved by PKWARE)" },
+    { 17, "17 (Reserved by PKWARE)" },
+    { 18, "IBM TERSE (new)" },
+    { 19, "IBM LZ77 z Architecture (PFS)" },
+    { 20, "Zstandard compressed data (obsolete)" },
+    { 93, "Zstandard compressed data" },
+    { 95, "XZ compressed data" },
+    { 97, "WavPack compressed data" },
+    { 98, "PPMd version I, Rev 1" },
+    { 99, "WinZIP AES Encryption" },
+    { UINT32_MAX, NULL }
+};
+
+const enum_map_t extra_fields[] = {
+    /* PKWARE defined */
+    { 0x0001, "Zip64 extended information" },
+    { 0x0007, "AV Info" },
+    { 0x0008, "Reserved for extended language encoding data (PFS)" },
+    { 0x0009, "OS/2" },
+    { 0x000a, "NTFS" },
+    { 0x000c, "OpenVMS" },
+    { 0x000d, "UNIX" },
+    { 0x000e, "Reserved for file stream and fork descriptors" },
+    { 0x000f, "Patch Descriptor" },
+    { 0x0014, "PKCS#7 Store for X.509 Certificates" },
+    { 0x0015, "X.509 Certificate ID and Signature for individual file" },
+    { 0x0016, "X.509 Certificate ID for Central Directory" },
+    { 0x0017, "Strong Encryption Header" },
+    { 0x0018, "Record Management Controls" },
+    { 0x0019, "PKCS#7 Encryption Recipient Certificate List" },
+    { 0x0065, "IBM S/390 (Z390), AS/400 (I400) attributes - uncompressed" },
+    { 0x0066, "Reserved for IBM S/390 (Z390), AS/400 (I400) attributes - compressed" },
+    { 0x4690, "POSZIP 4690 (reserved)" },
+
+    /* Third-Party defined; see InfoZIP unzip sources proginfo/extrafld.txt */
+    { 0x07c8, "Info-ZIP Macintosh (old)" },
+    { 0x2605, "ZipIt Macintosh (first version)" },
+    { 0x2705, "ZipIt Macintosh 1.3.5+ (w/o full filename)" },
+    { 0x2805, "ZipIt Macintosh 1.3.5+" },
+    { 0x334d, "Info-ZIP Macintosh (new)" },
+    { 0x4154, "Tandem NSK" },
+    { 0x4341, "Acorn/SparkFS" },
+    { 0x4453, "Windows NT security descriptor" },
+    { 0x4704, "VM/CMS" },
+    { 0x470f, "MVS" },
+    { 0x4854, "Theos, old inofficial port" },
+    { 0x4b46, "FWKCS MD5" },
+    { 0x4c41, "OS/2 access control list (text ACL)" },
+    { 0x4d49, "Info-ZIP OpenVMS (obsolete)" },
+    { 0x4d63, "Macintosh SmartZIP" },
+    { 0x4f4c, "Xceed original location extra field" },
+    { 0x5356, "AOS/VS (ACL)" },
+    { 0x5455, "extended timestamp" },
+    { 0x554e, "Xceed unicode extra field" },
+    { 0x5855, "Info-ZIP UNIX (original)" },
+    { 0x6375, "Info-ZIP UTF-8 comment field" },
+    { 0x6542, "BeOS (BeBox, PowerMac, etc.)" },
+    { 0x6854, "Theos" },
+    { 0x7075, "Info-ZIP UTF-8 name field" },
+    { 0x7441, "AtheOS (AtheOS/Syllable attributes)" },
+    { 0x756e, "ASi UNIX" },
+    { 0x7855, "Info-ZIP UNIX" },
+    { 0x7875, "Info-ZIP UNIX 3rd generation" },
+    { 0x9901, "WinZIP AES encryption" },
+    { 0xa220, "Microsoft Open Packaging Growth Hint" },
+    { 0xcafe, "executable Java JAR file" },
+    { 0xfb4a, "SMS/QDOS" }, /* per InfoZIP extrafld.txt */
+    { 0xfd4a, "SMS/QDOS" }, /* per appnote.txt */
+    { UINT32_MAX, NULL }
+};
+
+
 const char *progname;
 
 #define PROGRAM "zipcmp"
@@ -94,6 +190,7 @@ char help_head[] = PROGRAM " (" PACKAGE ") by Dieter Baron and Thomas Klausner\n
 
 char help[] = "\n\
   -h       display this help message\n\
+  -C       check archive consistencies\n\
   -i       compare names ignoring case distinctions\n\
   -p       compare as many details as possible\n\
   -q       be quiet\n\
@@ -104,33 +201,38 @@ char help[] = "\n\
 Report bugs to <libzip@nih.at>.\n";
 
 char version_string[] = PROGRAM " (" PACKAGE " " VERSION ")\n\
-Copyright (C) 2003-2019 Dieter Baron and Thomas Klausner\n\
+Copyright (C) 2003-2021 Dieter Baron and Thomas Klausner\n\
 " PACKAGE " comes with ABSOLUTELY NO WARRANTY, to the extent permitted by law.\n";
 
-#define OPTIONS "hVipqtv"
+#define OPTIONS "hVCipqtv"
 
 
 #define BOTH_ARE_ZIPS(a) (a[0].za && a[1].za)
 
 static int comment_compare(const char *c1, size_t l1, const char *c2, size_t l2);
-static int compare_list(char *const name[], const void *l[], const zip_uint64_t n[], int size, int (*cmp)(const void *, const void *), int (*checks)(char *const name[2], const void *, const void *), void (*print)(const void *));
+static int compare_list(char *const name[2], const void *list[2], const zip_uint64_t list_length[2], int element_size, int (*cmp)(const void *a, const void *b), int (*ignore)(const void *list, int last, const void *other), int (*check)(char *const name[2], const void *a, const void *b), void (*print)(char side, const void *element), void (*start_file)(const void *element));
 static int compare_zip(char *const zn[]);
 static int ef_compare(char *const name[2], const struct entry *e1, const struct entry *e2);
 static int ef_order(const void *a, const void *b);
-static void ef_print(const void *p);
+static void ef_print(char side, const void *p);
 static int ef_read(zip_t *za, zip_uint64_t idx, struct entry *e);
 static int entry_cmp(const void *p1, const void *p2);
+static int entry_ignore(const void *p1, int last, const void *o);
 static int entry_paranoia_checks(char *const name[2], const void *p1, const void *p2);
-static void entry_print(const void *p);
+static void entry_print(char side, const void *p);
+static void entry_start_file(const void *p);
+static const char *map_enum(const enum_map_t *map, uint32_t value);
+
 static int is_directory(const char *name);
 #ifdef HAVE_FTS_H
 static int list_directory(const char *name, struct archive *a);
 #endif
 static int list_zip(const char *name, struct archive *a);
-static int test_file(zip_t *za, zip_uint64_t idx, zip_uint64_t size, zip_uint32_t crc);
+static int test_file(zip_t *za, zip_uint64_t idx, const char *zipname, const char *filename, zip_uint64_t size, zip_uint32_t crc);
+
+int ignore_case, test_files, paranoid, verbose, have_directory, check_consistency;
 
-int ignore_case, test_files, paranoid, verbose;
-int header_done;
+diff_output_t output;
 
 
 int
@@ -141,45 +243,50 @@ main(int argc, char *const argv[]) {
 
     ignore_case = 0;
     test_files = 0;
+    check_consistency = 0;
     paranoid = 0;
+    have_directory = 0;
     verbose = 1;
 
     while ((c = getopt(argc, argv, OPTIONS)) != -1) {
-       switch (c) {
-       case 'i':
-           ignore_case = 1;
-           break;
-       case 'p':
-           paranoid = 1;
-           break;
-       case 'q':
-           verbose = 0;
-           break;
-       case 't':
-           test_files = 1;
-           break;
-       case 'v':
-           verbose = 1;
-           break;
-
-       case 'h':
-           fputs(help_head, stdout);
-           printf(USAGE, progname);
-           fputs(help, stdout);
-           exit(0);
-       case 'V':
-           fputs(version_string, stdout);
-           exit(0);
-
-       default:
-           fprintf(stderr, USAGE, progname);
-           exit(2);
-       }
+        switch (c) {
+            case 'C':
+                check_consistency = 1;
+                break;
+            case 'i':
+                ignore_case = 1;
+                break;
+            case 'p':
+                paranoid = 1;
+                break;
+            case 'q':
+                verbose = 0;
+                break;
+            case 't':
+                test_files = 1;
+                break;
+            case 'v':
+                verbose = 1;
+                break;
+                
+            case 'h':
+                fputs(help_head, stdout);
+                printf(USAGE, progname);
+                fputs(help, stdout);
+                exit(0);
+            case 'V':
+                fputs(version_string, stdout);
+                exit(0);
+                
+            default:
+                fprintf(stderr, USAGE, progname);
+                exit(2);
+        }
     }
 
     if (argc != optind + 2) {
-       fprintf(stderr, USAGE, progname);
-       exit(2);
+        fprintf(stderr, USAGE, progname);
+        exit(2);
     }
 
     exit((compare_zip(argv + optind) == 0) ? 0 : 1);
@@ -195,70 +302,73 @@ compare_zip(char *const zn[]) {
     int res;
 
     for (i = 0; i < 2; i++) {
-       a[i].name = zn[i];
-       a[i].entry = NULL;
-       a[i].nentry = 0;
-       a[i].za = NULL;
-       a[i].comment = NULL;
-       a[i].comment_length = 0;
-
-       if (is_directory(zn[i])) {
+        a[i].name = zn[i];
+        a[i].entry = NULL;
+        a[i].nentry = 0;
+        a[i].za = NULL;
+        a[i].comment = NULL;
+        a[i].comment_length = 0;
+
+        if (is_directory(zn[i])) {
 #ifndef HAVE_FTS_H
-           fprintf(stderr, "%s: reading directories not supported\n", progname);
-           exit(2);
+            fprintf(stderr, "%s: reading directories not supported\n", progname);
+            exit(2);
 #else
-           if (list_directory(zn[i], a + i) < 0)
-               exit(2);
-           paranoid = 0; /* paranoid checks make no sense for directories, since they compare zip metadata */
+            if (list_directory(zn[i], a + i) < 0)
+                exit(2);
+            have_directory = 1;
+            paranoid = 0; /* paranoid checks make no sense for directories, since they compare zip metadata */
 #endif
-       }
-       else {
-           if (list_zip(zn[i], a + i) < 0)
-               exit(2);
-       }
-       if (a[i].nentry > 0)
-           qsort(a[i].entry, a[i].nentry, sizeof(a[i].entry[0]), entry_cmp);
+        }
+        else {
+            if (list_zip(zn[i], a + i) < 0)
+                exit(2);
+        }
+        if (a[i].nentry > 0)
+            qsort(a[i].entry, a[i].nentry, sizeof(a[i].entry[0]), entry_cmp);
     }
 
-    header_done = 0;
+    diff_output_init(&output, verbose, zn);
 
     e[0] = a[0].entry;
     e[1] = a[1].entry;
     n[0] = a[0].nentry;
     n[1] = a[1].nentry;
-    res = compare_list(zn, (const void **)e, n, sizeof(e[i][0]), entry_cmp, paranoid ? entry_paranoia_checks : NULL, entry_print);
+    res = compare_list(zn, (const void **)e, n, sizeof(e[i][0]), entry_cmp, have_directory ? entry_ignore : NULL, paranoid ? entry_paranoia_checks : NULL, entry_print, entry_start_file);
 
     if (paranoid) {
-       if (comment_compare(a[0].comment, a[0].comment_length, a[1].comment, a[1].comment_length) != 0) {
-           if (verbose) {
-               printf("--- archive comment (%zu)\n", a[0].comment_length);
-               printf("+++ archive comment (%zu)\n", a[1].comment_length);
-           }
-           res = 1;
-       }
+        if (comment_compare(a[0].comment, a[0].comment_length, a[1].comment, a[1].comment_length) != 0) {
+            if (a[0].comment_length > 0) {
+                diff_output_data(&output, '-', (const zip_uint8_t *)a[0].comment, a[0].comment_length, "archive comment");
+            }
+            if (a[1].comment_length > 0) {
+                diff_output_data(&output, '+', (const zip_uint8_t *)a[1].comment, a[1].comment_length, "archive comment");
+            }
+            res = 1;
+        }
     }
 
     for (i = 0; i < 2; i++) {
-       zip_uint64_t j;
-
-       if (a[i].za) {
-           zip_close(a[i].za);
-       }
-       for (j = 0; j < a[i].nentry; j++) {
-           free(a[i].entry[j].name);
-       }
-       free(a[i].entry);
+        zip_uint64_t j;
+
+        if (a[i].za) {
+            zip_close(a[i].za);
+        }
+        for (j = 0; j < a[i].nentry; j++) {
+            free(a[i].entry[j].name);
+        }
+        free(a[i].entry);
     }
 
     switch (res) {
     case 0:
-       exit(0);
+        exit(0);
 
     case 1:
-       exit(1);
+        exit(1);
 
     default:
-       exit(2);
+        exit(2);
     }
 }
 
@@ -272,18 +382,18 @@ compute_crc(const char *fname) {
 
 
     if ((f = fopen(fname, "rb")) == NULL) {
-       fprintf(stderr, "%s: can't open %s: %s\n", progname, fname, strerror(errno));
-       return -1;
+        fprintf(stderr, "%s: can't open %s: %s\n", progname, fname, strerror(errno));
+        return -1;
     }
 
     while ((n = fread(buffer, 1, sizeof(buffer), f)) > 0) {
-       crc = crc32(crc, buffer, (unsigned int)n);
+        crc = crc32(crc, buffer, (unsigned int)n);
     }
 
     if (ferror(f)) {
-       fprintf(stderr, "%s: read error on %s: %s\n", progname, fname, strerror(errno));
-       fclose(f);
-       return -1;
+        fprintf(stderr, "%s: read error on %s: %s\n", progname, fname, strerror(errno));
+        fclose(f);
+        return -1;
     }
 
     fclose(f);
@@ -298,7 +408,7 @@ is_directory(const char *name) {
     struct stat st;
 
     if (stat(name, &st) < 0)
-       return 0;
+        return 0;
 
     return S_ISDIR(st.st_mode);
 }
@@ -316,64 +426,83 @@ list_directory(const char *name, struct archive *a) {
 
 
     if ((fts = fts_open(names, FTS_NOCHDIR | FTS_LOGICAL, NULL)) == NULL) {
-       fprintf(stderr, "%s: can't open directory '%s': %s\n", progname, name, strerror(errno));
-       return -1;
+        fprintf(stderr, "%s: can't open directory '%s': %s\n", progname, name, strerror(errno));
+        return -1;
     }
     prefix_length = strlen(name) + 1;
 
     nalloc = 0;
 
     while ((ent = fts_read(fts))) {
-       zip_int64_t crc;
-
-       switch (ent->fts_info) {
-       case FTS_D:
-       case FTS_DOT:
-       case FTS_DP:
-       case FTS_DEFAULT:
-       case FTS_SL:
-       case FTS_NSOK:
-           break;
-
-       case FTS_DC:
-       case FTS_DNR:
-       case FTS_ERR:
-       case FTS_NS:
-       case FTS_SLNONE:
-           /* TODO: error */
-           fts_close(fts);
-           return -1;
-
-       case FTS_F:
-           if (a->nentry >= nalloc) {
-               nalloc += 16;
-               if (nalloc > SIZE_MAX / sizeof(a->entry[0])) {
-                   fprintf(stderr, "%s: malloc failure\n", progname);
-                   exit(1);
-               }
-               a->entry = realloc(a->entry, sizeof(a->entry[0]) * nalloc);
-               if (a->entry == NULL) {
-                   fprintf(stderr, "%s: malloc failure\n", progname);
-                   exit(1);
-               }
-           }
-
-           a->entry[a->nentry].name = strdup(ent->fts_path + prefix_length);
-           a->entry[a->nentry].size = (zip_uint64_t)ent->fts_statp->st_size;
-           if ((crc = compute_crc(ent->fts_accpath)) < 0) {
-               fts_close(fts);
-               return -1;
-           }
-
-           a->entry[a->nentry].crc = (zip_uint32_t)crc;
-           a->nentry++;
-           break;
-       }
+        zip_int64_t crc;
+
+        switch (ent->fts_info) {
+            case FTS_DOT:
+            case FTS_DP:
+            case FTS_DEFAULT:
+            case FTS_SL:
+            case FTS_NSOK:
+                break;
+
+            case FTS_DC:
+            case FTS_DNR:
+            case FTS_ERR:
+            case FTS_NS:
+            case FTS_SLNONE:
+                /* TODO: error */
+                fts_close(fts);
+                return -1;
+
+            case FTS_D:
+            case FTS_F:
+                if (a->nentry >= nalloc) {
+                    nalloc += 16;
+                    if (nalloc > SIZE_MAX / sizeof(a->entry[0])) {
+                        fprintf(stderr, "%s: malloc failure\n", progname);
+                        exit(1);
+                    }
+                    a->entry = realloc(a->entry, sizeof(a->entry[0]) * nalloc);
+                    if (a->entry == NULL) {
+                        fprintf(stderr, "%s: malloc failure\n", progname);
+                        exit(1);
+                    }
+                }
+                
+                if (ent->fts_info == FTS_D) {
+                    char *dir_name;
+                    
+                    if (ent->fts_path[prefix_length - 1] == '\0') {
+                        break;
+                    }
+                    
+                    dir_name = malloc(strlen(ent->fts_path + prefix_length) + 2);
+                    if (dir_name == NULL) {
+                        fprintf(stderr, "%s: malloc failure\n", progname);
+                        exit(1);
+                    }
+                    sprintf(dir_name, "%s/", ent->fts_path + prefix_length);
+                    a->entry[a->nentry].name = dir_name;
+                    a->entry[a->nentry].size = 0;
+                    a->entry[a->nentry].crc = 0;
+                }
+                else {
+                    a->entry[a->nentry].name = strdup(ent->fts_path + prefix_length);
+                    a->entry[a->nentry].size = (zip_uint64_t)ent->fts_statp->st_size;
+                    if ((crc = compute_crc(ent->fts_accpath)) < 0) {
+                        fts_close(fts);
+                        return -1;
+                    }
+                
+                    a->entry[a->nentry].crc = (zip_uint32_t)crc;
+                }
+                a->nentry++;
+                break;
+        }
     }
 
     if (fts_close(fts)) {
-       fprintf(stderr, "%s: error closing directory '%s': %s\n", progname, a->name, strerror(errno));
-       return -1;
+        fprintf(stderr, "%s: error closing directory '%s': %s\n", progname, a->name, strerror(errno));
+        return -1;
     }
 
     return 0;
@@ -388,52 +517,52 @@ list_zip(const char *name, struct archive *a) {
     struct zip_stat st;
     unsigned int i;
 
-    if ((za = zip_open(name, paranoid ? ZIP_CHECKCONS : 0, &err)) == NULL) {
-       zip_error_t error;
-       zip_error_init_with_code(&error, err);
-       fprintf(stderr, "%s: cannot open zip archive '%s': %s\n", progname, name, zip_error_strerror(&error));
-       zip_error_fini(&error);
-       return -1;
+    if ((za = zip_open(name, check_consistency ? ZIP_CHECKCONS : 0, &err)) == NULL) {
+        zip_error_t error;
+        zip_error_init_with_code(&error, err);
+        fprintf(stderr, "%s: cannot open zip archive '%s': %s\n", progname, name, zip_error_strerror(&error));
+        zip_error_fini(&error);
+        return -1;
     }
 
     a->za = za;
     a->nentry = (zip_uint64_t)zip_get_num_entries(za, 0);
 
     if (a->nentry == 0)
-       a->entry = NULL;
+        a->entry = NULL;
     else {
-       if ((a->nentry > SIZE_MAX / sizeof(a->entry[0])) || (a->entry = (struct entry *)malloc(sizeof(a->entry[0]) * a->nentry)) == NULL) {
-           fprintf(stderr, "%s: malloc failure\n", progname);
-           exit(1);
-       }
-
-       for (i = 0; i < a->nentry; i++) {
-           zip_stat_index(za, i, 0, &st);
-           a->entry[i].name = strdup(st.name);
-           a->entry[i].size = st.size;
-           a->entry[i].crc = st.crc;
-           if (test_files)
-               test_file(za, i, st.size, st.crc);
-           if (paranoid) {
-               a->entry[i].comp_method = st.comp_method;
-               ef_read(za, i, a->entry + i);
-               a->entry[i].comment = zip_file_get_comment(za, i, &a->entry[i].comment_length, 0);
-           }
-           else {
-               a->entry[i].comp_method = 0;
-               a->entry[i].n_extra_fields = 0;
-           }
-       }
-
-       if (paranoid) {
-           int length;
-           a->comment = zip_get_archive_comment(za, &length, 0);
-           a->comment_length = (size_t)length;
-       }
-       else {
-           a->comment = NULL;
-           a->comment_length = 0;
-       }
+        if ((a->nentry > SIZE_MAX / sizeof(a->entry[0])) || (a->entry = (struct entry *)malloc(sizeof(a->entry[0]) * a->nentry)) == NULL) {
+            fprintf(stderr, "%s: malloc failure\n", progname);
+            exit(1);
+        }
+
+        for (i = 0; i < a->nentry; i++) {
+            zip_stat_index(za, i, 0, &st);
+            a->entry[i].name = strdup(st.name);
+            a->entry[i].size = st.size;
+            a->entry[i].crc = st.crc;
+            if (test_files)
+                test_file(za, i, name, st.name, st.size, st.crc);
+            if (paranoid) {
+                a->entry[i].comp_method = st.comp_method;
+                ef_read(za, i, a->entry + i);
+                a->entry[i].comment = zip_file_get_comment(za, i, &a->entry[i].comment_length, 0);
+            }
+            else {
+                a->entry[i].comp_method = 0;
+                a->entry[i].n_extra_fields = 0;
+            }
+        }
+
+        if (paranoid) {
+            int length;
+            a->comment = zip_get_archive_comment(za, &length, 0);
+            a->comment_length = (size_t)length;
+        }
+        else {
+            a->comment = NULL;
+            a->comment_length = 0;
+        }
     }
 
     return 0;
@@ -443,64 +572,66 @@ list_zip(const char *name, struct archive *a) {
 static int
 comment_compare(const char *c1, size_t l1, const char *c2, size_t l2) {
     if (l1 != l2)
-       return 1;
+        return 1;
 
     if (l1 == 0)
-       return 0;
+        return 0;
 
     if (c1 == NULL || c2 == NULL)
-       return c1 == c2;
+        return c1 == c2;
 
     return memcmp(c1, c2, (size_t)l2);
 }
 
 
-static int
-compare_list(char *const name[2], const void *l[2], const zip_uint64_t n[2], int size, int (*cmp)(const void *, const void *), int (*check)(char *const name[2], const void *, const void *), void (*print)(const void *)) {
+static int compare_list(char *const name[2], const void *list[2], const zip_uint64_t list_length[2], int element_size, int (*cmp)(const void *a, const void *b), int (*ignore)(const void *list, int last, const void *other), int (*check)(char *const name[2], const void *a, const void *b), void (*print)(char side, const void *element), void (*start_file)(const void *element)) {
     unsigned int i[2];
-    int j, c;
+    int j;
     int diff;
 
-#define INC(k) (i[k]++, l[k] = ((const char *)l[k]) + size)
+#define INC(k) (i[k]++, list[k] = ((const char *)list[k]) + element_size)
 #define PRINT(k)                                          \
     do {                                                  \
-       if (header_done == 0 && verbose) {                \
-           printf("--- %s\n+++ %s\n", name[0], name[1]); \
-           header_done = 1;                              \
-       }                                                 \
-       if (verbose) {                                    \
-           printf("%c ", (k) ? '+' : '-');               \
-           print(l[k]);                                  \
-       }                                                 \
-       diff = 1;                                         \
+        if (ignore && ignore(list[k], i[k] >= list_length[k] - 1, i[1-k] < list_length[1-k] ? list[1-k] : NULL)) {   \
+            break;                                        \
+        }                                                 \
+        print((k) ? '+' : '-', list[k]);                  \
+        diff = 1;                                         \
     } while (0)
 
     i[0] = i[1] = 0;
     diff = 0;
-    while (i[0] < n[0] && i[1] < n[1]) {
-       c = cmp(l[0], l[1]);
-
-       if (c == 0) {
-           if (check)
-               diff |= check(name, l[0], l[1]);
-           INC(0);
-           INC(1);
-       }
-       else if (c < 0) {
-           PRINT(0);
-           INC(0);
-       }
-       else {
-           PRINT(1);
-           INC(1);
-       }
+    while (i[0] < list_length[0] && i[1] < list_length[1]) {
+        int c = cmp(list[0], list[1]);
+
+        if (c == 0) {
+            if (check) {
+                if (start_file) {
+                    start_file(list[0]);
+                }
+                diff |= check(name, list[0], list[1]);
+                if (start_file) {
+                    diff_output_end_file(&output);
+                }
+            }
+            INC(0);
+            INC(1);
+        }
+        else if (c < 0) {
+            PRINT(0);
+            INC(0);
+        }
+        else {
+            PRINT(1);
+            INC(1);
+        }
     }
 
     for (j = 0; j < 2; j++) {
-       while (i[j] < n[j]) {
-           PRINT(j);
-           INC(j);
-       }
+        while (i[j] < list_length[j]) {
+            PRINT(j);
+            INC(j);
+        }
     }
 
     return diff;
@@ -513,27 +644,27 @@ ef_read(zip_t *za, zip_uint64_t idx, struct entry *e) {
     zip_uint16_t i;
 
     if ((n_local = zip_file_extra_fields_count(za, idx, ZIP_FL_LOCAL)) < 0 || (n_central = zip_file_extra_fields_count(za, idx, ZIP_FL_CENTRAL)) < 0) {
-       return -1;
+        return -1;
     }
 
     e->n_extra_fields = (zip_uint16_t)(n_local + n_central);
 
     if ((e->extra_fields = (struct ef *)malloc(sizeof(e->extra_fields[0]) * e->n_extra_fields)) == NULL)
-       return -1;
+        return -1;
 
     for (i = 0; i < n_local; i++) {
-       e->extra_fields[i].name = e->name;
-       e->extra_fields[i].data = zip_file_extra_field_get(za, idx, i, &e->extra_fields[i].id, &e->extra_fields[i].size, ZIP_FL_LOCAL);
-       if (e->extra_fields[i].data == NULL)
-           return -1;
-       e->extra_fields[i].flags = ZIP_FL_LOCAL;
+        e->extra_fields[i].name = e->name;
+        e->extra_fields[i].data = zip_file_extra_field_get(za, idx, i, &e->extra_fields[i].id, &e->extra_fields[i].size, ZIP_FL_LOCAL);
+        if (e->extra_fields[i].data == NULL)
+            return -1;
+        e->extra_fields[i].flags = ZIP_FL_LOCAL;
     }
     for (; i < e->n_extra_fields; i++) {
-       e->extra_fields[i].name = e->name;
-       e->extra_fields[i].data = zip_file_extra_field_get(za, idx, (zip_uint16_t)(i - n_local), &e->extra_fields[i].id, &e->extra_fields[i].size, ZIP_FL_CENTRAL);
-       if (e->extra_fields[i].data == NULL)
-           return -1;
-       e->extra_fields[i].flags = ZIP_FL_CENTRAL;
+        e->extra_fields[i].name = e->name;
+        e->extra_fields[i].data = zip_file_extra_field_get(za, idx, (zip_uint16_t)(i - n_local), &e->extra_fields[i].id, &e->extra_fields[i].size, ZIP_FL_CENTRAL);
+        if (e->extra_fields[i].data == NULL)
+            return -1;
+        e->extra_fields[i].flags = ZIP_FL_CENTRAL;
     }
 
     qsort(e->extra_fields, e->n_extra_fields, sizeof(e->extra_fields[0]), ef_order);
@@ -552,7 +683,7 @@ ef_compare(char *const name[2], const struct entry *e1, const struct entry *e2)
     n[0] = e1->n_extra_fields;
     n[1] = e2->n_extra_fields;
 
-    return compare_list(name, (const void **)ef, n, sizeof(struct ef), ef_order, NULL, ef_print);
+    return compare_list(name, (const void **)ef, n, sizeof(struct ef), ef_order, NULL, NULL, ef_print, NULL);
 }
 
 
@@ -564,25 +695,20 @@ ef_order(const void *ap, const void *bp) {
     b = (struct ef *)bp;
 
     if (a->flags != b->flags)
-       return a->flags - b->flags;
+        return a->flags - b->flags;
     if (a->id != b->id)
-       return a->id - b->id;
+        return a->id - b->id;
     if (a->size != b->size)
-       return a->size - b->size;
+        return a->size - b->size;
     return memcmp(a->data, b->data, a->size);
 }
 
 
 static void
-ef_print(const void *p) {
+ef_print(char side, const void *p) {
     const struct ef *ef = (struct ef *)p;
-    int i;
 
-    printf("                    %s  ", ef->name);
-    printf("%04x %c <", ef->id, ef->flags == ZIP_FL_LOCAL ? 'l' : 'c');
-    for (i = 0; i < ef->size; i++)
-       printf("%s%02x", i ? " " : "", ef->data[i]);
-    printf(">\n");
+    diff_output_data(&output, side, ef->data, ef->size, "  %s extra field %s", ef->flags == ZIP_FL_LOCAL ? "local" : "central", map_enum(extra_fields, ef->id));
 }
 
 
@@ -595,21 +721,48 @@ entry_cmp(const void *p1, const void *p2) {
     e2 = (struct entry *)p2;
 
     if ((c = (ignore_case ? strcasecmp : strcmp)(e1->name, e2->name)) != 0)
-       return c;
+        return c;
     if (e1->size != e2->size) {
-       if (e1->size > e2->size)
-           return 1;
-       else
-           return -1;
+        if (e1->size > e2->size)
+            return 1;
+        else
+            return -1;
     }
     if (e1->crc != e2->crc)
-       return (int)e1->crc - (int)e2->crc;
+        return (int)e1->crc - (int)e2->crc;
 
     return 0;
 }
 
 
 static int
+entry_ignore(const void *p, int last, const void *o) {
+    const struct entry *e = (const struct entry *)p;
+    const struct entry *other = (const struct entry *)o;
+    
+    size_t length = strlen(e[0].name);
+    
+    if (length == 0 || e[0].name[length - 1] != '/') {
+        /* not a directory */
+        return 0;
+    }
+    
+    if (other != NULL && strlen(other->name) > length && strncmp(other->name, e[0].name, length) == 0) {
+        /* not empty in other archive */
+        return 1;
+    }
+    
+    if (last || (strlen(e[1].name) < length || strncmp(e[0].name, e[1].name, length) != 0)) {
+        /* empty in this archive */
+        return 0;
+    }
+    
+    /* not empty in this archive */
+    return 1;
+}
+
+
+static int
 entry_paranoia_checks(char *const name[2], const void *p1, const void *p2) {
     const struct entry *e1, *e2;
     int ret;
@@ -619,53 +772,42 @@ entry_paranoia_checks(char *const name[2], const void *p1, const void *p2) {
 
     ret = 0;
 
-    if (ef_compare(name, e1, e2) != 0)
-       ret = 1;
-
     if (e1->comp_method != e2->comp_method) {
-       if (verbose) {
-           if (header_done == 0) {
-               printf("--- %s\n+++ %s\n", name[0], name[1]);
-               header_done = 1;
-           }
-           printf("---                     %s  ", e1->name);
-           printf("method %u\n", e1->comp_method);
-           printf("+++                     %s  ", e1->name);
-           printf("method %u\n", e2->comp_method);
-       }
-       ret = 1;
+        diff_output(&output, '-', "  compression method %s", map_enum(comp_methods, e1->comp_method));
+        diff_output(&output, '+', "  compression method %s", map_enum(comp_methods, e2->comp_method));
+        ret = 1;
     }
+
+    if (ef_compare(name, e1, e2) != 0) {
+        ret = 1;
+    }
+
     if (comment_compare(e1->comment, e1->comment_length, e2->comment, e2->comment_length) != 0) {
-       if (verbose) {
-           if (header_done == 0) {
-               printf("--- %s\n+++ %s\n", name[0], name[1]);
-               header_done = 1;
-           }
-           printf("---                     %s  ", e1->name);
-           printf("comment %" PRIu32 "\n", e1->comment_length);
-           printf("+++                     %s  ", e1->name);
-           printf("comment %" PRIu32 "\n", e2->comment_length);
-       }
-       ret = 1;
+        diff_output_data(&output, '-', (const zip_uint8_t *)e1->comment, e1->comment_length, "  comment");
+        diff_output_data(&output, '+', (const zip_uint8_t *)e2->comment, e2->comment_length, "  comment");
+        ret = 1;
     }
 
     return ret;
 }
 
 
-static void
-entry_print(const void *p) {
-    const struct entry *e;
+static void entry_print(char side, const void *p) {
+    const struct entry *e = (struct entry *)p;
+
+    diff_output_file(&output, side, e->name, e->size, e->crc);
+}
 
-    e = (struct entry *)p;
 
-    /* TODO PRId64 */
-    printf("%10lu %08x %s\n", (unsigned long)e->size, e->crc, e->name);
+static void entry_start_file(const void *p) {
+    const struct entry *e = (struct entry *)p;
+    
+    diff_output_start_file(&output, e->name, e->size, e->crc);
 }
 
 
 static int
-test_file(zip_t *za, zip_uint64_t idx, zip_uint64_t size, zip_uint32_t crc) {
+test_file(zip_t *za, zip_uint64_t idx, const char *zipname, const char *filename, zip_uint64_t size, zip_uint32_t crc) {
     zip_file_t *zf;
     char buf[8192];
     zip_uint64_t nsize;
@@ -673,34 +815,52 @@ test_file(zip_t *za, zip_uint64_t idx, zip_uint64_t size, zip_uint32_t crc) {
     zip_uint32_t ncrc;
 
     if ((zf = zip_fopen_index(za, idx, 0)) == NULL) {
-       fprintf(stderr, "%s: cannot open file %" PRIu64 " in archive: %s\n", progname, idx, zip_strerror(za));
-       return -1;
+        fprintf(stderr, "%s: %s: cannot open file %s (index %" PRIu64 "): %s\n", progname, zipname, filename, idx, zip_strerror(za));
+        return -1;
     }
 
     ncrc = (zip_uint32_t)crc32(0, NULL, 0);
     nsize = 0;
 
     while ((n = zip_fread(zf, buf, sizeof(buf))) > 0) {
-       nsize += (zip_uint64_t)n;
-       ncrc = (zip_uint32_t)crc32(ncrc, (const Bytef *)buf, (unsigned int)n);
+        nsize += (zip_uint64_t)n;
+        ncrc = (zip_uint32_t)crc32(ncrc, (const Bytef *)buf, (unsigned int)n);
     }
 
     if (n < 0) {
-       fprintf(stderr, "%s: error reading file %" PRIu64 " in archive: %s\n", progname, idx, zip_file_strerror(zf));
-       zip_fclose(zf);
-       return -1;
+        fprintf(stderr, "%s: %s: error reading file %s (index %" PRIu64 "): %s\n", progname, zipname, filename, idx, zip_file_strerror(zf));
+        zip_fclose(zf);
+        return -1;
     }
 
     zip_fclose(zf);
 
     if (nsize != size) {
-       fprintf(stderr, "%s: file %" PRIu64 ": unexpected length %" PRId64 " (should be %" PRId64 ")\n", progname, idx, nsize, size);
-       return -2;
+        fprintf(stderr, "%s: %s: file %s (index %" PRIu64 "): unexpected length %" PRId64 " (should be %" PRId64 ")\n", progname, zipname, filename, idx, nsize, size);
+        return -2;
     }
     if (ncrc != crc) {
-       fprintf(stderr, "%s: file %" PRIu64 ": unexpected length %x (should be %x)\n", progname, idx, ncrc, crc);
-       return -2;
+        fprintf(stderr, "%s: %s: file %s (index %" PRIu64 "): unexpected length %x (should be %x)\n", progname, zipname, filename, idx, ncrc, crc);
+        return -2;
     }
 
     return 0;
 }
+
+
+static const char *map_enum(const enum_map_t *map, uint32_t value) {
+    static char unknown[16];
+    size_t i = 0;
+    
+    while (map[i].value < UINT32_MAX) {
+        if (map[i].value == value) {
+            return map[i].name;
+        }
+        i++;
+    }
+    
+    snprintf(unknown, sizeof(unknown), "unknown (%u)", value);
+    unknown[sizeof(unknown) - 1] = '\0';
+    
+    return unknown;
+}
index cb3247a..5361321 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zipmerge.c -- merge zip archives
-  Copyright (C) 2004-2019 Dieter Baron and Thomas Klausner
+  Copyright (C) 2004-2021 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -66,7 +66,7 @@ char help[] = "\n\
 Report bugs to <libzip@nih.at>.\n";
 
 char version_string[] = PROGRAM " (" PACKAGE " " VERSION ")\n\
-Copyright (C) 2004-2019 Dieter Baron and Thomas Klausner\n\
+Copyright (C) 2004-2021 Dieter Baron and Thomas Klausner\n\
 " PACKAGE " comes with ABSOLUTELY NO WARRANTY, to the extent permitted by law.\n";
 
 #define OPTIONS "hVDiIsS"
@@ -97,43 +97,43 @@ main(int argc, char *argv[]) {
     name_flags = 0;
 
     while ((c = getopt(argc, argv, OPTIONS)) != -1) {
-       switch (c) {
-       case 'D':
-           name_flags |= ZIP_FL_NODIR;
-           break;
-       case 'i':
-           confirm &= ~CONFIRM_ALL_YES;
-           break;
-       case 'I':
-           name_flags |= ZIP_FL_NOCASE;
-           break;
-       case 's':
-           confirm &= ~CONFIRM_SAME_NO;
-           confirm |= CONFIRM_SAME_YES;
-           break;
-       case 'S':
-           confirm &= ~CONFIRM_SAME_YES;
-           confirm |= CONFIRM_SAME_NO;
-           break;
-
-       case 'h':
-           fputs(help_head, stdout);
-           printf(USAGE, progname);
-           fputs(help, stdout);
-           exit(0);
-       case 'V':
-           fputs(version_string, stdout);
-           exit(0);
-
-       default:
-           fprintf(stderr, USAGE, progname);
-           exit(2);
-       }
+        switch (c) {
+        case 'D':
+            name_flags |= ZIP_FL_NODIR;
+            break;
+        case 'i':
+            confirm &= ~CONFIRM_ALL_YES;
+            break;
+        case 'I':
+            name_flags |= ZIP_FL_NOCASE;
+            break;
+        case 's':
+            confirm &= ~CONFIRM_SAME_NO;
+            confirm |= CONFIRM_SAME_YES;
+            break;
+        case 'S':
+            confirm &= ~CONFIRM_SAME_YES;
+            confirm |= CONFIRM_SAME_NO;
+            break;
+
+        case 'h':
+            fputs(help_head, stdout);
+            printf(USAGE, progname);
+            fputs(help, stdout);
+            exit(0);
+        case 'V':
+            fputs(version_string, stdout);
+            exit(0);
+
+        default:
+            fprintf(stderr, USAGE, progname);
+            exit(2);
+        }
     }
 
     if (argc < optind + 2) {
-       fprintf(stderr, USAGE, progname);
-       exit(2);
+        fprintf(stderr, USAGE, progname);
+        exit(2);
     }
 
     tname = argv[optind++];
@@ -141,30 +141,30 @@ main(int argc, char *argv[]) {
 
     n = (unsigned int)(argc - optind);
     if ((zs = (zip_t **)malloc(sizeof(zs[0]) * n)) == NULL) {
-       fprintf(stderr, "%s: out of memory\n", progname);
-       exit(1);
+        fprintf(stderr, "%s: out of memory\n", progname);
+        exit(1);
     }
 
     if ((za = zip_open(tname, ZIP_CREATE, &err)) == NULL) {
-       zip_error_t error;
-       zip_error_init_with_code(&error, err);
-       fprintf(stderr, "%s: can't open zip archive '%s': %s\n", progname, tname, zip_error_strerror(&error));
-       zip_error_fini(&error);
-       exit(1);
+        zip_error_t error;
+        zip_error_init_with_code(&error, err);
+        fprintf(stderr, "%s: can't open zip archive '%s': %s\n", progname, tname, zip_error_strerror(&error));
+        zip_error_fini(&error);
+        exit(1);
     }
 
     for (i = 0; i < n; i++) {
-       if ((zs[i] = merge_zip(za, tname, argv[i])) == NULL)
-           exit(1);
+        if ((zs[i] = merge_zip(za, tname, argv[i])) == NULL)
+            exit(1);
     }
 
     if (zip_close(za) < 0) {
-       fprintf(stderr, "%s: cannot write zip archive '%s': %s\n", progname, tname, zip_strerror(za));
-       exit(1);
+        fprintf(stderr, "%s: cannot write zip archive '%s': %s\n", progname, tname, zip_strerror(za));
+        exit(1);
     }
 
     for (i = 0; i < n; i++)
-       zip_close(zs[i]);
+        zip_close(zs[i]);
 
     exit(0);
 }
@@ -176,38 +176,38 @@ confirm_replace(zip_t *za, const char *tname, zip_uint64_t it, zip_t *zs, const
     struct zip_stat st, ss;
 
     if (confirm & CONFIRM_ALL_YES)
-       return 1;
+        return 1;
     else if (confirm & CONFIRM_ALL_NO)
-       return 0;
+        return 0;
 
     if (zip_stat_index(za, it, ZIP_FL_UNCHANGED, &st) < 0) {
-       fprintf(stderr, "%s: cannot stat file %" PRIu64 " in '%s': %s\n", progname, it, tname, zip_strerror(za));
-       return -1;
+        fprintf(stderr, "%s: cannot stat file %" PRIu64 " in '%s': %s\n", progname, it, tname, zip_strerror(za));
+        return -1;
     }
     if (zip_stat_index(zs, is, 0, &ss) < 0) {
-       fprintf(stderr, "%s: cannot stat file %" PRIu64 " in '%s': %s\n", progname, is, sname, zip_strerror(zs));
-       return -1;
+        fprintf(stderr, "%s: cannot stat file %" PRIu64 " in '%s': %s\n", progname, is, sname, zip_strerror(zs));
+        return -1;
     }
 
     if (st.size == ss.size && st.crc == ss.crc) {
-       if (confirm & CONFIRM_SAME_YES)
-           return 1;
-       else if (confirm & CONFIRM_SAME_NO)
-           return 0;
+        if (confirm & CONFIRM_SAME_YES)
+            return 1;
+        else if (confirm & CONFIRM_SAME_NO)
+            return 0;
     }
 
     printf("replace '%s' (%" PRIu64 " / %08x) in `%s'\n"
-          "   with '%s' (%" PRIu64 " / %08x) from `%s'? ",
-          st.name, st.size, st.crc, tname, ss.name, ss.size, ss.crc, sname);
+           "   with '%s' (%" PRIu64 " / %08x) from `%s'? ",
+           st.name, st.size, st.crc, tname, ss.name, ss.size, ss.crc, sname);
     fflush(stdout);
 
     if (fgets(line, sizeof(line), stdin) == NULL) {
-       fprintf(stderr, "%s: read error from stdin: %s\n", progname, strerror(errno));
-       return -1;
+        fprintf(stderr, "%s: read error from stdin: %s\n", progname, strerror(errno));
+        return -1;
     }
 
     if (tolower((unsigned char)line[0]) == 'y')
-       return 1;
+        return 1;
 
     return 0;
 }
@@ -223,56 +223,56 @@ merge_zip(zip_t *za, const char *tname, const char *sname) {
     const char *fname;
 
     if ((zs = zip_open(sname, 0, &err)) == NULL) {
-       zip_error_t error;
-       zip_error_init_with_code(&error, err);
-       fprintf(stderr, "%s: can't open zip archive '%s': %s\n", progname, sname, zip_error_strerror(&error));
-       zip_error_fini(&error);
-       return NULL;
+        zip_error_t error;
+        zip_error_init_with_code(&error, err);
+        fprintf(stderr, "%s: can't open zip archive '%s': %s\n", progname, sname, zip_error_strerror(&error));
+        zip_error_fini(&error);
+        return NULL;
     }
 
     ret = zip_get_num_entries(zs, 0);
     if (ret < 0) {
-       fprintf(stderr, "%s: cannot get number of entries for '%s': %s\n", progname, sname, zip_strerror(za));
-       return NULL;
+        fprintf(stderr, "%s: cannot get number of entries for '%s': %s\n", progname, sname, zip_strerror(za));
+        return NULL;
     }
     for (i = 0; i < (zip_uint64_t)ret; i++) {
-       fname = zip_get_name(zs, i, 0);
-
-       if ((idx = zip_name_locate(za, fname, name_flags)) >= 0) {
-           switch (confirm_replace(za, tname, (zip_uint64_t)idx, zs, sname, i)) {
-           case 0:
-               break;
-
-           case 1:
-               if ((source = zip_source_zip(za, zs, i, 0, 0, 0)) == NULL || zip_replace(za, (zip_uint64_t)idx, source) < 0) {
-                   zip_source_free(source);
-                   fprintf(stderr, "%s: cannot replace '%s' in `%s': %s\n", progname, fname, tname, zip_strerror(za));
-                   zip_close(zs);
-                   return NULL;
-               }
-               break;
-
-           case -1:
-               zip_close(zs);
-               return NULL;
-
-           default:
-               fprintf(stderr,
-                       "%s: internal error: "
-                       "unexpected return code from confirm (%d)\n",
-                       progname, err);
-               zip_close(zs);
-               return NULL;
-           }
-       }
-       else {
-           if ((source = zip_source_zip(za, zs, i, 0, 0, 0)) == NULL || zip_add(za, fname, source) < 0) {
-               zip_source_free(source);
-               fprintf(stderr, "%s: cannot add '%s' to `%s': %s\n", progname, fname, tname, zip_strerror(za));
-               zip_close(zs);
-               return NULL;
-           }
-       }
+        fname = zip_get_name(zs, i, 0);
+
+        if ((idx = zip_name_locate(za, fname, name_flags)) >= 0) {
+            switch (confirm_replace(za, tname, (zip_uint64_t)idx, zs, sname, i)) {
+            case 0:
+                break;
+
+            case 1:
+                if ((source = zip_source_zip(za, zs, i, 0, 0, 0)) == NULL || zip_replace(za, (zip_uint64_t)idx, source) < 0) {
+                    zip_source_free(source);
+                    fprintf(stderr, "%s: cannot replace '%s' in `%s': %s\n", progname, fname, tname, zip_strerror(za));
+                    zip_close(zs);
+                    return NULL;
+                }
+                break;
+
+            case -1:
+                zip_close(zs);
+                return NULL;
+
+            default:
+                fprintf(stderr,
+                        "%s: internal error: "
+                        "unexpected return code from confirm (%d)\n",
+                        progname, err);
+                zip_close(zs);
+                return NULL;
+            }
+        }
+        else {
+            if ((source = zip_source_zip(za, zs, i, 0, 0, 0)) == NULL || zip_add(za, fname, source) < 0) {
+                zip_source_free(source);
+                fprintf(stderr, "%s: cannot add '%s' to `%s': %s\n", progname, fname, tname, zip_strerror(za));
+                zip_close(zs);
+                return NULL;
+            }
+        }
     }
 
     return zs;
index cdcecc7..149381b 100644 (file)
@@ -85,14 +85,14 @@ add(int argc, char *argv[]) {
     zip_source_t *zs;
 
     if ((zs = zip_source_buffer(za, argv[1], strlen(argv[1]), 0)) == NULL) {
-       fprintf(stderr, "can't create zip_source from buffer: %s\n", zip_strerror(za));
-       return -1;
+        fprintf(stderr, "can't create zip_source from buffer: %s\n", zip_strerror(za));
+        return -1;
     }
 
     if (zip_add(za, argv[0], zs) == -1) {
-       zip_source_free(zs);
-       fprintf(stderr, "can't add file '%s': %s\n", argv[0], zip_strerror(za));
-       return -1;
+        zip_source_free(zs);
+        fprintf(stderr, "can't add file '%s': %s\n", argv[0], zip_strerror(za));
+        return -1;
     }
     return 0;
 }
@@ -101,8 +101,8 @@ static int
 add_dir(int argc, char *argv[]) {
     /* add directory */
     if (zip_add_dir(za, argv[0]) < 0) {
-       fprintf(stderr, "can't add directory '%s': %s\n", argv[0], zip_strerror(za));
-       return -1;
+        fprintf(stderr, "can't add directory '%s': %s\n", argv[0], zip_strerror(za));
+        return -1;
     }
     return 0;
 }
@@ -114,22 +114,22 @@ add_file(int argc, char *argv[]) {
     zip_int64_t len = strtoll(argv[3], NULL, 10);
 
     if (strcmp(argv[1], "/dev/stdin") == 0) {
-       if ((zs = zip_source_filep(za, stdin, start, len)) == NULL) {
-           fprintf(stderr, "can't create zip_source from stdin: %s\n", zip_strerror(za));
-           return -1;
-       }
+        if ((zs = zip_source_filep(za, stdin, start, len)) == NULL) {
+            fprintf(stderr, "can't create zip_source from stdin: %s\n", zip_strerror(za));
+            return -1;
+        }
     }
     else {
-       if ((zs = zip_source_file(za, argv[1], start, len)) == NULL) {
-           fprintf(stderr, "can't create zip_source from file: %s\n", zip_strerror(za));
-           return -1;
-       }
+        if ((zs = zip_source_file(za, argv[1], start, len)) == NULL) {
+            fprintf(stderr, "can't create zip_source from file: %s\n", zip_strerror(za));
+            return -1;
+        }
     }
 
     if (zip_add(za, argv[0], zs) == -1) {
-       zip_source_free(zs);
-       fprintf(stderr, "can't add file '%s': %s\n", argv[0], zip_strerror(za));
-       return -1;
+        zip_source_free(zs);
+        fprintf(stderr, "can't add file '%s': %s\n", argv[0], zip_strerror(za));
+        return -1;
     }
     return 0;
 }
@@ -145,22 +145,22 @@ add_from_zip(int argc, char *argv[]) {
     start = strtoull(argv[3], NULL, 10);
     len = strtoll(argv[4], NULL, 10);
     if ((z_in[z_in_count] = zip_open(argv[1], ZIP_CHECKCONS, &err)) == NULL) {
-       zip_error_t error;
-       zip_error_init_with_code(&error, err);
-       fprintf(stderr, "can't open zip archive '%s': %s\n", argv[1], zip_error_strerror(&error));
-       zip_error_fini(&error);
-       return -1;
+        zip_error_t error;
+        zip_error_init_with_code(&error, err);
+        fprintf(stderr, "can't open zip archive '%s': %s\n", argv[1], zip_error_strerror(&error));
+        zip_error_fini(&error);
+        return -1;
     }
     if ((zs = zip_source_zip(za, z_in[z_in_count], idx, 0, start, len)) == NULL) {
-       fprintf(stderr, "error creating file source from '%s' index '%" PRIu64 "': %s\n", argv[1], idx, zip_strerror(za));
-       zip_close(z_in[z_in_count]);
-       return -1;
+        fprintf(stderr, "error creating file source from '%s' index '%" PRIu64 "': %s\n", argv[1], idx, zip_strerror(za));
+        zip_close(z_in[z_in_count]);
+        return -1;
     }
     if (zip_add(za, argv[0], zs) == -1) {
-       fprintf(stderr, "can't add file '%s': %s\n", argv[0], zip_strerror(za));
-       zip_source_free(zs);
-       zip_close(z_in[z_in_count]);
-       return -1;
+        fprintf(stderr, "can't add file '%s': %s\n", argv[0], zip_strerror(za));
+        zip_source_free(zs);
+        zip_close(z_in[z_in_count]);
+        return -1;
     }
     z_in_count++;
     return 0;
@@ -181,27 +181,27 @@ cat(int argc, char *argv[]) {
     setmode(fileno(stdout), _O_BINARY);
 #endif
     if ((zf = zip_fopen_index(za, idx, 0)) == NULL) {
-       fprintf(stderr, "can't open file at index '%" PRIu64 "': %s\n", idx, zip_strerror(za));
-       return -1;
+        fprintf(stderr, "can't open file at index '%" PRIu64 "': %s\n", idx, zip_strerror(za));
+        return -1;
     }
     while ((n = zip_fread(zf, buf, sizeof(buf))) > 0) {
-       if (fwrite(buf, (size_t)n, 1, stdout) != 1) {
-           zip_fclose(zf);
-           fprintf(stderr, "can't write file contents to stdout: %s\n", strerror(errno));
-           return -1;
-       }
+        if (fwrite(buf, (size_t)n, 1, stdout) != 1) {
+            zip_fclose(zf);
+            fprintf(stderr, "can't write file contents to stdout: %s\n", strerror(errno));
+            return -1;
+        }
     }
     if (n == -1) {
-       fprintf(stderr, "can't read file at index '%" PRIu64 "': %s\n", idx, zip_file_strerror(zf));
-       zip_fclose(zf);
-       return -1;
+        fprintf(stderr, "can't read file at index '%" PRIu64 "': %s\n", idx, zip_file_strerror(zf));
+        zip_fclose(zf);
+        return -1;
     }
     if ((err = zip_fclose(zf)) != 0) {
-       zip_error_t error;
+        zip_error_t error;
 
-       zip_error_init_with_code(&error, err);
-       fprintf(stderr, "can't close file at index '%" PRIu64 "': %s\n", idx, zip_error_strerror(&error));
-       return -1;
+        zip_error_init_with_code(&error, err);
+        fprintf(stderr, "can't close file at index '%" PRIu64 "': %s\n", idx, zip_error_strerror(&error));
+        return -1;
     }
 
     return 0;
@@ -215,11 +215,11 @@ count_extra(int argc, char *argv[]) {
     idx = strtoull(argv[0], NULL, 10);
     ceflags = get_flags(argv[1]);
     if ((count = zip_file_extra_fields_count(za, idx, ceflags)) < 0) {
-       fprintf(stderr, "can't get extra field count for file at index '%" PRIu64 "': %s\n", idx, zip_strerror(za));
-       return -1;
+        fprintf(stderr, "can't get extra field count for file at index '%" PRIu64 "': %s\n", idx, zip_strerror(za));
+        return -1;
     }
     else {
-       printf("Extra field count: %d\n", count);
+        printf("Extra field count: %d\n", count);
     }
     return 0;
 }
@@ -234,11 +234,11 @@ count_extra_by_id(int argc, char *argv[]) {
     eid = (zip_uint16_t)strtoull(argv[1], NULL, 10);
     ceflags = get_flags(argv[2]);
     if ((count = zip_file_extra_fields_count_by_id(za, idx, eid, ceflags)) < 0) {
-       fprintf(stderr, "can't get extra field count for file at index '%" PRIu64 "' and for id '%d': %s\n", idx, eid, zip_strerror(za));
-       return -1;
+        fprintf(stderr, "can't get extra field count for file at index '%" PRIu64 "' and for id '%d': %s\n", idx, eid, zip_strerror(za));
+        return -1;
     }
     else {
-       printf("Extra field count: %d\n", count);
+        printf("Extra field count: %d\n", count);
     }
     return 0;
 }
@@ -247,8 +247,8 @@ static int delete (int argc, char *argv[]) {
     zip_uint64_t idx;
     idx = strtoull(argv[0], NULL, 10);
     if (zip_delete(za, idx) < 0) {
-       fprintf(stderr, "can't delete file at index '%" PRIu64 "': %s\n", idx, zip_strerror(za));
-       return -1;
+        fprintf(stderr, "can't delete file at index '%" PRIu64 "': %s\n", idx, zip_strerror(za));
+        return -1;
     }
     return 0;
 }
@@ -262,8 +262,8 @@ delete_extra(int argc, char *argv[]) {
     eid = (zip_uint16_t)strtoull(argv[1], NULL, 10);
     geflags = get_flags(argv[2]);
     if ((zip_file_extra_field_delete(za, idx, eid, geflags)) < 0) {
-       fprintf(stderr, "can't delete extra field data for file at index '%" PRIu64 "', extra field id '%d': %s\n", idx, eid, zip_strerror(za));
-       return -1;
+        fprintf(stderr, "can't delete extra field data for file at index '%" PRIu64 "', extra field id '%d': %s\n", idx, eid, zip_strerror(za));
+        return -1;
     }
     return 0;
 }
@@ -278,8 +278,8 @@ delete_extra_by_id(int argc, char *argv[]) {
     eidx = (zip_uint16_t)strtoull(argv[2], NULL, 10);
     geflags = get_flags(argv[3]);
     if ((zip_file_extra_field_delete_by_id(za, idx, eid, eidx, geflags)) < 0) {
-       fprintf(stderr, "can't delete extra field data for file at index '%" PRIu64 "', extra field id '%d', extra field idx '%d': %s\n", idx, eid, eidx, zip_strerror(za));
-       return -1;
+        fprintf(stderr, "can't delete extra field data for file at index '%" PRIu64 "', extra field id '%d', extra field idx '%d': %s\n", idx, eid, eidx, zip_strerror(za));
+        return -1;
     }
     return 0;
 }
@@ -290,9 +290,9 @@ get_archive_comment(int argc, char *argv[]) {
     int len;
     /* get archive comment */
     if ((comment = zip_get_archive_comment(za, &len, 0)) == NULL)
-       printf("No archive comment\n");
+        printf("No archive comment\n");
     else
-       printf("Archive comment: %.*s\n", len, comment);
+        printf("Archive comment: %.*s\n", len, comment);
     return 0;
 }
 
@@ -307,13 +307,13 @@ get_extra(int argc, char *argv[]) {
     eidx = (zip_uint16_t)strtoull(argv[1], NULL, 10);
     geflags = get_flags(argv[2]);
     if ((efdata = zip_file_extra_field_get(za, idx, eidx, &id, &eflen, geflags)) == NULL) {
-       fprintf(stderr, "can't get extra field data for file at index %" PRIu64 ", extra field %d, flags %u: %s\n", idx, eidx, geflags, zip_strerror(za));
-       return -1;
+        fprintf(stderr, "can't get extra field data for file at index %" PRIu64 ", extra field %d, flags %u: %s\n", idx, eidx, geflags, zip_strerror(za));
+        return -1;
     }
     printf("Extra field 0x%04x: len %d", id, eflen);
     if (eflen > 0) {
-       printf(", data ");
-       hexdump(efdata, eflen);
+        printf(", data ");
+        hexdump(efdata, eflen);
     }
     printf("\n");
     return 0;
@@ -330,13 +330,13 @@ get_extra_by_id(int argc, char *argv[]) {
     eidx = (zip_uint16_t)strtoull(argv[2], NULL, 10);
     geflags = get_flags(argv[3]);
     if ((efdata = zip_file_extra_field_get_by_id(za, idx, eid, eidx, &eflen, geflags)) == NULL) {
-       fprintf(stderr, "can't get extra field data for file at index %" PRIu64 ", extra field id %d, ef index %d, flags %u: %s\n", idx, eid, eidx, geflags, zip_strerror(za));
-       return -1;
+        fprintf(stderr, "can't get extra field data for file at index %" PRIu64 ", extra field id %d, ef index %d, flags %u: %s\n", idx, eid, eidx, geflags, zip_strerror(za));
+        return -1;
     }
     printf("Extra field 0x%04x: len %d", eid, eflen);
     if (eflen > 0) {
-       printf(", data ");
-       hexdump(efdata, eflen);
+        printf(", data ");
+        hexdump(efdata, eflen);
     }
     printf("\n");
     return 0;
@@ -350,13 +350,13 @@ get_file_comment(int argc, char *argv[]) {
     /* get file comment */
     idx = strtoull(argv[0], NULL, 10);
     if ((comment = zip_get_file_comment(za, idx, &len, 0)) == NULL) {
-       fprintf(stderr, "can't get comment for '%s': %s\n", zip_get_name(za, idx, 0), zip_strerror(za));
-       return -1;
+        fprintf(stderr, "can't get comment for '%s': %s\n", zip_get_name(za, idx, 0), zip_strerror(za));
+        return -1;
     }
     else if (len == 0)
-       printf("No comment for '%s'\n", zip_get_name(za, idx, 0));
+        printf("No comment for '%s'\n", zip_get_name(za, idx, 0));
     else
-       printf("File comment for '%s': %.*s\n", zip_get_name(za, idx, 0), len, comment);
+        printf("File comment for '%s': %.*s\n", zip_get_name(za, idx, 0), len, comment);
     return 0;
 }
 
@@ -378,18 +378,18 @@ name_locate(int argc, char *argv[]) {
     flags = get_flags(argv[1]);
 
     if ((idx = zip_name_locate(za, argv[0], flags)) < 0) {
-       fprintf(stderr, "can't find entry with name '%s' using flags '%s'\n", argv[0], argv[1]);
+        fprintf(stderr, "can't find entry with name '%s' using flags '%s'\n", argv[0], argv[1]);
     }
     else {
-       printf("name '%s' using flags '%s' found at index %" PRId64 "\n", argv[0], argv[1], idx);
+        printf("name '%s' using flags '%s' found at index %" PRId64 "\n", argv[0], argv[1], idx);
     }
 
     return 0;
 }
 
 struct progress_userdata_s {
-  double percentage;
-  double limit;
+    double percentage;
+    double limit;
 };
 
 struct progress_userdata_s progress_userdata;
@@ -411,8 +411,8 @@ zrename(int argc, char *argv[]) {
     zip_uint64_t idx;
     idx = strtoull(argv[0], NULL, 10);
     if (zip_rename(za, idx, argv[1]) < 0) {
-       fprintf(stderr, "can't rename file at index '%" PRIu64 "' to '%s': %s\n", idx, argv[1], zip_strerror(za));
-       return -1;
+        fprintf(stderr, "can't rename file at index '%" PRIu64 "' to '%s': %s\n", idx, argv[1], zip_strerror(za));
+        return -1;
     }
     return 0;
 }
@@ -426,9 +426,9 @@ replace_file_contents(int argc, char *argv[]) {
     idx = strtoull(argv[0], NULL, 10);
     content = argv[1];
     if ((s = zip_source_buffer(za, content, strlen(content), 0)) == NULL || zip_file_replace(za, idx, s, 0) < 0) {
-       zip_source_free(s);
-       fprintf(stderr, "error replacing file data: %s\n", zip_strerror(za));
-       return -1;
+        zip_source_free(s);
+        fprintf(stderr, "error replacing file data: %s\n", zip_strerror(za));
+        return -1;
     }
     return 0;
 }
@@ -445,8 +445,8 @@ set_extra(int argc, char *argv[]) {
     geflags = get_flags(argv[3]);
     efdata = (zip_uint8_t *)argv[4];
     if ((zip_file_extra_field_set(za, idx, eid, eidx, efdata, (zip_uint16_t)strlen((const char *)efdata), geflags)) < 0) {
-       fprintf(stderr, "can't set extra field data for file at index '%" PRIu64 "', extra field id '%d', index '%d': %s\n", idx, eid, eidx, zip_strerror(za));
-       return -1;
+        fprintf(stderr, "can't set extra field data for file at index '%" PRIu64 "', extra field id '%d', index '%d': %s\n", idx, eid, eidx, zip_strerror(za));
+        return -1;
     }
     return 0;
 }
@@ -454,8 +454,8 @@ set_extra(int argc, char *argv[]) {
 static int
 set_archive_comment(int argc, char *argv[]) {
     if (zip_set_archive_comment(za, argv[0], (zip_uint16_t)strlen(argv[0])) < 0) {
-       fprintf(stderr, "can't set archive comment to '%s': %s\n", argv[0], zip_strerror(za));
-       return -1;
+        fprintf(stderr, "can't set archive comment to '%s': %s\n", argv[0], zip_strerror(za));
+        return -1;
     }
     return 0;
 }
@@ -465,8 +465,8 @@ set_file_comment(int argc, char *argv[]) {
     zip_uint64_t idx;
     idx = strtoull(argv[0], NULL, 10);
     if (zip_file_set_comment(za, idx, argv[1], (zip_uint16_t)strlen(argv[1]), 0) < 0) {
-       fprintf(stderr, "can't set file comment at index '%" PRIu64 "' to '%s': %s\n", idx, argv[1], zip_strerror(za));
-       return -1;
+        fprintf(stderr, "can't set file comment at index '%" PRIu64 "' to '%s': %s\n", idx, argv[1], zip_strerror(za));
+        return -1;
     }
     return 0;
 }
@@ -480,8 +480,8 @@ set_file_compression(int argc, char *argv[]) {
     method = get_compression_method(argv[1]);
     flags = (zip_uint32_t)strtoull(argv[2], NULL, 10);
     if (zip_set_file_compression(za, idx, method, flags) < 0) {
-       fprintf(stderr, "can't set file compression method at index '%" PRIu64 "' to '%s', flags '%" PRIu32 "': %s\n", idx, argv[1], flags, zip_strerror(za));
-       return -1;
+        fprintf(stderr, "can't set file compression method at index '%" PRIu64 "' to '%s', flags '%" PRIu32 "': %s\n", idx, argv[1], flags, zip_strerror(za));
+        return -1;
     }
     return 0;
 }
@@ -495,11 +495,11 @@ set_file_encryption(int argc, char *argv[]) {
     method = get_encryption_method(argv[1]);
     password = argv[2];
     if (strlen(password) == 0) {
-       password = NULL;
+        password = NULL;
     }
     if (zip_file_set_encryption(za, idx, method, password) < 0) {
-       fprintf(stderr, "can't set file encryption method at index '%" PRIu64 "' to '%s': %s\n", idx, argv[1], zip_strerror(za));
-       return -1;
+        fprintf(stderr, "can't set file encryption method at index '%" PRIu64 "' to '%s': %s\n", idx, argv[1], zip_strerror(za));
+        return -1;
     }
     return 0;
 }
@@ -513,8 +513,8 @@ set_file_dostime(int argc, char *argv[]) {
     dostime = (zip_uint16_t)strtoull(argv[1], NULL, 10);
     dosdate = (zip_uint16_t)strtoull(argv[2], NULL, 10);
     if (zip_file_set_dostime(za, idx, dostime, dosdate, 0) < 0) {
-       fprintf(stderr, "can't set file dostime at index '%" PRIu64 "' to '%d'/'%d': %s\n", idx, (int)dostime, (int)dosdate, zip_strerror(za));
-       return -1;
+        fprintf(stderr, "can't set file dostime at index '%" PRIu64 "' to '%d'/'%d': %s\n", idx, (int)dostime, (int)dosdate, zip_strerror(za));
+        return -1;
     }
     return 0;
 }
@@ -527,8 +527,8 @@ set_file_mtime(int argc, char *argv[]) {
     idx = strtoull(argv[0], NULL, 10);
     mtime = (time_t)strtoull(argv[1], NULL, 10);
     if (zip_file_set_mtime(za, idx, mtime, 0) < 0) {
-       fprintf(stderr, "can't set file mtime at index '%" PRIu64 "' to '%lld': %s\n", idx, (long long)mtime, zip_strerror(za));
-       return -1;
+        fprintf(stderr, "can't set file mtime at index '%" PRIu64 "' to '%lld': %s\n", idx, (long long)mtime, zip_strerror(za));
+        return -1;
     }
     return 0;
 }
@@ -542,14 +542,14 @@ set_file_mtime_all(int argc, char *argv[]) {
     mtime = (time_t)strtoull(argv[0], NULL, 10);
 
     if ((num_entries = zip_get_num_entries(za, 0)) < 0) {
-       fprintf(stderr, "can't get number of entries: %s\n", zip_strerror(za));
-       return -1;
+        fprintf(stderr, "can't get number of entries: %s\n", zip_strerror(za));
+        return -1;
     }
     for (idx = 0; idx < (zip_uint64_t)num_entries; idx++) {
-       if (zip_file_set_mtime(za, idx, mtime, 0) < 0) {
-           fprintf(stderr, "can't set file mtime at index '%" PRIu64 "' to '%lld': %s\n", idx, (long long)mtime, zip_strerror(za));
-           return -1;
-       }
+        if (zip_file_set_mtime(za, idx, mtime, 0) < 0) {
+            fprintf(stderr, "can't set file mtime at index '%" PRIu64 "' to '%lld': %s\n", idx, (long long)mtime, zip_strerror(za));
+            return -1;
+        }
     }
     return 0;
 }
@@ -558,8 +558,8 @@ static int
 set_password(int argc, char *argv[]) {
     /* set default password */
     if (zip_set_default_password(za, argv[0]) < 0) {
-       fprintf(stderr, "can't set default password to '%s'\n", argv[0]);
-       return -1;
+        fprintf(stderr, "can't set default password to '%s'\n", argv[0]);
+        return -1;
     }
     return 0;
 }
@@ -572,41 +572,42 @@ zstat(int argc, char *argv[]) {
     idx = strtoull(argv[0], NULL, 10);
 
     if (zip_stat_index(za, idx, stat_flags, &sb) < 0) {
-       fprintf(stderr, "zip_stat_index failed on '%" PRIu64 "' failed: %s\n", idx, zip_strerror(za));
-       return -1;
+        fprintf(stderr, "zip_stat_index failed on '%" PRIu64 "' failed: %s\n", idx, zip_strerror(za));
+        return -1;
     }
 
     if (sb.valid & ZIP_STAT_NAME)
-       printf("name: '%s'\n", sb.name);
+        printf("name: '%s'\n", sb.name);
     if (sb.valid & ZIP_STAT_INDEX)
-       printf("index: '%" PRIu64 "'\n", sb.index);
+        printf("index: '%" PRIu64 "'\n", sb.index);
     if (sb.valid & ZIP_STAT_SIZE)
-       printf("size: '%" PRIu64 "'\n", sb.size);
+        printf("size: '%" PRIu64 "'\n", sb.size);
     if (sb.valid & ZIP_STAT_COMP_SIZE)
-       printf("compressed size: '%" PRIu64 "'\n", sb.comp_size);
+        printf("compressed size: '%" PRIu64 "'\n", sb.comp_size);
     if (sb.valid & ZIP_STAT_MTIME) {
-       struct tm *tpm;
+        struct tm *tpm;
 #ifdef HAVE_LOCALTIME_R
-       struct tm tm;
-       tpm = localtime_r(&sb.mtime, &tm);
+        struct tm tm;
+        tpm = localtime_r(&sb.mtime, &tm);
 #else
-       tpm = localtime(&sb.mtime);
+        tpm = localtime(&sb.mtime);
 #endif
-       if (tpm == NULL) {
-           printf("mtime: <not valid>\n");
-       } else {
-           strftime(buf, sizeof(buf), "%a %b %d %Y %H:%M:%S", tpm);
-           printf("mtime: '%s'\n", buf);
-       }
+        if (tpm == NULL) {
+            printf("mtime: <not valid>\n");
+        }
+        else {
+            strftime(buf, sizeof(buf), "%a %b %d %Y %H:%M:%S", tpm);
+            printf("mtime: '%s'\n", buf);
+        }
     }
     if (sb.valid & ZIP_STAT_CRC)
-       printf("crc: '%0x'\n", sb.crc);
+        printf("crc: '%0x'\n", sb.crc);
     if (sb.valid & ZIP_STAT_COMP_METHOD)
-       printf("compression method: '%d'\n", sb.comp_method);
+        printf("compression method: '%d'\n", sb.comp_method);
     if (sb.valid & ZIP_STAT_ENCRYPTION_METHOD)
-       printf("encryption method: '%d'\n", sb.encryption_method);
+        printf("encryption method: '%d'\n", sb.encryption_method);
     if (sb.valid & ZIP_STAT_FLAGS)
-       printf("flags: '%ld'\n", (long)sb.flags);
+        printf("flags: '%ld'\n", (long)sb.flags);
     printf("\n");
 
     return 0;
@@ -616,62 +617,66 @@ static zip_flags_t
 get_flags(const char *arg) {
     zip_flags_t flags = 0;
     if (strchr(arg, 'C') != NULL)
-       flags |= ZIP_FL_NOCASE;
+        flags |= ZIP_FL_NOCASE;
     if (strchr(arg, 'c') != NULL)
-       flags |= ZIP_FL_CENTRAL;
+        flags |= ZIP_FL_CENTRAL;
     if (strchr(arg, 'd') != NULL)
-       flags |= ZIP_FL_NODIR;
+        flags |= ZIP_FL_NODIR;
     if (strchr(arg, 'l') != NULL)
-       flags |= ZIP_FL_LOCAL;
+        flags |= ZIP_FL_LOCAL;
     if (strchr(arg, 'u') != NULL)
-       flags |= ZIP_FL_UNCHANGED;
+        flags |= ZIP_FL_UNCHANGED;
     return flags;
 }
 
 static zip_int32_t
 get_compression_method(const char *arg) {
     if (strcasecmp(arg, "default") == 0)
-       return ZIP_CM_DEFAULT;
+        return ZIP_CM_DEFAULT;
     else if (strcasecmp(arg, "store") == 0)
-       return ZIP_CM_STORE;
+        return ZIP_CM_STORE;
     else if (strcasecmp(arg, "deflate") == 0)
-       return ZIP_CM_DEFLATE;
+        return ZIP_CM_DEFLATE;
 #if defined(HAVE_LIBBZ2)
     else if (strcasecmp(arg, "bzip2") == 0)
-       return ZIP_CM_BZIP2;
+        return ZIP_CM_BZIP2;
 #endif
 #if defined(HAVE_LIBLZMA)
-/*  Disabled - because 7z isn't able to unpack ZIP+LZMA ZIP+LZMA2
-    archives made this way - and vice versa.
+    /*  Disabled - because 7z isn't able to unpack ZIP+LZMA ZIP+LZMA2
+        archives made this way - and vice versa.
 
+        else if (strcasecmp(arg, "lzma2") == 0)
+          return ZIP_CM_LZMA2;
+    */
     else if (strcasecmp(arg, "lzma") == 0)
-      return ZIP_CM_LZMA;
-    else if (strcasecmp(arg, "lzma2") == 0)
-      return ZIP_CM_LZMA2;
-*/
+       return ZIP_CM_LZMA;
     else if (strcasecmp(arg, "xz") == 0)
-      return ZIP_CM_XZ;
+        return ZIP_CM_XZ;
+#endif
+#if defined(HAVE_LIBZSTD)
+    else if (strcasecmp(arg, "zstd") == 0)
+        return ZIP_CM_ZSTD;
 
 #endif
     else if (strcasecmp(arg, "unknown") == 0)
-       return 100;
+        return 100;
     return 0; /* TODO: error handling */
 }
 
 static zip_uint16_t
 get_encryption_method(const char *arg) {
     if (strcasecmp(arg, "none") == 0)
-       return ZIP_EM_NONE;
+        return ZIP_EM_NONE;
     else if (strcasecmp(arg, "PKWARE") == 0)
-       return ZIP_EM_TRAD_PKWARE;
+        return ZIP_EM_TRAD_PKWARE;
     else if (strcasecmp(arg, "AES-128") == 0)
-       return ZIP_EM_AES_128;
+        return ZIP_EM_AES_128;
     else if (strcasecmp(arg, "AES-192") == 0)
-       return ZIP_EM_AES_192;
+        return ZIP_EM_AES_192;
     else if (strcasecmp(arg, "AES-256") == 0)
-       return ZIP_EM_AES_256;
+        return ZIP_EM_AES_256;
     else if (strcasecmp(arg, "unknown") == 0)
-       return 100;
+        return 100;
     return (zip_uint16_t)-1; /* TODO: error handling */
 }
 
@@ -680,12 +685,12 @@ hexdump(const zip_uint8_t *data, zip_uint16_t len) {
     zip_uint16_t i;
 
     if (len <= 0)
-       return;
+        return;
 
     printf("0x");
 
     for (i = 0; i < len; i++)
-       printf("%02x", data[i]);
+        printf("%02x", data[i]);
 
     return;
 }
@@ -698,63 +703,63 @@ read_from_file(const char *archive, int flags, zip_error_t *error, zip_uint64_t
     int err;
 
     if (offset == 0 && length == 0) {
-       if (strcmp(archive, "/dev/stdin") == 0) {
-           zaa = zip_fdopen(STDIN_FILENO, flags & ~ZIP_CREATE, &err);
-       }
-       else {
-           zaa = zip_open(archive, flags, &err);
-       }
-       if (zaa == NULL) {
-           zip_error_set(error, err, errno);
-           return NULL;
-       }
+        if (strcmp(archive, "/dev/stdin") == 0) {
+            zaa = zip_fdopen(STDIN_FILENO, flags & ~ZIP_CREATE, &err);
+        }
+        else {
+            zaa = zip_open(archive, flags, &err);
+        }
+        if (zaa == NULL) {
+            zip_error_set(error, err, errno);
+            return NULL;
+        }
     }
     else {
-       if (length > ZIP_INT64_MAX) {
-           zip_error_set(error, ZIP_ER_INVAL, 0);
-           return NULL;
-       }
-       if ((source = zip_source_file_create(archive, offset, (zip_int64_t)length, error)) == NULL || (zaa = zip_open_from_source(source, flags, error)) == NULL) {
-           zip_source_free(source);
-           return NULL;
-       }
+        if (length > ZIP_INT64_MAX) {
+            zip_error_set(error, ZIP_ER_INVAL, 0);
+            return NULL;
+        }
+        if ((source = zip_source_file_create(archive, offset, (zip_int64_t)length, error)) == NULL || (zaa = zip_open_from_source(source, flags, error)) == NULL) {
+            zip_source_free(source);
+            return NULL;
+        }
     }
 
     return zaa;
 }
 
 dispatch_table_t dispatch_table[] = {{"add", 2, "name content", "add file called name using content", add},
-                                    {"add_dir", 1, "name", "add directory", add_dir},
-                                    {"add_file", 4, "name file_to_add offset len", "add file to archive, len bytes starting from offset", add_file},
-                                    {"add_from_zip", 5, "name archivename index offset len", "add file from another archive, len bytes starting from offset", add_from_zip},
-                                    {"cat", 1, "index", "output file contents to stdout", cat},
-                                    {"count_extra", 2, "index flags", "show number of extra fields for archive entry", count_extra},
-                                    {"count_extra_by_id", 3, "index extra_id flags", "show number of extra fields of type extra_id for archive entry", count_extra_by_id},
-                                    {"delete", 1, "index", "remove entry", delete},
-                                    {"delete_extra", 3, "index extra_idx flags", "remove extra field", delete_extra},
-                                    {"delete_extra_by_id", 4, "index extra_id extra_index flags", "remove extra field of type extra_id", delete_extra_by_id},
-                                    {"get_archive_comment", 0, "", "show archive comment", get_archive_comment},
-                                    {"get_extra", 3, "index extra_index flags", "show extra field", get_extra},
-                                    {"get_extra_by_id", 4, "index extra_id extra_index flags", "show extra field of type extra_id", get_extra_by_id},
-                                    {"get_file_comment", 1, "index", "get file comment", get_file_comment},
-                                    {"get_num_entries", 1, "flags", "get number of entries in archive", get_num_entries},
-                                    {"name_locate", 2, "name flags", "find entry in archive", name_locate},
-                                    {"print_progress", 0, "", "print progress during zip_close()", print_progress},
-                                    {"rename", 2, "index name", "rename entry", zrename},
-                                    {"replace_file_contents", 2, "index data", "replace entry with data", replace_file_contents},
-                                    {"set_archive_comment", 1, "comment", "set archive comment", set_archive_comment},
-                                    {"set_extra", 5, "index extra_id extra_index flags value", "set extra field", set_extra},
-                                    {"set_file_comment", 2, "index comment", "set file comment", set_file_comment},
-                                    {"set_file_compression", 3, "index method compression_flags", "set file compression method", set_file_compression},
-                                    {"set_file_dostime", 3, "index time date", "set file modification time and date (DOS format)", set_file_dostime},
-                                    {"set_file_encryption", 3, "index method password", "set file encryption method", set_file_encryption},
-                                    {"set_file_mtime", 2, "index timestamp", "set file modification time", set_file_mtime},
-                                    {"set_file_mtime_all", 1, "timestamp", "set file modification time for all files", set_file_mtime_all},
-                                    {"set_password", 1, "password", "set default password for encryption", set_password},
-                                    {"stat", 1, "index", "print information about entry", zstat}
+                                     {"add_dir", 1, "name", "add directory", add_dir},
+                                     {"add_file", 4, "name file_to_add offset len", "add file to archive, len bytes starting from offset", add_file},
+                                     {"add_from_zip", 5, "name archivename index offset len", "add file from another archive, len bytes starting from offset", add_from_zip},
+                                     {"cat", 1, "index", "output file contents to stdout", cat},
+                                     {"count_extra", 2, "index flags", "show number of extra fields for archive entry", count_extra},
+                                     {"count_extra_by_id", 3, "index extra_id flags", "show number of extra fields of type extra_id for archive entry", count_extra_by_id},
+                                     {"delete", 1, "index", "remove entry", delete},
+                                     {"delete_extra", 3, "index extra_idx flags", "remove extra field", delete_extra},
+                                     {"delete_extra_by_id", 4, "index extra_id extra_index flags", "remove extra field of type extra_id", delete_extra_by_id},
+                                     {"get_archive_comment", 0, "", "show archive comment", get_archive_comment},
+                                     {"get_extra", 3, "index extra_index flags", "show extra field", get_extra},
+                                     {"get_extra_by_id", 4, "index extra_id extra_index flags", "show extra field of type extra_id", get_extra_by_id},
+                                     {"get_file_comment", 1, "index", "get file comment", get_file_comment},
+                                     {"get_num_entries", 1, "flags", "get number of entries in archive", get_num_entries},
+                                     {"name_locate", 2, "name flags", "find entry in archive", name_locate},
+                                     {"print_progress", 0, "", "print progress during zip_close()", print_progress},
+                                     {"rename", 2, "index name", "rename entry", zrename},
+                                     {"replace_file_contents", 2, "index data", "replace entry with data", replace_file_contents},
+                                     {"set_archive_comment", 1, "comment", "set archive comment", set_archive_comment},
+                                     {"set_extra", 5, "index extra_id extra_index flags value", "set extra field", set_extra},
+                                     {"set_file_comment", 2, "index comment", "set file comment", set_file_comment},
+                                     {"set_file_compression", 3, "index method compression_flags", "set file compression method", set_file_compression},
+                                     {"set_file_dostime", 3, "index time date", "set file modification time and date (DOS format)", set_file_dostime},
+                                     {"set_file_encryption", 3, "index method password", "set file encryption method", set_file_encryption},
+                                     {"set_file_mtime", 2, "index timestamp", "set file modification time", set_file_mtime},
+                                     {"set_file_mtime_all", 1, "timestamp", "set file modification time for all files", set_file_mtime_all},
+                                     {"set_password", 1, "password", "set default password for encryption", set_password},
+                                     {"stat", 1, "index", "print information about entry", zstat}
 #ifdef DISPATCH_REGRESS
-                                    ,
-                                    DISPATCH_REGRESS
+                                     ,
+                                     DISPATCH_REGRESS
 #endif
 };
 
@@ -762,18 +767,18 @@ static int
 dispatch(int argc, char *argv[]) {
     unsigned int i;
     for (i = 0; i < sizeof(dispatch_table) / sizeof(dispatch_table_t); i++) {
-       if (strcmp(dispatch_table[i].cmdline_name, argv[0]) == 0) {
-           argc--;
-           argv++;
-           /* 1 for the command, argument_count for the arguments */
-           if (argc < dispatch_table[i].argument_count) {
-               fprintf(stderr, "not enough arguments for command '%s': %d available, %d needed\n", dispatch_table[i].cmdline_name, argc, dispatch_table[i].argument_count);
-               return -1;
-           }
-           if (dispatch_table[i].function(argc, argv) == 0)
-               return 1 + dispatch_table[i].argument_count;
-           return -1;
-       }
+        if (strcmp(dispatch_table[i].cmdline_name, argv[0]) == 0) {
+            argc--;
+            argv++;
+            /* 1 for the command, argument_count for the arguments */
+            if (argc < dispatch_table[i].argument_count) {
+                fprintf(stderr, "not enough arguments for command '%s': %d available, %d needed\n", dispatch_table[i].cmdline_name, argc, dispatch_table[i].argument_count);
+                return -1;
+            }
+            if (dispatch_table[i].function(argc, argv) == 0)
+                return 1 + dispatch_table[i].argument_count;
+            return -1;
+        }
     }
 
     fprintf(stderr, "unknown command '%s'\n", argv[0]);
@@ -786,66 +791,69 @@ usage(const char *progname, const char *reason) {
     unsigned int i;
     FILE *out;
     if (reason == NULL)
-       out = stdout;
+        out = stdout;
     else
-       out = stderr;
+        out = stderr;
     fprintf(out, "usage: %s [-ceghnrst]" USAGE_REGRESS " [-l len] [-o offset] archive command1 [args] [command2 [args] ...]\n", progname);
     if (reason != NULL) {
-       fprintf(out, "%s\n", reason);
-       exit(1);
+        fprintf(out, "%s\n", reason);
+        exit(1);
     }
 
     fprintf(out, "\nSupported options are:\n"
-                "\t-c\t\tcheck consistency\n"
-                "\t-e\t\terror if archive already exists (only useful with -n)\n"
+                 "\t-c\t\tcheck consistency\n"
+                 "\t-e\t\terror if archive already exists (only useful with -n)\n"
 #ifdef FOR_REGRESS
-                "\t-F size\t\tfragment size for in memory archive\n"
+                 "\t-F size\t\tfragment size for in memory archive\n"
 #endif
-                "\t-g\t\tguess file name encoding (for stat)\n"
+                 "\t-g\t\tguess file name encoding (for stat)\n"
 #ifdef FOR_REGRESS
-                "\t-H\t\twrite files with holes compactly\n"
+                 "\t-H\t\twrite files with holes compactly\n"
 #endif
-                "\t-h\t\tdisplay this usage\n"
-                "\t-l len\t\tonly use len bytes of file\n"
+                 "\t-h\t\tdisplay this usage\n"
+                 "\t-l len\t\tonly use len bytes of file\n"
 #ifdef FOR_REGRESS
-                "\t-m\t\tread archive into memory, and modify there; write out at end\n"
+                 "\t-m\t\tread archive into memory, and modify there; write out at end\n"
 #endif
-                "\t-n\t\tcreate archive if it doesn't exist\n"
-                "\t-o offset\tstart reading file at offset\n"
-                "\t-r\t\tprint raw file name encoding without translation (for stat)\n"
-                "\t-s\t\tfollow file name convention strictly (for stat)\n"
-                "\t-t\t\tdisregard current archive contents, if any\n");
+                 "\t-n\t\tcreate archive if it doesn't exist\n"
+                 "\t-o offset\tstart reading file at offset\n"
+                 "\t-r\t\tprint raw file name encoding without translation (for stat)\n"
+                 "\t-s\t\tfollow file name convention strictly (for stat)\n"
+                 "\t-t\t\tdisregard current archive contents, if any\n");
     fprintf(out, "\nSupported commands and arguments are:\n");
     for (i = 0; i < sizeof(dispatch_table) / sizeof(dispatch_table_t); i++) {
-       fprintf(out, "\t%s %s\n\t    %s\n\n", dispatch_table[i].cmdline_name, dispatch_table[i].arg_names, dispatch_table[i].description);
+        fprintf(out, "\t%s %s\n\t    %s\n\n", dispatch_table[i].cmdline_name, dispatch_table[i].arg_names, dispatch_table[i].description);
     }
     fprintf(out, "\nSupported flags are:\n"
-           "\t0\t(no flags)\n"
-           "\tC\tZIP_FL_NOCASE\n"
-           "\tc\tZIP_FL_CENTRAL\n"
-           "\td\tZIP_FL_NODIR\n"
-           "\tl\tZIP_FL_LOCAL\n"
-           "\tu\tZIP_FL_UNCHANGED\n");
+                 "\t0\t(no flags)\n"
+                 "\tC\tZIP_FL_NOCASE\n"
+                 "\tc\tZIP_FL_CENTRAL\n"
+                 "\td\tZIP_FL_NODIR\n"
+                 "\tl\tZIP_FL_LOCAL\n"
+                 "\tu\tZIP_FL_UNCHANGED\n");
     fprintf(out, "\nSupported compression methods are:\n"
-           "\tdefault\n");
+                 "\tdefault\n");
     if (zip_compression_method_supported(ZIP_CM_BZIP2, 1)) {
-       fprintf(out, "\tbzip2\n");
+        fprintf(out, "\tbzip2\n");
     }
     fprintf(out, "\tdeflate\n"
-           "\tstore\n");
+                 "\tstore\n");
     if (zip_compression_method_supported(ZIP_CM_XZ, 1)) {
-       fprintf(out, "\txz\n");
+        fprintf(out, "\txz\n");
+    }
+    if (zip_compression_method_supported(ZIP_CM_ZSTD, 1)) {
+        fprintf(out, "\tzstd\n");
     }
     fprintf(out, "\nSupported encryption methods are:\n"
-           "\tnone\n");
+                 "\tnone\n");
     if (zip_encryption_method_supported(ZIP_EM_AES_128, 1)) {
-       fprintf(out, "\tAES-128\n");
+        fprintf(out, "\tAES-128\n");
     }
     if (zip_encryption_method_supported(ZIP_EM_AES_192, 1)) {
-       fprintf(out, "\tAES-192\n");
+        fprintf(out, "\tAES-192\n");
     }
     if (zip_encryption_method_supported(ZIP_EM_AES_256, 1)) {
-       fprintf(out, "\tAES-256\n");
+        fprintf(out, "\tAES-256\n");
     }
     fprintf(out, "\tPKWARE\n");
     fprintf(out, "\nThe index is zero-based.\n");
@@ -873,93 +881,93 @@ main(int argc, char *argv[]) {
     prg = argv[0];
 
     while ((c = getopt(argc, argv, "ceghl:no:rst" OPTIONS_REGRESS)) != -1) {
-       switch (c) {
-       case 'c':
-           flags |= ZIP_CHECKCONS;
-           break;
-       case 'e':
-           flags |= ZIP_EXCL;
-           break;
-       case 'g':
-           stat_flags = ZIP_FL_ENC_GUESS;
-           break;
-       case 'h':
-           usage(prg, NULL);
-           break;
-       case 'l':
-           len = strtoull(optarg, NULL, 10);
-           break;
-       case 'n':
-           flags |= ZIP_CREATE;
-           break;
-       case 'o':
-           offset = strtoull(optarg, NULL, 10);
-           break;
-       case 'r':
-           stat_flags = ZIP_FL_ENC_RAW;
-           break;
-       case 's':
-           stat_flags = ZIP_FL_ENC_STRICT;
-           break;
-       case 't':
-           flags |= ZIP_TRUNCATE;
-           break;
+        switch (c) {
+        case 'c':
+            flags |= ZIP_CHECKCONS;
+            break;
+        case 'e':
+            flags |= ZIP_EXCL;
+            break;
+        case 'g':
+            stat_flags = ZIP_FL_ENC_GUESS;
+            break;
+        case 'h':
+            usage(prg, NULL);
+            break;
+        case 'l':
+            len = strtoull(optarg, NULL, 10);
+            break;
+        case 'n':
+            flags |= ZIP_CREATE;
+            break;
+        case 'o':
+            offset = strtoull(optarg, NULL, 10);
+            break;
+        case 'r':
+            stat_flags = ZIP_FL_ENC_RAW;
+            break;
+        case 's':
+            stat_flags = ZIP_FL_ENC_STRICT;
+            break;
+        case 't':
+            flags |= ZIP_TRUNCATE;
+            break;
 #ifdef GETOPT_REGRESS
-           GETOPT_REGRESS
+            GETOPT_REGRESS
 #endif
 
-       default: {
-           char reason[128];
-           snprintf(reason, sizeof(reason), "invalid option -%c", optopt);
-           usage(prg, reason);
-       }
-       }
+        default: {
+            char reason[128];
+            snprintf(reason, sizeof(reason), "invalid option -%c", optopt);
+            usage(prg, reason);
+        }
+        }
     }
 
     if (optind >= argc - 1)
-       usage(prg, "too few arguments");
+        usage(prg, "too few arguments");
 
     arg = optind;
 
     archive = argv[arg++];
 
     if (flags == 0)
-       flags = ZIP_CREATE;
+        flags = ZIP_CREATE;
 
     zip_error_init(&error);
     za = ziptool_open(archive, flags, &error, offset, len);
     if (za == NULL) {
-       fprintf(stderr, "can't open zip archive '%s': %s\n", archive, zip_error_strerror(&error));
-       zip_error_fini(&error);
-       return 1;
+        fprintf(stderr, "can't open zip archive '%s': %s\n", archive, zip_error_strerror(&error));
+        zip_error_fini(&error);
+        return 1;
     }
     zip_error_fini(&error);
 
     err = 0;
     while (arg < argc) {
-       int ret;
-       ret = dispatch(argc - arg, argv + arg);
-       if (ret > 0) {
-           arg += ret;
-       }
-       else {
-           err = 1;
-           break;
-       }
+        int ret;
+        ret = dispatch(argc - arg, argv + arg);
+        if (ret > 0) {
+            arg += ret;
+        }
+        else {
+            err = 1;
+            break;
+        }
     }
 
     if (zip_close(za) == -1) {
-       fprintf(stderr, "can't close zip archive '%s': %s\n", archive, zip_strerror(za));
-       return 1;
+        fprintf(stderr, "can't close zip archive '%s': %s\n", archive, zip_strerror(za));
+        return 1;
     }
     if (ziptool_post_close(archive) < 0) {
-       err = 1;
+        err = 1;
     }
 
     for (i = 0; i < z_in_count; i++) {
-       if (zip_close(z_in[i]) < 0) {
-           err = 1;
-       }
+        if (zip_close(z_in[i]) < 0) {
+            err = 1;
+        }
     }
 
     return err;