mirror of https://github.com/PCSX2/pcsx2.git
3rdparty: Un-submodule libzip
This commit is contained in:
parent
86ee1270e2
commit
c43775f7b2
|
@ -27,9 +27,6 @@
|
||||||
[submodule "3rdparty/sdl2/SDL"]
|
[submodule "3rdparty/sdl2/SDL"]
|
||||||
path = 3rdparty/sdl2/SDL
|
path = 3rdparty/sdl2/SDL
|
||||||
url = https://github.com/libsdl-org/SDL.git
|
url = https://github.com/libsdl-org/SDL.git
|
||||||
[submodule "3rdparty/libzip/libzip"]
|
|
||||||
path = 3rdparty/libzip/libzip
|
|
||||||
url = https://github.com/nih-at/libzip.git
|
|
||||||
[submodule "3rdparty/zstd/zstd"]
|
[submodule "3rdparty/zstd/zstd"]
|
||||||
path = 3rdparty/zstd/zstd
|
path = 3rdparty/zstd/zstd
|
||||||
url = https://github.com/facebook/zstd.git
|
url = https://github.com/facebook/zstd.git
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Dieter Baron <dillo@nih.at>
|
||||||
|
Thomas Klausner <tk@giga.or.at>
|
|
@ -1,31 +1,386 @@
|
||||||
set(BUILD_SHARED_LIBS OFF CACHE BOOL "")
|
cmake_minimum_required(VERSION 3.5.0)
|
||||||
set(LIBZIP_DO_INSTALL OFF CACHE BOOL "")
|
|
||||||
|
|
||||||
set(ENABLE_COMMONCRYPTO OFF CACHE BOOL "")
|
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||||
set(ENABLE_GNUTLS OFF CACHE BOOL "")
|
if (${CMAKE_VERSION} VERSION_LESS "3.17.0")
|
||||||
set(ENABLE_MBEDTLS OFF CACHE BOOL "")
|
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake-compat)
|
||||||
set(ENABLE_WINDOWS_CRYPTO OFF CACHE BOOL "")
|
|
||||||
set(ENABLE_OPENSSL OFF CACHE BOOL "")
|
|
||||||
set(ENABLE_BZIP2 OFF CACHE BOOL "")
|
|
||||||
set(ENABLE_LZMA OFF CACHE BOOL "")
|
|
||||||
set(ENABLE_ZSTD ON CACHE BOOL "")
|
|
||||||
|
|
||||||
set(BUILD_TOOLS OFF CACHE BOOL "")
|
|
||||||
set(BUILD_REGRESS OFF CACHE BOOL "")
|
|
||||||
set(BUILD_EXAMPLES OFF CACHE BOOL "")
|
|
||||||
set(BUILD_DOC OFF CACHE BOOL "")
|
|
||||||
|
|
||||||
if(WIN32)
|
|
||||||
# Needed otherwise find_package() will look in the system.
|
|
||||||
set(ZLIB_FOUND TRUE)
|
|
||||||
set(ZLIB_LIBRARY "$<TARGET_FILE:pcsx2-zlib>")
|
|
||||||
set(ZLIB_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/zlib")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Fill in the location of zstd, so find_package() doesn't try to use
|
project(libzip
|
||||||
# a potentially-old system version. It also picks up Zstd::Zstd.
|
VERSION 1.10.1
|
||||||
set(Zstd_FOUND TRUE)
|
LANGUAGES C)
|
||||||
set(Zstd_LIBRARY "$<TARGET_FILE:pcsx2-zstd>")
|
|
||||||
set(Zstd_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../zstd/zstd/lib")
|
|
||||||
|
|
||||||
add_subdirectory(libzip EXCLUDE_FROM_ALL)
|
set(ENABLE_FDOPEN ON)
|
||||||
|
set(HAVE_LIBZSTD TRUE)
|
||||||
|
set(ZIP_STATIC TRUE)
|
||||||
|
|
||||||
|
include(CheckFunctionExists)
|
||||||
|
include(CheckIncludeFiles)
|
||||||
|
include(CheckLibraryExists)
|
||||||
|
include(CheckSymbolExists)
|
||||||
|
include(CheckTypeSize)
|
||||||
|
include(CheckCSourceRuns)
|
||||||
|
include(CheckCSourceCompiles)
|
||||||
|
include(CheckStructHasMember)
|
||||||
|
include(TestBigEndian)
|
||||||
|
|
||||||
|
# Checks
|
||||||
|
|
||||||
|
# Request ISO C secure library functions (memcpy_s &c)
|
||||||
|
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D__STDC_WANT_LIB_EXT1__=1)
|
||||||
|
|
||||||
|
check_function_exists(_close HAVE__CLOSE)
|
||||||
|
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_symbol_exists(_snprintf stdio.h HAVE__SNPRINTF)
|
||||||
|
check_symbol_exists(_snprintf_s stdio.h HAVE__SNPRINTF_S)
|
||||||
|
check_symbol_exists(_snwprintf_s stdio.h HAVE__SNWPRINTF_S)
|
||||||
|
check_function_exists(_strdup HAVE__STRDUP)
|
||||||
|
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)
|
||||||
|
check_function_exists(arc4random HAVE_ARC4RANDOM)
|
||||||
|
check_function_exists(clonefile HAVE_CLONEFILE)
|
||||||
|
check_function_exists(explicit_bzero HAVE_EXPLICIT_BZERO)
|
||||||
|
check_function_exists(explicit_memset HAVE_EXPLICIT_MEMSET)
|
||||||
|
check_function_exists(fchmod HAVE_FCHMOD)
|
||||||
|
check_function_exists(fileno HAVE_FILENO)
|
||||||
|
check_function_exists(fseeko HAVE_FSEEKO)
|
||||||
|
check_function_exists(ftello HAVE_FTELLO)
|
||||||
|
check_function_exists(getprogname HAVE_GETPROGNAME)
|
||||||
|
check_symbol_exists(localtime_r time.h HAVE_LOCALTIME_R)
|
||||||
|
check_symbol_exists(localtime_s time.h HAVE_LOCALTIME_S)
|
||||||
|
check_function_exists(memcpy_s HAVE_MEMCPY_S)
|
||||||
|
check_function_exists(random HAVE_RANDOM)
|
||||||
|
check_function_exists(setmode HAVE_SETMODE)
|
||||||
|
check_symbol_exists(snprintf stdio.h HAVE_SNPRINTF)
|
||||||
|
check_symbol_exists(snprintf_s stdio.h HAVE_SNPRINTF_S)
|
||||||
|
check_symbol_exists(strcasecmp strings.h HAVE_STRCASECMP)
|
||||||
|
check_function_exists(strdup HAVE_STRDUP)
|
||||||
|
check_function_exists(strerror_s HAVE_STRERROR_S)
|
||||||
|
check_function_exists(strerrorlen_s HAVE_STRERRORLEN_S)
|
||||||
|
check_function_exists(stricmp HAVE_STRICMP)
|
||||||
|
check_function_exists(strncpy_s HAVE_STRNCPY_S)
|
||||||
|
check_function_exists(strtoll HAVE_STRTOLL)
|
||||||
|
check_function_exists(strtoull HAVE_STRTOULL)
|
||||||
|
|
||||||
|
check_include_files("sys/types.h;sys/stat.h;fts.h" HAVE_FTS_H)
|
||||||
|
# fts functions may be in external library
|
||||||
|
if(HAVE_FTS_H)
|
||||||
|
check_function_exists(fts_open HAVE_FTS_OPEN)
|
||||||
|
if(NOT HAVE_FTS_OPEN)
|
||||||
|
check_library_exists(fts fts_open "" HAVE_LIB_FTS)
|
||||||
|
else(NOT HAVE_FTS_OPEN)
|
||||||
|
set(HAVE_LIB_FTS "" CACHE INTERNAL "")
|
||||||
|
endif(NOT HAVE_FTS_OPEN)
|
||||||
|
else(HAVE_FTS_H)
|
||||||
|
set(HAVE_LIB_FTS "" CACHE INTERNAL "")
|
||||||
|
endif(HAVE_FTS_H)
|
||||||
|
|
||||||
|
if(HAVE_LIB_FTS)
|
||||||
|
set(FTS_LIB fts CACHE INTERNAL "")
|
||||||
|
else()
|
||||||
|
set(FTS_LIB "" CACHE INTERNAL "")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
check_include_files(stdbool.h HAVE_STDBOOL_H)
|
||||||
|
check_include_files(strings.h HAVE_STRINGS_H)
|
||||||
|
check_include_files(unistd.h HAVE_UNISTD_H)
|
||||||
|
|
||||||
|
check_include_files(inttypes.h HAVE_INTTYPES_H_LIBZIP)
|
||||||
|
check_include_files(stdint.h HAVE_STDINT_H_LIBZIP)
|
||||||
|
check_include_files(sys/types.h HAVE_SYS_TYPES_H_LIBZIP)
|
||||||
|
|
||||||
|
# TODO: fix test
|
||||||
|
# this test does not find __progname even when it exists
|
||||||
|
#check_symbol_exists(__progname stdlib.h HAVE___PROGNAME)
|
||||||
|
|
||||||
|
check_type_size(__int8 __INT8_LIBZIP)
|
||||||
|
check_type_size(int8_t INT8_T_LIBZIP)
|
||||||
|
check_type_size(uint8_t UINT8_T_LIBZIP)
|
||||||
|
check_type_size(__int16 __INT16_LIBZIP)
|
||||||
|
check_type_size(int16_t INT16_T_LIBZIP)
|
||||||
|
check_type_size(uint16_t UINT16_T_LIBZIP)
|
||||||
|
check_type_size(__int32 __INT32_LIBZIP)
|
||||||
|
check_type_size(int32_t INT32_T_LIBZIP)
|
||||||
|
check_type_size(uint32_t UINT32_T_LIBZIP)
|
||||||
|
check_type_size(__int64 __INT64_LIBZIP)
|
||||||
|
check_type_size(int64_t INT64_T_LIBZIP)
|
||||||
|
check_type_size(uint64_t UINT64_T_LIBZIP)
|
||||||
|
check_type_size("short" SHORT_LIBZIP)
|
||||||
|
check_type_size("int" INT_LIBZIP)
|
||||||
|
check_type_size("long" LONG_LIBZIP)
|
||||||
|
check_type_size("long long" LONG_LONG_LIBZIP)
|
||||||
|
check_type_size("off_t" SIZEOF_OFF_T)
|
||||||
|
check_type_size("size_t" SIZEOF_SIZE_T)
|
||||||
|
|
||||||
|
check_c_source_compiles("#include <sys/ioctl.h>
|
||||||
|
#include <linux/fs.h>
|
||||||
|
int main(int argc, char *argv[]) { unsigned long x = FICLONERANGE; }" HAVE_FICLONERANGE)
|
||||||
|
|
||||||
|
check_c_source_compiles("
|
||||||
|
int foo(char * _Nullable bar);
|
||||||
|
int main(int argc, char *argv[]) { }" HAVE_NULLABLE)
|
||||||
|
|
||||||
|
test_big_endian(WORDS_BIGENDIAN)
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
|
||||||
|
add_compile_definitions(_CRT_NONSTDC_NO_DEPRECATE)
|
||||||
|
endif(MSVC)
|
||||||
|
|
||||||
|
# fixed size integral types
|
||||||
|
|
||||||
|
if(HAVE_INTTYPES_H_LIBZIP)
|
||||||
|
set(LIBZIP_TYPES_INCLUDE "#if !defined(__STDC_FORMAT_MACROS)
|
||||||
|
#define __STDC_FORMAT_MACROS 1
|
||||||
|
#endif
|
||||||
|
#include <inttypes.h>")
|
||||||
|
elseif(HAVE_STDINT_H_LIBZIP)
|
||||||
|
set(LIBZIP_TYPES_INCLUDE "#include <stdint.h>")
|
||||||
|
elseif(HAVE_SYS_TYPES_H_LIBZIP)
|
||||||
|
set(LIBZIP_TYPES_INCLUDE "#include <sys/types.h>")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(HAVE_INT8_T_LIBZIP)
|
||||||
|
set(ZIP_INT8_T int8_t)
|
||||||
|
elseif(HAVE___INT8_LIBZIP)
|
||||||
|
set(ZIP_INT8_T __int8)
|
||||||
|
else()
|
||||||
|
set(ZIP_INT8_T "signed char")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(HAVE_UINT8_T_LIBZIP)
|
||||||
|
set(ZIP_UINT8_T uint8_t)
|
||||||
|
elseif(HAVE___INT8_LIBZIP)
|
||||||
|
set(ZIP_UINT8_T "unsigned __int8")
|
||||||
|
else()
|
||||||
|
set(ZIP_UINT8_T "unsigned char")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(HAVE_INT16_T_LIBZIP)
|
||||||
|
set(ZIP_INT16_T int16_t)
|
||||||
|
elseif(HAVE___INT16_LIBZIP)
|
||||||
|
set(INT16_T_LIBZIP __int16)
|
||||||
|
elseif(SHORT_LIBZIP EQUAL 2)
|
||||||
|
set(INT16_T_LIBZIP short)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(HAVE_UINT16_T_LIBZIP)
|
||||||
|
set(ZIP_UINT16_T uint16_t)
|
||||||
|
elseif(HAVE___INT16_LIBZIP)
|
||||||
|
set(UINT16_T_LIBZIP "unsigned __int16")
|
||||||
|
elseif(SHORT_LIBZIP EQUAL 2)
|
||||||
|
set(UINT16_T_LIBZIP "unsigned short")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(HAVE_INT32_T_LIBZIP)
|
||||||
|
set(ZIP_INT32_T int32_t)
|
||||||
|
elseif(HAVE___INT32_LIBZIP)
|
||||||
|
set(ZIP_INT32_T __int32)
|
||||||
|
elseif(INT_LIBZIP EQUAL 4)
|
||||||
|
set(ZIP_INT32_T int)
|
||||||
|
elseif(LONG_LIBZIP EQUAL 4)
|
||||||
|
set(ZIP_INT32_T long)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(HAVE_UINT32_T_LIBZIP)
|
||||||
|
set(ZIP_UINT32_T uint32_t)
|
||||||
|
elseif(HAVE___INT32_LIBZIP)
|
||||||
|
set(ZIP_UINT32_T "unsigned __int32")
|
||||||
|
elseif(INT_LIBZIP EQUAL 4)
|
||||||
|
set(ZIP_UINT32_T "unsigned int")
|
||||||
|
elseif(LONG_LIBZIP EQUAL 4)
|
||||||
|
set(ZIP_UINT32_T "unsigned long")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(HAVE_INT64_T_LIBZIP)
|
||||||
|
set(ZIP_INT64_T int64_t)
|
||||||
|
elseif(HAVE___INT64_LIBZIP)
|
||||||
|
set(ZIP_INT64_T __int64)
|
||||||
|
elseif(LONG_LIBZIP EQUAL 8)
|
||||||
|
set(ZIP_INT64_T long)
|
||||||
|
elseif(LONG_LONG_LIBZIP EQUAL 8)
|
||||||
|
set(ZIP_INT64_T "long long")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(HAVE_UINT64_T_LIBZIP)
|
||||||
|
set(ZIP_UINT64_T uint64_t)
|
||||||
|
elseif(HAVE___INT64_LIBZIP)
|
||||||
|
set(ZIP_UINT64_T "unsigned __int64")
|
||||||
|
elseif(LONG_LIBZIP EQUAL 8)
|
||||||
|
set(ZIP_UINT64_T "unsigned long")
|
||||||
|
elseif(LONG_LONG_LIBZIP EQUAL 8)
|
||||||
|
set(ZIP_UINT64_T "unsigned long long")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(HAVE_NULLABLE)
|
||||||
|
set(ZIP_NULLABLE_DEFINES)
|
||||||
|
else()
|
||||||
|
set(ZIP_NULLABLE_DEFINES "#define _Nullable
|
||||||
|
#define _Nonnull")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# write out config file
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake-config.h.in ${PROJECT_BINARY_DIR}/config.h)
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake-zipconf.h.in ${PROJECT_BINARY_DIR}/zipconf.h)
|
||||||
|
|
||||||
|
set(CMAKE_C_VISIBILITY_PRESET hidden)
|
||||||
|
|
||||||
|
add_library(zip STATIC
|
||||||
|
lib/zip_add.c
|
||||||
|
lib/zip_add_dir.c
|
||||||
|
lib/zip_add_entry.c
|
||||||
|
lib/zip_algorithm_deflate.c
|
||||||
|
lib/zip_buffer.c
|
||||||
|
lib/zip_close.c
|
||||||
|
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_name_locate.c
|
||||||
|
lib/zip_new.c
|
||||||
|
lib/zip_open.c
|
||||||
|
lib/zip_pkware.c
|
||||||
|
lib/zip_progress.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_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_pass_to_lower_layer.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_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
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/zip_err_str.c
|
||||||
|
)
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
target_sources(zip PRIVATE
|
||||||
|
lib/zip_source_file_win32.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_file_win32_ansi.c
|
||||||
|
lib/zip_random_win32.c
|
||||||
|
)
|
||||||
|
else(WIN32)
|
||||||
|
target_sources(zip PRIVATE
|
||||||
|
lib/zip_source_file_stdio_named.c
|
||||||
|
lib/zip_random_unix.c
|
||||||
|
)
|
||||||
|
endif(WIN32)
|
||||||
|
|
||||||
|
target_sources(zip PRIVATE lib/zip_algorithm_zstd.c)
|
||||||
|
target_link_libraries(zip PRIVATE Zstd::Zstd)
|
||||||
|
|
||||||
|
target_link_libraries(zip PRIVATE ZLIB::ZLIB)
|
||||||
|
target_include_directories(zip
|
||||||
|
PUBLIC
|
||||||
|
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/lib>
|
||||||
|
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>
|
||||||
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||||
|
)
|
||||||
|
|
||||||
|
# create zip_err_str.c from zip.h and zipint.h
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zip_err_str.c
|
||||||
|
COMMAND "${CMAKE_COMMAND}"
|
||||||
|
"-DPROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR}"
|
||||||
|
"-DCMAKE_CURRENT_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}"
|
||||||
|
"-P" "${PROJECT_SOURCE_DIR}/cmake/GenerateZipErrorStrings.cmake"
|
||||||
|
DEPENDS
|
||||||
|
${PROJECT_SOURCE_DIR}/cmake/GenerateZipErrorStrings.cmake
|
||||||
|
${PROJECT_SOURCE_DIR}/lib/zip.h
|
||||||
|
${PROJECT_SOURCE_DIR}/lib/zipint.h
|
||||||
|
COMMENT "Generating zip_err_str.c"
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(libzip::zip ALIAS zip)
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner
|
||||||
|
|
||||||
|
The authors can be contacted at <info@libzip.org>
|
||||||
|
|
||||||
|
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.
|
|
@ -0,0 +1,72 @@
|
||||||
|
#ifndef HAD_CONFIG_H
|
||||||
|
#define HAD_CONFIG_H
|
||||||
|
#ifndef _HAD_ZIPCONF_H
|
||||||
|
#include "zipconf.h"
|
||||||
|
#endif
|
||||||
|
/* BEGIN DEFINES */
|
||||||
|
#cmakedefine ENABLE_FDOPEN
|
||||||
|
#cmakedefine HAVE___PROGNAME
|
||||||
|
#cmakedefine HAVE__CLOSE
|
||||||
|
#cmakedefine HAVE__DUP
|
||||||
|
#cmakedefine HAVE__FDOPEN
|
||||||
|
#cmakedefine HAVE__FILENO
|
||||||
|
#cmakedefine HAVE__SETMODE
|
||||||
|
#cmakedefine HAVE__SNPRINTF
|
||||||
|
#cmakedefine HAVE__SNPRINTF_S
|
||||||
|
#cmakedefine HAVE__SNWPRINTF_S
|
||||||
|
#cmakedefine HAVE__STRDUP
|
||||||
|
#cmakedefine HAVE__STRICMP
|
||||||
|
#cmakedefine HAVE__STRTOI64
|
||||||
|
#cmakedefine HAVE__STRTOUI64
|
||||||
|
#cmakedefine HAVE__UNLINK
|
||||||
|
#cmakedefine HAVE_ARC4RANDOM
|
||||||
|
#cmakedefine HAVE_CLONEFILE
|
||||||
|
#cmakedefine HAVE_COMMONCRYPTO
|
||||||
|
#cmakedefine HAVE_CRYPTO
|
||||||
|
#cmakedefine HAVE_FICLONERANGE
|
||||||
|
#cmakedefine HAVE_FILENO
|
||||||
|
#cmakedefine HAVE_FCHMOD
|
||||||
|
#cmakedefine HAVE_FSEEKO
|
||||||
|
#cmakedefine HAVE_FTELLO
|
||||||
|
#cmakedefine HAVE_GETPROGNAME
|
||||||
|
#cmakedefine HAVE_GNUTLS
|
||||||
|
#cmakedefine HAVE_LIBBZ2
|
||||||
|
#cmakedefine HAVE_LIBLZMA
|
||||||
|
#cmakedefine HAVE_LIBZSTD
|
||||||
|
#cmakedefine HAVE_LOCALTIME_R
|
||||||
|
#cmakedefine HAVE_LOCALTIME_S
|
||||||
|
#cmakedefine HAVE_MEMCPY_S
|
||||||
|
#cmakedefine HAVE_MBEDTLS
|
||||||
|
#cmakedefine HAVE_MKSTEMP
|
||||||
|
#cmakedefine HAVE_NULLABLE
|
||||||
|
#cmakedefine HAVE_OPENSSL
|
||||||
|
#cmakedefine HAVE_SETMODE
|
||||||
|
#cmakedefine HAVE_SNPRINTF
|
||||||
|
#cmakedefine HAVE_SNPRINTF_S
|
||||||
|
#cmakedefine HAVE_STRCASECMP
|
||||||
|
#cmakedefine HAVE_STRDUP
|
||||||
|
#cmakedefine HAVE_STRERROR_S
|
||||||
|
#cmakedefine HAVE_STRERRORLEN_S
|
||||||
|
#cmakedefine HAVE_STRICMP
|
||||||
|
#cmakedefine HAVE_STRNCPY_S
|
||||||
|
#cmakedefine HAVE_STRTOLL
|
||||||
|
#cmakedefine HAVE_STRTOULL
|
||||||
|
#cmakedefine HAVE_STRUCT_TM_TM_ZONE
|
||||||
|
#cmakedefine HAVE_STDBOOL_H
|
||||||
|
#cmakedefine HAVE_STRINGS_H
|
||||||
|
#cmakedefine HAVE_UNISTD_H
|
||||||
|
#cmakedefine HAVE_WINDOWS_CRYPTO
|
||||||
|
#cmakedefine SIZEOF_OFF_T ${SIZEOF_OFF_T}
|
||||||
|
#cmakedefine SIZEOF_SIZE_T ${SIZEOF_SIZE_T}
|
||||||
|
#cmakedefine HAVE_DIRENT_H
|
||||||
|
#cmakedefine HAVE_FTS_H
|
||||||
|
#cmakedefine HAVE_NDIR_H
|
||||||
|
#cmakedefine HAVE_SYS_DIR_H
|
||||||
|
#cmakedefine HAVE_SYS_NDIR_H
|
||||||
|
#cmakedefine WORDS_BIGENDIAN
|
||||||
|
#cmakedefine HAVE_SHARED
|
||||||
|
/* END DEFINES */
|
||||||
|
#define PACKAGE "@CMAKE_PROJECT_NAME@"
|
||||||
|
#define VERSION "@CMAKE_PROJECT_VERSION@"
|
||||||
|
|
||||||
|
#endif /* HAD_CONFIG_H */
|
|
@ -0,0 +1,47 @@
|
||||||
|
#ifndef _HAD_ZIPCONF_H
|
||||||
|
#define _HAD_ZIPCONF_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
zipconf.h -- platform specific include file
|
||||||
|
|
||||||
|
This file was generated automatically by CMake
|
||||||
|
based on ../cmake-zipconf.h.in.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LIBZIP_VERSION "${libzip_VERSION}"
|
||||||
|
#define LIBZIP_VERSION_MAJOR ${libzip_VERSION_MAJOR}
|
||||||
|
#define LIBZIP_VERSION_MINOR ${libzip_VERSION_MINOR}
|
||||||
|
#define LIBZIP_VERSION_MICRO ${libzip_VERSION_PATCH}
|
||||||
|
|
||||||
|
#cmakedefine ZIP_STATIC
|
||||||
|
|
||||||
|
${ZIP_NULLABLE_DEFINES}
|
||||||
|
|
||||||
|
${LIBZIP_TYPES_INCLUDE}
|
||||||
|
|
||||||
|
typedef ${ZIP_INT8_T} zip_int8_t;
|
||||||
|
typedef ${ZIP_UINT8_T} zip_uint8_t;
|
||||||
|
typedef ${ZIP_INT16_T} zip_int16_t;
|
||||||
|
typedef ${ZIP_UINT16_T} zip_uint16_t;
|
||||||
|
typedef ${ZIP_INT32_T} zip_int32_t;
|
||||||
|
typedef ${ZIP_UINT32_T} zip_uint32_t;
|
||||||
|
typedef ${ZIP_INT64_T} zip_int64_t;
|
||||||
|
typedef ${ZIP_UINT64_T} zip_uint64_t;
|
||||||
|
|
||||||
|
#define ZIP_INT8_MIN (-ZIP_INT8_MAX-1)
|
||||||
|
#define ZIP_INT8_MAX 0x7f
|
||||||
|
#define ZIP_UINT8_MAX 0xff
|
||||||
|
|
||||||
|
#define ZIP_INT16_MIN (-ZIP_INT16_MAX-1)
|
||||||
|
#define ZIP_INT16_MAX 0x7fff
|
||||||
|
#define ZIP_UINT16_MAX 0xffff
|
||||||
|
|
||||||
|
#define ZIP_INT32_MIN (-ZIP_INT32_MAX-1L)
|
||||||
|
#define ZIP_INT32_MAX 0x7fffffffL
|
||||||
|
#define ZIP_UINT32_MAX 0xffffffffLU
|
||||||
|
|
||||||
|
#define ZIP_INT64_MIN (-ZIP_INT64_MAX-1LL)
|
||||||
|
#define ZIP_INT64_MAX 0x7fffffffffffffffLL
|
||||||
|
#define ZIP_UINT64_MAX 0xffffffffffffffffULL
|
||||||
|
|
||||||
|
#endif /* zipconf.h */
|
|
@ -0,0 +1,186 @@
|
||||||
|
# Copyright (C) 2020 Dieter Baron and Thomas Klausner
|
||||||
|
#
|
||||||
|
# The authors can be contacted at <info@libzip.org>
|
||||||
|
#
|
||||||
|
# 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::libzstd_shared``
|
||||||
|
The shared Zstandard library
|
||||||
|
``zstd::libzstd_static``
|
||||||
|
The shared 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.
|
||||||
|
|
||||||
|
Cache Variables
|
||||||
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The following cache variables may also be set:
|
||||||
|
|
||||||
|
``zstd_INCLUDE_DIR``
|
||||||
|
The directory containing ``zstd.h``.
|
||||||
|
``zstd_STATIC_LIBRARY``
|
||||||
|
The path to the Zstandard static library.
|
||||||
|
``zstd_SHARED_LIBRARY``
|
||||||
|
The path to the Zstandard shared library.
|
||||||
|
``zstd_DLL``
|
||||||
|
The path to the Zstandard DLL.
|
||||||
|
|
||||||
|
#]=======================================================================]
|
||||||
|
|
||||||
|
find_package(PkgConfig)
|
||||||
|
pkg_check_modules(PC_zstd QUIET libzstd)
|
||||||
|
|
||||||
|
find_path(zstd_INCLUDE_DIR
|
||||||
|
NAMES zstd.h
|
||||||
|
HINTS ${PC_zstd_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
|
||||||
|
find_file(zstd_DLL
|
||||||
|
NAMES libzstd.dll zstd.dll
|
||||||
|
PATH_SUFFIXES bin
|
||||||
|
HINTS ${PC_zstd_PREFIX}
|
||||||
|
)
|
||||||
|
|
||||||
|
# On Windows, we manually define the library names to avoid mistaking the
|
||||||
|
# implib for the static library
|
||||||
|
if(zstd_DLL)
|
||||||
|
set(_zstd_win_static_name zstd-static)
|
||||||
|
set(_zstd_win_shared_name zstd)
|
||||||
|
else()
|
||||||
|
# vcpkg removes the -static suffix in static builds
|
||||||
|
set(_zstd_win_static_name zstd zstd_static)
|
||||||
|
set(_zstd_win_shared_name)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(_previous_suffixes ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||||
|
set(CMAKE_FIND_LIBRARY_SUFFIXES ".so" ".dylib" ".dll.a" ".lib")
|
||||||
|
find_library(zstd_SHARED_LIBRARY
|
||||||
|
NAMES zstd ${_zstd_win_shared_name}
|
||||||
|
HINTS ${PC_zstd_LIBDIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ".lib")
|
||||||
|
find_library(zstd_STATIC_LIBRARY
|
||||||
|
NAMES zstd ${_zstd_win_static_name}
|
||||||
|
HINTS ${PC_zstd_LIBDIR}
|
||||||
|
)
|
||||||
|
set(CMAKE_FIND_LIBRARY_SUFFIXES ${_previous_suffixes})
|
||||||
|
|
||||||
|
# Set zstd_LIBRARY to the shared library or fall back to the static library
|
||||||
|
if(zstd_SHARED_LIBRARY)
|
||||||
|
set(_zstd_LIBRARY ${zstd_SHARED_LIBRARY})
|
||||||
|
else()
|
||||||
|
set(_zstd_LIBRARY ${zstd_STATIC_LIBRARY})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# 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 AND zstd_SHARED_LIBRARY AND NOT TARGET zstd::libzstd_shared)
|
||||||
|
add_library(zstd::libzstd_shared SHARED IMPORTED)
|
||||||
|
if(WIN32)
|
||||||
|
set_target_properties(zstd::libzstd_shared PROPERTIES
|
||||||
|
IMPORTED_LOCATION "${zstd_DLL}"
|
||||||
|
IMPORTED_IMPLIB "${zstd_SHARED_LIBRARY}"
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
set_target_properties(zstd::libzstd_shared PROPERTIES
|
||||||
|
IMPORTED_LOCATION "${zstd_SHARED_LIBRARY}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set_target_properties(zstd::libzstd_shared PROPERTIES
|
||||||
|
INTERFACE_COMPILE_OPTIONS "${PC_zstd_CFLAGS_OTHER}"
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "${zstd_INCLUDE_DIR}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(zstd_FOUND AND zstd_STATIC_LIBRARY AND NOT TARGET zstd::libzstd_static)
|
||||||
|
add_library(zstd::libzstd_static STATIC IMPORTED)
|
||||||
|
set_target_properties(zstd::libzstd_static PROPERTIES
|
||||||
|
IMPORTED_LOCATION "${zstd_STATIC_LIBRARY}"
|
||||||
|
INTERFACE_COMPILE_OPTIONS "${PC_zstd_CFLAGS_OTHER}"
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "${zstd_INCLUDE_DIR}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
mark_as_advanced(
|
||||||
|
zstd_INCLUDE_DIR
|
||||||
|
zstd_DLL
|
||||||
|
zstd_SHARED_LIBRARY
|
||||||
|
zstd_STATIC_LIBRARY
|
||||||
|
)
|
|
@ -0,0 +1,47 @@
|
||||||
|
# create zip_err_str.c from zip.h and zipint.h
|
||||||
|
file(READ ${PROJECT_SOURCE_DIR}/lib/zip.h 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 and zipint.h\; make changes there.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
#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-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 " { ${CMAKE_MATCH_1}, \"${err_t_tt}\" },\n")
|
||||||
|
endforeach()
|
||||||
|
string(APPEND zip_err_str [=[}\;
|
||||||
|
|
||||||
|
const int _zip_err_str_count = sizeof(_zip_err_str)/sizeof(_zip_err_str[0])\;
|
||||||
|
|
||||||
|
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_details_count = sizeof(_zip_err_details)/sizeof(_zip_err_details[0])\;
|
||||||
|
]=])
|
||||||
|
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/zip_err_str.c ${zip_err_str})
|
|
@ -0,0 +1,208 @@
|
||||||
|
include(CheckFunctionExists)
|
||||||
|
|
||||||
|
set(CMAKE_C_VISIBILITY_PRESET hidden)
|
||||||
|
|
||||||
|
add_library(zip
|
||||||
|
zip_add.c
|
||||||
|
zip_add_dir.c
|
||||||
|
zip_add_entry.c
|
||||||
|
zip_algorithm_deflate.c
|
||||||
|
zip_buffer.c
|
||||||
|
zip_close.c
|
||||||
|
zip_delete.c
|
||||||
|
zip_dir_add.c
|
||||||
|
zip_dirent.c
|
||||||
|
zip_discard.c
|
||||||
|
zip_entry.c
|
||||||
|
zip_error.c
|
||||||
|
zip_error_clear.c
|
||||||
|
zip_error_get.c
|
||||||
|
zip_error_get_sys_type.c
|
||||||
|
zip_error_strerror.c
|
||||||
|
zip_error_to_str.c
|
||||||
|
zip_extra_field.c
|
||||||
|
zip_extra_field_api.c
|
||||||
|
zip_fclose.c
|
||||||
|
zip_fdopen.c
|
||||||
|
zip_file_add.c
|
||||||
|
zip_file_error_clear.c
|
||||||
|
zip_file_error_get.c
|
||||||
|
zip_file_get_comment.c
|
||||||
|
zip_file_get_external_attributes.c
|
||||||
|
zip_file_get_offset.c
|
||||||
|
zip_file_rename.c
|
||||||
|
zip_file_replace.c
|
||||||
|
zip_file_set_comment.c
|
||||||
|
zip_file_set_encryption.c
|
||||||
|
zip_file_set_external_attributes.c
|
||||||
|
zip_file_set_mtime.c
|
||||||
|
zip_file_strerror.c
|
||||||
|
zip_fopen.c
|
||||||
|
zip_fopen_encrypted.c
|
||||||
|
zip_fopen_index.c
|
||||||
|
zip_fopen_index_encrypted.c
|
||||||
|
zip_fread.c
|
||||||
|
zip_fseek.c
|
||||||
|
zip_ftell.c
|
||||||
|
zip_get_archive_comment.c
|
||||||
|
zip_get_archive_flag.c
|
||||||
|
zip_get_encryption_implementation.c
|
||||||
|
zip_get_file_comment.c
|
||||||
|
zip_get_name.c
|
||||||
|
zip_get_num_entries.c
|
||||||
|
zip_get_num_files.c
|
||||||
|
zip_hash.c
|
||||||
|
zip_io_util.c
|
||||||
|
zip_libzip_version.c
|
||||||
|
zip_memdup.c
|
||||||
|
zip_name_locate.c
|
||||||
|
zip_new.c
|
||||||
|
zip_open.c
|
||||||
|
zip_pkware.c
|
||||||
|
zip_progress.c
|
||||||
|
zip_rename.c
|
||||||
|
zip_replace.c
|
||||||
|
zip_set_archive_comment.c
|
||||||
|
zip_set_archive_flag.c
|
||||||
|
zip_set_default_password.c
|
||||||
|
zip_set_file_comment.c
|
||||||
|
zip_set_file_compression.c
|
||||||
|
zip_set_name.c
|
||||||
|
zip_source_accept_empty.c
|
||||||
|
zip_source_begin_write.c
|
||||||
|
zip_source_begin_write_cloning.c
|
||||||
|
zip_source_buffer.c
|
||||||
|
zip_source_call.c
|
||||||
|
zip_source_close.c
|
||||||
|
zip_source_commit_write.c
|
||||||
|
zip_source_compress.c
|
||||||
|
zip_source_crc.c
|
||||||
|
zip_source_error.c
|
||||||
|
zip_source_file_common.c
|
||||||
|
zip_source_file_stdio.c
|
||||||
|
zip_source_free.c
|
||||||
|
zip_source_function.c
|
||||||
|
zip_source_get_file_attributes.c
|
||||||
|
zip_source_is_deleted.c
|
||||||
|
zip_source_layered.c
|
||||||
|
zip_source_open.c
|
||||||
|
zip_source_pass_to_lower_layer.c
|
||||||
|
zip_source_pkware_decode.c
|
||||||
|
zip_source_pkware_encode.c
|
||||||
|
zip_source_read.c
|
||||||
|
zip_source_remove.c
|
||||||
|
zip_source_rollback_write.c
|
||||||
|
zip_source_seek.c
|
||||||
|
zip_source_seek_write.c
|
||||||
|
zip_source_stat.c
|
||||||
|
zip_source_supports.c
|
||||||
|
zip_source_tell.c
|
||||||
|
zip_source_tell_write.c
|
||||||
|
zip_source_window.c
|
||||||
|
zip_source_write.c
|
||||||
|
zip_source_zip.c
|
||||||
|
zip_source_zip_new.c
|
||||||
|
zip_stat.c
|
||||||
|
zip_stat_index.c
|
||||||
|
zip_stat_init.c
|
||||||
|
zip_strerror.c
|
||||||
|
zip_string.c
|
||||||
|
zip_unchange.c
|
||||||
|
zip_unchange_all.c
|
||||||
|
zip_unchange_archive.c
|
||||||
|
zip_unchange_data.c
|
||||||
|
zip_utf-8.c
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/zip_err_str.c
|
||||||
|
)
|
||||||
|
add_library(libzip::zip ALIAS zip)
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
target_sources(zip PRIVATE
|
||||||
|
zip_source_file_win32.c
|
||||||
|
zip_source_file_win32_named.c
|
||||||
|
zip_source_file_win32_utf16.c
|
||||||
|
zip_source_file_win32_utf8.c
|
||||||
|
)
|
||||||
|
if(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES WindowsStore)
|
||||||
|
target_sources(zip PRIVATE zip_random_uwp.c)
|
||||||
|
else()
|
||||||
|
target_sources(zip PRIVATE zip_source_file_win32_ansi.c zip_random_win32.c)
|
||||||
|
target_link_libraries(zip PRIVATE advapi32)
|
||||||
|
endif()
|
||||||
|
else(WIN32)
|
||||||
|
target_sources(zip PRIVATE
|
||||||
|
zip_source_file_stdio_named.c
|
||||||
|
zip_random_unix.c
|
||||||
|
)
|
||||||
|
endif(WIN32)
|
||||||
|
|
||||||
|
if(HAVE_LIBBZ2)
|
||||||
|
target_sources(zip PRIVATE zip_algorithm_bzip2.c)
|
||||||
|
target_link_libraries(zip PRIVATE BZip2::BZip2)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(HAVE_LIBLZMA)
|
||||||
|
target_sources(zip PRIVATE zip_algorithm_xz.c)
|
||||||
|
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_TARGET})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(HAVE_COMMONCRYPTO)
|
||||||
|
target_sources(zip PRIVATE zip_crypto_commoncrypto.c)
|
||||||
|
elseif(HAVE_WINDOWS_CRYPTO)
|
||||||
|
target_sources(zip PRIVATE zip_crypto_win.c)
|
||||||
|
target_link_libraries(zip PRIVATE bcrypt)
|
||||||
|
elseif(HAVE_GNUTLS)
|
||||||
|
target_sources(zip PRIVATE zip_crypto_gnutls.c)
|
||||||
|
target_link_libraries(zip PRIVATE GnuTLS::GnuTLS Nettle::Nettle)
|
||||||
|
elseif(HAVE_OPENSSL)
|
||||||
|
target_sources(zip PRIVATE zip_crypto_openssl.c)
|
||||||
|
target_link_libraries(zip PRIVATE OpenSSL::Crypto)
|
||||||
|
elseif(HAVE_MBEDTLS)
|
||||||
|
target_sources(zip PRIVATE zip_crypto_mbedtls.c)
|
||||||
|
target_link_libraries(zip PRIVATE MbedTLS::MbedTLS)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(HAVE_CRYPTO)
|
||||||
|
target_sources(zip PRIVATE zip_winzip_aes.c zip_source_winzip_aes_decode.c zip_source_winzip_aes_encode.c)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(SHARED_LIB_VERSIONNING)
|
||||||
|
set_target_properties(zip PROPERTIES VERSION 5.5 SOVERSION 5)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_link_libraries(zip PRIVATE ZLIB::ZLIB)
|
||||||
|
target_include_directories(zip
|
||||||
|
PUBLIC
|
||||||
|
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/lib>
|
||||||
|
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>
|
||||||
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||||
|
)
|
||||||
|
|
||||||
|
if(LIBZIP_DO_INSTALL)
|
||||||
|
install(TARGETS zip
|
||||||
|
EXPORT ${PROJECT_NAME}-targets
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||||
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||||
|
install(FILES zip.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# create zip_err_str.c from zip.h and zipint.h
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zip_err_str.c
|
||||||
|
COMMAND "${CMAKE_COMMAND}"
|
||||||
|
"-DPROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR}"
|
||||||
|
"-DCMAKE_CURRENT_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}"
|
||||||
|
"-P" "${PROJECT_SOURCE_DIR}/cmake/GenerateZipErrorStrings.cmake"
|
||||||
|
DEPENDS
|
||||||
|
${PROJECT_SOURCE_DIR}/cmake/GenerateZipErrorStrings.cmake
|
||||||
|
${PROJECT_SOURCE_DIR}/lib/zip.h
|
||||||
|
${PROJECT_SOURCE_DIR}/lib/zipint.h
|
||||||
|
COMMENT "Generating zip_err_str.c"
|
||||||
|
)
|
|
@ -0,0 +1,240 @@
|
||||||
|
#ifndef _HAD_LIBZIP_COMPAT_H
|
||||||
|
#define _HAD_LIBZIP_COMPAT_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
compat.h -- compatibility defines.
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 "zipconf.h"
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
/* to have *_MAX definitions for all types when compiling with g++ */
|
||||||
|
#define __STDC_LIMIT_MACROS
|
||||||
|
|
||||||
|
/* to have ISO C secure library functions */
|
||||||
|
#define __STDC_WANT_LIB_EXT1__ 1
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#ifndef ZIP_EXTERN
|
||||||
|
#ifndef ZIP_STATIC
|
||||||
|
#define ZIP_EXTERN __declspec(dllexport)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
/* for dup(), close(), etc. */
|
||||||
|
#include <io.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_STDBOOL_H
|
||||||
|
#include <stdbool.h>
|
||||||
|
#else
|
||||||
|
typedef char bool;
|
||||||
|
#define true 1
|
||||||
|
#define false 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
/* at least MinGW does not provide EOPNOTSUPP, see
|
||||||
|
* http://sourceforge.net/p/mingw/bugs/263/
|
||||||
|
*/
|
||||||
|
#ifndef EOPNOTSUPP
|
||||||
|
#define EOPNOTSUPP EINVAL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* at least MinGW does not provide EOVERFLOW, see
|
||||||
|
* http://sourceforge.net/p/mingw/bugs/242/
|
||||||
|
*/
|
||||||
|
#ifndef EOVERFLOW
|
||||||
|
#define EOVERFLOW EFBIG
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* not supported on at least Windows */
|
||||||
|
#ifndef O_CLOEXEC
|
||||||
|
#define O_CLOEXEC 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#if defined(HAVE__CLOSE)
|
||||||
|
#define close _close
|
||||||
|
#endif
|
||||||
|
#if defined(HAVE__DUP)
|
||||||
|
#define dup _dup
|
||||||
|
#endif
|
||||||
|
/* crashes reported when using fdopen instead of _fdopen on Windows/Visual Studio 10/Win64 */
|
||||||
|
#if defined(HAVE__FDOPEN)
|
||||||
|
#define fdopen _fdopen
|
||||||
|
#endif
|
||||||
|
#if !defined(HAVE_FILENO) && defined(HAVE__FILENO)
|
||||||
|
#define fileno _fileno
|
||||||
|
#endif
|
||||||
|
#if !defined(HAVE_SNPRINTF) && defined(HAVE__SNPRINTF)
|
||||||
|
#define snprintf _snprintf
|
||||||
|
#endif
|
||||||
|
#if !defined(HAVE__SNWPRINTF_S)
|
||||||
|
#define _snwprintf_s(buf, bufsz, len, fmt, ...) (_snwprintf((buf), (len), (fmt), __VA_ARGS__))
|
||||||
|
#endif
|
||||||
|
#if defined(HAVE__STRDUP)
|
||||||
|
#if !defined(HAVE_STRDUP) || defined(_WIN32)
|
||||||
|
#undef strdup
|
||||||
|
#define strdup _strdup
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#if !defined(HAVE__SETMODE) && defined(HAVE_SETMODE)
|
||||||
|
#define _setmode setmode
|
||||||
|
#endif
|
||||||
|
#if !defined(HAVE_STRTOLL) && defined(HAVE__STRTOI64)
|
||||||
|
#define strtoll _strtoi64
|
||||||
|
#endif
|
||||||
|
#if !defined(HAVE_STRTOULL) && defined(HAVE__STRTOUI64)
|
||||||
|
#define strtoull _strtoui64
|
||||||
|
#endif
|
||||||
|
#if defined(HAVE__UNLINK)
|
||||||
|
#define unlink _unlink
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_FSEEKO
|
||||||
|
#define fseeko(s, o, w) (fseek((s), (long int)(o), (w)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_FTELLO
|
||||||
|
#define ftello(s) ((long)ftell((s)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_LOCALTIME_S
|
||||||
|
#ifdef _WIN32
|
||||||
|
/* Windows is incompatible to the C11 standard, hurray! */
|
||||||
|
#define zip_localtime(t, tm) (localtime_s((tm), (t)) == 0 ? tm : NULL)
|
||||||
|
#else
|
||||||
|
#define zip_localtime localtime_s
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#ifdef HAVE_LOCALTIME_R
|
||||||
|
#define zip_localtime localtime_r
|
||||||
|
#else
|
||||||
|
#define zip_localtime(t, tm) (localtime(t))
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_MEMCPY_S
|
||||||
|
#define memcpy_s(dest, destsz, src, count) (memcpy((dest), (src), (count)) == NULL)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_SNPRINTF_S
|
||||||
|
#ifdef HAVE__SNPRINTF_S
|
||||||
|
#define snprintf_s(buf, bufsz, fmt, ...) (_snprintf_s((buf), (bufsz), (bufsz), (fmt), __VA_ARGS__))
|
||||||
|
#else
|
||||||
|
#define snprintf_s snprintf
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(HAVE_STRCASECMP)
|
||||||
|
#if defined(HAVE__STRICMP)
|
||||||
|
#define strcasecmp _stricmp
|
||||||
|
#elif defined(HAVE_STRICMP)
|
||||||
|
#define strcasecmp stricmp
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_STRNCPY_S
|
||||||
|
#define strncpy_s(dest, destsz, src, count) (strncpy((dest), (src), (count)), 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_STRERROR_S
|
||||||
|
#define strerrorlen_s(errnum) (strlen(strerror(errnum)))
|
||||||
|
#define strerror_s(buf, bufsz, errnum) ((void)strncpy_s((buf), (bufsz), strerror(errnum), (bufsz)), (buf)[(bufsz)-1] = '\0', strerrorlen_s(errnum) >= (bufsz))
|
||||||
|
#else
|
||||||
|
#ifndef HAVE_STRERRORLEN_S
|
||||||
|
#define strerrorlen_s(errnum) 8192
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if SIZEOF_OFF_T == 8
|
||||||
|
#define ZIP_OFF_MAX ZIP_INT64_MAX
|
||||||
|
#define ZIP_OFF_MIN ZIP_INT64_MIN
|
||||||
|
#elif SIZEOF_OFF_T == 4
|
||||||
|
#define ZIP_OFF_MAX ZIP_INT32_MAX
|
||||||
|
#define ZIP_OFF_MIN ZIP_INT32_MIN
|
||||||
|
#elif SIZEOF_OFF_T == 2
|
||||||
|
#define ZIP_OFF_MAX ZIP_INT16_MAX
|
||||||
|
#define ZIP_OFF_MIN ZIP_INT16_MIN
|
||||||
|
#else
|
||||||
|
#error unsupported size of off_t
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_FTELLO) && defined(HAVE_FSEEKO)
|
||||||
|
#define ZIP_FSEEK_MAX ZIP_OFF_MAX
|
||||||
|
#define ZIP_FSEEK_MIN ZIP_OFF_MIN
|
||||||
|
#else
|
||||||
|
#include <limits.h>
|
||||||
|
#define ZIP_FSEEK_MAX LONG_MAX
|
||||||
|
#define ZIP_FSEEK_MIN LONG_MIN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SIZE_MAX
|
||||||
|
#if SIZEOF_SIZE_T == 8
|
||||||
|
#define SIZE_MAX ZIP_INT64_MAX
|
||||||
|
#elif SIZEOF_SIZE_T == 4
|
||||||
|
#define SIZE_MAX ZIP_INT32_MAX
|
||||||
|
#elif SIZEOF_SIZE_T == 2
|
||||||
|
#define SIZE_MAX ZIP_INT16_MAX
|
||||||
|
#else
|
||||||
|
#error unsupported size of size_t
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PRId64
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define PRId64 "I64d"
|
||||||
|
#else
|
||||||
|
#define PRId64 "lld"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PRIu64
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define PRIu64 "I64u"
|
||||||
|
#else
|
||||||
|
#define PRIu64 "llu"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef S_ISDIR
|
||||||
|
#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef S_ISREG
|
||||||
|
#define S_ISREG(mode) (((mode)&S_IFMT) == S_IFREG)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* compat.h */
|
|
@ -0,0 +1,517 @@
|
||||||
|
#ifndef _HAD_ZIP_H
|
||||||
|
#define _HAD_ZIP_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
zip.h -- exported declarations.
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#if 0
|
||||||
|
} /* fix autoindent */
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <zipconf.h>
|
||||||
|
|
||||||
|
#ifndef ZIP_EXTERN
|
||||||
|
#ifndef ZIP_STATIC
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define ZIP_EXTERN __declspec(dllimport)
|
||||||
|
#elif defined(__GNUC__) && __GNUC__ >= 4
|
||||||
|
#define ZIP_EXTERN __attribute__((visibility("default")))
|
||||||
|
#else
|
||||||
|
#define ZIP_EXTERN
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define ZIP_EXTERN
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ZIP_DEPRECATED
|
||||||
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
|
#define ZIP_DEPRECATED(x) __attribute__((deprecated(x)))
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
#define ZIP_DEPRECATED(x) __declspec(deprecated(x))
|
||||||
|
#else
|
||||||
|
#define ZIP_DEPRECATED(x)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
/* flags for zip_open */
|
||||||
|
|
||||||
|
#define ZIP_CREATE 1
|
||||||
|
#define ZIP_EXCL 2
|
||||||
|
#define ZIP_CHECKCONS 4
|
||||||
|
#define ZIP_TRUNCATE 8
|
||||||
|
#define ZIP_RDONLY 16
|
||||||
|
|
||||||
|
|
||||||
|
/* flags for zip_name_locate, zip_fopen, zip_stat, ... */
|
||||||
|
|
||||||
|
#define ZIP_FL_NOCASE 1u /* ignore case on name lookup */
|
||||||
|
#define ZIP_FL_NODIR 2u /* ignore directory component */
|
||||||
|
#define ZIP_FL_COMPRESSED 4u /* read compressed data */
|
||||||
|
#define ZIP_FL_UNCHANGED 8u /* use original data, ignoring changes */
|
||||||
|
/* 16u was ZIP_FL_RECOMPRESS, which is deprecated */
|
||||||
|
#define ZIP_FL_ENCRYPTED 32u /* read encrypted data (implies ZIP_FL_COMPRESSED) */
|
||||||
|
#define ZIP_FL_ENC_GUESS 0u /* guess string encoding (is default) */
|
||||||
|
#define ZIP_FL_ENC_RAW 64u /* get unmodified string */
|
||||||
|
#define ZIP_FL_ENC_STRICT 128u /* follow specification strictly */
|
||||||
|
#define ZIP_FL_LOCAL 256u /* in local header */
|
||||||
|
#define ZIP_FL_CENTRAL 512u /* in central directory */
|
||||||
|
/* 1024u reserved for internal use */
|
||||||
|
#define ZIP_FL_ENC_UTF_8 2048u /* string is UTF-8 encoded */
|
||||||
|
#define ZIP_FL_ENC_CP437 4096u /* string is CP437 encoded */
|
||||||
|
#define ZIP_FL_OVERWRITE 8192u /* zip_file_add: if file with name exists, overwrite (replace) it */
|
||||||
|
|
||||||
|
/* archive global flags flags */
|
||||||
|
|
||||||
|
#define ZIP_AFL_RDONLY 2u /* read only -- cannot be cleared */
|
||||||
|
#define ZIP_AFL_IS_TORRENTZIP 4u /* current archive is torrentzipped */
|
||||||
|
#define ZIP_AFL_WANT_TORRENTZIP 8u /* write archive in torrentzip format */
|
||||||
|
#define ZIP_AFL_CREATE_OR_KEEP_FILE_FOR_EMPTY_ARCHIVE 16u /* don't remove file if archive is empty */
|
||||||
|
|
||||||
|
|
||||||
|
/* create a new extra field */
|
||||||
|
|
||||||
|
#define ZIP_EXTRA_FIELD_ALL ZIP_UINT16_MAX
|
||||||
|
#define ZIP_EXTRA_FIELD_NEW ZIP_UINT16_MAX
|
||||||
|
|
||||||
|
/* length parameter to various functions */
|
||||||
|
|
||||||
|
#define ZIP_LENGTH_TO_END 0
|
||||||
|
#define ZIP_LENGTH_UNCHECKED (-2) /* only supported by zip_source_file and its variants */
|
||||||
|
|
||||||
|
/* libzip error codes */
|
||||||
|
|
||||||
|
#define ZIP_ER_OK 0 /* N No error */
|
||||||
|
#define ZIP_ER_MULTIDISK 1 /* N Multi-disk zip archives not supported */
|
||||||
|
#define ZIP_ER_RENAME 2 /* S Renaming temporary file failed */
|
||||||
|
#define ZIP_ER_CLOSE 3 /* S Closing zip archive failed */
|
||||||
|
#define ZIP_ER_SEEK 4 /* S Seek error */
|
||||||
|
#define ZIP_ER_READ 5 /* S Read error */
|
||||||
|
#define ZIP_ER_WRITE 6 /* S Write error */
|
||||||
|
#define ZIP_ER_CRC 7 /* N CRC error */
|
||||||
|
#define ZIP_ER_ZIPCLOSED 8 /* N Containing zip archive was closed */
|
||||||
|
#define ZIP_ER_NOENT 9 /* N No such file */
|
||||||
|
#define ZIP_ER_EXISTS 10 /* N File already exists */
|
||||||
|
#define ZIP_ER_OPEN 11 /* S Can't open file */
|
||||||
|
#define ZIP_ER_TMPOPEN 12 /* S Failure to create temporary file */
|
||||||
|
#define ZIP_ER_ZLIB 13 /* Z Zlib error */
|
||||||
|
#define ZIP_ER_MEMORY 14 /* N Malloc failure */
|
||||||
|
#define ZIP_ER_CHANGED 15 /* N Entry has been changed */
|
||||||
|
#define ZIP_ER_COMPNOTSUPP 16 /* N Compression method not supported */
|
||||||
|
#define ZIP_ER_EOF 17 /* N Premature end of file */
|
||||||
|
#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 /* 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 */
|
||||||
|
#define ZIP_ER_RDONLY 25 /* N Read-only archive */
|
||||||
|
#define ZIP_ER_NOPASSWD 26 /* N No password provided */
|
||||||
|
#define ZIP_ER_WRONGPASSWD 27 /* N Wrong password provided */
|
||||||
|
#define ZIP_ER_OPNOTSUPP 28 /* N Operation not supported */
|
||||||
|
#define ZIP_ER_INUSE 29 /* N Resource still in use */
|
||||||
|
#define ZIP_ER_TELL 30 /* S Tell error */
|
||||||
|
#define ZIP_ER_COMPRESSED_DATA 31 /* N Compressed data invalid */
|
||||||
|
#define ZIP_ER_CANCELLED 32 /* N Operation cancelled */
|
||||||
|
#define ZIP_ER_DATA_LENGTH 33 /* N Unexpected length of data */
|
||||||
|
#define ZIP_ER_NOT_ALLOWED 34 /* N Not allowed in torrentzip */
|
||||||
|
|
||||||
|
/* 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_LIBZIP 3 /* sys_err is libzip error code */
|
||||||
|
|
||||||
|
/* compression methods */
|
||||||
|
|
||||||
|
#define ZIP_CM_DEFAULT -1 /* better of deflate or store */
|
||||||
|
#define ZIP_CM_STORE 0 /* stored (uncompressed) */
|
||||||
|
#define ZIP_CM_SHRINK 1 /* shrunk */
|
||||||
|
#define ZIP_CM_REDUCE_1 2 /* reduced with factor 1 */
|
||||||
|
#define ZIP_CM_REDUCE_2 3 /* reduced with factor 2 */
|
||||||
|
#define ZIP_CM_REDUCE_3 4 /* reduced with factor 3 */
|
||||||
|
#define ZIP_CM_REDUCE_4 5 /* reduced with factor 4 */
|
||||||
|
#define ZIP_CM_IMPLODE 6 /* imploded */
|
||||||
|
/* 7 - Reserved for Tokenizing compression algorithm */
|
||||||
|
#define ZIP_CM_DEFLATE 8 /* deflated */
|
||||||
|
#define ZIP_CM_DEFLATE64 9 /* deflate64 */
|
||||||
|
#define ZIP_CM_PKWARE_IMPLODE 10 /* PKWARE imploding */
|
||||||
|
/* 11 - Reserved by PKWARE */
|
||||||
|
#define ZIP_CM_BZIP2 12 /* compressed using BZIP2 algorithm */
|
||||||
|
/* 13 - Reserved by PKWARE */
|
||||||
|
#define ZIP_CM_LZMA 14 /* LZMA (EFS) */
|
||||||
|
/* 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 */
|
||||||
|
#define ZIP_CM_PPMD 98 /* PPMd version I, Rev 1 */
|
||||||
|
|
||||||
|
/* encryption methods */
|
||||||
|
|
||||||
|
#define ZIP_EM_NONE 0 /* not encrypted */
|
||||||
|
#define ZIP_EM_TRAD_PKWARE 1 /* traditional PKWARE encryption */
|
||||||
|
#if 0 /* Strong Encryption Header not parsed yet */
|
||||||
|
#define ZIP_EM_DES 0x6601 /* strong encryption: DES */
|
||||||
|
#define ZIP_EM_RC2_OLD 0x6602 /* strong encryption: RC2, version < 5.2 */
|
||||||
|
#define ZIP_EM_3DES_168 0x6603
|
||||||
|
#define ZIP_EM_3DES_112 0x6609
|
||||||
|
#define ZIP_EM_PKZIP_AES_128 0x660e
|
||||||
|
#define ZIP_EM_PKZIP_AES_192 0x660f
|
||||||
|
#define ZIP_EM_PKZIP_AES_256 0x6610
|
||||||
|
#define ZIP_EM_RC2 0x6702 /* strong encryption: RC2, version >= 5.2 */
|
||||||
|
#define ZIP_EM_RC4 0x6801
|
||||||
|
#endif
|
||||||
|
#define ZIP_EM_AES_128 0x0101 /* Winzip AES encryption */
|
||||||
|
#define ZIP_EM_AES_192 0x0102
|
||||||
|
#define ZIP_EM_AES_256 0x0103
|
||||||
|
#define ZIP_EM_UNKNOWN 0xffff /* unknown algorithm */
|
||||||
|
|
||||||
|
#define ZIP_OPSYS_DOS 0x00u
|
||||||
|
#define ZIP_OPSYS_AMIGA 0x01u
|
||||||
|
#define ZIP_OPSYS_OPENVMS 0x02u
|
||||||
|
#define ZIP_OPSYS_UNIX 0x03u
|
||||||
|
#define ZIP_OPSYS_VM_CMS 0x04u
|
||||||
|
#define ZIP_OPSYS_ATARI_ST 0x05u
|
||||||
|
#define ZIP_OPSYS_OS_2 0x06u
|
||||||
|
#define ZIP_OPSYS_MACINTOSH 0x07u
|
||||||
|
#define ZIP_OPSYS_Z_SYSTEM 0x08u
|
||||||
|
#define ZIP_OPSYS_CPM 0x09u
|
||||||
|
#define ZIP_OPSYS_WINDOWS_NTFS 0x0au
|
||||||
|
#define ZIP_OPSYS_MVS 0x0bu
|
||||||
|
#define ZIP_OPSYS_VSE 0x0cu
|
||||||
|
#define ZIP_OPSYS_ACORN_RISC 0x0du
|
||||||
|
#define ZIP_OPSYS_VFAT 0x0eu
|
||||||
|
#define ZIP_OPSYS_ALTERNATE_MVS 0x0fu
|
||||||
|
#define ZIP_OPSYS_BEOS 0x10u
|
||||||
|
#define ZIP_OPSYS_TANDEM 0x11u
|
||||||
|
#define ZIP_OPSYS_OS_400 0x12u
|
||||||
|
#define ZIP_OPSYS_OS_X 0x13u
|
||||||
|
|
||||||
|
#define ZIP_OPSYS_DEFAULT ZIP_OPSYS_UNIX
|
||||||
|
|
||||||
|
|
||||||
|
enum zip_source_cmd {
|
||||||
|
ZIP_SOURCE_OPEN, /* prepare for reading */
|
||||||
|
ZIP_SOURCE_READ, /* read data */
|
||||||
|
ZIP_SOURCE_CLOSE, /* reading is done */
|
||||||
|
ZIP_SOURCE_STAT, /* get meta information */
|
||||||
|
ZIP_SOURCE_ERROR, /* get error information */
|
||||||
|
ZIP_SOURCE_FREE, /* cleanup and free resources */
|
||||||
|
ZIP_SOURCE_SEEK, /* set position for reading */
|
||||||
|
ZIP_SOURCE_TELL, /* get read position */
|
||||||
|
ZIP_SOURCE_BEGIN_WRITE, /* prepare for writing */
|
||||||
|
ZIP_SOURCE_COMMIT_WRITE, /* writing is done */
|
||||||
|
ZIP_SOURCE_ROLLBACK_WRITE, /* discard written changes */
|
||||||
|
ZIP_SOURCE_WRITE, /* write data */
|
||||||
|
ZIP_SOURCE_SEEK_WRITE, /* set position for writing */
|
||||||
|
ZIP_SOURCE_TELL_WRITE, /* get write position */
|
||||||
|
ZIP_SOURCE_SUPPORTS, /* check whether source supports command */
|
||||||
|
ZIP_SOURCE_REMOVE, /* remove file */
|
||||||
|
ZIP_SOURCE_RESERVED_1, /* previously used internally */
|
||||||
|
ZIP_SOURCE_BEGIN_WRITE_CLONING, /* like ZIP_SOURCE_BEGIN_WRITE, but keep part of original file */
|
||||||
|
ZIP_SOURCE_ACCEPT_EMPTY, /* whether empty files are valid archives */
|
||||||
|
ZIP_SOURCE_GET_FILE_ATTRIBUTES, /* get additional file attributes */
|
||||||
|
ZIP_SOURCE_SUPPORTS_REOPEN /* allow reading from changed entry */
|
||||||
|
};
|
||||||
|
typedef enum zip_source_cmd zip_source_cmd_t;
|
||||||
|
|
||||||
|
#define ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd) (((zip_int64_t)1) << (cmd))
|
||||||
|
|
||||||
|
#define ZIP_SOURCE_CHECK_SUPPORTED(supported, cmd) (((supported) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd)) != 0)
|
||||||
|
|
||||||
|
/* clang-format off */
|
||||||
|
|
||||||
|
#define ZIP_SOURCE_SUPPORTS_READABLE (ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_OPEN) \
|
||||||
|
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_READ) \
|
||||||
|
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_CLOSE) \
|
||||||
|
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_STAT) \
|
||||||
|
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ERROR) \
|
||||||
|
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_FREE))
|
||||||
|
|
||||||
|
#define ZIP_SOURCE_SUPPORTS_SEEKABLE (ZIP_SOURCE_SUPPORTS_READABLE \
|
||||||
|
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK) \
|
||||||
|
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_TELL) \
|
||||||
|
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SUPPORTS))
|
||||||
|
|
||||||
|
#define ZIP_SOURCE_SUPPORTS_WRITABLE (ZIP_SOURCE_SUPPORTS_SEEKABLE \
|
||||||
|
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE) \
|
||||||
|
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_COMMIT_WRITE) \
|
||||||
|
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ROLLBACK_WRITE) \
|
||||||
|
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_WRITE) \
|
||||||
|
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK_WRITE) \
|
||||||
|
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_TELL_WRITE) \
|
||||||
|
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_REMOVE))
|
||||||
|
|
||||||
|
/* clang-format on */
|
||||||
|
|
||||||
|
/* for use by sources */
|
||||||
|
struct zip_source_args_seek {
|
||||||
|
zip_int64_t offset;
|
||||||
|
int whence;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct zip_source_args_seek zip_source_args_seek_t;
|
||||||
|
#define ZIP_SOURCE_GET_ARGS(type, data, len, error) ((len) < sizeof(type) ? zip_error_set((error), ZIP_ER_INVAL, 0), (type *)NULL : (type *)(data))
|
||||||
|
|
||||||
|
|
||||||
|
/* error information */
|
||||||
|
/* use zip_error_*() to access */
|
||||||
|
struct zip_error {
|
||||||
|
int zip_err; /* libzip error code (ZIP_ER_*) */
|
||||||
|
int sys_err; /* copy of errno (E*) or zlib error code */
|
||||||
|
char *_Nullable str; /* string representation or NULL */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ZIP_STAT_NAME 0x0001u
|
||||||
|
#define ZIP_STAT_INDEX 0x0002u
|
||||||
|
#define ZIP_STAT_SIZE 0x0004u
|
||||||
|
#define ZIP_STAT_COMP_SIZE 0x0008u
|
||||||
|
#define ZIP_STAT_MTIME 0x0010u
|
||||||
|
#define ZIP_STAT_CRC 0x0020u
|
||||||
|
#define ZIP_STAT_COMP_METHOD 0x0040u
|
||||||
|
#define ZIP_STAT_ENCRYPTION_METHOD 0x0080u
|
||||||
|
#define ZIP_STAT_FLAGS 0x0100u
|
||||||
|
|
||||||
|
struct zip_stat {
|
||||||
|
zip_uint64_t valid; /* which fields have valid values */
|
||||||
|
const char *_Nullable name; /* name of the file */
|
||||||
|
zip_uint64_t index; /* index within archive */
|
||||||
|
zip_uint64_t size; /* size of file (uncompressed) */
|
||||||
|
zip_uint64_t comp_size; /* size of file (compressed) */
|
||||||
|
time_t mtime; /* modification time */
|
||||||
|
zip_uint32_t crc; /* crc of file data */
|
||||||
|
zip_uint16_t comp_method; /* compression method used */
|
||||||
|
zip_uint16_t encryption_method; /* encryption method used */
|
||||||
|
zip_uint32_t flags; /* reserved for future use */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct zip_buffer_fragment {
|
||||||
|
zip_uint8_t *_Nonnull data;
|
||||||
|
zip_uint64_t length;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct zip_file_attributes {
|
||||||
|
zip_uint64_t valid; /* which fields have valid values */
|
||||||
|
zip_uint8_t version; /* version of this struct, currently 1 */
|
||||||
|
zip_uint8_t host_system; /* host system on which file was created */
|
||||||
|
zip_uint8_t ascii; /* flag whether file is ASCII text */
|
||||||
|
zip_uint8_t version_needed; /* minimum version needed to extract file */
|
||||||
|
zip_uint32_t external_file_attributes; /* external file attributes (host-system specific) */
|
||||||
|
zip_uint16_t general_purpose_bit_flags; /* general purpose big flags, only some bits are honored */
|
||||||
|
zip_uint16_t general_purpose_bit_mask; /* which bits in general_purpose_bit_flags are valid */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ZIP_FILE_ATTRIBUTES_HOST_SYSTEM 0x0001u
|
||||||
|
#define ZIP_FILE_ATTRIBUTES_ASCII 0x0002u
|
||||||
|
#define ZIP_FILE_ATTRIBUTES_VERSION_NEEDED 0x0004u
|
||||||
|
#define ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES 0x0008u
|
||||||
|
#define ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS 0x0010u
|
||||||
|
|
||||||
|
struct zip;
|
||||||
|
struct zip_file;
|
||||||
|
struct zip_source;
|
||||||
|
|
||||||
|
typedef struct zip zip_t;
|
||||||
|
typedef struct zip_error zip_error_t;
|
||||||
|
typedef struct zip_file zip_file_t;
|
||||||
|
typedef struct zip_file_attributes zip_file_attributes_t;
|
||||||
|
typedef struct zip_source zip_source_t;
|
||||||
|
typedef struct zip_stat zip_stat_t;
|
||||||
|
typedef struct zip_buffer_fragment zip_buffer_fragment_t;
|
||||||
|
|
||||||
|
typedef zip_uint32_t zip_flags_t;
|
||||||
|
|
||||||
|
typedef zip_int64_t (*zip_source_callback)(void *_Nullable, void *_Nullable, zip_uint64_t, zip_source_cmd_t);
|
||||||
|
typedef zip_int64_t (*zip_source_layered_callback)(zip_source_t *_Nonnull, void *_Nullable, void *_Nullable, zip_uint64_t, enum zip_source_cmd);
|
||||||
|
typedef void (*zip_progress_callback)(zip_t *_Nonnull, double, void *_Nullable);
|
||||||
|
typedef int (*zip_cancel_callback)(zip_t *_Nonnull, void *_Nullable);
|
||||||
|
|
||||||
|
#ifndef ZIP_DISABLE_DEPRECATED
|
||||||
|
#define ZIP_FL_RECOMPRESS 16u /* force recompression of data */
|
||||||
|
|
||||||
|
typedef void (*zip_progress_callback_t)(double);
|
||||||
|
ZIP_DEPRECATED("use 'zip_register_progress_callback_with_state' instead") ZIP_EXTERN void zip_register_progress_callback(zip_t *_Nonnull, zip_progress_callback_t _Nullable);
|
||||||
|
|
||||||
|
ZIP_DEPRECATED("use 'zip_file_add' instead") ZIP_EXTERN zip_int64_t zip_add(zip_t *_Nonnull, const char *_Nonnull, zip_source_t *_Nonnull);
|
||||||
|
ZIP_DEPRECATED("use 'zip_dir_add' instead") ZIP_EXTERN zip_int64_t zip_add_dir(zip_t *_Nonnull, const char *_Nonnull);
|
||||||
|
ZIP_DEPRECATED("use 'zip_file_get_comment' instead") ZIP_EXTERN const char *_Nullable zip_get_file_comment(zip_t *_Nonnull, zip_uint64_t, int *_Nullable, int);
|
||||||
|
ZIP_DEPRECATED("use 'zip_get_num_entries' instead") ZIP_EXTERN int zip_get_num_files(zip_t *_Nonnull);
|
||||||
|
ZIP_DEPRECATED("use 'zip_file_rename' instead") ZIP_EXTERN int zip_rename(zip_t *_Nonnull, zip_uint64_t, const char *_Nonnull);
|
||||||
|
ZIP_DEPRECATED("use 'zip_file_replace' instead") ZIP_EXTERN int zip_replace(zip_t *_Nonnull, zip_uint64_t, zip_source_t *_Nonnull);
|
||||||
|
ZIP_DEPRECATED("use 'zip_file_set_comment' instead") ZIP_EXTERN int zip_set_file_comment(zip_t *_Nonnull, zip_uint64_t, const char *_Nullable, int);
|
||||||
|
ZIP_DEPRECATED("use 'zip_error_init_with_code' and 'zip_error_system_type' instead") ZIP_EXTERN int zip_error_get_sys_type(int);
|
||||||
|
ZIP_DEPRECATED("use 'zip_get_error' instead") ZIP_EXTERN void zip_error_get(zip_t *_Nonnull, int *_Nullable, int *_Nullable);
|
||||||
|
ZIP_DEPRECATED("use 'zip_error_strerror' instead") ZIP_EXTERN int zip_error_to_str(char *_Nonnull, zip_uint64_t, int, int);
|
||||||
|
ZIP_DEPRECATED("use 'zip_file_get_error' instead") ZIP_EXTERN void zip_file_error_get(zip_file_t *_Nonnull, int *_Nullable, int *_Nullable);
|
||||||
|
ZIP_DEPRECATED("use 'zip_source_zip_file' instead") 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_DEPRECATED("use 'zip_source_zip_file_create' instead") 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);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ZIP_EXTERN int zip_close(zip_t *_Nonnull);
|
||||||
|
ZIP_EXTERN int zip_delete(zip_t *_Nonnull, zip_uint64_t);
|
||||||
|
ZIP_EXTERN zip_int64_t zip_dir_add(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t);
|
||||||
|
ZIP_EXTERN void zip_discard(zip_t *_Nonnull);
|
||||||
|
|
||||||
|
ZIP_EXTERN zip_error_t *_Nonnull zip_get_error(zip_t *_Nonnull);
|
||||||
|
ZIP_EXTERN void zip_error_clear(zip_t *_Nonnull);
|
||||||
|
ZIP_EXTERN int zip_error_code_zip(const zip_error_t *_Nonnull);
|
||||||
|
ZIP_EXTERN int zip_error_code_system(const zip_error_t *_Nonnull);
|
||||||
|
ZIP_EXTERN void zip_error_fini(zip_error_t *_Nonnull);
|
||||||
|
ZIP_EXTERN void zip_error_init(zip_error_t *_Nonnull);
|
||||||
|
ZIP_EXTERN void zip_error_init_with_code(zip_error_t *_Nonnull, int);
|
||||||
|
ZIP_EXTERN void zip_error_set(zip_error_t *_Nullable, int, int);
|
||||||
|
ZIP_EXTERN void zip_error_set_from_source(zip_error_t *_Nonnull, zip_source_t *_Nullable);
|
||||||
|
ZIP_EXTERN const char *_Nonnull zip_error_strerror(zip_error_t *_Nonnull);
|
||||||
|
ZIP_EXTERN int zip_error_system_type(const zip_error_t *_Nonnull);
|
||||||
|
ZIP_EXTERN zip_int64_t zip_error_to_data(const zip_error_t *_Nonnull, void *_Nonnull, zip_uint64_t);
|
||||||
|
|
||||||
|
ZIP_EXTERN int zip_fclose(zip_file_t *_Nonnull);
|
||||||
|
ZIP_EXTERN zip_t *_Nullable zip_fdopen(int, int, int *_Nullable);
|
||||||
|
ZIP_EXTERN zip_int64_t zip_file_add(zip_t *_Nonnull, const char *_Nonnull, zip_source_t *_Nonnull, zip_flags_t);
|
||||||
|
ZIP_EXTERN void zip_file_attributes_init(zip_file_attributes_t *_Nonnull);
|
||||||
|
ZIP_EXTERN void zip_file_error_clear(zip_file_t *_Nonnull);
|
||||||
|
ZIP_EXTERN int zip_file_extra_field_delete(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_flags_t);
|
||||||
|
ZIP_EXTERN int zip_file_extra_field_delete_by_id(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_flags_t);
|
||||||
|
ZIP_EXTERN int zip_file_extra_field_set(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t, const zip_uint8_t *_Nullable, zip_uint16_t, zip_flags_t);
|
||||||
|
ZIP_EXTERN zip_int16_t zip_file_extra_fields_count(zip_t *_Nonnull, zip_uint64_t, zip_flags_t);
|
||||||
|
ZIP_EXTERN zip_int16_t zip_file_extra_fields_count_by_id(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_flags_t);
|
||||||
|
ZIP_EXTERN const zip_uint8_t *_Nullable zip_file_extra_field_get(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t *_Nullable, zip_uint16_t *_Nullable, zip_flags_t);
|
||||||
|
ZIP_EXTERN const zip_uint8_t *_Nullable zip_file_extra_field_get_by_id(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_uint16_t *_Nullable, zip_flags_t);
|
||||||
|
ZIP_EXTERN const char *_Nullable zip_file_get_comment(zip_t *_Nonnull, zip_uint64_t, zip_uint32_t *_Nullable, zip_flags_t);
|
||||||
|
ZIP_EXTERN zip_error_t *_Nonnull zip_file_get_error(zip_file_t *_Nonnull);
|
||||||
|
ZIP_EXTERN int zip_file_get_external_attributes(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint8_t *_Nullable, zip_uint32_t *_Nullable);
|
||||||
|
ZIP_EXTERN int zip_file_is_seekable(zip_file_t *_Nonnull);
|
||||||
|
ZIP_EXTERN int zip_file_rename(zip_t *_Nonnull, zip_uint64_t, const char *_Nonnull, zip_flags_t);
|
||||||
|
ZIP_EXTERN int zip_file_replace(zip_t *_Nonnull, zip_uint64_t, zip_source_t *_Nonnull, zip_flags_t);
|
||||||
|
ZIP_EXTERN int zip_file_set_comment(zip_t *_Nonnull, zip_uint64_t, const char *_Nullable, zip_uint16_t, zip_flags_t);
|
||||||
|
ZIP_EXTERN int zip_file_set_dostime(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_flags_t);
|
||||||
|
ZIP_EXTERN int zip_file_set_encryption(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, const char *_Nullable);
|
||||||
|
ZIP_EXTERN int zip_file_set_external_attributes(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint8_t, zip_uint32_t);
|
||||||
|
ZIP_EXTERN int zip_file_set_mtime(zip_t *_Nonnull, zip_uint64_t, time_t, zip_flags_t);
|
||||||
|
ZIP_EXTERN const char *_Nonnull zip_file_strerror(zip_file_t *_Nonnull);
|
||||||
|
ZIP_EXTERN zip_file_t *_Nullable zip_fopen(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t);
|
||||||
|
ZIP_EXTERN zip_file_t *_Nullable zip_fopen_encrypted(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t, const char *_Nullable);
|
||||||
|
ZIP_EXTERN zip_file_t *_Nullable zip_fopen_index(zip_t *_Nonnull, zip_uint64_t, zip_flags_t);
|
||||||
|
ZIP_EXTERN zip_file_t *_Nullable zip_fopen_index_encrypted(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, const char *_Nullable);
|
||||||
|
ZIP_EXTERN zip_int64_t zip_fread(zip_file_t *_Nonnull, void *_Nonnull, zip_uint64_t);
|
||||||
|
ZIP_EXTERN zip_int8_t zip_fseek(zip_file_t *_Nonnull, zip_int64_t, int);
|
||||||
|
ZIP_EXTERN zip_int64_t zip_ftell(zip_file_t *_Nonnull);
|
||||||
|
ZIP_EXTERN const char *_Nullable zip_get_archive_comment(zip_t *_Nonnull, int *_Nullable, zip_flags_t);
|
||||||
|
ZIP_EXTERN int zip_get_archive_flag(zip_t *_Nonnull, zip_flags_t, zip_flags_t);
|
||||||
|
ZIP_EXTERN const char *_Nullable zip_get_name(zip_t *_Nonnull, zip_uint64_t, zip_flags_t);
|
||||||
|
ZIP_EXTERN zip_int64_t zip_get_num_entries(zip_t *_Nonnull, zip_flags_t);
|
||||||
|
ZIP_EXTERN const char *_Nonnull zip_libzip_version(void);
|
||||||
|
ZIP_EXTERN zip_int64_t zip_name_locate(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t);
|
||||||
|
ZIP_EXTERN zip_t *_Nullable zip_open(const char *_Nonnull, int, int *_Nullable);
|
||||||
|
ZIP_EXTERN zip_t *_Nullable zip_open_from_source(zip_source_t *_Nonnull, int, zip_error_t *_Nullable);
|
||||||
|
ZIP_EXTERN int zip_register_progress_callback_with_state(zip_t *_Nonnull, double, zip_progress_callback _Nullable, void (*_Nullable)(void *_Nullable), void *_Nullable);
|
||||||
|
ZIP_EXTERN int zip_register_cancel_callback_with_state(zip_t *_Nonnull, zip_cancel_callback _Nullable, void (*_Nullable)(void *_Nullable), void *_Nullable);
|
||||||
|
ZIP_EXTERN int zip_set_archive_comment(zip_t *_Nonnull, const char *_Nullable, zip_uint16_t);
|
||||||
|
ZIP_EXTERN int zip_set_archive_flag(zip_t *_Nonnull, zip_flags_t, int);
|
||||||
|
ZIP_EXTERN int zip_set_default_password(zip_t *_Nonnull, const char *_Nullable);
|
||||||
|
ZIP_EXTERN int zip_set_file_compression(zip_t *_Nonnull, zip_uint64_t, zip_int32_t, zip_uint32_t);
|
||||||
|
ZIP_EXTERN int zip_source_begin_write(zip_source_t *_Nonnull);
|
||||||
|
ZIP_EXTERN int zip_source_begin_write_cloning(zip_source_t *_Nonnull, zip_uint64_t);
|
||||||
|
ZIP_EXTERN zip_source_t *_Nullable zip_source_buffer(zip_t *_Nonnull, const void *_Nullable, zip_uint64_t, int);
|
||||||
|
ZIP_EXTERN zip_source_t *_Nullable zip_source_buffer_create(const void *_Nullable, zip_uint64_t, int, zip_error_t *_Nullable);
|
||||||
|
ZIP_EXTERN zip_source_t *_Nullable zip_source_buffer_fragment(zip_t *_Nonnull, const zip_buffer_fragment_t *_Nonnull, zip_uint64_t, int);
|
||||||
|
ZIP_EXTERN zip_source_t *_Nullable zip_source_buffer_fragment_create(const zip_buffer_fragment_t *_Nullable, zip_uint64_t, int, zip_error_t *_Nullable);
|
||||||
|
ZIP_EXTERN int zip_source_close(zip_source_t *_Nonnull);
|
||||||
|
ZIP_EXTERN int zip_source_commit_write(zip_source_t *_Nonnull);
|
||||||
|
ZIP_EXTERN zip_error_t *_Nonnull zip_source_error(zip_source_t *_Nonnull);
|
||||||
|
ZIP_EXTERN zip_source_t *_Nullable zip_source_file(zip_t *_Nonnull, const char *_Nonnull, zip_uint64_t, zip_int64_t);
|
||||||
|
ZIP_EXTERN zip_source_t *_Nullable zip_source_file_create(const char *_Nonnull, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable);
|
||||||
|
ZIP_EXTERN zip_source_t *_Nullable zip_source_filep(zip_t *_Nonnull, FILE *_Nonnull, zip_uint64_t, zip_int64_t);
|
||||||
|
ZIP_EXTERN zip_source_t *_Nullable zip_source_filep_create(FILE *_Nonnull, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable);
|
||||||
|
ZIP_EXTERN void zip_source_free(zip_source_t *_Nullable);
|
||||||
|
ZIP_EXTERN zip_source_t *_Nullable zip_source_function(zip_t *_Nonnull, zip_source_callback _Nonnull, void *_Nullable);
|
||||||
|
ZIP_EXTERN zip_source_t *_Nullable zip_source_function_create(zip_source_callback _Nonnull, void *_Nullable, zip_error_t *_Nullable);
|
||||||
|
ZIP_EXTERN int zip_source_get_file_attributes(zip_source_t *_Nonnull, zip_file_attributes_t *_Nonnull);
|
||||||
|
ZIP_EXTERN int zip_source_is_deleted(zip_source_t *_Nonnull);
|
||||||
|
ZIP_EXTERN int zip_source_is_seekable(zip_source_t *_Nonnull);
|
||||||
|
ZIP_EXTERN void zip_source_keep(zip_source_t *_Nonnull);
|
||||||
|
ZIP_EXTERN zip_source_t *_Nullable zip_source_layered(zip_t *_Nullable, zip_source_t *_Nonnull, zip_source_layered_callback _Nonnull, void *_Nullable);
|
||||||
|
ZIP_EXTERN zip_source_t *_Nullable zip_source_layered_create(zip_source_t *_Nonnull, zip_source_layered_callback _Nonnull, void *_Nullable, zip_error_t *_Nullable);
|
||||||
|
ZIP_EXTERN zip_int64_t zip_source_make_command_bitmap(zip_source_cmd_t, ...);
|
||||||
|
ZIP_EXTERN int zip_source_open(zip_source_t *_Nonnull);
|
||||||
|
ZIP_EXTERN zip_int64_t zip_source_pass_to_lower_layer(zip_source_t *_Nonnull, void *_Nullable, zip_uint64_t, zip_source_cmd_t);
|
||||||
|
ZIP_EXTERN zip_int64_t zip_source_read(zip_source_t *_Nonnull, void *_Nonnull, zip_uint64_t);
|
||||||
|
ZIP_EXTERN void zip_source_rollback_write(zip_source_t *_Nonnull);
|
||||||
|
ZIP_EXTERN int zip_source_seek(zip_source_t *_Nonnull, zip_int64_t, int);
|
||||||
|
ZIP_EXTERN zip_int64_t zip_source_seek_compute_offset(zip_uint64_t, zip_uint64_t, void *_Nonnull, zip_uint64_t, zip_error_t *_Nullable);
|
||||||
|
ZIP_EXTERN int zip_source_seek_write(zip_source_t *_Nonnull, zip_int64_t, int);
|
||||||
|
ZIP_EXTERN int zip_source_stat(zip_source_t *_Nonnull, zip_stat_t *_Nonnull);
|
||||||
|
ZIP_EXTERN zip_int64_t zip_source_tell(zip_source_t *_Nonnull);
|
||||||
|
ZIP_EXTERN zip_int64_t zip_source_tell_write(zip_source_t *_Nonnull);
|
||||||
|
#ifdef _WIN32
|
||||||
|
ZIP_EXTERN zip_source_t *_Nullable zip_source_win32a(zip_t *_Nonnull, const char *_Nonnull, zip_uint64_t, zip_int64_t);
|
||||||
|
ZIP_EXTERN zip_source_t *_Nullable zip_source_win32a_create(const char *_Nonnull, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable);
|
||||||
|
ZIP_EXTERN zip_source_t *_Nullable zip_source_win32handle(zip_t *_Nonnull, void *_Nonnull, zip_uint64_t, zip_int64_t);
|
||||||
|
ZIP_EXTERN zip_source_t *_Nullable zip_source_win32handle_create(void *_Nonnull, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable);
|
||||||
|
ZIP_EXTERN zip_source_t *_Nullable zip_source_win32w(zip_t *_Nonnull, const wchar_t *_Nonnull, zip_uint64_t, zip_int64_t);
|
||||||
|
ZIP_EXTERN zip_source_t *_Nullable zip_source_win32w_create(const wchar_t *_Nonnull, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable);
|
||||||
|
#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_file(zip_t *_Nonnull, zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t, const char *_Nullable);
|
||||||
|
ZIP_EXTERN zip_source_t *_Nullable zip_source_zip_file_create(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t, const char *_Nullable, 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);
|
||||||
|
ZIP_EXTERN const char *_Nonnull zip_strerror(zip_t *_Nonnull);
|
||||||
|
ZIP_EXTERN int zip_unchange(zip_t *_Nonnull, zip_uint64_t);
|
||||||
|
ZIP_EXTERN int zip_unchange_all(zip_t *_Nonnull);
|
||||||
|
ZIP_EXTERN int zip_unchange_archive(zip_t *_Nonnull);
|
||||||
|
ZIP_EXTERN int zip_compression_method_supported(zip_int32_t method, int compress);
|
||||||
|
ZIP_EXTERN int zip_encryption_method_supported(zip_uint16_t method, int encode);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _HAD_ZIP_H */
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
zip_add.c -- add file via callback function
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define _ZIP_COMPILING_DEPRECATED
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ZIP_EXTERN zip_int64_t
|
||||||
|
zip_add(zip_t *za, const char *name, zip_source_t *source) {
|
||||||
|
return zip_file_add(za, name, source, 0);
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
zip_add_dir.c -- add directory
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define _ZIP_COMPILING_DEPRECATED
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */
|
||||||
|
|
||||||
|
ZIP_EXTERN zip_int64_t
|
||||||
|
zip_add_dir(zip_t *za, const char *name) {
|
||||||
|
return zip_dir_add(za, name, 0);
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
zip_add_entry.c -- create and init struct zip_entry
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <stdlib.h>
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */
|
||||||
|
|
||||||
|
zip_int64_t
|
||||||
|
_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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
idx = za->nentry++;
|
||||||
|
|
||||||
|
_zip_entry_init(za->entry + idx);
|
||||||
|
|
||||||
|
return (zip_int64_t)idx;
|
||||||
|
}
|
|
@ -0,0 +1,293 @@
|
||||||
|
/*
|
||||||
|
zip_algorithm_bzip2.c -- bzip2 (de)compression routines
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <bzlib.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
struct ctx {
|
||||||
|
zip_error_t *error;
|
||||||
|
bool compress;
|
||||||
|
int compression_flags;
|
||||||
|
bool end_of_input;
|
||||||
|
bz_stream zstr;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
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, zip_uint32_t compression_flags, zip_error_t *error) {
|
||||||
|
struct ctx *ctx;
|
||||||
|
|
||||||
|
if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->error = error;
|
||||||
|
ctx->compress = compress;
|
||||||
|
if (compression_flags >= 1 && compression_flags <= 9) {
|
||||||
|
ctx->compression_flags = (int)compression_flags;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ctx->compression_flags = 9;
|
||||||
|
}
|
||||||
|
ctx->end_of_input = false;
|
||||||
|
|
||||||
|
ctx->zstr.bzalloc = NULL;
|
||||||
|
ctx->zstr.bzfree = NULL;
|
||||||
|
ctx->zstr.opaque = NULL;
|
||||||
|
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *
|
||||||
|
compress_allocate(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error) {
|
||||||
|
(void)method;
|
||||||
|
return allocate(true, compression_flags, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *
|
||||||
|
decompress_allocate(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error) {
|
||||||
|
(void)method;
|
||||||
|
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) {
|
||||||
|
(void)ud;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
map_error(int ret) {
|
||||||
|
switch (ret) {
|
||||||
|
case BZ_FINISH_OK:
|
||||||
|
case BZ_FLUSH_OK:
|
||||||
|
case BZ_OK:
|
||||||
|
case BZ_RUN_OK:
|
||||||
|
case BZ_STREAM_END:
|
||||||
|
return ZIP_ER_OK;
|
||||||
|
|
||||||
|
case BZ_DATA_ERROR:
|
||||||
|
case BZ_DATA_ERROR_MAGIC:
|
||||||
|
case BZ_UNEXPECTED_EOF:
|
||||||
|
return ZIP_ER_COMPRESSED_DATA;
|
||||||
|
|
||||||
|
case BZ_MEM_ERROR:
|
||||||
|
return ZIP_ER_MEMORY;
|
||||||
|
|
||||||
|
case BZ_PARAM_ERROR:
|
||||||
|
return ZIP_ER_INVAL;
|
||||||
|
|
||||||
|
case BZ_CONFIG_ERROR: /* actually, bzip2 miscompiled */
|
||||||
|
case BZ_IO_ERROR:
|
||||||
|
case BZ_OUTBUFF_FULL:
|
||||||
|
case BZ_SEQUENCE_ERROR:
|
||||||
|
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;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
(void)st;
|
||||||
|
(void)attributes;
|
||||||
|
|
||||||
|
ctx->zstr.avail_in = 0;
|
||||||
|
ctx->zstr.next_in = NULL;
|
||||||
|
ctx->zstr.avail_out = 0;
|
||||||
|
ctx->zstr.next_out = NULL;
|
||||||
|
|
||||||
|
if (ctx->compress) {
|
||||||
|
ret = BZ2_bzCompressInit(&ctx->zstr, ctx->compression_flags, 0, 30);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = BZ2_bzDecompressInit(&ctx->zstr, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret != BZ_OK) {
|
||||||
|
zip_error_set(ctx->error, map_error(ret), 0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
end(void *ud) {
|
||||||
|
struct ctx *ctx = (struct ctx *)ud;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (ctx->compress) {
|
||||||
|
err = BZ2_bzCompressEnd(&ctx->zstr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
err = BZ2_bzDecompressEnd(&ctx->zstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err != BZ_OK) {
|
||||||
|
zip_error_set(ctx->error, map_error(err), 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 > UINT_MAX || ctx->zstr.avail_in > 0) {
|
||||||
|
zip_error_set(ctx->error, ZIP_ER_INVAL, 0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->zstr.avail_in = (unsigned int)length;
|
||||||
|
ctx->zstr.next_in = (char *)data;
|
||||||
|
|
||||||
|
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;
|
||||||
|
unsigned int avail_out;
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (ctx->zstr.avail_in == 0 && !ctx->end_of_input) {
|
||||||
|
*length = 0;
|
||||||
|
return ZIP_COMPRESSION_NEED_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
avail_out = (unsigned int)ZIP_MIN(UINT_MAX, *length);
|
||||||
|
ctx->zstr.avail_out = avail_out;
|
||||||
|
ctx->zstr.next_out = (char *)data;
|
||||||
|
|
||||||
|
if (ctx->compress) {
|
||||||
|
ret = BZ2_bzCompress(&ctx->zstr, ctx->end_of_input ? BZ_FINISH : BZ_RUN);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = BZ2_bzDecompress(&ctx->zstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
*length = avail_out - ctx->zstr.avail_out;
|
||||||
|
|
||||||
|
switch (ret) {
|
||||||
|
case BZ_FINISH_OK: /* compression */
|
||||||
|
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;
|
||||||
|
|
||||||
|
case BZ_STREAM_END:
|
||||||
|
return ZIP_COMPRESSION_END;
|
||||||
|
|
||||||
|
default:
|
||||||
|
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,
|
||||||
|
46,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
input,
|
||||||
|
end_of_input,
|
||||||
|
process
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
zip_compression_algorithm_t zip_algorithm_bzip2_decompress = {
|
||||||
|
maximum_compressed_size,
|
||||||
|
decompress_allocate,
|
||||||
|
deallocate,
|
||||||
|
general_purpose_bit_flags,
|
||||||
|
46,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
input,
|
||||||
|
end_of_input,
|
||||||
|
process
|
||||||
|
};
|
||||||
|
|
||||||
|
/* clang-format on */
|
|
@ -0,0 +1,276 @@
|
||||||
|
/*
|
||||||
|
zip_algorithm_deflate.c -- deflate (de)compression routines
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <zlib.h>
|
||||||
|
|
||||||
|
struct ctx {
|
||||||
|
zip_error_t *error;
|
||||||
|
bool compress;
|
||||||
|
int level;
|
||||||
|
int mem_level;
|
||||||
|
bool end_of_input;
|
||||||
|
z_stream zstr;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
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, zip_uint32_t 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->error = error;
|
||||||
|
ctx->compress = compress;
|
||||||
|
if (compression_flags >= 1 && compression_flags <= 9) {
|
||||||
|
ctx->level = (int)compression_flags;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ctx->level = Z_BEST_COMPRESSION;
|
||||||
|
}
|
||||||
|
ctx->mem_level = compression_flags == TORRENTZIP_COMPRESSION_FLAGS ? TORRENTZIP_MEM_LEVEL : MAX_MEM_LEVEL;
|
||||||
|
ctx->end_of_input = false;
|
||||||
|
|
||||||
|
ctx->zstr.zalloc = Z_NULL;
|
||||||
|
ctx->zstr.zfree = Z_NULL;
|
||||||
|
ctx->zstr.opaque = NULL;
|
||||||
|
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *
|
||||||
|
compress_allocate(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error) {
|
||||||
|
(void)method;
|
||||||
|
return allocate(true, compression_flags, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *
|
||||||
|
decompress_allocate(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error) {
|
||||||
|
(void)method;
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (!ctx->compress) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->level < 3) {
|
||||||
|
return 2 << 1;
|
||||||
|
}
|
||||||
|
else if (ctx->level > 7) {
|
||||||
|
return 1 << 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
start(void *ud, zip_stat_t *st, zip_file_attributes_t *attributes) {
|
||||||
|
struct ctx *ctx = (struct ctx *)ud;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
(void)st;
|
||||||
|
(void)attributes;
|
||||||
|
|
||||||
|
ctx->zstr.avail_in = 0;
|
||||||
|
ctx->zstr.next_in = NULL;
|
||||||
|
ctx->zstr.avail_out = 0;
|
||||||
|
ctx->zstr.next_out = NULL;
|
||||||
|
|
||||||
|
if (ctx->compress) {
|
||||||
|
/* negative value to tell zlib not to write a header */
|
||||||
|
ret = deflateInit2(&ctx->zstr, ctx->level, Z_DEFLATED, -MAX_WBITS, ctx->mem_level, Z_DEFAULT_STRATEGY);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = inflateInit2(&ctx->zstr, -MAX_WBITS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret != Z_OK) {
|
||||||
|
zip_error_set(ctx->error, ZIP_ER_ZLIB, ret);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
end(void *ud) {
|
||||||
|
struct ctx *ctx = (struct ctx *)ud;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (ctx->compress) {
|
||||||
|
err = deflateEnd(&ctx->zstr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
err = inflateEnd(&ctx->zstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err != Z_OK) {
|
||||||
|
zip_error_set(ctx->error, ZIP_ER_ZLIB, err);
|
||||||
|
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 > UINT_MAX || ctx->zstr.avail_in > 0) {
|
||||||
|
zip_error_set(ctx->error, ZIP_ER_INVAL, 0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->zstr.avail_in = (uInt)length;
|
||||||
|
ctx->zstr.next_in = (Bytef *)data;
|
||||||
|
|
||||||
|
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;
|
||||||
|
uInt avail_out;
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
avail_out = (uInt)ZIP_MIN(UINT_MAX, *length);
|
||||||
|
ctx->zstr.avail_out = avail_out;
|
||||||
|
ctx->zstr.next_out = (Bytef *)data;
|
||||||
|
|
||||||
|
if (ctx->compress) {
|
||||||
|
ret = deflate(&ctx->zstr, ctx->end_of_input ? Z_FINISH : 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = inflate(&ctx->zstr, Z_SYNC_FLUSH);
|
||||||
|
}
|
||||||
|
|
||||||
|
*length = avail_out - ctx->zstr.avail_out;
|
||||||
|
|
||||||
|
switch (ret) {
|
||||||
|
case Z_OK:
|
||||||
|
return ZIP_COMPRESSION_OK;
|
||||||
|
|
||||||
|
case Z_STREAM_END:
|
||||||
|
return ZIP_COMPRESSION_END;
|
||||||
|
|
||||||
|
case Z_BUF_ERROR:
|
||||||
|
if (ctx->zstr.avail_in == 0) {
|
||||||
|
return ZIP_COMPRESSION_NEED_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fallthrough */
|
||||||
|
|
||||||
|
default:
|
||||||
|
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,
|
||||||
|
20,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
input,
|
||||||
|
end_of_input,
|
||||||
|
process
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
zip_compression_algorithm_t zip_algorithm_deflate_decompress = {
|
||||||
|
maximum_compressed_size,
|
||||||
|
decompress_allocate,
|
||||||
|
deallocate,
|
||||||
|
general_purpose_bit_flags,
|
||||||
|
20,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
input,
|
||||||
|
end_of_input,
|
||||||
|
process
|
||||||
|
};
|
||||||
|
|
||||||
|
/* clang-format on */
|
|
@ -0,0 +1,408 @@
|
||||||
|
/*
|
||||||
|
zip_algorithm_xz.c -- LZMA/XZ (de)compression routines
|
||||||
|
Bazed on zip_algorithm_deflate.c -- deflate (de)compression routines
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <lzma.h>
|
||||||
|
#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;
|
||||||
|
zip_uint32_t compression_flags;
|
||||||
|
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, zip_uint32_t compression_flags, zip_error_t *error, zip_uint16_t method) {
|
||||||
|
struct ctx *ctx;
|
||||||
|
|
||||||
|
if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) {
|
||||||
|
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->error = error;
|
||||||
|
ctx->compress = compress;
|
||||||
|
if (compression_flags <= 9) {
|
||||||
|
ctx->compression_flags = compression_flags;
|
||||||
|
} else {
|
||||||
|
ctx->compression_flags = 6; /* default value */
|
||||||
|
}
|
||||||
|
ctx->compression_flags |= LZMA_PRESET_EXTREME;
|
||||||
|
ctx->end_of_input = false;
|
||||||
|
memset(ctx->header, 0, sizeof(ctx->header));
|
||||||
|
ctx->header_bytes_offset = 0;
|
||||||
|
if (method == ZIP_CM_LZMA) {
|
||||||
|
ctx->header_state = INCOMPLETE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ctx->header_state = DONE;
|
||||||
|
}
|
||||||
|
memset(&ctx->zstr, 0, sizeof(ctx->zstr));
|
||||||
|
ctx->method = method;
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *
|
||||||
|
compress_allocate(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error) {
|
||||||
|
return allocate(true, compression_flags, error, method);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *
|
||||||
|
decompress_allocate(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error) {
|
||||||
|
return allocate(false, compression_flags, error, method);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
case LZMA_MEM_ERROR:
|
||||||
|
return ZIP_ER_MEMORY;
|
||||||
|
|
||||||
|
case LZMA_OPTIONS_ERROR:
|
||||||
|
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;
|
||||||
|
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},
|
||||||
|
};
|
||||||
|
|
||||||
|
ctx->zstr.avail_in = 0;
|
||||||
|
ctx->zstr.next_in = NULL;
|
||||||
|
ctx->zstr.avail_out = 0;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
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 (ret != LZMA_OK) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
end(void *ud) {
|
||||||
|
struct ctx *ctx = (struct ctx *)ud;
|
||||||
|
|
||||||
|
lzma_end(&ctx->zstr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
(void)memcpy_s(ctx->header + ctx->header_bytes_offset, sizeof(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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
uInt avail_out;
|
||||||
|
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);
|
||||||
|
(void)memcpy_s(data, *length, 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
avail_out = (uInt)ZIP_MIN(UINT_MAX, *length);
|
||||||
|
ctx->zstr.avail_out = avail_out;
|
||||||
|
ctx->zstr.next_out = (Bytef *)data;
|
||||||
|
|
||||||
|
ret = lzma_code(&ctx->zstr, ctx->end_of_input ? LZMA_FINISH : LZMA_RUN);
|
||||||
|
*length = avail_out - ctx->zstr.avail_out;
|
||||||
|
|
||||||
|
switch (ret) {
|
||||||
|
case LZMA_OK:
|
||||||
|
return ZIP_COMPRESSION_OK;
|
||||||
|
|
||||||
|
case LZMA_STREAM_END:
|
||||||
|
return ZIP_COMPRESSION_END;
|
||||||
|
|
||||||
|
case LZMA_BUF_ERROR:
|
||||||
|
if (ctx->zstr.avail_in == 0) {
|
||||||
|
return ZIP_COMPRESSION_NEED_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fallthrough */
|
||||||
|
default:
|
||||||
|
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,
|
||||||
|
20,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
input,
|
||||||
|
end_of_input,
|
||||||
|
process
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
zip_compression_algorithm_t zip_algorithm_xz_decompress = {
|
||||||
|
maximum_compressed_size,
|
||||||
|
decompress_allocate,
|
||||||
|
deallocate,
|
||||||
|
general_purpose_bit_flags,
|
||||||
|
20,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
input,
|
||||||
|
end_of_input,
|
||||||
|
process
|
||||||
|
};
|
||||||
|
|
||||||
|
/* clang-format on */
|
|
@ -0,0 +1,298 @@
|
||||||
|
/*
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <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, zip_uint32_t compression_flags, zip_error_t *error) {
|
||||||
|
struct ctx *ctx;
|
||||||
|
|
||||||
|
if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->compression_flags = (zip_int32_t)compression_flags;
|
||||||
|
if (ctx->compression_flags < ZSTD_minCLevel() || ctx->compression_flags > ZSTD_maxCLevel()) {
|
||||||
|
ctx->compression_flags = 0; /* let zstd choose */
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->error = error;
|
||||||
|
ctx->compress = compress;
|
||||||
|
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, zip_uint32_t compression_flags, zip_error_t *error) {
|
||||||
|
(void)method;
|
||||||
|
return allocate(true, compression_flags, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *
|
||||||
|
decompress_allocate(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error) {
|
||||||
|
(void)method;
|
||||||
|
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) {
|
||||||
|
(void)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;
|
||||||
|
|
||||||
|
(void)st;
|
||||||
|
(void)attributes;
|
||||||
|
|
||||||
|
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 */
|
|
@ -0,0 +1,337 @@
|
||||||
|
/*
|
||||||
|
zip_buffer.c -- bounds checked access to memory buffer
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
zip_uint8_t *
|
||||||
|
_zip_buffer_data(zip_buffer_t *buffer) {
|
||||||
|
return buffer->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_zip_buffer_free(zip_buffer_t *buffer) {
|
||||||
|
if (buffer == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer->free_data) {
|
||||||
|
free(buffer->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
_zip_buffer_eof(zip_buffer_t *buffer) {
|
||||||
|
return buffer->ok && buffer->offset == buffer->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
zip_uint8_t *
|
||||||
|
_zip_buffer_get(zip_buffer_t *buffer, zip_uint64_t length) {
|
||||||
|
zip_uint8_t *data;
|
||||||
|
|
||||||
|
data = _zip_buffer_peek(buffer, length);
|
||||||
|
|
||||||
|
if (data != NULL) {
|
||||||
|
buffer->offset += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
zip_uint16_t
|
||||||
|
_zip_buffer_get_16(zip_buffer_t *buffer) {
|
||||||
|
zip_uint8_t *data = _zip_buffer_get(buffer, 2);
|
||||||
|
|
||||||
|
if (data == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (zip_uint16_t)(data[0] + (data[1] << 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
zip_uint32_t
|
||||||
|
_zip_buffer_get_32(zip_buffer_t *buffer) {
|
||||||
|
zip_uint8_t *data = _zip_buffer_get(buffer, 4);
|
||||||
|
|
||||||
|
if (data == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((((((zip_uint32_t)data[3] << 8) + data[2]) << 8) + data[1]) << 8) + data[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
zip_uint64_t
|
||||||
|
_zip_buffer_get_64(zip_buffer_t *buffer) {
|
||||||
|
zip_uint8_t *data = _zip_buffer_get(buffer, 8);
|
||||||
|
|
||||||
|
if (data == NULL) {
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
zip_uint8_t
|
||||||
|
_zip_buffer_get_8(zip_buffer_t *buffer) {
|
||||||
|
zip_uint8_t *data = _zip_buffer_get(buffer, 1);
|
||||||
|
|
||||||
|
if (data == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
zip_uint64_t
|
||||||
|
_zip_buffer_left(zip_buffer_t *buffer) {
|
||||||
|
return buffer->ok ? buffer->size - buffer->offset : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
zip_uint64_t
|
||||||
|
_zip_buffer_read(zip_buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length) {
|
||||||
|
zip_uint64_t copied;
|
||||||
|
|
||||||
|
if (_zip_buffer_left(buffer) < length) {
|
||||||
|
length = _zip_buffer_left(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
copied = 0;
|
||||||
|
while (copied < length) {
|
||||||
|
size_t n = ZIP_MIN(length - copied, SIZE_MAX);
|
||||||
|
(void)memcpy_s(data + copied, n, _zip_buffer_get(buffer, n), n);
|
||||||
|
copied += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return copied;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
zip_buffer_t *
|
||||||
|
_zip_buffer_new(zip_uint8_t *data, zip_uint64_t size) {
|
||||||
|
bool free_data = (data == NULL);
|
||||||
|
zip_buffer_t *buffer;
|
||||||
|
|
||||||
|
#if ZIP_UINT64_MAX > SIZE_MAX
|
||||||
|
if (size > SIZE_MAX) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (data == NULL) {
|
||||||
|
if ((data = (zip_uint8_t *)malloc((size_t)size)) == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((buffer = (zip_buffer_t *)malloc(sizeof(*buffer))) == NULL) {
|
||||||
|
if (free_data) {
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->ok = true;
|
||||||
|
buffer->data = data;
|
||||||
|
buffer->size = size;
|
||||||
|
buffer->offset = 0;
|
||||||
|
buffer->free_data = free_data;
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
zip_buffer_t *
|
||||||
|
_zip_buffer_new_from_source(zip_source_t *src, zip_uint64_t size, zip_uint8_t *buf, zip_error_t *error) {
|
||||||
|
zip_buffer_t *buffer;
|
||||||
|
|
||||||
|
if ((buffer = _zip_buffer_new(buf, size)) == 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
zip_uint64_t
|
||||||
|
_zip_buffer_offset(zip_buffer_t *buffer) {
|
||||||
|
return buffer->ok ? buffer->offset : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
_zip_buffer_ok(zip_buffer_t *buffer) {
|
||||||
|
return buffer->ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
zip_uint8_t *
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = buffer->data + buffer->offset;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)memcpy_s(dst, length, src, length);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
data[0] = (zip_uint8_t)(i & 0xff);
|
||||||
|
data[1] = (zip_uint8_t)((i >> 8) & 0xff);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
data[0] = (zip_uint8_t)(i & 0xff);
|
||||||
|
data[1] = (zip_uint8_t)((i >> 8) & 0xff);
|
||||||
|
data[2] = (zip_uint8_t)((i >> 16) & 0xff);
|
||||||
|
data[3] = (zip_uint8_t)((i >> 24) & 0xff);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
data[0] = (zip_uint8_t)(i & 0xff);
|
||||||
|
data[1] = (zip_uint8_t)((i >> 8) & 0xff);
|
||||||
|
data[2] = (zip_uint8_t)((i >> 16) & 0xff);
|
||||||
|
data[3] = (zip_uint8_t)((i >> 24) & 0xff);
|
||||||
|
data[4] = (zip_uint8_t)((i >> 32) & 0xff);
|
||||||
|
data[5] = (zip_uint8_t)((i >> 40) & 0xff);
|
||||||
|
data[6] = (zip_uint8_t)((i >> 48) & 0xff);
|
||||||
|
data[7] = (zip_uint8_t)((i >> 56) & 0xff);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
data[0] = i;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
_zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset) {
|
||||||
|
if (offset > buffer->size) {
|
||||||
|
buffer->ok = false;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->ok = true;
|
||||||
|
buffer->offset = offset;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
return _zip_buffer_set_offset(buffer, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
zip_uint64_t
|
||||||
|
_zip_buffer_size(zip_buffer_t *buffer) {
|
||||||
|
return buffer->size;
|
||||||
|
}
|
|
@ -0,0 +1,745 @@
|
||||||
|
/*
|
||||||
|
zip_close.c -- close zip archive and update changes
|
||||||
|
Copyright (C) 1999-2022 Dieter Baron and Thomas Klausner
|
||||||
|
|
||||||
|
This file is part of libzip, a library to manipulate ZIP archives.
|
||||||
|
The authors can be contacted at <info@libzip.org>
|
||||||
|
|
||||||
|
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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <io.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static int add_data(zip_t *, zip_source_t *, zip_dirent_t *, zip_uint32_t);
|
||||||
|
static int copy_data(zip_t *, zip_uint64_t);
|
||||||
|
static int copy_source(zip_t *, zip_source_t *, zip_int64_t);
|
||||||
|
static int torrentzip_compare_names(const void *a, const void *b);
|
||||||
|
static int write_cdir(zip_t *, const zip_filelist_t *, zip_uint64_t);
|
||||||
|
static int write_data_descriptor(zip_t *za, const zip_dirent_t *dirent, int is_zip64);
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
zip_close(zip_t *za) {
|
||||||
|
zip_uint64_t i, j, survivors, unchanged_offset;
|
||||||
|
zip_int64_t off;
|
||||||
|
int error;
|
||||||
|
zip_filelist_t *filelist;
|
||||||
|
int changed;
|
||||||
|
|
||||||
|
if (za == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
changed = _zip_changed(za, &survivors);
|
||||||
|
|
||||||
|
if (survivors == 0 && !(za->ch_flags & ZIP_AFL_CREATE_OR_KEEP_FILE_FOR_EMPTY_ARCHIVE)) {
|
||||||
|
/* don't create zip files with no entries */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Always write empty archive if we are told to keep it, otherwise it wouldn't be created if the file doesn't already exist. */
|
||||||
|
if (!changed && survivors > 0) {
|
||||||
|
zip_discard(za);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (survivors > za->nentry) {
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
filelist[j].name = zip_get_name(za, i, 0);
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
if (j < survivors) {
|
||||||
|
free(filelist);
|
||||||
|
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ZIP_WANT_TORRENTZIP(za)) {
|
||||||
|
qsort(filelist, (size_t)survivors, sizeof(filelist[0]), torrentzip_compare_names);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ZIP_WANT_TORRENTZIP(za) || (zip_source_supports(za->src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING)) == 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 == 0) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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)) || (ZIP_WANT_TORRENTZIP(za) && !ZIP_IS_TORRENTZIP(za));
|
||||||
|
|
||||||
|
/* 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 (ZIP_WANT_TORRENTZIP(za)) {
|
||||||
|
zip_dirent_torrentzip_normalize(entry->changes);
|
||||||
|
}
|
||||||
|
|
||||||
|
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_file_create(za, i, ZIP_FL_UNCHANGED, 0, -1, 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 ((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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (error) {
|
||||||
|
zip_source_rollback_write(za->src);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
zip_discard(za);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
|
||||||
|
zip_int64_t offstart, offdata, offend, data_length;
|
||||||
|
zip_stat_t st;
|
||||||
|
zip_file_attributes_t attributes;
|
||||||
|
zip_source_t *src_final, *src_tmp;
|
||||||
|
int ret;
|
||||||
|
int is_zip64;
|
||||||
|
zip_flags_t flags;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((st.valid & ZIP_STAT_COMP_METHOD) == 0) {
|
||||||
|
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;
|
||||||
|
else if (de->comp_method == ZIP_CM_STORE && (st.valid & ZIP_STAT_SIZE)) {
|
||||||
|
st.valid |= ZIP_STAT_COMP_SIZE;
|
||||||
|
st.comp_size = st.size;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
flags = ZIP_EF_LOCAL;
|
||||||
|
|
||||||
|
if ((st.valid & ZIP_STAT_SIZE) == 0) {
|
||||||
|
/* TODO: not valid for torrentzip */
|
||||||
|
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_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) {
|
||||||
|
/* TODO: not valid for torrentzip */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
needs_recompress = ZIP_WANT_TORRENTZIP(za) || 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);
|
||||||
|
|
||||||
|
needs_reencrypt = needs_recompress || (de->changed & ZIP_DIRENT_PASSWORD) || (de->encryption_method != st.encryption_method);
|
||||||
|
needs_decrypt = needs_reencrypt && (st.encryption_method != ZIP_EM_NONE);
|
||||||
|
needs_encrypt = needs_reencrypt && (de->encryption_method != ZIP_EM_NONE);
|
||||||
|
|
||||||
|
src_final = src;
|
||||||
|
zip_source_keep(src_final);
|
||||||
|
|
||||||
|
if (!needs_decrypt && st.encryption_method == ZIP_EM_TRAD_PKWARE && (de->changed & ZIP_DIRENT_LAST_MOD)) {
|
||||||
|
/* PKWare encryption uses the last modification time for password verification, therefore we can't change it without re-encrypting. Ignoring the requested modification time change seems more sensible than failing to close the archive. */
|
||||||
|
de->changed &= ~ZIP_DIRENT_LAST_MOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needs_decrypt) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
src_final = src_tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needs_crc) {
|
||||||
|
if ((src_tmp = zip_source_crc_create(src_final, 0, &za->error)) == NULL) {
|
||||||
|
zip_source_free(src_final);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (de->encryption_method == ZIP_EM_TRAD_PKWARE) {
|
||||||
|
de->bitflags |= ZIP_GPBF_DATA_DESCRIPTOR;
|
||||||
|
|
||||||
|
/* PKWare encryption uses last_mod, make sure it gets the right value. */
|
||||||
|
if (de->changed & ZIP_DIRENT_LAST_MOD) {
|
||||||
|
zip_stat_t st_mtime;
|
||||||
|
zip_stat_init(&st_mtime);
|
||||||
|
st_mtime.valid = ZIP_STAT_MTIME;
|
||||||
|
st_mtime.mtime = de->last_mod;
|
||||||
|
if ((src_tmp = _zip_source_window_new(src_final, 0, -1, &st_mtime, 0, NULL, NULL, 0, true, &za->error)) == NULL) {
|
||||||
|
zip_source_free(src_final);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
src_final = src_tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
src_final = src_tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ((offdata = zip_source_tell_write(za->src)) < 0) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zip_source_get_file_attributes(src_final, &attributes) != 0) {
|
||||||
|
zip_error_set_from_source(&za->error, src_final);
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
zip_source_free(src_final);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((offend = zip_source_tell_write(za->src)) < 0) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0) {
|
||||||
|
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;
|
||||||
|
de->uncomp_size = st.size;
|
||||||
|
de->comp_size = (zip_uint64_t)(offend - offdata);
|
||||||
|
_zip_dirent_apply_attributes(de, &attributes, (flags & ZIP_FL_FORCE_ZIP64) != 0, changed);
|
||||||
|
|
||||||
|
if (ZIP_WANT_TORRENTZIP(za)) {
|
||||||
|
zip_dirent_torrentzip_normalize(de);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = _zip_dirent_write(za, de, flags)) < 0)
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zip_source_seek_write(za->src, offend, SEEK_SET) < 0) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
copy_data(zip_t *za, zip_uint64_t len) {
|
||||||
|
DEFINE_BYTE_ARRAY(buf, BUFSIZE);
|
||||||
|
double total = (double)len;
|
||||||
|
|
||||||
|
if (!byte_array_init(buf, BUFSIZE)) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (len > 0) {
|
||||||
|
zip_uint64_t n = ZIP_MIN(len, BUFSIZE);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
len -= n;
|
||||||
|
|
||||||
|
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);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length) {
|
||||||
|
DEFINE_BYTE_ARRAY(buf, BUFSIZE);
|
||||||
|
zip_int64_t n, current;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (zip_source_open(src) < 0) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (n < 0) {
|
||||||
|
zip_error_set_from_source(&za->error, src);
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte_array_fini(buf);
|
||||||
|
|
||||||
|
zip_source_close(src);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
write_cdir(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors) {
|
||||||
|
if (zip_source_tell_write(za->src) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_zip_cdir_write(za, filelist, survivors) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zip_source_tell_write(za->src) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
_zip_changed(const zip_t *za, zip_uint64_t *survivorsp) {
|
||||||
|
int changed;
|
||||||
|
zip_uint64_t i, survivors;
|
||||||
|
|
||||||
|
changed = 0;
|
||||||
|
survivors = 0;
|
||||||
|
|
||||||
|
if (za->comment_changed || (ZIP_WANT_TORRENTZIP(za) && !ZIP_IS_TORRENTZIP(za))) {
|
||||||
|
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 (survivorsp) {
|
||||||
|
*survivorsp = survivors;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
write_data_descriptor(zip_t *za, const zip_dirent_t *de, int is_zip64) {
|
||||||
|
zip_buffer_t *buffer = _zip_buffer_new(NULL, MAX_DATA_DESCRIPTOR_LENGTH);
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (buffer == NULL) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = _zip_write(za, _zip_buffer_data(buffer), _zip_buffer_offset(buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
_zip_buffer_free(buffer);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int torrentzip_compare_names(const void *a, const void *b) {
|
||||||
|
const char *aname = ((const zip_filelist_t *)a)->name;
|
||||||
|
const char *bname = ((const zip_filelist_t *)b)->name;
|
||||||
|
|
||||||
|
if (aname == NULL) {
|
||||||
|
return (bname != NULL) * -1;
|
||||||
|
}
|
||||||
|
else if (bname == NULL) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return strcasecmp(aname, bname);
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
zip_crypto.h -- crypto definitions
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HAD_ZIP_CRYPTO_H
|
||||||
|
#define HAD_ZIP_CRYPTO_H
|
||||||
|
|
||||||
|
#define ZIP_CRYPTO_SHA1_LENGTH 20
|
||||||
|
#define ZIP_CRYPTO_AES_BLOCK_LENGTH 16
|
||||||
|
|
||||||
|
#if defined(HAVE_WINDOWS_CRYPTO)
|
||||||
|
#include "zip_crypto_win.h"
|
||||||
|
#elif defined(HAVE_COMMONCRYPTO)
|
||||||
|
#include "zip_crypto_commoncrypto.h"
|
||||||
|
#elif defined(HAVE_GNUTLS)
|
||||||
|
#include "zip_crypto_gnutls.h"
|
||||||
|
#elif defined(HAVE_OPENSSL)
|
||||||
|
#include "zip_crypto_openssl.h"
|
||||||
|
#elif defined(HAVE_MBEDTLS)
|
||||||
|
#include "zip_crypto_mbedtls.h"
|
||||||
|
#else
|
||||||
|
#error "no crypto backend found"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* HAD_ZIP_CRYPTO_H */
|
|
@ -0,0 +1,110 @@
|
||||||
|
/*
|
||||||
|
zip_crypto_commoncrypto.c -- CommonCrypto wrapper.
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <stdlib.h>
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
#include "zip_crypto.h"
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
_zip_crypto_aes_free(_zip_crypto_aes_t *aes) {
|
||||||
|
if (aes == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CCCryptorRelease(aes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
_zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out) {
|
||||||
|
size_t len;
|
||||||
|
CCCryptorUpdate(aes, in, ZIP_CRYPTO_AES_BLOCK_LENGTH, out, ZIP_CRYPTO_AES_BLOCK_LENGTH, &len);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_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;
|
||||||
|
CCCryptorStatus ret;
|
||||||
|
|
||||||
|
ret = CCCryptorCreate(kCCEncrypt, kCCAlgorithmAES, kCCOptionECBMode, key, key_size / 8, NULL, &aes);
|
||||||
|
|
||||||
|
switch (ret) {
|
||||||
|
case kCCSuccess:
|
||||||
|
return aes;
|
||||||
|
|
||||||
|
case kCCMemoryFailure:
|
||||||
|
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
case kCCParamError:
|
||||||
|
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
default:
|
||||||
|
zip_error_set(error, ZIP_ER_INTERNAL, 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) {
|
||||||
|
if (hmac == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_zip_crypto_clear(hmac, sizeof(*hmac));
|
||||||
|
free(hmac);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_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;
|
||||||
|
|
||||||
|
if ((hmac = (_zip_crypto_hmac_t *)malloc(sizeof(*hmac))) == NULL) {
|
||||||
|
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
CCHmacInit(hmac, kCCHmacAlgSHA1, secret, secret_length);
|
||||||
|
|
||||||
|
return hmac;
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
zip_crypto_commoncrypto.h -- definitions for CommonCrypto wrapper.
|
||||||
|
Copyright (C) 2018 Dieter Baron and Thomas Klausner
|
||||||
|
|
||||||
|
This file is part of libzip, a library to manipulate ZIP archives.
|
||||||
|
The authors can be contacted at <info@libzip.org>
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HAD_ZIP_CRYPTO_COMMONCRYPTO_H
|
||||||
|
#define HAD_ZIP_CRYPTO_COMMONCRYPTO_H
|
||||||
|
|
||||||
|
#include <CommonCrypto/CommonCrypto.h>
|
||||||
|
|
||||||
|
#define _zip_crypto_aes_t struct _CCCryptor
|
||||||
|
#define _zip_crypto_hmac_t CCHmacContext
|
||||||
|
|
||||||
|
void _zip_crypto_aes_free(_zip_crypto_aes_t *aes);
|
||||||
|
bool _zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out);
|
||||||
|
_zip_crypto_aes_t *_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error);
|
||||||
|
|
||||||
|
#define _zip_crypto_hmac(hmac, data, length) (CCHmacUpdate((hmac), (data), (length)), true)
|
||||||
|
void _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac);
|
||||||
|
_zip_crypto_hmac_t *_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error);
|
||||||
|
#define _zip_crypto_hmac_output(hmac, data) (CCHmacFinal((hmac), (data)), true)
|
||||||
|
|
||||||
|
#define _zip_crypto_pbkdf2(key, key_length, salt, salt_length, iterations, output, output_length) (CCKeyDerivationPBKDF(kCCPBKDF2, (const char *)(key), (key_length), (salt), (salt_length), kCCPRFHmacAlgSHA1, (iterations), (output), (output_length)) == kCCSuccess)
|
||||||
|
|
||||||
|
#endif /* HAD_ZIP_CRYPTO_COMMONCRYPTO_H */
|
|
@ -0,0 +1,134 @@
|
||||||
|
/*
|
||||||
|
zip_crypto_gnutls.c -- GnuTLS wrapper.
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <stdlib.h>
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
#include "zip_crypto.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
aes->key_size = key_size;
|
||||||
|
|
||||||
|
switch (aes->key_size) {
|
||||||
|
case 128:
|
||||||
|
nettle_aes128_set_encrypt_key(&aes->ctx.ctx_128, key);
|
||||||
|
break;
|
||||||
|
case 192:
|
||||||
|
nettle_aes192_set_encrypt_key(&aes->ctx.ctx_192, key);
|
||||||
|
break;
|
||||||
|
case 256:
|
||||||
|
nettle_aes256_set_encrypt_key(&aes->ctx.ctx_256, key);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||||
|
free(aes);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return aes;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
case 192:
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_zip_crypto_aes_free(_zip_crypto_aes_t *aes) {
|
||||||
|
if (aes == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_zip_crypto_clear(aes, sizeof(*aes));
|
||||||
|
free(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;
|
||||||
|
|
||||||
|
if ((hmac = (_zip_crypto_hmac_t *)malloc(sizeof(*hmac))) == NULL) {
|
||||||
|
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) {
|
||||||
|
zip_uint8_t buf[ZIP_CRYPTO_SHA1_LENGTH];
|
||||||
|
|
||||||
|
if (hmac == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnutls_hmac_deinit(*hmac, buf);
|
||||||
|
_zip_crypto_clear(hmac, sizeof(*hmac));
|
||||||
|
free(hmac);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN bool
|
||||||
|
zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) {
|
||||||
|
return gnutls_rnd(GNUTLS_RND_KEY, buffer, length) == 0;
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
zip_crypto_gnutls.h -- definitions for GnuTLS wrapper.
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HAD_ZIP_CRYPTO_GNUTLS_H
|
||||||
|
#define HAD_ZIP_CRYPTO_GNUTLS_H
|
||||||
|
|
||||||
|
#define HAVE_SECURE_RANDOM
|
||||||
|
|
||||||
|
#include <nettle/aes.h>
|
||||||
|
#include <nettle/pbkdf2.h>
|
||||||
|
|
||||||
|
#include <gnutls/gnutls.h>
|
||||||
|
|
||||||
|
#include <gnutls/crypto.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
union {
|
||||||
|
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;
|
||||||
|
|
||||||
|
#define _zip_crypto_hmac_t gnutls_hmac_hd_t
|
||||||
|
|
||||||
|
void _zip_crypto_aes_free(_zip_crypto_aes_t *aes);
|
||||||
|
bool _zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out);
|
||||||
|
_zip_crypto_aes_t *_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error);
|
||||||
|
|
||||||
|
#define _zip_crypto_hmac(hmac, data, length) (gnutls_hmac(*(hmac), (data), (length)) == 0)
|
||||||
|
void _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac);
|
||||||
|
_zip_crypto_hmac_t *_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error);
|
||||||
|
#define _zip_crypto_hmac_output(hmac, data) (gnutls_hmac_output(*(hmac), (data)), true)
|
||||||
|
|
||||||
|
#define _zip_crypto_pbkdf2(key, key_length, salt, salt_length, iterations, output, output_length) (pbkdf2_hmac_sha1((key_length), (key), (iterations), (salt_length), (salt), (output_length), (output)), true)
|
||||||
|
|
||||||
|
#endif /* HAD_ZIP_CRYPTO_GNUTLS_H */
|
|
@ -0,0 +1,171 @@
|
||||||
|
/*
|
||||||
|
zip_crypto_mbedtls.c -- mbed TLS wrapper
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <stdlib.h>
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
#include "zip_crypto.h"
|
||||||
|
|
||||||
|
#include <mbedtls/ctr_drbg.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
mbedtls_aes_init(aes);
|
||||||
|
mbedtls_aes_setkey_enc(aes, (const unsigned char *)key, (unsigned int)key_size);
|
||||||
|
|
||||||
|
return aes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_zip_crypto_aes_free(_zip_crypto_aes_t *aes) {
|
||||||
|
if (aes == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mbedtls_aes_free(aes);
|
||||||
|
free(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;
|
||||||
|
|
||||||
|
if (secret_length > INT_MAX) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hmac;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) {
|
||||||
|
if (hmac == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mbedtls_md_free(hmac);
|
||||||
|
free(hmac);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
_zip_crypto_pbkdf2(const zip_uint8_t *key, zip_uint64_t key_length, const zip_uint8_t *salt, zip_uint16_t salt_length, int iterations, zip_uint8_t *output, zip_uint64_t output_length) {
|
||||||
|
mbedtls_md_context_t sha1_ctx;
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
#if MBEDTLS_VERSION_NUMBER < 0x03030000
|
||||||
|
|
||||||
|
mbedtls_md_init(&sha1_ctx);
|
||||||
|
|
||||||
|
if (mbedtls_md_setup(&sha1_ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), 1) != 0) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
mbedtls_md_free(&sha1_ctx);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
ok = mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA1, (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;
|
||||||
|
|
||||||
|
#endif // !defined(MBEDTLS_DEPRECATED_REMOVED) || MBEDTLS_VERSION_NUMBER < 0x03030000
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mbedtls_entropy_context entropy;
|
||||||
|
mbedtls_ctr_drbg_context ctr_drbg;
|
||||||
|
} zip_random_context_t;
|
||||||
|
|
||||||
|
ZIP_EXTERN bool
|
||||||
|
zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) {
|
||||||
|
static zip_random_context_t *ctx = NULL;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mbedtls_ctr_drbg_random(&ctx->ctr_drbg, (unsigned char *)buffer, (size_t)length) == 0;
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
zip_crypto_mbedtls.h -- definitions for mbedtls wrapper
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HAD_ZIP_CRYPTO_MBEDTLS_H
|
||||||
|
#define HAD_ZIP_CRYPTO_MBEDTLS_H
|
||||||
|
|
||||||
|
#define HAVE_SECURE_RANDOM
|
||||||
|
|
||||||
|
#include <mbedtls/aes.h>
|
||||||
|
#include <mbedtls/md.h>
|
||||||
|
|
||||||
|
#define _zip_crypto_aes_t mbedtls_aes_context
|
||||||
|
#define _zip_crypto_hmac_t mbedtls_md_context_t
|
||||||
|
|
||||||
|
_zip_crypto_aes_t *_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error);
|
||||||
|
#define _zip_crypto_aes_encrypt_block(aes, in, out) (mbedtls_aes_crypt_ecb((aes), MBEDTLS_AES_ENCRYPT, (in), (out)) == 0)
|
||||||
|
void _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);
|
||||||
|
#define _zip_crypto_hmac(hmac, data, length) (mbedtls_md_hmac_update((hmac), (data), (length)) == 0)
|
||||||
|
#define _zip_crypto_hmac_output(hmac, data) (mbedtls_md_hmac_finish((hmac), (data)) == 0)
|
||||||
|
void _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac);
|
||||||
|
|
||||||
|
bool _zip_crypto_pbkdf2(const zip_uint8_t *key, zip_uint64_t key_length, const zip_uint8_t *salt, zip_uint16_t salt_length, int iterations, zip_uint8_t *output, zip_uint64_t output_length);
|
||||||
|
|
||||||
|
#endif /* HAD_ZIP_CRYPTO_MBEDTLS_H */
|
|
@ -0,0 +1,229 @@
|
||||||
|
/*
|
||||||
|
zip_crypto_openssl.c -- OpenSSL wrapper.
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <stdlib.h>
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
#include "zip_crypto.h"
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <openssl/rand.h>
|
||||||
|
|
||||||
|
#ifdef USE_OPENSSL_3_API
|
||||||
|
static _zip_crypto_hmac_t* hmac_new() {
|
||||||
|
_zip_crypto_hmac_t *hmac = (_zip_crypto_hmac_t*)malloc(sizeof(*hmac));
|
||||||
|
if (hmac != NULL) {
|
||||||
|
hmac->mac = NULL;
|
||||||
|
hmac->ctx = NULL;
|
||||||
|
}
|
||||||
|
return hmac;
|
||||||
|
}
|
||||||
|
static void hmac_free(_zip_crypto_hmac_t* hmac) {
|
||||||
|
if (hmac != NULL) {
|
||||||
|
if (hmac->ctx != NULL) {
|
||||||
|
EVP_MAC_CTX_free(hmac->ctx);
|
||||||
|
}
|
||||||
|
if (hmac->mac != NULL) {
|
||||||
|
EVP_MAC_free(hmac->mac);
|
||||||
|
}
|
||||||
|
free(hmac);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_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;
|
||||||
|
const EVP_CIPHER* cipher_type;
|
||||||
|
|
||||||
|
switch (key_size) {
|
||||||
|
case 128:
|
||||||
|
cipher_type = EVP_aes_128_ecb();
|
||||||
|
break;
|
||||||
|
case 192:
|
||||||
|
cipher_type = EVP_aes_192_ecb();
|
||||||
|
break;
|
||||||
|
case 256:
|
||||||
|
cipher_type = EVP_aes_256_ecb();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
zip_error_set(error, ZIP_ER_INTERNAL, 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_OPENSSL_1_0_API
|
||||||
|
if ((aes = (_zip_crypto_aes_t *)malloc(sizeof(*aes))) == NULL) {
|
||||||
|
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memset(aes, 0, sizeof(*aes));
|
||||||
|
#else
|
||||||
|
if ((aes = EVP_CIPHER_CTX_new()) == NULL) {
|
||||||
|
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (EVP_EncryptInit_ex(aes, cipher_type, NULL, key, NULL) != 1) {
|
||||||
|
#ifdef USE_OPENSSL_1_0_API
|
||||||
|
free(aes);
|
||||||
|
#else
|
||||||
|
EVP_CIPHER_CTX_free(aes);
|
||||||
|
#endif
|
||||||
|
zip_error_set(error, ZIP_ER_INTERNAL, 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return aes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_zip_crypto_aes_free(_zip_crypto_aes_t *aes) {
|
||||||
|
if (aes == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_OPENSSL_1_0_API
|
||||||
|
EVP_CIPHER_CTX_cleanup(aes);
|
||||||
|
_zip_crypto_clear(aes, sizeof(*aes));
|
||||||
|
free(aes);
|
||||||
|
#else
|
||||||
|
EVP_CIPHER_CTX_free(aes);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
_zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out) {
|
||||||
|
int len;
|
||||||
|
if (EVP_EncryptUpdate(aes, out, &len, in, ZIP_CRYPTO_AES_BLOCK_LENGTH) != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_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;
|
||||||
|
|
||||||
|
if (secret_length > INT_MAX) {
|
||||||
|
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_OPENSSL_3_API
|
||||||
|
if ((hmac = hmac_new()) == NULL
|
||||||
|
|| (hmac->mac = EVP_MAC_fetch(NULL, "HMAC", "provider=default")) == NULL
|
||||||
|
|| (hmac->ctx = EVP_MAC_CTX_new(hmac->mac)) == NULL) {
|
||||||
|
hmac_free(hmac);
|
||||||
|
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
OSSL_PARAM params[2];
|
||||||
|
params[0] = OSSL_PARAM_construct_utf8_string("digest", "SHA1", 0);
|
||||||
|
params[1] = OSSL_PARAM_construct_end();
|
||||||
|
|
||||||
|
if (!EVP_MAC_init(hmac->ctx, (const unsigned char *)secret, secret_length, params)) {
|
||||||
|
zip_error_set(error, ZIP_ER_INTERNAL, 0);
|
||||||
|
hmac_free(hmac);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
HMAC_CTX_init(hmac);
|
||||||
|
#else
|
||||||
|
if ((hmac = HMAC_CTX_new()) == 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);
|
||||||
|
#ifdef USE_OPENSSL_1_0_API
|
||||||
|
free(hmac);
|
||||||
|
#else
|
||||||
|
HMAC_CTX_free(hmac);
|
||||||
|
#endif
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return hmac;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) {
|
||||||
|
if (hmac == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(USE_OPENSSL_3_API)
|
||||||
|
hmac_free(hmac);
|
||||||
|
#elif defined(USE_OPENSSL_1_0_API)
|
||||||
|
HMAC_CTX_cleanup(hmac);
|
||||||
|
_zip_crypto_clear(hmac, sizeof(*hmac));
|
||||||
|
free(hmac);
|
||||||
|
#else
|
||||||
|
HMAC_CTX_free(hmac);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
_zip_crypto_hmac_output(_zip_crypto_hmac_t *hmac, zip_uint8_t *data) {
|
||||||
|
#ifdef USE_OPENSSL_3_API
|
||||||
|
size_t length;
|
||||||
|
return EVP_MAC_final(hmac->ctx, data, &length, ZIP_CRYPTO_SHA1_LENGTH) == 1 && length == ZIP_CRYPTO_SHA1_LENGTH;
|
||||||
|
#else
|
||||||
|
unsigned int length;
|
||||||
|
return HMAC_Final(hmac, data, &length) == 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN bool
|
||||||
|
zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) {
|
||||||
|
return RAND_bytes(buffer, length) == 1;
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
zip_crypto_openssl.h -- definitions for OpenSSL wrapper.
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HAD_ZIP_CRYPTO_OPENSSL_H
|
||||||
|
#define HAD_ZIP_CRYPTO_OPENSSL_H
|
||||||
|
|
||||||
|
#define HAVE_SECURE_RANDOM
|
||||||
|
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/hmac.h>
|
||||||
|
|
||||||
|
#if OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
|
||||||
|
#define USE_OPENSSL_1_0_API
|
||||||
|
#elif OPENSSL_VERSION_NUMBER < 0x3000000fL
|
||||||
|
#define USE_OPENSSL_1_1_API
|
||||||
|
#else
|
||||||
|
#define USE_OPENSSL_3_API
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define _zip_crypto_aes_t EVP_CIPHER_CTX
|
||||||
|
#ifdef USE_OPENSSL_3_API
|
||||||
|
struct _zip_crypto_hmac_t {
|
||||||
|
EVP_MAC *mac;
|
||||||
|
EVP_MAC_CTX *ctx;
|
||||||
|
};
|
||||||
|
typedef struct _zip_crypto_hmac_t _zip_crypto_hmac_t;
|
||||||
|
#define _zip_crypto_hmac(hmac, data, length) (EVP_MAC_update((hmac->ctx), (data), (length)) == 1)
|
||||||
|
#else
|
||||||
|
#define _zip_crypto_hmac_t HMAC_CTX
|
||||||
|
#define _zip_crypto_hmac(hmac, data, length) (HMAC_Update((hmac), (data), (length)) == 1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void _zip_crypto_aes_free(_zip_crypto_aes_t *aes);
|
||||||
|
bool _zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out);
|
||||||
|
_zip_crypto_aes_t *_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error);
|
||||||
|
|
||||||
|
void _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac);
|
||||||
|
_zip_crypto_hmac_t *_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error);
|
||||||
|
bool _zip_crypto_hmac_output(_zip_crypto_hmac_t *hmac, zip_uint8_t *data);
|
||||||
|
|
||||||
|
#define _zip_crypto_pbkdf2(key, key_length, salt, salt_length, iterations, output, output_length) (PKCS5_PBKDF2_HMAC_SHA1((const char *)(key), (key_length), (salt), (salt_length), (iterations), (output_length), (output)))
|
||||||
|
|
||||||
|
#endif /* HAD_ZIP_CRYPTO_OPENSSL_H */
|
|
@ -0,0 +1,495 @@
|
||||||
|
/*
|
||||||
|
zip_crypto_win.c -- Windows Crypto API wrapper.
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <stdlib.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
#include "zip_crypto.h"
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#define NOCRYPT
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <bcrypt.h>
|
||||||
|
|
||||||
|
#pragma comment(lib, "bcrypt.lib")
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This code is using the Cryptography API: Next Generation (CNG)
|
||||||
|
https://docs.microsoft.com/en-us/windows/desktop/seccng/cng-portal
|
||||||
|
|
||||||
|
This API is supported on
|
||||||
|
- Windows Vista or later (client OS)
|
||||||
|
- Windows Server 2008 (server OS)
|
||||||
|
- Windows Embedded Compact 2013 (don't know about Windows Embedded Compact 7)
|
||||||
|
|
||||||
|
The code was developed for Windows Embedded Compact 2013 (WEC2013),
|
||||||
|
but should be working for all of the above mentioned OSes.
|
||||||
|
|
||||||
|
There are 2 restrictions for WEC2013, Windows Vista and Windows Server 2008:
|
||||||
|
|
||||||
|
1.) The function "BCryptDeriveKeyPBKDF2" is not available
|
||||||
|
|
||||||
|
I found some code which is implementing this function using the deprecated Crypto API here:
|
||||||
|
https://www.idrix.fr/Root/content/view/37/54/
|
||||||
|
|
||||||
|
I took this code and converted it to the newer CNG API. The original code was more
|
||||||
|
flexible, but this is not needed here so i refactored it a bit and just kept what is needed.
|
||||||
|
|
||||||
|
The define "HAS_BCRYPTDERIVEKEYPBKDF2" controls whether "BCryptDeriveKeyPBKDF2"
|
||||||
|
of the CNG API is used or not. This define must not be set if you are compiling for WEC2013 or Windows Vista.
|
||||||
|
|
||||||
|
|
||||||
|
2.) "BCryptCreateHash" can't manage the memory needed for the hash object internally
|
||||||
|
|
||||||
|
On Windows 7 or later it is possible to pass NULL for the hash object buffer.
|
||||||
|
This is not supported on WEC2013, so we have to handle the memory allocation/deallocation ourselves.
|
||||||
|
There is no #ifdef to control that, because this is working for all supported OSes.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(WINCE) && !defined(__MINGW32__)
|
||||||
|
#define HAS_BCRYPTDERIVEKEYPBKDF2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAS_BCRYPTDERIVEKEYPBKDF2
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = BCRYPT_SUCCESS(BCryptDeriveKeyPBKDF2(hAlgorithm, (PUCHAR)key, (ULONG)key_length, (PUCHAR)salt, salt_length, iterations, output, output_length, 0));
|
||||||
|
|
||||||
|
BCryptCloseAlgorithmProvider(hAlgorithm, 0);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#define DIGEST_SIZE 20
|
||||||
|
#define BLOCK_SIZE 64
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
BCRYPT_ALG_HANDLE hAlgorithm;
|
||||||
|
BCRYPT_HASH_HANDLE hInnerHash;
|
||||||
|
BCRYPT_HASH_HANDLE hOuterHash;
|
||||||
|
ULONG cbHashObject;
|
||||||
|
PUCHAR pbInnerHash;
|
||||||
|
PUCHAR pbOuterHash;
|
||||||
|
} PRF_CTX;
|
||||||
|
|
||||||
|
static void
|
||||||
|
hmacFree(PRF_CTX *pContext) {
|
||||||
|
if (pContext->hOuterHash)
|
||||||
|
BCryptDestroyHash(pContext->hOuterHash);
|
||||||
|
if (pContext->hInnerHash)
|
||||||
|
BCryptDestroyHash(pContext->hInnerHash);
|
||||||
|
free(pContext->pbOuterHash);
|
||||||
|
free(pContext->pbInnerHash);
|
||||||
|
if (pContext->hAlgorithm)
|
||||||
|
BCryptCloseAlgorithmProvider(pContext->hAlgorithm, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL
|
||||||
|
hmacPrecomputeDigest(BCRYPT_HASH_HANDLE hHash, PUCHAR pbPassword, DWORD cbPassword, BYTE mask) {
|
||||||
|
BYTE buffer[BLOCK_SIZE];
|
||||||
|
DWORD i;
|
||||||
|
|
||||||
|
if (cbPassword > BLOCK_SIZE) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(buffer, mask, sizeof(buffer));
|
||||||
|
|
||||||
|
for (i = 0; i < cbPassword; ++i) {
|
||||||
|
buffer[i] = (char)(pbPassword[i] ^ mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
return BCRYPT_SUCCESS(BCryptHashData(hHash, buffer, sizeof(buffer), 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL
|
||||||
|
hmacInit(PRF_CTX *pContext, PUCHAR pbPassword, DWORD cbPassword) {
|
||||||
|
BOOL bStatus = FALSE;
|
||||||
|
ULONG cbResult;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cbPassword > BLOCK_SIZE) {
|
||||||
|
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));
|
||||||
|
|
||||||
|
if (hHash)
|
||||||
|
BCryptDestroyHash(hHash);
|
||||||
|
free(pbHashObject);
|
||||||
|
|
||||||
|
if (!bStatus) {
|
||||||
|
goto hmacInit_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
pbPassword = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
bStatus = hmacPrecomputeDigest(pContext->hInnerHash, pbPassword, cbPassword, 0x36) && hmacPrecomputeDigest(pContext->hOuterHash, pbPassword, cbPassword, 0x5C);
|
||||||
|
|
||||||
|
hmacInit_end:
|
||||||
|
|
||||||
|
if (bStatus == FALSE)
|
||||||
|
hmacFree(pContext);
|
||||||
|
|
||||||
|
return bStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL
|
||||||
|
hmacCalculateInternal(BCRYPT_HASH_HANDLE hHashTemplate, PUCHAR pbData, DWORD cbData, PUCHAR pbOutput, DWORD cbOutput, DWORD cbHashObject) {
|
||||||
|
BOOL success = FALSE;
|
||||||
|
BCRYPT_HASH_HANDLE hHash = NULL;
|
||||||
|
PUCHAR pbHashObject = malloc(cbHashObject);
|
||||||
|
|
||||||
|
if (pbHashObject == NULL) {
|
||||||
|
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));
|
||||||
|
|
||||||
|
BCryptDestroyHash(hHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(pbHashObject);
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL
|
||||||
|
hmacCalculate(PRF_CTX *pContext, PUCHAR pbData, DWORD cbData, PUCHAR pbDigest) {
|
||||||
|
DWORD cbResult;
|
||||||
|
DWORD cbHashObject;
|
||||||
|
|
||||||
|
return BCRYPT_SUCCESS(BCryptGetProperty(pContext->hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&cbHashObject, sizeof(cbHashObject), &cbResult, 0)) && hmacCalculateInternal(pContext->hInnerHash, pbData, cbData, pbDigest, DIGEST_SIZE, cbHashObject) && hmacCalculateInternal(pContext->hOuterHash, pbDigest, DIGEST_SIZE, pbDigest, DIGEST_SIZE, cbHashObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
myxor(LPBYTE ptr1, LPBYTE ptr2, DWORD dwLen) {
|
||||||
|
while (dwLen--)
|
||||||
|
*ptr1++ ^= *ptr2++;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
pbkdf2(PUCHAR pbPassword, ULONG cbPassword, PUCHAR pbSalt, ULONG cbSalt, DWORD cIterations, PUCHAR pbDerivedKey, ULONG cbDerivedKey) {
|
||||||
|
BOOL bStatus = FALSE;
|
||||||
|
DWORD l, r, dwULen, i, j;
|
||||||
|
BYTE Ti[DIGEST_SIZE];
|
||||||
|
BYTE V[DIGEST_SIZE];
|
||||||
|
LPBYTE U = malloc(max((cbSalt + 4), DIGEST_SIZE));
|
||||||
|
PRF_CTX prfCtx = {0};
|
||||||
|
|
||||||
|
if (U == NULL) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pbPassword == NULL || cbPassword == 0 || pbSalt == NULL || cbSalt == 0 || cIterations == 0 || pbDerivedKey == NULL || cbDerivedKey == 0) {
|
||||||
|
free(U);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hmacInit(&prfCtx, pbPassword, cbPassword)) {
|
||||||
|
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 */
|
||||||
|
(void)memcpy_s(U, cbSalt, 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 {
|
||||||
|
(void)memcpy_s(U, DIGEST_SIZE, V, DIGEST_SIZE);
|
||||||
|
dwULen = DIGEST_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hmacCalculate(&prfCtx, U, dwULen, V)) {
|
||||||
|
goto PBKDF2_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
myxor(Ti, V, DIGEST_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i != l) {
|
||||||
|
(void)memcpy_s(&pbDerivedKey[(i - 1) * DIGEST_SIZE], cbDerivedKey - (i - 1) * DIGEST_SIZE, Ti, DIGEST_SIZE);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Take only the first r bytes */
|
||||||
|
(void)memcpy_s(&pbDerivedKey[(i - 1) * DIGEST_SIZE], cbDerivedKey - (i - 1) * DIGEST_SIZE, Ti, r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bStatus = TRUE;
|
||||||
|
|
||||||
|
PBKDF2_end:
|
||||||
|
|
||||||
|
hmacFree(&prfCtx);
|
||||||
|
free(U);
|
||||||
|
return bStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
return (key_length <= ZIP_UINT32_MAX) && pbkdf2((PUCHAR)key, (ULONG)key_length, (PUCHAR)salt, salt_length, iterations, output, output_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
struct _zip_crypto_aes_s {
|
||||||
|
BCRYPT_ALG_HANDLE hAlgorithm;
|
||||||
|
BCRYPT_KEY_HANDLE hKey;
|
||||||
|
ULONG cbKeyObject;
|
||||||
|
PUCHAR pbKeyObject;
|
||||||
|
};
|
||||||
|
|
||||||
|
_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 = (_zip_crypto_aes_t *)calloc(1, sizeof(*aes));
|
||||||
|
|
||||||
|
ULONG cbResult;
|
||||||
|
ULONG key_length = key_size / 8;
|
||||||
|
|
||||||
|
if (aes == 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!BCRYPT_SUCCESS(BCryptGetProperty(aes->hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&aes->cbKeyObject, sizeof(aes->cbKeyObject), &cbResult, 0))) {
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!BCRYPT_SUCCESS(BCryptGenerateSymmetricKey(aes->hAlgorithm, &aes->hKey, aes->pbKeyObject, aes->cbKeyObject, (PUCHAR)key, key_length, 0))) {
|
||||||
|
_zip_crypto_aes_free(aes);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return aes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_zip_crypto_aes_free(_zip_crypto_aes_t *aes) {
|
||||||
|
if (aes == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aes->hKey != NULL) {
|
||||||
|
BCryptDestroyKey(aes->hKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aes->pbKeyObject != NULL) {
|
||||||
|
free(aes->pbKeyObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aes->hAlgorithm != NULL) {
|
||||||
|
BCryptCloseAlgorithmProvider(aes->hAlgorithm, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(aes);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
_zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out) {
|
||||||
|
ULONG cbResult;
|
||||||
|
NTSTATUS status = BCryptEncrypt(aes->hKey, (PUCHAR)in, ZIP_CRYPTO_AES_BLOCK_LENGTH, NULL, NULL, 0, (PUCHAR)out, ZIP_CRYPTO_AES_BLOCK_LENGTH, &cbResult, 0);
|
||||||
|
return BCRYPT_SUCCESS(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct _zip_crypto_hmac_s {
|
||||||
|
BCRYPT_ALG_HANDLE hAlgorithm;
|
||||||
|
BCRYPT_HASH_HANDLE hHash;
|
||||||
|
DWORD cbHashObject;
|
||||||
|
PUCHAR pbHashObject;
|
||||||
|
DWORD cbHash;
|
||||||
|
PUCHAR pbHash;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* https://code.msdn.microsoft.com/windowsdesktop/Hmac-Computation-Sample-11fe8ec1/sourcecode?fileId=42820&pathId=283874677 */
|
||||||
|
|
||||||
|
_zip_crypto_hmac_t *
|
||||||
|
_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error) {
|
||||||
|
NTSTATUS status;
|
||||||
|
ULONG cbResult;
|
||||||
|
_zip_crypto_hmac_t *hmac;
|
||||||
|
|
||||||
|
if (secret_length > INT_MAX) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = BCryptOpenAlgorithmProvider(&hmac->hAlgorithm, BCRYPT_SHA1_ALGORITHM, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG);
|
||||||
|
if (!BCRYPT_SUCCESS(status)) {
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
hmac->pbHashObject = malloc(hmac->cbHashObject);
|
||||||
|
if (hmac->pbHashObject == 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
hmac->pbHash = malloc(hmac->cbHash);
|
||||||
|
if (hmac->pbHash == 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hmac;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) {
|
||||||
|
if (hmac == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hmac->hHash != NULL) {
|
||||||
|
BCryptDestroyHash(hmac->hHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hmac->pbHash != NULL) {
|
||||||
|
free(hmac->pbHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hmac->pbHashObject != NULL) {
|
||||||
|
free(hmac->pbHashObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hmac->hAlgorithm) {
|
||||||
|
BCryptCloseAlgorithmProvider(hmac->hAlgorithm, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(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 BCRYPT_SUCCESS(BCryptHashData(hmac->hHash, data, (ULONG)length, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
_zip_crypto_hmac_output(_zip_crypto_hmac_t *hmac, zip_uint8_t *data) {
|
||||||
|
if (hmac == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BCRYPT_SUCCESS(BCryptFinishHash(hmac->hHash, data, hmac->cbHash, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
ZIP_EXTERN bool
|
||||||
|
zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) {
|
||||||
|
return BCRYPT_SUCCESS(BCryptGenRandom(NULL, buffer, length, BCRYPT_USE_SYSTEM_PREFERRED_RNG));
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
zip_crypto_win.h -- Windows Crypto API wrapper.
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HAD_ZIP_CRYPTO_WIN_H
|
||||||
|
#define HAD_ZIP_CRYPTO_WIN_H
|
||||||
|
|
||||||
|
#define HAVE_SECURE_RANDOM
|
||||||
|
|
||||||
|
typedef struct _zip_crypto_aes_s _zip_crypto_aes_t;
|
||||||
|
typedef struct _zip_crypto_hmac_s _zip_crypto_hmac_t;
|
||||||
|
|
||||||
|
void _zip_crypto_aes_free(_zip_crypto_aes_t *aes);
|
||||||
|
_zip_crypto_aes_t *_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error);
|
||||||
|
bool _zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
_zip_crypto_hmac_t *_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error);
|
||||||
|
void _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);
|
||||||
|
bool _zip_crypto_hmac_output(_zip_crypto_hmac_t *hmac, zip_uint8_t *data);
|
||||||
|
|
||||||
|
#endif /* HAD_ZIP_CRYPTO_WIN_H */
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
zip_delete.c -- delete file from zip archive
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ZIP_IS_RDONLY(za)) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((name = _zip_get_name(za, idx, 0, &za->error)) == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_zip_hash_delete(za->names, (const zip_uint8_t *)name, &za->error)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allow duplicate file names, because the file will
|
||||||
|
* be removed directly afterwards */
|
||||||
|
if (_zip_unchange(za, idx, 1) != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
za->entry[idx].deleted = 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
zip_dir_add.c -- add directory
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */
|
||||||
|
|
||||||
|
ZIP_EXTERN zip_int64_t
|
||||||
|
zip_dir_add(zip_t *za, const char *name, zip_flags_t flags) {
|
||||||
|
size_t len;
|
||||||
|
zip_int64_t idx;
|
||||||
|
char *s;
|
||||||
|
zip_source_t *source;
|
||||||
|
|
||||||
|
if (ZIP_IS_RDONLY(za)) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = NULL;
|
||||||
|
len = strlen(name);
|
||||||
|
|
||||||
|
if (name[len - 1] != '/') {
|
||||||
|
if (len > SIZE_MAX - 2 || (s = (char *)malloc(len + 2)) == NULL) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
(void)strncpy_s(s, len + 2, name, len);
|
||||||
|
s[len] = '/';
|
||||||
|
s[len + 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((source = zip_source_buffer(za, NULL, 0, 0)) == NULL) {
|
||||||
|
free(s);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
idx = _zip_file_replace(za, ZIP_UINT64_MAX, s ? s : name, source, flags);
|
||||||
|
|
||||||
|
free(s);
|
||||||
|
|
||||||
|
if (idx < 0)
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return idx;
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
zip_discard.c -- discard and free struct zip
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <stdlib.h>
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* zip_discard:
|
||||||
|
frees the space allocated to a zipfile struct, and closes the
|
||||||
|
corresponding file. */
|
||||||
|
|
||||||
|
void
|
||||||
|
zip_discard(zip_t *za) {
|
||||||
|
zip_uint64_t i;
|
||||||
|
|
||||||
|
if (za == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (za->src) {
|
||||||
|
zip_source_close(za->src);
|
||||||
|
zip_source_free(za->src);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(za->default_password);
|
||||||
|
_zip_string_free(za->comment_orig);
|
||||||
|
_zip_string_free(za->comment_changes);
|
||||||
|
|
||||||
|
_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->nopen_source; i++) {
|
||||||
|
_zip_source_invalidate(za->open_source[i]);
|
||||||
|
}
|
||||||
|
free(za->open_source);
|
||||||
|
|
||||||
|
_zip_progress_free(za->progress);
|
||||||
|
|
||||||
|
zip_error_fini(&za->error);
|
||||||
|
|
||||||
|
free(za);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
zip_entry.c -- struct zip_entry helper functions
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
void
|
||||||
|
_zip_entry_finalize(zip_entry_t *e) {
|
||||||
|
_zip_unchange_data(e);
|
||||||
|
_zip_dirent_free(e->orig);
|
||||||
|
_zip_dirent_free(e->changes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_zip_entry_init(zip_entry_t *e) {
|
||||||
|
e->orig = NULL;
|
||||||
|
e->changes = NULL;
|
||||||
|
e->source = NULL;
|
||||||
|
e->deleted = 0;
|
||||||
|
}
|
|
@ -0,0 +1,156 @@
|
||||||
|
/*
|
||||||
|
zip_error.c -- zip_error_t helper functions
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <stdlib.h>
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
zip_error_code_system(const zip_error_t *error) {
|
||||||
|
return error->sys_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
zip_error_code_zip(const zip_error_t *error) {
|
||||||
|
return error->zip_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN void
|
||||||
|
zip_error_fini(zip_error_t *err) {
|
||||||
|
free(err->str);
|
||||||
|
err->str = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN void
|
||||||
|
zip_error_init(zip_error_t *err) {
|
||||||
|
err->zip_err = ZIP_ER_OK;
|
||||||
|
err->sys_err = 0;
|
||||||
|
err->str = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZIP_EXTERN void
|
||||||
|
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:
|
||||||
|
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_err_str_count)
|
||||||
|
return ZIP_ET_NONE;
|
||||||
|
|
||||||
|
return _zip_err_str[error->zip_err].type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_zip_error_clear(zip_error_t *err) {
|
||||||
|
if (err == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
err->zip_err = ZIP_ER_OK;
|
||||||
|
err->sys_err = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_zip_error_copy(zip_error_t *dst, const zip_error_t *src) {
|
||||||
|
if (dst == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst->zip_err = src->zip_err;
|
||||||
|
dst->sys_err = src->sys_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_zip_error_get(const zip_error_t *err, int *zep, int *sep) {
|
||||||
|
if (zep)
|
||||||
|
*zep = err->zip_err;
|
||||||
|
if (sep) {
|
||||||
|
if (zip_error_system_type(err) != ZIP_ET_NONE)
|
||||||
|
*sep = err->sys_err;
|
||||||
|
else
|
||||||
|
*sep = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
zip_error_set(zip_error_t *err, int ze, int se) {
|
||||||
|
if (err) {
|
||||||
|
err->zip_err = ze;
|
||||||
|
err->sys_err = se;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
zip_error_set_from_source(zip_error_t *err, zip_source_t *src) {
|
||||||
|
if (src == NULL) {
|
||||||
|
zip_error_set(err, ZIP_ER_INVAL, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_zip_error_copy(err, zip_source_error(src));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
zip_int64_t
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
e[0] = zip_error_code_zip(error);
|
||||||
|
e[1] = zip_error_code_system(error);
|
||||||
|
return sizeof(int) * 2;
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
zip_error_clear.c -- clear zip error
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN void
|
||||||
|
zip_error_clear(zip_t *za) {
|
||||||
|
if (za == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_zip_error_clear(&za->error);
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
zip_error_get.c -- get zip error
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define _ZIP_COMPILING_DEPRECATED
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN void
|
||||||
|
zip_error_get(zip_t *za, int *zep, int *sep) {
|
||||||
|
_zip_error_get(&za->error, zep, sep);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN zip_error_t *
|
||||||
|
zip_get_error(zip_t *za) {
|
||||||
|
return &za->error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN zip_error_t *
|
||||||
|
zip_file_get_error(zip_file_t *f) {
|
||||||
|
return &f->error;
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
zip_error_get_sys_type.c -- return type of system error code
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _ZIP_COMPILING_DEPRECATED
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
zip_error_get_sys_type(int ze) {
|
||||||
|
if (ze < 0 || ze >= _zip_err_str_count) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _zip_err_str[ze].type;
|
||||||
|
}
|
|
@ -0,0 +1,128 @@
|
||||||
|
/*
|
||||||
|
zip_error_sterror.c -- get string representation of struct zip_error
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <zlib.h>
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
ZIP_EXTERN const char *
|
||||||
|
zip_error_strerror(zip_error_t *err) {
|
||||||
|
const char *zip_error_string, *system_error_string;
|
||||||
|
char *s;
|
||||||
|
char *system_error_buffer = NULL;
|
||||||
|
|
||||||
|
zip_error_fini(err);
|
||||||
|
|
||||||
|
if (err->zip_err < 0 || err->zip_err >= _zip_err_str_count) {
|
||||||
|
system_error_buffer = (char *)malloc(128);
|
||||||
|
snprintf_s(system_error_buffer, 128, "Unknown error %d", err->zip_err);
|
||||||
|
system_error_buffer[128 - 1] = '\0'; /* make sure string is NUL-terminated */
|
||||||
|
zip_error_string = NULL;
|
||||||
|
system_error_string = system_error_buffer;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
zip_error_string = _zip_err_str[err->zip_err].description;
|
||||||
|
|
||||||
|
switch (_zip_err_str[err->zip_err].type) {
|
||||||
|
case ZIP_ET_SYS: {
|
||||||
|
size_t len = strerrorlen_s(err->sys_err) + 1;
|
||||||
|
system_error_buffer = malloc(len);
|
||||||
|
strerror_s(system_error_buffer, len, err->sys_err);
|
||||||
|
system_error_string = system_error_buffer;
|
||||||
|
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) {
|
||||||
|
system_error_buffer = (char *)malloc(128);
|
||||||
|
snprintf_s(system_error_buffer, 128, "invalid detail error %u", error);
|
||||||
|
system_error_buffer[128 - 1] = '\0'; /* make sure string is NUL-terminated */
|
||||||
|
system_error_string = system_error_buffer;
|
||||||
|
}
|
||||||
|
else if (_zip_err_details[error].type == ZIP_DETAIL_ET_ENTRY && index < MAX_DETAIL_INDEX) {
|
||||||
|
system_error_buffer = (char *)malloc(128);
|
||||||
|
snprintf_s(system_error_buffer, 128, "entry %d: %s", index, _zip_err_details[error].description);
|
||||||
|
system_error_buffer[128 - 1] = '\0'; /* make sure string is NUL-terminated */
|
||||||
|
system_error_string = system_error_buffer;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
system_error_string = _zip_err_details[error].description;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
system_error_string = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (system_error_string == NULL) {
|
||||||
|
free(system_error_buffer);
|
||||||
|
return zip_error_string;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
size_t length = strlen(system_error_string);
|
||||||
|
if (zip_error_string) {
|
||||||
|
size_t length_error = strlen(zip_error_string);
|
||||||
|
if (length + length_error + 2 < length) {
|
||||||
|
free(system_error_buffer);
|
||||||
|
return _zip_err_str[ZIP_ER_MEMORY].description;
|
||||||
|
}
|
||||||
|
length += length_error + 2;
|
||||||
|
}
|
||||||
|
if (length == SIZE_MAX || (s = (char *)malloc(length + 1)) == NULL) {
|
||||||
|
free(system_error_buffer);
|
||||||
|
return _zip_err_str[ZIP_ER_MEMORY].description;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf_s(s, length + 1, "%s%s%s", (zip_error_string ? zip_error_string : ""), (zip_error_string ? ": " : ""), system_error_string);
|
||||||
|
err->str = s;
|
||||||
|
|
||||||
|
free(system_error_buffer);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
zip_error_to_str.c -- get string representation of zip error code
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define _ZIP_COMPILING_DEPRECATED
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
zip_error_to_str(char *buf, zip_uint64_t len, int ze, int se) {
|
||||||
|
zip_error_t error;
|
||||||
|
const char *error_string;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
zip_error_init(&error);
|
||||||
|
zip_error_set(&error, ze, se);
|
||||||
|
|
||||||
|
error_string = zip_error_strerror(&error);
|
||||||
|
|
||||||
|
ret = snprintf_s(buf, ZIP_MIN(len, SIZE_MAX), error_string, strlen(error_string));
|
||||||
|
|
||||||
|
zip_error_fini(&error);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -0,0 +1,427 @@
|
||||||
|
/*
|
||||||
|
zip_extra_field.c -- manipulate extra fields
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
|
||||||
|
zip_extra_field_t *
|
||||||
|
_zip_ef_clone(const zip_extra_field_t *ef, zip_error_t *error) {
|
||||||
|
zip_extra_field_t *head, *prev, *def;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
zip_extra_field_t *
|
||||||
|
_zip_ef_delete_by_id(zip_extra_field_t *ef, zip_uint16_t id, zip_uint16_t id_idx, zip_flags_t flags) {
|
||||||
|
zip_extra_field_t *head, *prev;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const zip_uint8_t *
|
||||||
|
_zip_ef_get_by_id(const zip_extra_field_t *ef, zip_uint16_t *lenp, zip_uint16_t id, zip_uint16_t id_idx, zip_flags_t flags, zip_error_t *error) {
|
||||||
|
static const zip_uint8_t empty[1] = {'\0'};
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
zip_error_set(error, ZIP_ER_NOENT, 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
zip_extra_field_t *
|
||||||
|
_zip_ef_merge(zip_extra_field_t *to, zip_extra_field_t *from) {
|
||||||
|
zip_extra_field_t *ef2, *tt, *tail;
|
||||||
|
int duplicate;
|
||||||
|
|
||||||
|
if (to == NULL)
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return to;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
zip_extra_field_t *
|
||||||
|
_zip_ef_new(zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, zip_flags_t flags) {
|
||||||
|
zip_extra_field_t *ef;
|
||||||
|
|
||||||
|
if ((ef = (zip_extra_field_t *)malloc(sizeof(*ef))) == 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ef->data = NULL;
|
||||||
|
|
||||||
|
return ef;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
_zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_extra_field_t **ef_head_p, zip_error_t *error) {
|
||||||
|
zip_buffer_t *buffer;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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, 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 */
|
||||||
|
/* buffer is at most 64k long, so this can't overflow. */
|
||||||
|
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", (size_t)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;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_zip_ef_free(ef_head);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
zip_extra_field_t *
|
||||||
|
_zip_ef_remove_internal(zip_extra_field_t *ef) {
|
||||||
|
zip_extra_field_t *ef_head;
|
||||||
|
zip_extra_field_t *prev, *next;
|
||||||
|
|
||||||
|
ef_head = 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ef_head;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
zip_uint16_t
|
||||||
|
_zip_ef_size(const zip_extra_field_t *ef, zip_flags_t flags) {
|
||||||
|
zip_uint16_t size;
|
||||||
|
|
||||||
|
size = 0;
|
||||||
|
for (; ef; ef = ef->next) {
|
||||||
|
if (ef->flags & flags & ZIP_EF_BOTH)
|
||||||
|
size = (zip_uint16_t)(size + 4 + ef->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
_zip_ef_write(zip_t *za, const zip_extra_field_t *ef, zip_flags_t flags) {
|
||||||
|
zip_uint8_t b[4];
|
||||||
|
zip_buffer_t *buffer = _zip_buffer_new(b, sizeof(b));
|
||||||
|
|
||||||
|
if (buffer == NULL) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_zip_buffer_free(buffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
_zip_read_local_ef(zip_t *za, zip_uint64_t idx) {
|
||||||
|
zip_entry_t *e;
|
||||||
|
unsigned char b[4];
|
||||||
|
zip_buffer_t *buffer;
|
||||||
|
zip_uint16_t fname_len, ef_len;
|
||||||
|
|
||||||
|
if (idx >= za->nentry) {
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (e->orig->offset + 26 > ZIP_INT64_MAX) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((buffer = _zip_buffer_new_from_source(za->src, sizeof(b), b, &za->error)) == NULL) {
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (ef_len > 0) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
ef_raw = _zip_read_data(NULL, za->src, ef_len, 0, &za->error);
|
||||||
|
|
||||||
|
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 (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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,367 @@
|
||||||
|
/*
|
||||||
|
zip_extra_field_api.c -- public extra fields API functions
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
zip_file_extra_field_delete(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_flags_t flags) {
|
||||||
|
zip_dirent_t *de;
|
||||||
|
|
||||||
|
if ((flags & ZIP_EF_BOTH) == 0) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (ZIP_IS_RDONLY(za)) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (ZIP_WANT_TORRENTZIP(za)) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_zip_file_extra_field_prepare_for_change(za, idx) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
de = za->entry[idx].changes;
|
||||||
|
|
||||||
|
de->extra_fields = _zip_ef_delete_by_id(de->extra_fields, ZIP_EXTRA_FIELD_ALL, ef_idx, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
zip_file_extra_field_delete_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, zip_flags_t flags) {
|
||||||
|
zip_dirent_t *de;
|
||||||
|
|
||||||
|
if ((flags & ZIP_EF_BOTH) == 0) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (ZIP_IS_RDONLY(za)) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (ZIP_WANT_TORRENTZIP(za)) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_zip_file_extra_field_prepare_for_change(za, idx) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
de = za->entry[idx].changes;
|
||||||
|
|
||||||
|
de->extra_fields = _zip_ef_delete_by_id(de->extra_fields, ef_id, ef_idx, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN const zip_uint8_t *
|
||||||
|
zip_file_extra_field_get(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_uint16_t *idp, zip_uint16_t *lenp, zip_flags_t flags) {
|
||||||
|
static const zip_uint8_t empty[1] = {'\0'};
|
||||||
|
|
||||||
|
zip_dirent_t *de;
|
||||||
|
zip_extra_field_t *ef;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ((flags & ZIP_EF_BOTH) == 0) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (flags & ZIP_FL_LOCAL)
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
zip_error_set(&za->error, ZIP_ER_NOENT, 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN const zip_uint8_t *
|
||||||
|
zip_file_extra_field_get_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, zip_uint16_t *lenp, zip_flags_t flags) {
|
||||||
|
zip_dirent_t *de;
|
||||||
|
|
||||||
|
if ((flags & ZIP_EF_BOTH) == 0) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (flags & ZIP_FL_LOCAL)
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN zip_int16_t
|
||||||
|
zip_file_extra_fields_count(zip_t *za, zip_uint64_t idx, zip_flags_t flags) {
|
||||||
|
zip_dirent_t *de;
|
||||||
|
zip_extra_field_t *ef;
|
||||||
|
zip_uint16_t n;
|
||||||
|
|
||||||
|
if ((flags & ZIP_EF_BOTH) == 0) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (flags & ZIP_FL_LOCAL)
|
||||||
|
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++;
|
||||||
|
|
||||||
|
return (zip_int16_t)n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN zip_int16_t
|
||||||
|
zip_file_extra_fields_count_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_flags_t flags) {
|
||||||
|
zip_dirent_t *de;
|
||||||
|
zip_extra_field_t *ef;
|
||||||
|
zip_uint16_t n;
|
||||||
|
|
||||||
|
if ((flags & ZIP_EF_BOTH) == 0) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (flags & ZIP_FL_LOCAL)
|
||||||
|
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++;
|
||||||
|
|
||||||
|
return (zip_int16_t)n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
zip_file_extra_field_set(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags) {
|
||||||
|
zip_dirent_t *de;
|
||||||
|
zip_uint16_t ls, cs;
|
||||||
|
zip_extra_field_t *ef, *ef_prev, *ef_new;
|
||||||
|
int i, found, new_len;
|
||||||
|
|
||||||
|
if ((flags & ZIP_EF_BOTH) == 0) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (ZIP_IS_RDONLY(za)) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (ZIP_WANT_TORRENTZIP(za)) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ZIP_EF_IS_INTERNAL(ef_id)) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_zip_file_extra_field_prepare_for_change(za, idx) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
de = za->entry[idx].changes;
|
||||||
|
|
||||||
|
ef = de->extra_fields;
|
||||||
|
ef_prev = NULL;
|
||||||
|
i = 0;
|
||||||
|
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 (i < ef_idx && ef_idx != ZIP_EXTRA_FIELD_NEW) {
|
||||||
|
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);
|
||||||
|
else
|
||||||
|
ls = 0;
|
||||||
|
if (flags & ZIP_EF_CENTRAL)
|
||||||
|
cs = _zip_ef_size(de->extra_fields, ZIP_EF_CENTRAL);
|
||||||
|
else
|
||||||
|
cs = 0;
|
||||||
|
|
||||||
|
new_len = ls > cs ? ls : cs;
|
||||||
|
if (found)
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ef_new = _zip_ef_new(ef_id, len, data, flags)) == NULL) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ef_prev) {
|
||||||
|
ef_new->next = ef_prev->next;
|
||||||
|
ef_prev->next = ef_new;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
de->extra_fields = ef_new;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
e = za->entry + idx;
|
||||||
|
|
||||||
|
if (e->changes && (e->changes->changed & ZIP_DIRENT_EXTRA_FIELD))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (e->orig) {
|
||||||
|
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->orig && e->orig->extra_fields) {
|
||||||
|
if ((e->changes->extra_fields = _zip_ef_clone(e->orig->extra_fields, &za->error)) == NULL)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
e->changes->changed |= ZIP_DIRENT_EXTRA_FIELD;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
zip_fclose.c -- close file in zip archive
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <stdlib.h>
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
zip_fclose(zip_file_t *zf) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (zf->src)
|
||||||
|
zip_source_free(zf->src);
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
if (zf->error.zip_err)
|
||||||
|
ret = zf->error.zip_err;
|
||||||
|
|
||||||
|
zip_error_fini(&zf->error);
|
||||||
|
free(zf);
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
zip_fdopen.c -- open read-only archive from file descriptor
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN zip_t *
|
||||||
|
zip_fdopen(int fd_orig, int _flags, int *zep) {
|
||||||
|
int fd;
|
||||||
|
FILE *fp;
|
||||||
|
zip_t *za;
|
||||||
|
zip_source_t *src;
|
||||||
|
struct zip_error error;
|
||||||
|
|
||||||
|
if (_flags < 0 || (_flags & ~(ZIP_CHECKCONS | ZIP_RDONLY))) {
|
||||||
|
_zip_set_open_error(zep, NULL, ZIP_ER_INVAL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef ENABLE_FDOPEN
|
||||||
|
_zip_set_open_error(zep, NULL, ZIP_ER_OPNOTSUPP);
|
||||||
|
return NULL;
|
||||||
|
#else
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fp = fdopen(fd, "rb")) == 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_error_fini(&error);
|
||||||
|
close(fd_orig);
|
||||||
|
return za;
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
zip_file_add.c -- add file via callback function
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _zip_file_replace(za, ZIP_UINT64_MAX, name, source, flags);
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
zip_file_error_clear.c -- clear zip file error
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN void
|
||||||
|
zip_file_error_clear(zip_file_t *zf) {
|
||||||
|
if (zf == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_zip_error_clear(&zf->error);
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
zip_file_error_get.c -- get zip file error
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _ZIP_COMPILING_DEPRECATED
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN void
|
||||||
|
zip_file_error_get(zip_file_t *zf, int *zep, int *sep) {
|
||||||
|
_zip_error_get(&zf->error, zep, sep);
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
zip_file_get_comment.c -- get file comment
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
/* lenp is 32 bit because converted comment can be longer than ZIP_UINT16_MAX */
|
||||||
|
|
||||||
|
ZIP_EXTERN const char *
|
||||||
|
zip_file_get_comment(zip_t *za, zip_uint64_t idx, zip_uint32_t *lenp, zip_flags_t flags) {
|
||||||
|
zip_dirent_t *de;
|
||||||
|
zip_uint32_t len;
|
||||||
|
const zip_uint8_t *str;
|
||||||
|
|
||||||
|
if ((de = _zip_get_dirent(za, idx, flags, NULL)) == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if ((str = _zip_string_get(de->comment, &len, flags, &za->error)) == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (lenp)
|
||||||
|
*lenp = len;
|
||||||
|
|
||||||
|
return (const char *)str;
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
zip_file_get_external_attributes.c -- get opsys/external attributes
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
int
|
||||||
|
zip_file_get_external_attributes(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_uint8_t *opsys, zip_uint32_t *attributes) {
|
||||||
|
zip_dirent_t *de;
|
||||||
|
|
||||||
|
if ((de = _zip_get_dirent(za, idx, flags, NULL)) == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (opsys)
|
||||||
|
*opsys = (zip_uint8_t)((de->version_madeby >> 8) & 0xff);
|
||||||
|
|
||||||
|
if (attributes)
|
||||||
|
*attributes = de->ext_attrib;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
zip_file_get_offset.c -- get offset of file data in archive.
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* _zip_file_get_offset(za, ze):
|
||||||
|
Returns the offset of the file data for entry ze.
|
||||||
|
|
||||||
|
On error, fills in za->error and returns 0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
zip_uint64_t
|
||||||
|
_zip_file_get_offset(const zip_t *za, zip_uint64_t idx, zip_error_t *error) {
|
||||||
|
zip_uint64_t offset;
|
||||||
|
zip_int32_t size;
|
||||||
|
|
||||||
|
if (za->entry[idx].orig == NULL) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: cache? */
|
||||||
|
if ((size = _zip_dirent_size(za->src, ZIP_EF_LOCAL, error)) < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (offset + (zip_uint32_t)size > ZIP_INT64_MAX) {
|
||||||
|
zip_error_set(error, ZIP_ER_SEEK, EFBIG);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return offset + (zip_uint32_t)size;
|
||||||
|
}
|
||||||
|
|
||||||
|
zip_uint64_t
|
||||||
|
_zip_file_get_end(const zip_t *za, zip_uint64_t index, zip_error_t *error) {
|
||||||
|
zip_uint64_t offset;
|
||||||
|
zip_dirent_t *entry;
|
||||||
|
|
||||||
|
if ((offset = _zip_file_get_offset(za, index, error)) == 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;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
zip_file_rename.c -- rename file in zip archive
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <string.h>
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
zip_file_rename(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags) {
|
||||||
|
const char *old_name;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ZIP_IS_RDONLY(za)) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((old_name = zip_get_name(za, idx, 0)) == NULL)
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _zip_set_name(za, idx, name, flags);
|
||||||
|
}
|
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
zip_file_replace.c -- replace file via callback function
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_zip_file_replace(za, idx, NULL, source, flags) == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */
|
||||||
|
|
||||||
|
zip_int64_t
|
||||||
|
_zip_file_replace(zip_t *za, zip_uint64_t idx, const char *name, zip_source_t *source, zip_flags_t flags) {
|
||||||
|
zip_uint64_t za_nentry_prev;
|
||||||
|
|
||||||
|
if (ZIP_IS_RDONLY(za)) {
|
||||||
|
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;
|
||||||
|
|
||||||
|
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 (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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* does not change any name related data, so we can do it here;
|
||||||
|
* needed for a double add of the same file name */
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
za->entry[idx].source = source;
|
||||||
|
|
||||||
|
return (zip_int64_t)idx;
|
||||||
|
}
|
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
zip_file_set_comment.c -- set comment for file in archive
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <stdlib.h>
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
zip_file_set_comment(zip_t *za, zip_uint64_t idx, const char *comment, zip_uint16_t len, zip_flags_t flags) {
|
||||||
|
zip_entry_t *e;
|
||||||
|
zip_string_t *cstr;
|
||||||
|
int changed;
|
||||||
|
|
||||||
|
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (ZIP_IS_RDONLY(za)) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (ZIP_WANT_TORRENTZIP(za)) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len > 0 && comment == NULL) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e->orig && e->orig->comment)
|
||||||
|
changed = !_zip_string_equal(e->orig->comment, cstr);
|
||||||
|
else
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_zip_string_free(cstr);
|
||||||
|
if (e->changes && e->changes->changed == 0) {
|
||||||
|
_zip_dirent_free(e->changes);
|
||||||
|
e->changes = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,120 @@
|
||||||
|
/*
|
||||||
|
zip_file_set_encryption.c -- set encryption for file in archive
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
zip_file_set_encryption(zip_t *za, zip_uint64_t idx, zip_uint16_t method, const char *password) {
|
||||||
|
zip_entry_t *e;
|
||||||
|
zip_uint16_t old_method;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
if (ZIP_WANT_TORRENTZIP(za)) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
e = za->entry + idx;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
zip_file_set_external_attributes.c -- set external attributes for entry
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
zip_file_set_external_attributes(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_uint8_t opsys, zip_uint32_t attributes) {
|
||||||
|
zip_entry_t *e;
|
||||||
|
int changed;
|
||||||
|
zip_uint8_t unchanged_opsys;
|
||||||
|
zip_uint32_t unchanged_attributes;
|
||||||
|
|
||||||
|
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (ZIP_IS_RDONLY(za)) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (ZIP_WANT_TORRENTZIP(za)) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
e = za->entry + idx;
|
||||||
|
|
||||||
|
unchanged_opsys = (e->orig ? (zip_uint8_t)(e->orig->version_madeby >> 8) : (zip_uint8_t)ZIP_OPSYS_DEFAULT);
|
||||||
|
unchanged_attributes = e->orig ? e->orig->ext_attrib : ZIP_EXT_ATTRIB_DEFAULT;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
zip_file_set_mtime.c -- set modification time of entry.
|
||||||
|
Copyright (C) 2014-2022 Dieter Baron and Thomas Klausner
|
||||||
|
|
||||||
|
This file is part of libzip, a library to manipulate ZIP archives.
|
||||||
|
The authors can be contacted at <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
zip_file_set_dostime(zip_t *za, zip_uint64_t idx, zip_uint16_t dtime, zip_uint16_t ddate, zip_flags_t flags) {
|
||||||
|
time_t mtime;
|
||||||
|
mtime = _zip_d2u_time(dtime, ddate);
|
||||||
|
return zip_file_set_mtime(za, idx, mtime, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (ZIP_IS_RDONLY(za)) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (ZIP_WANT_TORRENTZIP(za)) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
e = za->entry + idx;
|
||||||
|
|
||||||
|
if (e->orig != NULL && e->orig->encryption_method == ZIP_EM_TRAD_PKWARE && !ZIP_ENTRY_CHANGED(e, ZIP_DIRENT_ENCRYPTION_METHOD) && !ZIP_ENTRY_DATA_CHANGED(e)) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
e->changes->last_mod = mtime;
|
||||||
|
e->changes->changed |= ZIP_DIRENT_LAST_MOD;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
zip_file_sterror.c -- get string representation of zip file error
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN const char *
|
||||||
|
zip_file_strerror(zip_file_t *zf) {
|
||||||
|
return zip_error_strerror(&zf->error);
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
zip_fopen.c -- open file in zip archive for reading
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN zip_file_t *
|
||||||
|
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 zip_fopen_index_encrypted(za, (zip_uint64_t)idx, flags, za->default_password);
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
zip_fopen_encrypted.c -- open file for reading with password
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN zip_file_t *
|
||||||
|
zip_fopen_encrypted(zip_t *za, const char *fname, zip_flags_t flags, const char *password) {
|
||||||
|
zip_int64_t idx;
|
||||||
|
|
||||||
|
if ((idx = zip_name_locate(za, fname, flags)) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return zip_fopen_index_encrypted(za, (zip_uint64_t)idx, flags, password);
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
zip_fopen_index.c -- open file in zip archive for reading by index
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN zip_file_t *
|
||||||
|
zip_fopen_index(zip_t *za, zip_uint64_t index, zip_flags_t flags) {
|
||||||
|
return zip_fopen_index_encrypted(za, index, flags, za->default_password);
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
zip_fopen_index_encrypted.c -- open file for reading by index w/ password
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
static zip_file_t *_zip_file_new(zip_t *za);
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN zip_file_t *
|
||||||
|
zip_fopen_index_encrypted(zip_t *za, zip_uint64_t index, zip_flags_t flags, const char *password) {
|
||||||
|
zip_file_t *zf;
|
||||||
|
zip_source_t *src;
|
||||||
|
|
||||||
|
if (password != NULL && password[0] == '\0') {
|
||||||
|
password = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((src = zip_source_zip_file_create(za, index, flags, 0, -1, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((zf = _zip_file_new(za)) == NULL) {
|
||||||
|
zip_source_free(src);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
zf->src = src;
|
||||||
|
|
||||||
|
return zf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static zip_file_t *
|
||||||
|
_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_init(&zf->error);
|
||||||
|
zf->src = NULL;
|
||||||
|
|
||||||
|
return zf;
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
zip_fread.c -- read from file
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN zip_int64_t
|
||||||
|
zip_fread(zip_file_t *zf, void *outbuf, zip_uint64_t toread) {
|
||||||
|
zip_int64_t n;
|
||||||
|
|
||||||
|
if (!zf)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (zf->error.zip_err != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (toread > ZIP_INT64_MAX) {
|
||||||
|
zip_error_set(&zf->error, ZIP_ER_INVAL, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toread == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((n = zip_source_read(zf->src, outbuf, toread)) < 0) {
|
||||||
|
zip_error_set_from_source(&zf->error, zf->src);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
zip_fseek.c -- seek in file
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
ZIP_EXTERN zip_int8_t
|
||||||
|
zip_fseek(zip_file_t *zf, zip_int64_t offset, int whence) {
|
||||||
|
if (!zf)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (zf->error.zip_err != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (zip_source_seek(zf->src, offset, whence) < 0) {
|
||||||
|
zip_error_set_from_source(&zf->error, zf->src);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
zip_file_is_seekable(zip_file_t *zfile) {
|
||||||
|
if (!zfile) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return zip_source_is_seekable(zfile->src);
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
zip_ftell.c -- tell position in file
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
ZIP_EXTERN zip_int64_t
|
||||||
|
zip_ftell(zip_file_t *zf) {
|
||||||
|
zip_int64_t res;
|
||||||
|
|
||||||
|
if (!zf)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (zf->error.zip_err != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
res = zip_source_tell(zf->src);
|
||||||
|
if (res < 0) {
|
||||||
|
zip_error_set_from_source(&zf->error, zf->src);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
zip_get_archive_comment.c -- get archive comment
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <string.h>
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN const char *
|
||||||
|
zip_get_archive_comment(zip_t *za, int *lenp, zip_flags_t flags) {
|
||||||
|
zip_string_t *comment;
|
||||||
|
zip_uint32_t len;
|
||||||
|
const zip_uint8_t *str;
|
||||||
|
|
||||||
|
if ((flags & ZIP_FL_UNCHANGED) || (za->comment_changes == NULL))
|
||||||
|
comment = za->comment_orig;
|
||||||
|
else
|
||||||
|
comment = za->comment_changes;
|
||||||
|
|
||||||
|
if ((str = _zip_string_get(comment, &len, flags, &za->error)) == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (lenp)
|
||||||
|
*lenp = (int)len;
|
||||||
|
|
||||||
|
return (const char *)str;
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
zip_get_archive_flag.c -- get archive global flag
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
zip_get_archive_flag(zip_t *za, zip_flags_t flag, zip_flags_t flags) {
|
||||||
|
unsigned int fl;
|
||||||
|
|
||||||
|
fl = (flags & ZIP_FL_UNCHANGED) ? za->flags : za->ch_flags;
|
||||||
|
|
||||||
|
return (fl & flag) ? 1 : 0;
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
zip_get_encryption_implementation.c -- get encryption implementation
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
#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;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
zip_encryption_method_supported(zip_uint16_t method, int encode) {
|
||||||
|
if (method == ZIP_EM_NONE) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return _zip_get_encryption_implementation(method, encode ? ZIP_CODEC_ENCODE : ZIP_CODEC_DECODE) != NULL;
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
zip_get_file_comment.c -- get file comment
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define _ZIP_COMPILING_DEPRECATED
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN const char *
|
||||||
|
zip_get_file_comment(zip_t *za, zip_uint64_t idx, int *lenp, int flags) {
|
||||||
|
zip_uint32_t len;
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
if ((s = zip_file_get_comment(za, idx, &len, (zip_flags_t)flags)) != NULL) {
|
||||||
|
if (lenp)
|
||||||
|
*lenp = (int)len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
zip_get_name.c -- get filename for a file in zip file
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <string.h>
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN const char *
|
||||||
|
zip_get_name(zip_t *za, zip_uint64_t idx, zip_flags_t flags) {
|
||||||
|
return _zip_get_name(za, idx, flags, &za->error);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char *
|
||||||
|
_zip_get_name(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *error) {
|
||||||
|
zip_dirent_t *de;
|
||||||
|
const zip_uint8_t *str;
|
||||||
|
|
||||||
|
if ((de = _zip_get_dirent(za, idx, flags, error)) == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if ((str = _zip_string_get(de->filename, NULL, flags, error)) == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return (const char *)str;
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
zip_get_num_entries.c -- get number of entries in archive
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN zip_int64_t
|
||||||
|
zip_get_num_entries(zip_t *za, zip_flags_t flags) {
|
||||||
|
zip_uint64_t n;
|
||||||
|
|
||||||
|
if (za == NULL)
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
return (zip_int64_t)za->nentry;
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
zip_get_num_files.c -- get number of files in archive
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define _ZIP_COMPILING_DEPRECATED
|
||||||
|
#include "zipint.h"
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
zip_get_num_files(zip_t *za) {
|
||||||
|
if (za == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (za->nentry > INT_MAX) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int)za->nentry;
|
||||||
|
}
|
|
@ -0,0 +1,410 @@
|
||||||
|
/*
|
||||||
|
zip_hash.c -- hash table string -> uint64
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* parameter for the string hash function */
|
||||||
|
#define HASH_MULTIPLIER 33
|
||||||
|
#define HASH_START 5381
|
||||||
|
|
||||||
|
/* hash table's fill ratio is kept between these by doubling/halfing its size as necessary */
|
||||||
|
#define HASH_MAX_FILL .75
|
||||||
|
#define HASH_MIN_FILL .01
|
||||||
|
|
||||||
|
/* but hash table size is kept between these */
|
||||||
|
#define HASH_MIN_SIZE 256
|
||||||
|
#define HASH_MAX_SIZE 0x80000000ul
|
||||||
|
|
||||||
|
struct zip_hash_entry {
|
||||||
|
const zip_uint8_t *name;
|
||||||
|
zip_int64_t orig_index;
|
||||||
|
zip_int64_t current_index;
|
||||||
|
struct zip_hash_entry *next;
|
||||||
|
zip_uint32_t hash_value;
|
||||||
|
};
|
||||||
|
typedef struct zip_hash_entry zip_hash_entry_t;
|
||||||
|
|
||||||
|
struct zip_hash {
|
||||||
|
zip_uint32_t table_size;
|
||||||
|
zip_uint64_t nentries;
|
||||||
|
zip_hash_entry_t **table;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* free list of entries */
|
||||||
|
static void
|
||||||
|
free_list(zip_hash_entry_t *entry) {
|
||||||
|
while (entry != NULL) {
|
||||||
|
zip_hash_entry_t *next = entry->next;
|
||||||
|
free(entry);
|
||||||
|
entry = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* compute hash of string, full 32 bit value */
|
||||||
|
static zip_uint32_t
|
||||||
|
hash_string(const zip_uint8_t *name) {
|
||||||
|
zip_uint64_t value = HASH_START;
|
||||||
|
|
||||||
|
if (name == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*name != 0) {
|
||||||
|
value = (zip_uint64_t)(((value * HASH_MULTIPLIER) + (zip_uint8_t)*name) % 0x100000000ul);
|
||||||
|
name++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (zip_uint32_t)value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* resize hash table; new_size must be a power of 2, can be larger or smaller than current size */
|
||||||
|
static bool
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hash->nentries > 0) {
|
||||||
|
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;
|
||||||
|
|
||||||
|
zip_uint32_t new_index = entry->hash_value % new_size;
|
||||||
|
|
||||||
|
entry->next = new_table[new_index];
|
||||||
|
new_table[new_index] = entry;
|
||||||
|
|
||||||
|
entry = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(hash->table);
|
||||||
|
hash->table = new_table;
|
||||||
|
hash->table_size = new_size;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static zip_uint32_t
|
||||||
|
size_for_capacity(zip_uint64_t capacity) {
|
||||||
|
double needed_size = capacity / HASH_MAX_FILL;
|
||||||
|
zip_uint32_t v;
|
||||||
|
|
||||||
|
if (needed_size > ZIP_UINT32_MAX) {
|
||||||
|
v = ZIP_UINT32_MAX;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
v = (zip_uint32_t)needed_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v > HASH_MAX_SIZE) {
|
||||||
|
return HASH_MAX_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* From Bit Twiddling Hacks by Sean Eron Anderson <seander@cs.stanford.edu>
|
||||||
|
(http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2). */
|
||||||
|
|
||||||
|
v--;
|
||||||
|
v |= v >> 1;
|
||||||
|
v |= v >> 2;
|
||||||
|
v |= v >> 4;
|
||||||
|
v |= v >> 8;
|
||||||
|
v |= v >> 16;
|
||||||
|
v++;
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
zip_hash_t *
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
hash->table_size = 0;
|
||||||
|
hash->nentries = 0;
|
||||||
|
hash->table = NULL;
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_zip_hash_free(zip_hash_t *hash) {
|
||||||
|
zip_uint32_t i;
|
||||||
|
|
||||||
|
if (hash == NULL) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
free(hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* insert into hash, return error on existence or memory issues */
|
||||||
|
bool
|
||||||
|
_zip_hash_add(zip_hash_t *hash, const zip_uint8_t *name, zip_uint64_t index, zip_flags_t flags, zip_error_t *error) {
|
||||||
|
zip_uint32_t hash_value, table_index;
|
||||||
|
zip_hash_entry_t *entry;
|
||||||
|
|
||||||
|
if (hash == NULL || name == NULL || index > ZIP_INT64_MAX) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 == 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 (flags & ZIP_FL_UNCHANGED) {
|
||||||
|
entry->orig_index = (zip_int64_t)index;
|
||||||
|
}
|
||||||
|
entry->current_index = (zip_int64_t)index;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* remove entry from hash, error if not found */
|
||||||
|
bool
|
||||||
|
_zip_hash_delete(zip_hash_t *hash, const zip_uint8_t *name, zip_error_t *error) {
|
||||||
|
zip_uint32_t hash_value, index;
|
||||||
|
zip_hash_entry_t *entry, *previous;
|
||||||
|
|
||||||
|
if (hash == NULL || name == NULL) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
zip_error_set(error, ZIP_ER_NOENT, 0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* find value for entry in hash, -1 if not found */
|
||||||
|
zip_int64_t
|
||||||
|
_zip_hash_lookup(zip_hash_t *hash, const zip_uint8_t *name, zip_flags_t flags, zip_error_t *error) {
|
||||||
|
zip_uint32_t hash_value, index;
|
||||||
|
zip_hash_entry_t *entry;
|
||||||
|
|
||||||
|
if (hash == NULL || name == NULL) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
zip_error_set(error, ZIP_ER_NOENT, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
_zip_hash_reserve_capacity(zip_hash_t *hash, zip_uint64_t capacity, zip_error_t *error) {
|
||||||
|
zip_uint32_t new_size;
|
||||||
|
|
||||||
|
if (capacity == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_size = size_for_capacity(capacity);
|
||||||
|
|
||||||
|
if (new_size <= hash->table_size) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hash_resize(hash, new_size, error)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
_zip_hash_revert(zip_hash_t *hash, zip_error_t *error) {
|
||||||
|
zip_uint32_t i;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,146 @@
|
||||||
|
/*
|
||||||
|
zip_io_util.c -- I/O helper functions
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <zlib.h>
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
_zip_read(zip_source_t *src, zip_uint8_t *b, zip_uint64_t length, zip_error_t *error) {
|
||||||
|
zip_int64_t n;
|
||||||
|
|
||||||
|
if (length > ZIP_INT64_MAX) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n < (zip_int64_t)length) {
|
||||||
|
zip_error_set(error, ZIP_ER_EOF, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
zip_uint8_t *
|
||||||
|
_zip_read_data(zip_buffer_t *buffer, zip_source_t *src, size_t length, bool nulp, zip_error_t *error) {
|
||||||
|
zip_uint8_t *r;
|
||||||
|
|
||||||
|
if (length == 0 && !nulp) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = (zip_uint8_t *)malloc(length + (nulp ? 1 : 0));
|
||||||
|
if (!r) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
(void)memcpy_s(r, length, data, length);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
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 = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
zip_string_t *
|
||||||
|
_zip_read_string(zip_buffer_t *buffer, zip_source_t *src, zip_uint16_t len, bool nulp, zip_error_t *error) {
|
||||||
|
zip_uint8_t *raw;
|
||||||
|
zip_string_t *s;
|
||||||
|
|
||||||
|
if ((raw = _zip_read_data(buffer, src, len, nulp, error)) == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
s = _zip_string_new(raw, len, ZIP_FL_ENC_GUESS, error);
|
||||||
|
free(raw);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
if ((zip_uint64_t)n != length) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_WRITE, EINTR);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (za->write_crc != NULL) {
|
||||||
|
zip_uint64_t position = 0;
|
||||||
|
while (position < length) {
|
||||||
|
zip_uint64_t nn = ZIP_MIN(UINT_MAX, length - position);
|
||||||
|
|
||||||
|
*za->write_crc = (zip_uint32_t)crc32(*za->write_crc, (const Bytef *)data + position, (uInt)nn);
|
||||||
|
position += nn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
zip_libzip_version.c -- return run-time version of library
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN const char *
|
||||||
|
zip_libzip_version(void) {
|
||||||
|
return LIBZIP_VERSION;
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
zip_memdup.c -- internal zip function, "strdup" with len
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
|
||||||
|
void *
|
||||||
|
_zip_memdup(const void *mem, size_t len, zip_error_t *error) {
|
||||||
|
void *ret;
|
||||||
|
|
||||||
|
if (len == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ret = malloc(len);
|
||||||
|
if (!ret) {
|
||||||
|
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)memcpy_s(ret, len, mem, len);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -0,0 +1,116 @@
|
||||||
|
/*
|
||||||
|
zip_name_locate.c -- get index by name
|
||||||
|
Copyright (C) 1999-2022 Dieter Baron and Thomas Klausner
|
||||||
|
|
||||||
|
This file is part of libzip, a library to manipulate ZIP archives.
|
||||||
|
The authors can be contacted at <info@libzip.org>
|
||||||
|
|
||||||
|
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 <string.h>
|
||||||
|
#ifdef HAVE_STRINGS_H
|
||||||
|
#include <strings.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN zip_int64_t
|
||||||
|
zip_name_locate(zip_t *za, const char *fname, zip_flags_t flags) {
|
||||||
|
return _zip_name_locate(za, fname, flags, &za->error);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
zip_int64_t
|
||||||
|
_zip_name_locate(zip_t *za, const char *fname, zip_flags_t flags, zip_error_t *error) {
|
||||||
|
int (*cmp)(const char *, const char *);
|
||||||
|
size_t fname_length;
|
||||||
|
zip_string_t *str = NULL;
|
||||||
|
const char *fn, *p;
|
||||||
|
zip_uint64_t i;
|
||||||
|
|
||||||
|
if (za == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fname == NULL) {
|
||||||
|
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fname_length = strlen(fname);
|
||||||
|
|
||||||
|
if (fname_length > ZIP_UINT16_MAX) {
|
||||||
|
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & (ZIP_FL_ENC_UTF_8 | ZIP_FL_ENC_RAW)) == 0 && fname[0] != '\0') {
|
||||||
|
if ((str = _zip_string_new((const zip_uint8_t *)fname, (zip_uint16_t)strlen(fname), flags, error)) == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((fname = (const char *)_zip_string_get(str, NULL, 0, error)) == NULL) {
|
||||||
|
_zip_string_free(str);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & (ZIP_FL_NOCASE | ZIP_FL_NODIR | ZIP_FL_ENC_RAW | ZIP_FL_ENC_STRICT)) {
|
||||||
|
/* 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);
|
||||||
|
_zip_string_free(str);
|
||||||
|
return (zip_int64_t)i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
zip_error_set(error, ZIP_ER_NOENT, 0);
|
||||||
|
_zip_string_free(str);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
zip_int64_t ret = _zip_hash_lookup(za->names, (const zip_uint8_t *)fname, flags, error);
|
||||||
|
_zip_string_free(str);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
zip_new.c -- create and init struct zip
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <stdlib.h>
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* _zip_new:
|
||||||
|
creates a new zipfile struct, and sets the contents to zero; returns
|
||||||
|
the new struct. */
|
||||||
|
|
||||||
|
zip_t *
|
||||||
|
_zip_new(zip_error_t *error) {
|
||||||
|
zip_t *za;
|
||||||
|
|
||||||
|
za = (zip_t *)malloc(sizeof(struct zip));
|
||||||
|
if (!za) {
|
||||||
|
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((za->names = _zip_hash_new(error)) == NULL) {
|
||||||
|
free(za);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
za->src = NULL;
|
||||||
|
za->open_flags = 0;
|
||||||
|
zip_error_init(&za->error);
|
||||||
|
za->flags = za->ch_flags = 0;
|
||||||
|
za->default_password = NULL;
|
||||||
|
za->comment_orig = za->comment_changes = NULL;
|
||||||
|
za->comment_changed = 0;
|
||||||
|
za->nentry = za->nentry_alloc = 0;
|
||||||
|
za->entry = NULL;
|
||||||
|
za->nopen_source = za->nopen_source_alloc = 0;
|
||||||
|
za->open_source = NULL;
|
||||||
|
za->progress = NULL;
|
||||||
|
|
||||||
|
return za;
|
||||||
|
}
|
|
@ -0,0 +1,967 @@
|
||||||
|
/*
|
||||||
|
zip_open.c -- open zip archive by name
|
||||||
|
Copyright (C) 1999-2022 Dieter Baron and Thomas Klausner
|
||||||
|
|
||||||
|
This file is part of libzip, a library to manipulate ZIP archives.
|
||||||
|
The authors can be contacted at <info@libzip.org>
|
||||||
|
|
||||||
|
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 <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
typedef enum { EXISTS_ERROR = -1, EXISTS_NOT = 0, EXISTS_OK } exists_t;
|
||||||
|
static zip_t *_zip_allocate_new(zip_source_t *src, unsigned int flags, zip_error_t *error);
|
||||||
|
static zip_int64_t _zip_checkcons(zip_t *za, zip_cdir_t *cdir, zip_error_t *error);
|
||||||
|
static void zip_check_torrentzip(zip_t *za, const zip_cdir_t *cdir);
|
||||||
|
static zip_cdir_t *_zip_find_central_dir(zip_t *za, zip_uint64_t len);
|
||||||
|
static exists_t _zip_file_exists(zip_source_t *src, zip_error_t *error);
|
||||||
|
static int _zip_headercomp(const zip_dirent_t *, const zip_dirent_t *);
|
||||||
|
static const unsigned char *_zip_memmem(const unsigned char *, size_t, const unsigned char *, size_t);
|
||||||
|
static zip_cdir_t *_zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_error_t *error);
|
||||||
|
static zip_cdir_t *_zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error);
|
||||||
|
static zip_cdir_t *_zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error);
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN zip_t *
|
||||||
|
zip_open(const char *fn, int _flags, int *zep) {
|
||||||
|
zip_t *za;
|
||||||
|
zip_source_t *src;
|
||||||
|
struct zip_error error;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_error_fini(&error);
|
||||||
|
return za;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN zip_t *
|
||||||
|
zip_open_from_source(zip_source_t *src, int _flags, zip_error_t *error) {
|
||||||
|
unsigned int flags;
|
||||||
|
zip_int64_t supported;
|
||||||
|
exists_t exists;
|
||||||
|
|
||||||
|
if (_flags < 0 || src == NULL) {
|
||||||
|
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
flags = (unsigned int)_flags;
|
||||||
|
|
||||||
|
supported = zip_source_supports(src);
|
||||||
|
if ((supported & ZIP_SOURCE_SUPPORTS_SEEKABLE) != ZIP_SOURCE_SUPPORTS_SEEKABLE) {
|
||||||
|
zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if ((supported & ZIP_SOURCE_SUPPORTS_WRITABLE) != ZIP_SOURCE_SUPPORTS_WRITABLE) {
|
||||||
|
flags |= ZIP_RDONLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & (ZIP_RDONLY | ZIP_TRUNCATE)) == (ZIP_RDONLY | ZIP_TRUNCATE)) {
|
||||||
|
zip_error_set(error, ZIP_ER_RDONLY, 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
exists = _zip_file_exists(src, error);
|
||||||
|
switch (exists) {
|
||||||
|
case EXISTS_ERROR:
|
||||||
|
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);
|
||||||
|
|
||||||
|
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 *
|
||||||
|
_zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error) {
|
||||||
|
zip_t *za;
|
||||||
|
zip_cdir_t *cdir;
|
||||||
|
struct zip_stat st;
|
||||||
|
zip_uint64_t len, idx;
|
||||||
|
|
||||||
|
zip_stat_init(&st);
|
||||||
|
if (zip_source_stat(src, &st) < 0) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
len = st.size;
|
||||||
|
|
||||||
|
|
||||||
|
if ((za = _zip_allocate_new(src, flags, error)) == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* treat empty files as empty archives */
|
||||||
|
if (len == 0 && zip_source_accept_empty(src)) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
za->entry = cdir->entry;
|
||||||
|
za->nentry = cdir->nentry;
|
||||||
|
za->nentry_alloc = cdir->nentry_alloc;
|
||||||
|
|
||||||
|
zip_check_torrentzip(za, cdir);
|
||||||
|
|
||||||
|
if (ZIP_IS_TORRENTZIP(za)) {
|
||||||
|
/* Torrentzip uses the archive comment to detect changes by tools that are not torrentzip aware. */
|
||||||
|
_zip_string_free(cdir->comment);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
za->comment_orig = cdir->comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(cdir);
|
||||||
|
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
za->ch_flags = za->flags;
|
||||||
|
|
||||||
|
return za;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_zip_set_open_error(int *zep, const zip_error_t *err, int ze) {
|
||||||
|
if (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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* _zip_readcdir:
|
||||||
|
tries to find a valid end-of-central-directory at the beginning of
|
||||||
|
buf, and then the corresponding central directory entries.
|
||||||
|
Returns a struct zip_cdir which contains the central directory
|
||||||
|
entries, or NULL if unsuccessful. */
|
||||||
|
|
||||||
|
static zip_cdir_t *
|
||||||
|
_zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_error_t *error) {
|
||||||
|
zip_cdir_t *cd;
|
||||||
|
zip_uint16_t comment_len;
|
||||||
|
zip_uint64_t i, left;
|
||||||
|
zip_uint64_t eocd_offset = _zip_buffer_offset(buffer);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_zip_buffer_set_offset(buffer, eocd_offset);
|
||||||
|
cd = _zip_read_eocd(buffer, buf_offset, za->flags, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cd == 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, 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_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, 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 (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, 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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (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));
|
||||||
|
}
|
||||||
|
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, 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, ZIP_ER_DETAIL_CDIR_LENGTH_INVALID);
|
||||||
|
_zip_buffer_free(cd_buffer);
|
||||||
|
_zip_cdir_free(cd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_zip_buffer_free(cd_buffer);
|
||||||
|
return cd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* _zip_checkcons:
|
||||||
|
Checks the consistency of the central directory by comparing central
|
||||||
|
directory entries with local headers and checking for plausible
|
||||||
|
file and header offsets. Returns -1 if not plausible, else the
|
||||||
|
difference between the lowest and the highest fileposition reached */
|
||||||
|
|
||||||
|
static zip_int64_t
|
||||||
|
_zip_checkcons(zip_t *za, zip_cdir_t *cd, zip_error_t *error) {
|
||||||
|
zip_uint64_t i;
|
||||||
|
zip_uint64_t min, max, j;
|
||||||
|
struct zip_dirent temp;
|
||||||
|
|
||||||
|
_zip_dirent_init(&temp);
|
||||||
|
if (cd->nentry) {
|
||||||
|
max = cd->entry[0].orig->offset;
|
||||||
|
min = cd->entry[0].orig->offset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
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) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* _zip_headercomp:
|
||||||
|
compares a central directory entry and a local file header
|
||||||
|
Return 0 if they are consistent, -1 if not. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
_zip_headercomp(const zip_dirent_t *central, const zip_dirent_t *local) {
|
||||||
|
if ((central->version_needed < local->version_needed)
|
||||||
|
#if 0
|
||||||
|
/* some zip-files have different values in 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;
|
||||||
|
|
||||||
|
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.
|
||||||
|
macOS Archive sets the compressed size even when data descriptor is used ( but not the others),
|
||||||
|
also in violation of the appnote.
|
||||||
|
*/
|
||||||
|
/* if data descriptor is not used, the values must match */
|
||||||
|
if ((local->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* when using a data descriptor, the local header value must be zero or match */
|
||||||
|
if ((local->crc != 0 && central->crc != local->crc) ||
|
||||||
|
(local->comp_size != 0 && central->comp_size != local->comp_size) ||
|
||||||
|
(local->uncomp_size != 0 && central->uncomp_size != local->uncomp_size)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static zip_t *
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
za->src = src;
|
||||||
|
za->open_flags = flags;
|
||||||
|
za->flags = 0;
|
||||||
|
za->ch_flags = 0;
|
||||||
|
za->write_crc = NULL;
|
||||||
|
|
||||||
|
if (flags & ZIP_RDONLY) {
|
||||||
|
za->flags |= ZIP_AFL_RDONLY;
|
||||||
|
za->ch_flags |= ZIP_AFL_RDONLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return za;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* tests for file existence
|
||||||
|
*/
|
||||||
|
static exists_t
|
||||||
|
_zip_file_exists(zip_source_t *src, zip_error_t *error) {
|
||||||
|
struct zip_stat st;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXISTS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static zip_cdir_t *
|
||||||
|
_zip_find_central_dir(zip_t *za, zip_uint64_t len) {
|
||||||
|
zip_cdir_t *cdir, *cdirnew;
|
||||||
|
const zip_uint8_t *match;
|
||||||
|
zip_int64_t buf_offset;
|
||||||
|
zip_uint64_t buflen;
|
||||||
|
zip_int64_t a;
|
||||||
|
zip_int64_t best;
|
||||||
|
zip_error_t error;
|
||||||
|
zip_buffer_t *buffer;
|
||||||
|
|
||||||
|
if (len < EOCDLEN) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((buf_offset = zip_source_tell(za->src)) < 0) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
best = -1;
|
||||||
|
cdir = NULL;
|
||||||
|
if (buflen >= CDBUFSIZE) {
|
||||||
|
/* 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);
|
||||||
|
/* The size of buffer never greater than CDBUFSIZE. */
|
||||||
|
while (_zip_buffer_left(buffer) >= EOCDLEN && (match = _zip_memmem(match, (size_t)_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_free(buffer);
|
||||||
|
|
||||||
|
if (best < 0) {
|
||||||
|
_zip_error_copy(&za->error, &error);
|
||||||
|
_zip_cdir_free(cdir);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cdir;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const unsigned char *_zip_memmem(const unsigned char *big, size_t biglen, const unsigned char *little, size_t littlelen) {
|
||||||
|
const unsigned char *p;
|
||||||
|
|
||||||
|
if (littlelen == 0) {
|
||||||
|
return big;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (biglen < littlelen) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = big;
|
||||||
|
while (true) {
|
||||||
|
p = (const unsigned char *)memchr(p, little[0], biglen - (littlelen - 1) - (size_t)(p - big));
|
||||||
|
if (p == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (memcmp(p + 1, little + 1, littlelen - 1) == 0) {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
p += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static zip_cdir_t *
|
||||||
|
_zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error) {
|
||||||
|
zip_cdir_t *cd;
|
||||||
|
zip_uint64_t i, nentry, size, offset, eocd_offset;
|
||||||
|
|
||||||
|
if (_zip_buffer_left(buffer) < EOCDLEN) {
|
||||||
|
zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EOCD_LENGTH_INVALID);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
eocd_offset = _zip_buffer_offset(buffer);
|
||||||
|
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* number of cdir-entries on this disk */
|
||||||
|
i = _zip_buffer_get_16(buffer);
|
||||||
|
/* number of cdir-entries */
|
||||||
|
nentry = _zip_buffer_get_16(buffer);
|
||||||
|
|
||||||
|
if (nentry != i) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset + size > buf_offset + eocd_offset) {
|
||||||
|
/* 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, ZIP_ER_DETAIL_CDIR_LENGTH_INVALID);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((cd = _zip_cdir_new(nentry, error)) == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
cd->is_zip64 = false;
|
||||||
|
cd->size = size;
|
||||||
|
cd->offset = offset;
|
||||||
|
|
||||||
|
return cd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static zip_cdir_t *
|
||||||
|
_zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error) {
|
||||||
|
zip_cdir_t *cd;
|
||||||
|
zip_uint64_t offset;
|
||||||
|
zip_uint8_t eocd[EOCD64LEN];
|
||||||
|
zip_uint64_t eocd_offset;
|
||||||
|
zip_uint64_t size, nentry, i, eocdloc_offset;
|
||||||
|
bool free_buffer;
|
||||||
|
zip_uint32_t num_disks, num_disks64, eocd_disk, eocd_disk64;
|
||||||
|
|
||||||
|
eocdloc_offset = _zip_buffer_offset(buffer);
|
||||||
|
|
||||||
|
_zip_buffer_get(buffer, 4); /* magic already verified */
|
||||||
|
|
||||||
|
num_disks = _zip_buffer_get_16(buffer);
|
||||||
|
eocd_disk = _zip_buffer_get_16(buffer);
|
||||||
|
eocd_offset = _zip_buffer_get_64(buffer);
|
||||||
|
|
||||||
|
/* valid seek value for start of EOCD */
|
||||||
|
if (eocd_offset > ZIP_INT64_MAX) {
|
||||||
|
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, 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;
|
||||||
|
}
|
||||||
|
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 (memcmp(_zip_buffer_get(buffer, 4), EOCD64_MAGIC, 4) != 0) {
|
||||||
|
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 */
|
||||||
|
size = _zip_buffer_get_64(buffer);
|
||||||
|
|
||||||
|
/* 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, 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 */
|
||||||
|
|
||||||
|
num_disks64 = _zip_buffer_get_32(buffer);
|
||||||
|
eocd_disk64 = _zip_buffer_get_32(buffer);
|
||||||
|
|
||||||
|
/* if eocd values are 0xffff, we have to use eocd64 values.
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
if (eocd_disk == 0xffff) {
|
||||||
|
eocd_disk = eocd_disk64;
|
||||||
|
}
|
||||||
|
if ((flags & ZIP_CHECKCONS) && (eocd_disk != eocd_disk64 || num_disks != num_disks64)) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = _zip_buffer_get_64(buffer);
|
||||||
|
offset = _zip_buffer_get_64(buffer);
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (free_buffer) {
|
||||||
|
_zip_buffer_free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset > ZIP_INT64_MAX || offset + size < offset) {
|
||||||
|
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, 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, ZIP_ER_DETAIL_CDIR_OVERLAPS_EOCD);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nentry > size / CDENTRYSIZE) {
|
||||||
|
zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_INVALID);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((cd = _zip_cdir_new(nentry, error)) == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
cd->is_zip64 = true;
|
||||||
|
cd->size = size;
|
||||||
|
cd->offset = offset;
|
||||||
|
|
||||||
|
return cd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int decode_hex(char c) {
|
||||||
|
if (c >= '0' && c <= '9') {
|
||||||
|
return c - '0';
|
||||||
|
}
|
||||||
|
else if (c >= 'A' && c <= 'F') {
|
||||||
|
return c - 'A' + 10;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* _zip_check_torrentzip:
|
||||||
|
check whether ZA has a valid TORRENTZIP comment, i.e. is torrentzipped */
|
||||||
|
|
||||||
|
static void zip_check_torrentzip(zip_t *za, const zip_cdir_t *cdir) {
|
||||||
|
zip_uint32_t crc_should;
|
||||||
|
char buf[8+1];
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (cdir == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_zip_string_length(cdir->comment) != TORRENTZIP_SIGNATURE_LENGTH + TORRENTZIP_CRC_LENGTH
|
||||||
|
|| strncmp((const char *)cdir->comment->raw, TORRENTZIP_SIGNATURE, TORRENTZIP_SIGNATURE_LENGTH) != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memcpy(buf, cdir->comment->raw + TORRENTZIP_SIGNATURE_LENGTH, TORRENTZIP_CRC_LENGTH);
|
||||||
|
buf[TORRENTZIP_CRC_LENGTH] = '\0';
|
||||||
|
crc_should = 0;
|
||||||
|
for (i = 0; i < TORRENTZIP_CRC_LENGTH; i += 2) {
|
||||||
|
int low, high;
|
||||||
|
high = decode_hex((buf[i]));
|
||||||
|
low = decode_hex(buf[i + 1]);
|
||||||
|
if (high < 0 || low < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
crc_should = (crc_should << 8) + (high << 4) + low;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
zip_stat_t st;
|
||||||
|
zip_source_t* src_window;
|
||||||
|
zip_source_t* src_crc;
|
||||||
|
zip_uint8_t buffer[512];
|
||||||
|
zip_int64_t ret;
|
||||||
|
|
||||||
|
zip_stat_init(&st);
|
||||||
|
st.valid |= ZIP_STAT_SIZE | ZIP_STAT_CRC;
|
||||||
|
st.size = cdir->size;
|
||||||
|
st.crc = crc_should;
|
||||||
|
if ((src_window = _zip_source_window_new(za->src, cdir->offset, cdir->size, &st, 0, NULL, NULL, 0, false, NULL)) == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((src_crc = zip_source_crc_create(src_window, 1, NULL)) == NULL) {
|
||||||
|
zip_source_free(src_window);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (zip_source_open(src_crc) != 0) {
|
||||||
|
zip_source_free(src_crc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while ((ret = zip_source_read(src_crc, buffer, sizeof(buffer))) > 0) {
|
||||||
|
}
|
||||||
|
zip_source_free(src_crc);
|
||||||
|
if (ret < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: if check consistency, check cdir entries for valid values */
|
||||||
|
za->flags |= ZIP_AFL_IS_TORRENTZIP;
|
||||||
|
}
|
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
zip_pkware.c -- Traditional PKWARE de/encryption backend routines
|
||||||
|
Copyright (C) 2009-2020 Dieter Baron and Thomas Klausner
|
||||||
|
|
||||||
|
This file is part of libzip, a library to manipulate ZIP archives.
|
||||||
|
The authors can be contacted at <info@libzip.org>
|
||||||
|
|
||||||
|
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 <stdlib.h>
|
||||||
|
#include <zlib.h>
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
#define PKWARE_KEY0 305419896
|
||||||
|
#define PKWARE_KEY1 591751049
|
||||||
|
#define PKWARE_KEY2 878082192
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_keys(zip_pkware_keys_t *keys, zip_uint8_t b) {
|
||||||
|
keys->key[0] = (zip_uint32_t)crc32(keys->key[0] ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL;
|
||||||
|
keys->key[1] = (keys->key[1] + (keys->key[0] & 0xff)) * 134775813 + 1;
|
||||||
|
b = (zip_uint8_t)(keys->key[1] >> 24);
|
||||||
|
keys->key[2] = (zip_uint32_t)crc32(keys->key[2] ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static zip_uint8_t
|
||||||
|
crypt_byte(zip_pkware_keys_t *keys) {
|
||||||
|
zip_uint16_t tmp;
|
||||||
|
tmp = (zip_uint16_t)(keys->key[2] | 2);
|
||||||
|
tmp = (zip_uint16_t)(((zip_uint32_t)tmp * (tmp ^ 1)) >> 8);
|
||||||
|
return (zip_uint8_t)tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_zip_pkware_keys_reset(zip_pkware_keys_t *keys) {
|
||||||
|
keys->key[0] = PKWARE_KEY0;
|
||||||
|
keys->key[1] = PKWARE_KEY1;
|
||||||
|
keys->key[2] = PKWARE_KEY2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_zip_pkware_encrypt(zip_pkware_keys_t *keys, zip_uint8_t *out, const zip_uint8_t *in, zip_uint64_t len) {
|
||||||
|
zip_uint64_t i;
|
||||||
|
zip_uint8_t b;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_zip_pkware_decrypt(zip_pkware_keys_t *keys, zip_uint8_t *out, const zip_uint8_t *in, zip_uint64_t len) {
|
||||||
|
zip_uint64_t i;
|
||||||
|
zip_uint8_t b;
|
||||||
|
zip_uint8_t tmp;
|
||||||
|
|
||||||
|
for (i = 0; i < len; 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
update_keys(keys, b);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,293 @@
|
||||||
|
/*
|
||||||
|
zip_progress.c -- progress reporting
|
||||||
|
Copyright (C) 2017-2020 Dieter Baron and Thomas Klausner
|
||||||
|
|
||||||
|
This file is part of libzip, a library to manipulate ZIP archives.
|
||||||
|
The authors can be contacted at <info@libzip.org>
|
||||||
|
|
||||||
|
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 <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define _ZIP_COMPILING_DEPRECATED
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
struct zip_progress {
|
||||||
|
zip_t *za;
|
||||||
|
|
||||||
|
zip_progress_callback callback_progress;
|
||||||
|
void (*ud_progress_free)(void *);
|
||||||
|
void *ud_progress;
|
||||||
|
|
||||||
|
zip_cancel_callback callback_cancel;
|
||||||
|
void (*ud_cancel_free)(void *);
|
||||||
|
void *ud_cancel;
|
||||||
|
|
||||||
|
double precision;
|
||||||
|
|
||||||
|
/* state */
|
||||||
|
double last_update; /* last value callback function was called with */
|
||||||
|
|
||||||
|
double start; /* start of sub-progress section */
|
||||||
|
double end; /* end of sub-progress section */
|
||||||
|
};
|
||||||
|
|
||||||
|
static void _zip_progress_free_cancel_callback(zip_progress_t *progress);
|
||||||
|
static void _zip_progress_free_progress_callback(zip_progress_t *progress);
|
||||||
|
static zip_progress_t *_zip_progress_new(zip_t *za);
|
||||||
|
static void _zip_progress_set_cancel_callback(zip_progress_t *progress, zip_cancel_callback callback, void (*ud_free)(void *), void *ud);
|
||||||
|
static void _zip_progress_set_progress_callback(zip_progress_t *progress, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud);
|
||||||
|
|
||||||
|
void
|
||||||
|
_zip_progress_end(zip_progress_t *progress) {
|
||||||
|
_zip_progress_update(progress, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_zip_progress_free(zip_progress_t *progress) {
|
||||||
|
if (progress == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_zip_progress_free_progress_callback(progress);
|
||||||
|
_zip_progress_free_cancel_callback(progress);
|
||||||
|
|
||||||
|
free(progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static zip_progress_t *
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
progress->za = za;
|
||||||
|
|
||||||
|
progress->callback_progress = NULL;
|
||||||
|
progress->ud_progress_free = NULL;
|
||||||
|
progress->ud_progress = NULL;
|
||||||
|
progress->precision = 0.0;
|
||||||
|
|
||||||
|
progress->callback_cancel = NULL;
|
||||||
|
progress->ud_cancel_free = NULL;
|
||||||
|
progress->ud_cancel = NULL;
|
||||||
|
|
||||||
|
return progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_zip_progress_free_progress_callback(zip_progress_t *progress) {
|
||||||
|
if (progress->ud_progress_free) {
|
||||||
|
progress->ud_progress_free(progress->ud_progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
progress->callback_progress = NULL;
|
||||||
|
progress->ud_progress = NULL;
|
||||||
|
progress->ud_progress_free = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_zip_progress_free_cancel_callback(zip_progress_t *progress) {
|
||||||
|
if (progress->ud_cancel_free) {
|
||||||
|
progress->ud_cancel_free(progress->ud_cancel);
|
||||||
|
}
|
||||||
|
|
||||||
|
progress->callback_cancel = NULL;
|
||||||
|
progress->ud_cancel = NULL;
|
||||||
|
progress->ud_cancel_free = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_zip_progress_set_progress_callback(zip_progress_t *progress, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud) {
|
||||||
|
_zip_progress_free_progress_callback(progress);
|
||||||
|
|
||||||
|
progress->callback_progress = callback;
|
||||||
|
progress->ud_progress_free = ud_free;
|
||||||
|
progress->ud_progress = ud;
|
||||||
|
progress->precision = precision;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_zip_progress_set_cancel_callback(zip_progress_t *progress, zip_cancel_callback callback, void (*ud_free)(void *), void *ud) {
|
||||||
|
_zip_progress_free_cancel_callback(progress);
|
||||||
|
|
||||||
|
progress->callback_cancel = callback;
|
||||||
|
progress->ud_cancel_free = ud_free;
|
||||||
|
progress->ud_cancel = ud;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_zip_progress_start(zip_progress_t *progress) {
|
||||||
|
if (progress == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (progress->callback_progress != NULL) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
_zip_progress_subrange(zip_progress_t *progress, double start, double end) {
|
||||||
|
if (progress == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
progress->start = start;
|
||||||
|
progress->end = end;
|
||||||
|
|
||||||
|
return _zip_progress_update(progress, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_zip_progress_update(zip_progress_t *progress, double sub_current) {
|
||||||
|
double current;
|
||||||
|
|
||||||
|
if (progress == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (progress->callback_progress != NULL) {
|
||||||
|
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 (progress->callback_cancel != NULL) {
|
||||||
|
if (progress->callback_cancel(progress->za, progress->ud_cancel)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct legacy_ud {
|
||||||
|
zip_progress_callback_t callback;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
_zip_legacy_progress_callback(zip_t *za, double progress, void *vud) {
|
||||||
|
struct legacy_ud *ud = (struct legacy_ud *)vud;
|
||||||
|
|
||||||
|
ud->callback(progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZIP_EXTERN void
|
||||||
|
zip_register_progress_callback(zip_t *za, zip_progress_callback_t progress_callback) {
|
||||||
|
struct legacy_ud *ud;
|
||||||
|
|
||||||
|
if (progress_callback == NULL) {
|
||||||
|
zip_register_progress_callback_with_state(za, 0, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ud = (struct legacy_ud *)malloc(sizeof(*ud))) == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ud->callback = progress_callback;
|
||||||
|
|
||||||
|
if (zip_register_progress_callback_with_state(za, 0.001, _zip_legacy_progress_callback, free, ud) < 0) {
|
||||||
|
free(ud);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,110 @@
|
||||||
|
/*
|
||||||
|
zip_random_unix.c -- fill the user's buffer with random stuff (Unix version)
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
#ifdef HAVE_CRYPTO
|
||||||
|
#include "zip_crypto.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_ARC4RANDOM
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifndef HAVE_SECURE_RANDOM
|
||||||
|
ZIP_EXTERN bool
|
||||||
|
zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) {
|
||||||
|
arc4random_buf(buffer, length);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_RANDOM_UINT32
|
||||||
|
zip_uint32_t
|
||||||
|
zip_random_uint32(void) {
|
||||||
|
return arc4random();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else /* HAVE_ARC4RANDOM */
|
||||||
|
|
||||||
|
#ifndef HAVE_SECURE_RANDOM
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
ZIP_EXTERN bool
|
||||||
|
zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) {
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if ((fd = open("/dev/urandom", O_RDONLY)) < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read(fd, buffer, length) != length) {
|
||||||
|
close(fd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_RANDOM_UINT32
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifndef HAVE_RANDOM
|
||||||
|
#define srandom srand
|
||||||
|
#define random rand
|
||||||
|
#endif
|
||||||
|
|
||||||
|
zip_uint32_t
|
||||||
|
zip_random_uint32(void) {
|
||||||
|
static bool seeded = false;
|
||||||
|
|
||||||
|
zip_uint32_t value;
|
||||||
|
|
||||||
|
if (zip_secure_random((zip_uint8_t *)&value, sizeof(value))) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!seeded) {
|
||||||
|
srandom((unsigned int)time(NULL));
|
||||||
|
seeded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (zip_uint32_t)random();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* HAVE_ARC4RANDOM */
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
zip_random_uwp.c -- fill the user's buffer with random stuff (UWP version)
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
#ifdef HAVE_CRYPTO
|
||||||
|
#include "zip_crypto.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_SECURE_RANDOM
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <bcrypt.h>
|
||||||
|
|
||||||
|
ZIP_EXTERN bool
|
||||||
|
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 (!BCRYPT_SUCCESS(hr) || hAlg == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
hr = BCryptGenRandom(&hAlg, buffer, length, 0);
|
||||||
|
BCryptCloseAlgorithmProvider(&hAlg, 0);
|
||||||
|
if (!BCRYPT_SUCCESS(hr)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_RANDOM_UINT32
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
zip_uint32_t
|
||||||
|
zip_random_uint32(void) {
|
||||||
|
static bool seeded = false;
|
||||||
|
|
||||||
|
zip_uint32_t value;
|
||||||
|
|
||||||
|
if (zip_secure_random((zip_uint8_t *)&value, sizeof(value))) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!seeded) {
|
||||||
|
srand((unsigned int)time(NULL));
|
||||||
|
seeded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (zip_uint32_t)rand();
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
zip_random_win32.c -- fill the user's buffer with random stuff (Windows version)
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
#ifdef HAVE_CRYPTO
|
||||||
|
#include "zip_crypto.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#ifndef HAVE_SECURE_RANDOM
|
||||||
|
|
||||||
|
#include <wincrypt.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
if (!CryptGenRandom(hprov, length, buffer)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!CryptReleaseContext(hprov, 0)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_RANDOM_UINT32
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
zip_uint32_t
|
||||||
|
zip_random_uint32(void) {
|
||||||
|
static bool seeded = false;
|
||||||
|
|
||||||
|
zip_uint32_t value;
|
||||||
|
|
||||||
|
if (zip_secure_random((zip_uint8_t *)&value, sizeof(value))) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!seeded) {
|
||||||
|
srand((unsigned int)time(NULL));
|
||||||
|
seeded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (zip_uint32_t)rand();
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
zip_rename.c -- rename file in zip archive
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define _ZIP_COMPILING_DEPRECATED
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
zip_rename(zip_t *za, zip_uint64_t idx, const char *name) {
|
||||||
|
return zip_file_rename(za, idx, name, 0);
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
zip_replace.c -- replace file via callback function
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define _ZIP_COMPILING_DEPRECATED
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
zip_replace(zip_t *za, zip_uint64_t idx, zip_source_t *source) {
|
||||||
|
return zip_file_replace(za, idx, source, 0);
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
zip_set_archive_comment.c -- set archive comment
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <stdlib.h>
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
if (ZIP_WANT_TORRENTZIP(za)) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len > 0 && comment == NULL) {
|
||||||
|
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 (_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;
|
||||||
|
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
za->comment_changes = cstr;
|
||||||
|
za->comment_changed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
zip_get_archive_flag.c -- set archive global flag
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
zip_set_archive_flag(zip_t *za, zip_flags_t flag, int value) {
|
||||||
|
unsigned int new_flags;
|
||||||
|
|
||||||
|
if (flag == ZIP_AFL_IS_TORRENTZIP) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: when setting ZIP_AFL_WANT_TORRENTZIP, we should error out if any changes have been made that are not allowed for torrentzip. */
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
new_flags = za->ch_flags | flag;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
new_flags = za->ch_flags & ~flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_flags == za->ch_flags) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allow removing ZIP_AFL_RDONLY if manually set, not if archive was opened read-only. */
|
||||||
|
if (za->flags & ZIP_AFL_RDONLY) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
za->ch_flags = new_flags;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
zip_set_default_password.c -- set default password for decryption
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
zip_set_default_password(zip_t *za, const char *passwd) {
|
||||||
|
if (za == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
free(za->default_password);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
zip_set_file_comment.c -- set comment for file in archive
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define _ZIP_COMPILING_DEPRECATED
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
return zip_file_set_comment(za, idx, comment, (zip_uint16_t)len, 0);
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
zip_set_file_compression.c -- set compression for file in archive
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
zip_set_file_compression(zip_t *za, zip_uint64_t idx, zip_int32_t method, zip_uint32_t flags) {
|
||||||
|
zip_entry_t *e;
|
||||||
|
zip_int32_t old_method;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
if (ZIP_WANT_TORRENTZIP(za)) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!zip_compression_method_supported(method, true)) {
|
||||||
|
zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
e = za->entry + idx;
|
||||||
|
|
||||||
|
old_method = (e->orig == NULL ? ZIP_CM_DEFAULT : e->orig->comp_method);
|
||||||
|
|
||||||
|
/* TODO: do we want to recompress if level is set? Only if it's
|
||||||
|
* different than what bit flags tell us, but those are not
|
||||||
|
* defined for all compression methods, or not directly mappable
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,157 @@
|
||||||
|
/*
|
||||||
|
zip_set_name.c -- rename helper function
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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 <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
_zip_set_name(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags) {
|
||||||
|
zip_entry_t *e;
|
||||||
|
zip_string_t *str;
|
||||||
|
bool same_as_orig;
|
||||||
|
zip_int64_t i;
|
||||||
|
const zip_uint8_t *old_name, *new_name;
|
||||||
|
zip_string_t *old_str;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* no effective name change */
|
||||||
|
if (i >= 0 && (zip_uint64_t)i == idx) {
|
||||||
|
_zip_string_free(str);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
e = za->entry + idx;
|
||||||
|
|
||||||
|
if (e->orig)
|
||||||
|
same_as_orig = _zip_string_equal(e->orig->filename, str);
|
||||||
|
else
|
||||||
|
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 ((new_name = _zip_string_get(same_as_orig ? e->orig->filename : str, NULL, 0, &za->error)) == NULL) {
|
||||||
|
_zip_string_free(str);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e->changes) {
|
||||||
|
old_str = e->changes->filename;
|
||||||
|
}
|
||||||
|
else if (e->orig) {
|
||||||
|
old_str = e->orig->filename;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
old_name = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_zip_hash_add(za->names, new_name, idx, 0, &za->error) == false) {
|
||||||
|
_zip_string_free(str);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (old_name) {
|
||||||
|
_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);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
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;
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
zip_source_accept_empty.c -- if empty source is a valid archive
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
zip_source_accept_empty(zip_source_t *src) {
|
||||||
|
zip_int64_t 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = _zip_source_call(src, NULL, 0, ZIP_SOURCE_ACCEPT_EMPTY);
|
||||||
|
|
||||||
|
return ret != 0;
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
zip_source_begin_write.c -- start a new file for writing
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
zip_source_begin_write(zip_source_t *src) {
|
||||||
|
if (ZIP_SOURCE_IS_LAYERED(src)) {
|
||||||
|
zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ZIP_SOURCE_IS_OPEN_WRITING(src)) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
src->write_state = ZIP_SOURCE_WRITE_OPEN;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
zip_source_begin_write_cloning.c -- clone part of file for writing
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
zip_source_begin_write_cloning(zip_source_t *src, zip_uint64_t offset) {
|
||||||
|
if (ZIP_SOURCE_IS_LAYERED(src)) {
|
||||||
|
zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ZIP_SOURCE_IS_OPEN_WRITING(src)) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
src->write_state = ZIP_SOURCE_WRITE_OPEN;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,643 @@
|
||||||
|
/*
|
||||||
|
zip_source_buffer.c -- create zip data source from buffer
|
||||||
|
Copyright (C) 1999-2022 Dieter Baron and Thomas Klausner
|
||||||
|
|
||||||
|
This file is part of libzip, a library to manipulate ZIP archives.
|
||||||
|
The authors can be contacted at <info@libzip.org>
|
||||||
|
|
||||||
|
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 <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "zipint.h"
|
||||||
|
|
||||||
|
#ifndef WRITE_FRAGMENT_SIZE
|
||||||
|
#define WRITE_FRAGMENT_SIZE (64 * 1024)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct buffer {
|
||||||
|
zip_buffer_fragment_t *fragments; /* fragments */
|
||||||
|
zip_uint64_t *fragment_offsets; /* offset of each fragment from start of buffer, nfragments+1 entries */
|
||||||
|
zip_uint64_t nfragments; /* number of allocated fragments */
|
||||||
|
zip_uint64_t fragments_capacity; /* size of fragments (number of pointers) */
|
||||||
|
|
||||||
|
zip_uint64_t first_owned_fragment; /* first fragment to free data from */
|
||||||
|
|
||||||
|
zip_uint64_t shared_fragments; /* number of shared fragments */
|
||||||
|
struct buffer *shared_buffer; /* buffer fragments are shared with */
|
||||||
|
|
||||||
|
zip_uint64_t size; /* size of buffer */
|
||||||
|
zip_uint64_t offset; /* current offset in buffer */
|
||||||
|
zip_uint64_t current_fragment; /* fragment current offset is in */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct buffer buffer_t;
|
||||||
|
|
||||||
|
struct read_data {
|
||||||
|
zip_error_t error;
|
||||||
|
time_t mtime;
|
||||||
|
zip_file_attributes_t attributes;
|
||||||
|
buffer_t *in;
|
||||||
|
buffer_t *out;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define buffer_capacity(buffer) ((buffer)->fragment_offsets[(buffer)->nfragments])
|
||||||
|
#define buffer_size(buffer) ((buffer)->size)
|
||||||
|
|
||||||
|
static buffer_t *buffer_clone(buffer_t *buffer, zip_uint64_t length, zip_error_t *error);
|
||||||
|
static zip_uint64_t buffer_find_fragment(const buffer_t *buffer, zip_uint64_t offset);
|
||||||
|
static void buffer_free(buffer_t *buffer);
|
||||||
|
static bool buffer_grow_fragments(buffer_t *buffer, zip_uint64_t capacity, zip_error_t *error);
|
||||||
|
static buffer_t *buffer_new(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int free_data, zip_error_t *error);
|
||||||
|
static zip_int64_t buffer_read(buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length);
|
||||||
|
static int buffer_seek(buffer_t *buffer, void *data, zip_uint64_t len, zip_error_t *error);
|
||||||
|
static zip_int64_t buffer_write(buffer_t *buffer, const zip_uint8_t *data, zip_uint64_t length, zip_error_t *);
|
||||||
|
|
||||||
|
static zip_int64_t read_data(void *, void *, zip_uint64_t, zip_source_cmd_t);
|
||||||
|
|
||||||
|
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);
|
||||||
|
zip_source_t *zip_source_buffer_fragment_with_attributes_create(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep, zip_file_attributes_t *attributes, zip_error_t *error);
|
||||||
|
|
||||||
|
|
||||||
|
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 zip_source_buffer_with_attributes_create(data, len, freep, NULL, &za->error);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN zip_source_t *
|
||||||
|
zip_source_buffer_create(const void *data, zip_uint64_t len, int freep, zip_error_t *error) {
|
||||||
|
return zip_source_buffer_with_attributes_create(data, len, freep, NULL, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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) {
|
||||||
|
zip_buffer_fragment_t fragment;
|
||||||
|
|
||||||
|
if (data == 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment.data = (zip_uint8_t *)data;
|
||||||
|
fragment.length = len;
|
||||||
|
|
||||||
|
return zip_source_buffer_fragment_with_attributes_create(&fragment, 1, freep, attributes, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 zip_source_buffer_fragment_with_attributes_create(fragments, nfragments, freep, NULL, &za->error);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN zip_source_t *
|
||||||
|
zip_source_buffer_fragment_create(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep, zip_error_t *error) {
|
||||||
|
return zip_source_buffer_fragment_with_attributes_create(fragments, nfragments, freep, NULL, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
zip_source_t *
|
||||||
|
zip_source_buffer_fragment_with_attributes_create(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep, zip_file_attributes_t *attributes, zip_error_t *error) {
|
||||||
|
struct read_data *ctx;
|
||||||
|
zip_source_t *zs;
|
||||||
|
buffer_t *buffer;
|
||||||
|
|
||||||
|
if (fragments == NULL && nfragments > 0) {
|
||||||
|
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((buffer = buffer_new(fragments, nfragments, freep, error)) == 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->in = buffer;
|
||||||
|
ctx->out = NULL;
|
||||||
|
ctx->mtime = time(NULL);
|
||||||
|
if (attributes) {
|
||||||
|
(void)memcpy_s(&ctx->attributes, sizeof(ctx->attributes), attributes, sizeof(ctx->attributes));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return zs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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) {
|
||||||
|
return zip_source_buffer_with_attributes_create(data, len, freep, attributes, &za->error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static zip_int64_t
|
||||||
|
read_data(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
|
||||||
|
struct read_data *ctx = (struct read_data *)state;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
case ZIP_SOURCE_CLOSE:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case ZIP_SOURCE_COMMIT_WRITE:
|
||||||
|
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);
|
||||||
|
|
||||||
|
case ZIP_SOURCE_FREE:
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)memcpy_s(data, sizeof(ctx->attributes), &ctx->attributes, sizeof(ctx->attributes));
|
||||||
|
|
||||||
|
return sizeof(ctx->attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
case ZIP_SOURCE_OPEN:
|
||||||
|
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);
|
||||||
|
|
||||||
|
case ZIP_SOURCE_REMOVE: {
|
||||||
|
buffer_t *empty = buffer_new(NULL, 0, 0, &ctx->error);
|
||||||
|
if (empty == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer_free(ctx->in);
|
||||||
|
ctx->in = empty;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ZIP_SOURCE_ROLLBACK_WRITE:
|
||||||
|
buffer_free(ctx->out);
|
||||||
|
ctx->out = NULL;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case ZIP_SOURCE_SEEK:
|
||||||
|
return buffer_seek(ctx->in, data, len, &ctx->error);
|
||||||
|
|
||||||
|
case ZIP_SOURCE_SEEK_WRITE:
|
||||||
|
return buffer_seek(ctx->out, data, len, &ctx->error);
|
||||||
|
|
||||||
|
case ZIP_SOURCE_STAT: {
|
||||||
|
zip_stat_t *st;
|
||||||
|
|
||||||
|
if (len < sizeof(*st)) {
|
||||||
|
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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, ZIP_SOURCE_SUPPORTS_REOPEN, -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;
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
default:
|
||||||
|
zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static buffer_t *
|
||||||
|
buffer_clone(buffer_t *buffer, zip_uint64_t offset, zip_error_t *error) {
|
||||||
|
zip_uint64_t fragment, fragment_offset, waste;
|
||||||
|
buffer_t *clone;
|
||||||
|
|
||||||
|
if (offset == 0) {
|
||||||
|
return buffer_new(NULL, 0, 1, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset > buffer->size) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment = buffer_find_fragment(buffer, offset);
|
||||||
|
fragment_offset = offset - buffer->fragment_offsets[fragment];
|
||||||
|
|
||||||
|
if (fragment_offset == 0) {
|
||||||
|
fragment--;
|
||||||
|
fragment_offset = buffer->fragments[fragment].length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: This should also consider the length of the fully shared fragments */
|
||||||
|
waste = buffer->fragments[fragment].length - fragment_offset;
|
||||||
|
if (waste > offset) {
|
||||||
|
zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((clone = buffer_new(buffer->fragments, fragment + 1, 0, error)) == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef __clang_analyzer__
|
||||||
|
/* clone->fragments can't be null, since it was created with at least one fragment */
|
||||||
|
clone->fragments[fragment].length = fragment_offset;
|
||||||
|
#endif
|
||||||
|
clone->fragment_offsets[clone->nfragments] = offset;
|
||||||
|
clone->size = offset;
|
||||||
|
|
||||||
|
clone->first_owned_fragment = ZIP_MIN(buffer->first_owned_fragment, clone->nfragments);
|
||||||
|
|
||||||
|
buffer->shared_buffer = clone;
|
||||||
|
clone->shared_buffer = buffer;
|
||||||
|
buffer->shared_fragments = fragment + 1;
|
||||||
|
clone->shared_fragments = fragment + 1;
|
||||||
|
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static zip_uint64_t
|
||||||
|
buffer_find_fragment(const buffer_t *buffer, zip_uint64_t offset) {
|
||||||
|
zip_uint64_t low, high, mid;
|
||||||
|
|
||||||
|
if (buffer->nfragments == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
low = 0;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return low;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
buffer_free(buffer_t *buffer) {
|
||||||
|
zip_uint64_t i;
|
||||||
|
|
||||||
|
if (buffer == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer->shared_buffer != NULL) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = buffer->first_owned_fragment; i < buffer->nfragments; i++) {
|
||||||
|
free(buffer->fragments[i].data);
|
||||||
|
}
|
||||||
|
free(buffer->fragments);
|
||||||
|
free(buffer->fragment_offsets);
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
buffer_grow_fragments(buffer_t *buffer, zip_uint64_t capacity, zip_error_t *error) {
|
||||||
|
zip_buffer_fragment_t *fragments;
|
||||||
|
zip_uint64_t *offsets;
|
||||||
|
|
||||||
|
if (capacity < buffer->fragments_capacity) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
zip_uint64_t fragments_size = sizeof(buffer->fragments[0]) * capacity;
|
||||||
|
zip_uint64_t offsets_size = sizeof(buffer->fragment_offsets[0]) * (capacity + 1);
|
||||||
|
|
||||||
|
if (capacity == ZIP_UINT64_MAX || fragments_size < capacity || fragments_size > SIZE_MAX|| offsets_size < capacity || offsets_size > SIZE_MAX) {
|
||||||
|
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fragments = realloc(buffer->fragments, (size_t)fragments_size)) == NULL) {
|
||||||
|
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
buffer->fragments = fragments;
|
||||||
|
if ((offsets = realloc(buffer->fragment_offsets, (size_t)offsets_size)) == NULL) {
|
||||||
|
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
buffer->fragment_offsets = offsets;
|
||||||
|
buffer->fragments_capacity = capacity;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static buffer_t *
|
||||||
|
buffer_new(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int free_data, zip_error_t *error) {
|
||||||
|
buffer_t *buffer;
|
||||||
|
|
||||||
|
if ((buffer = malloc(sizeof(*buffer))) == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->offset = 0;
|
||||||
|
buffer->first_owned_fragment = 0;
|
||||||
|
buffer->size = 0;
|
||||||
|
buffer->fragments = NULL;
|
||||||
|
buffer->fragment_offsets = NULL;
|
||||||
|
buffer->nfragments = 0;
|
||||||
|
buffer->fragments_capacity = 0;
|
||||||
|
buffer->shared_buffer = NULL;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
/* TODO: overflow */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static zip_int64_t
|
||||||
|
buffer_read(buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length) {
|
||||||
|
zip_uint64_t n, i, fragment_offset;
|
||||||
|
|
||||||
|
length = ZIP_MIN(length, buffer->size - buffer->offset);
|
||||||
|
|
||||||
|
if (length == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (length > ZIP_INT64_MAX) {
|
||||||
|
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);
|
||||||
|
#if ZIP_UINT64_MAX > SIZE_MAX
|
||||||
|
left = ZIP_MIN(left, SIZE_MAX);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
(void)memcpy_s(data + n, (size_t)left, buffer->fragments[i].data + fragment_offset, (size_t)left);
|
||||||
|
|
||||||
|
if (left == buffer->fragments[i].length - fragment_offset) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
n += left;
|
||||||
|
fragment_offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->offset += n;
|
||||||
|
buffer->current_fragment = i;
|
||||||
|
return (zip_int64_t)n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->offset = (zip_uint64_t)new_offset;
|
||||||
|
buffer->current_fragment = buffer_find_fragment(buffer, buffer->offset);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static zip_int64_t
|
||||||
|
buffer_write(buffer_t *buffer, const zip_uint8_t *data, zip_uint64_t length, zip_error_t *error) {
|
||||||
|
zip_uint64_t copied, i, fragment_offset, capacity;
|
||||||
|
|
||||||
|
if (buffer->offset + length + WRITE_FRAGMENT_SIZE - 1 < length) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i = buffer->current_fragment;
|
||||||
|
fragment_offset = buffer->offset - buffer->fragment_offsets[i];
|
||||||
|
copied = 0;
|
||||||
|
while (copied < length) {
|
||||||
|
zip_uint64_t n = ZIP_MIN(ZIP_MIN(length - copied, buffer->fragments[i].length - fragment_offset), SIZE_MAX);
|
||||||
|
#if ZIP_UINT64_MAX > SIZE_MAX
|
||||||
|
n = ZIP_MIN(n, SIZE_MAX);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
(void)memcpy_s(buffer->fragments[i].data + fragment_offset, (size_t)n, data + copied, (size_t)n);
|
||||||
|
|
||||||
|
if (n == buffer->fragments[i].length - fragment_offset) {
|
||||||
|
i++;
|
||||||
|
fragment_offset = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fragment_offset += n;
|
||||||
|
}
|
||||||
|
copied += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->offset += copied;
|
||||||
|
buffer->current_fragment = i;
|
||||||
|
if (buffer->offset > buffer->size) {
|
||||||
|
buffer->size = buffer->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (zip_int64_t)copied;
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
zip_source_call.c -- invoke callback command on zip_source
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
|
||||||
|
zip_int64_t
|
||||||
|
_zip_source_call(zip_source_t *src, void *data, zip_uint64_t length, zip_source_cmd_t command) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src->src == NULL) {
|
||||||
|
ret = src->cb.f(src->ud, data, length, command);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
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 (_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;
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
zip_source_close.c -- close zip_source (stop reading)
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
src->open_count--;
|
||||||
|
if (src->open_count == 0) {
|
||||||
|
_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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
zip_source_commit_write.c -- commit changes to file
|
||||||
|
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 <info@libzip.org>
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
|
||||||
|
ZIP_EXTERN int
|
||||||
|
zip_source_commit_write(zip_source_t *src) {
|
||||||
|
if (ZIP_SOURCE_IS_LAYERED(src)) {
|
||||||
|
zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ZIP_SOURCE_IS_OPEN_WRITING(src)) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
else if (ZIP_SOURCE_IS_OPEN_READING(src)) {
|
||||||
|
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_CLOSED;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue