aefb3263e2449b0b62095b2e50e9010d073fb670 s
aefb3263e2449b0b62095b2e50e9010d073fb670 s
0000000000000000000000000000000000000000 s
+c43a9681c5ca2d577636a75dc1f29b384c82f51a rel-1-2-0
# 2. installation not tested.
# 3. Problems generating html pages.
# 4. create usable libtool .la file
+# 5. runtest not created
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
SET(PACKAGE "libzip")
SET(PACKAGE_NAME ${PACKAGE})
SET(PACKAGE_VERSION_MAJOR "1")
-SET(PACKAGE_VERSION_MINOR "2")
+SET(PACKAGE_VERSION_MINOR "3")
SET(PACKAGE_VERSION_PATCH "0")
#SET(VERSION "${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR}")
SET(VERSION "${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR}.${PACKAGE_VERSION_PATCH}")
# Checks
+CHECK_FUNCTION_EXISTS(_chmod HAVE__CHMOD)
CHECK_FUNCTION_EXISTS(_close HAVE__CLOSE)
CHECK_FUNCTION_EXISTS(_dup HAVE__DUP)
CHECK_FUNCTION_EXISTS(_fdopen HAVE__FDOPEN)
CHECK_FUNCTION_EXISTS(_stricmp HAVE__STRICMP)
CHECK_FUNCTION_EXISTS(_strtoi64 HAVE__STRTOI64)
CHECK_FUNCTION_EXISTS(_strtoui64 HAVE__STRTOUI64)
+CHECK_FUNCTION_EXISTS(_umask HAVE__UMASK)
+CHECK_FUNCTION_EXISTS(_unlink HAVE__UNLINK)
CHECK_FUNCTION_EXISTS(explict_bzero HAVE_EXPLICIT_BZERO)
CHECK_FUNCTION_EXISTS(explicit_memset HAVE_EXPLICIT_MEMSET)
CHECK_FUNCTION_EXISTS(fileno HAVE_FILENO)
MESSAGE(FATAL_ERROR "-- ZLIB version too old, please install at least v1.1.2")
ENDIF(ZLIB_VERSION_STRING VERSION_LESS "1.1.2")
+FIND_PACKAGE(BZip2)
+IF(BZIP2_FOUND)
+ SET (HAVE_LIBBZ2 1)
+
+ INCLUDE_DIRECTORIES(${BZIP2_INCLUDE_DIR})
+ SET (OPTIONAL_LIBRARY ${BZIP2_LIBRARY})
+ENDIF(BZIP2_FOUND)
+
IF(MSVC)
ADD_DEFINITIONS("-D_CRT_SECURE_NO_WARNINGS")
+ADD_DEFINITIONS("-D_CRT_NONSTDC_NO_DEPRECATE")
ENDIF(MSVC)
ADD_DEFINITIONS("-DHAVE_CONFIG_H")
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/cmake-zipconf.h.in
${CMAKE_CURRENT_BINARY_DIR}/zipconf.h)
+# for tests
+
+SET(srcdir ${CMAKE_CURRENT_SOURCE_DIR}/regress)
+SET(abs_srcdir ${CMAKE_CURRENT_SOURCE_DIR}/regress)
+SET(top_builddir ${CMAKE_BINARY_DIR})
+
+CONFIGURE_FILE(regress/runtest.in ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/runtest @ONLY)
+FILE(COPY ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/runtest
+ DESTINATION ${CMAKE_BINARY_DIR}/regress
+ FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
+)
+
# installation
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/zipconf.h DESTINATION lib/libzip/include)
+1.3.0 [2017-09-02]
+==================
+
+* Support bzip2 compressed zip archives
+* Improve file progress callback code
+* Fix zip_fdopen()
+* CVE-2017-12858: Fix double free().
+* CVE-2017-14107: Improve EOCD64 parsing.
+
1.2.0 [2017-02-19]
==================
* Support for AES encryption (Winzip version), both encryption
- and decryption.
-* Support legacy zip files with >64k entries.
-* Fix seeking in zip_source_file if start > 0.
-* Add zip_fseek() for seeking in uncompressed data.
+ and decryption
+* Support legacy zip files with >64k entries
+* Fix seeking in zip_source_file if start > 0
+* Add zip_fseek() for seeking in uncompressed data
* Add zip_ftell() for telling position in uncompressed data.
* Add zip_register_progress_callback() for UI updates during zip_close()
To build libzip from the repository using autotools, you need to
install autoconf, automake, and libtool; then run
-> autoreconf -fi
+```shell
+autoreconf -fi
+```
Afterwards you can run configure as usual.
Alternatively, use cmake.
+
+```shell
+mkdir build
+cd build
+cmake .. -DBUILD_SHARED_LIBS:BOOL=ON
+```
+
+If you prefer building a static library, leave define `BUILD_SHARED_LIBS` to `OFF`
with most operating systems nowadays, or you can get it at
> http://www.zlib.net/
+For supporting bzip2-compressed zip archives, bzip2 from
+> http://bzip.org/
+needs to be installed.
+
When using a static Windows library, you need to define `ZIP_STATIC`
when compiling packages using libzip.
distribution site:
> http://www.nih.at/libzip/
-The latest version can always be found there.
+The latest version can always be found there. The official mercurial
+repository is at http://hg.nih.at/libzip/ and a read-only git mirror
+exists at https://github.com/nih-at/libzip/
There is a mailing list for developers using libzip. You can
subscribe to it by sending a mail with the subject "subscribe
Thanks to these people for suggestions, testing, and bug reports:
+Agostino Sarubbo
Alexander Galanin <al@galanin.nnov.ru>
Alexandr Shadchin <alexandr.shadchin@gmail.com>
Andrew Brampton <brampton@gmail.com>
Benjamin Gilbert <bgilbert@backtick.net>
Boaz Stolk <bstolk@aweta.nl>
Bogdan <bogiebog@gmail.com>
+Brian 'geeknik' Carpenter <geeknik@protonmail.ch>
Chris Nehren <cnehren+libzip@pobox.com>
Coverity <info@coverity.com>
Dane Springmeyer <dane.springmeyer@gmail.com>
const zip_uint8_t *zip_get_archive_prefix(struct zip *za, zip_uint64_t *lengthp);
````
+# Compression
+
+* Test CMAKE for bzip2
+* add lzma support
+
# API Issues
* `zip_get_archive_comment` has `int *lenp` argument. Cleaner would be `zip_uint32_t *`.
* test cases encryption: no password, default password, file-specific password, 128/192/256, <=20, >20
* support testing on Linux
* support testing on macOS
-* xz support
* consistently use `_zip_crypto_clear()` for passwords
-* implement compression flags for `zip_set_file_compression()`
-* support setting extra fields from zip_source
+* support setting extra fields from `zip_source`
* introduce layers of extra fields:
* original
- * from zip_source
+ * from `zip_source`
* manually set
* when querying extra fields, search all of them in reverse order
* add whiteout (deleted) flag
* set `O_CLOEXEC` flag after fopen and mkstemp
* add append-only mode writing file to disk incrementally to keep memory usage low
* `zip_file_set_mtime()`: support InfoZIP time stamps
-
+* `zipcmp`: support comparing more features:
+ * version needed/made by
+ * general purpose bit flags
* support streaming output (creating new archive to e.g. stdout)
* add functions to:
* read/set ASCII file flag? (more general options?)
# Cleanup
+* go over cdir parser and rename various offset/size variables to make it clearer
* use bool
* use `ZIP_SOURCE_SUPPORTS_{READABLE,SEEKABLE,WRITABLE}`
* use `zip_source_seek_compute_offset()`
# Test Case Issues
+* add test cases for lots of files (including too many)
+* add test cases for holes (between files, between files and cdir, between cdir and eocd, + zip64 where appropriate)
* unchange on added file
* test seek in `zip_source_crc()`
* test cases for `set_extra*`, `delete_extra*`, `*extra_field*`
#endif
/* BEGIN DEFINES */
#cmakedefine HAVE___PROGNAME
+#cmakedefine HAVE__CHMOD
#cmakedefine HAVE__CLOSE
#cmakedefine HAVE__DUP
#cmakedefine HAVE__FDOPEN
#cmakedefine HAVE__STRICMP
#cmakedefine HAVE__STRTOI64
#cmakedefine HAVE__STRTOUI64
+#cmakedefine HAVE__UMASK
+#cmakedefine HAVE__UNLINK
#cmakedefine HAVE_FILENO
#cmakedefine HAVE_FSEEKO
#cmakedefine HAVE_FTELLO
#cmakedefine HAVE_GETPROGNAME
+#cmakedefine HAVE_LIBBZ2
#cmakedefine HAVE_OPEN
#cmakedefine HAVE_MKSTEMP
#cmakedefine HAVE_SETMODE
AC_PREREQ([2.60])
-AC_INIT([libzip],[1.2.0],[libzip@nih.at])
+AC_INIT([libzip],[1.3.0],[libzip@nih.at])
AC_CONFIG_SRCDIR([lib/zip_add.c])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
AC_MSG_ERROR([ZLIB version too old, please install at least v1.1.2])
fi
+AC_ARG_WITH(bzip2,
+ [ --with-bzip2=PREFIX specify prefix for bzip2 library],,
+ with_bzip2=yes)
+
+if test "$with_bzip2" != "yes"
+then
+ if test -f "$with_bzip2"/bzlib.h
+ then
+ # PREFIX is to uninstalled version in distribution directory
+ CFLAGS="$CFLAGS -I$with_bzip2"
+ LDFLAGS="$LDFLAGS -L$with_bzip2"
+ else if test -f "$with_bzip2"/include/bzlib.h
+ then
+ # PREFIX is installation prefix
+ CFLAGS="$CFLAGS -I$with_bzip2/include"
+ LDFLAGS="$LDFLAGS -L$with_bzip2/lib"
+ fi
+ fi
+fi
+if test "$with_bzip2" != "no"
+then
+ AC_CHECK_LIB(bz2, main)
+fi
+
AC_EXEEXT
LT_INIT
-AC_CHECK_FUNCS([_close _dup _fdopen _fileno _open _setmode _snprintf _strdup _stricmp _strtoi64 _strtoui64 explicit_bzero explicit_memset fileno fseeko ftello getopt getprogname open setmode snprintf strcasecmp strdup stricmp strtoll strtoull])
+if test "$enable_shared" = "yes"
+then
+ AC_DEFINE([HAVE_SHARED], [1], [Define when building shared libraries])
+fi
+
+AC_CHECK_FUNCS([_chmod _close _dup _fdopen _fileno _open _setmode _snprintf _strdup _stricmp _strtoi64 _strtoui64 _umask _unlink explicit_bzero explicit_memset fileno fseeko ftello getopt getprogname open setmode snprintf strcasecmp strdup stricmp strtoll strtoull])
AC_CHECK_FUNCS([mkstemp], [], [AC_LIBOBJ(mkstemp)])
dnl assume dlsym in libc, but check in libdl
zip_add.c
zip_add_dir.c
zip_add_entry.c
+ zip_algorithm_bzip2.c
+ zip_algorithm_deflate.c
zip_buffer.c
zip_close.c
zip_delete.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_compression_implementation.c
zip_get_encryption_implementation.c
zip_get_file_comment.c
zip_get_name.c
zip_name_locate.c
zip_new.c
zip_open.c
+ zip_progress.c
zip_rename.c
zip_replace.c
zip_set_archive_comment.c
zip_source_call.c
zip_source_close.c
zip_source_commit_write.c
+ zip_source_compress.c
zip_source_crc.c
- zip_source_deflate.c
zip_source_error.c
zip_source_filep.c
zip_source_free.c
zip_source_function.c
+ zip_source_get_compression_flags.c
zip_source_is_deleted.c
zip_source_layered.c
zip_source_open.c
SET(LIBZIP_EXTRA_FILES mkstemp.c)
ENDIF(NOT HAVE_MKSTEMP)
-ADD_LIBRARY(zip SHARED ${LIBZIP_SOURCES} ${LIBZIP_EXTRA_FILES} ${LIBZIP_OPSYS_FILES})
+ADD_LIBRARY(zip ${LIBZIP_SOURCES} ${LIBZIP_EXTRA_FILES} ${LIBZIP_OPSYS_FILES})
SET_TARGET_PROPERTIES(zip PROPERTIES VERSION 3.0 SOVERSION 3 )
-TARGET_LINK_LIBRARIES(zip ${ZLIB_LIBRARY})
+TARGET_LINK_LIBRARIES(zip ${ZLIB_LIBRARY} ${OPTIONAL_LIBRARY})
INSTALL(TARGETS zip
RUNTIME DESTINATION bin
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib)
#CREATE_LIBTOOL_FILE(zip lib)
-
-#ADD_LIBRARY(zipstatic STATIC ${LIBZIP_SOURCES} ${LIBZIP_EXTRA_FILES} ${LIBZIP_OPSYS_FILES})
-#SET_TARGET_PROPERTIES(zipstatic PROPERTIES VERSION 3.0 SOVERSION 3 )
-#TARGET_LINK_LIBRARIES(zipstatic ${ZLIB_LIBRARY})
-#INSTALL(TARGETS zipstatic
-# RUNTIME DESTINATION bin
-# ARCHIVE DESTINATION lib
-# LIBRARY DESTINATION lib)
zip_add.c \
zip_add_dir.c \
zip_add_entry.c \
+ zip_algorithm_bzip2.c \
+ zip_algorithm_deflate.c \
zip_buffer.c \
zip_close.c \
zip_delete.c \
zip_ftell.c \
zip_get_archive_comment.c \
zip_get_archive_flag.c \
- zip_get_compression_implementation.c \
zip_get_encryption_implementation.c \
zip_get_file_comment.c \
zip_get_num_entries.c \
zip_name_locate.c \
zip_new.c \
zip_open.c \
+ zip_progress.c \
zip_rename.c \
zip_replace.c \
zip_set_archive_comment.c \
zip_source_call.c \
zip_source_close.c \
zip_source_commit_write.c \
+ zip_source_compress.c \
zip_source_crc.c \
- zip_source_deflate.c \
zip_source_error.c \
zip_source_filep.c \
zip_source_free.c \
zip_source_function.c \
+ zip_source_get_compression_flags.c \
zip_source_is_deleted.c \
zip_source_layered.c \
zip_source_open.c \
#endif
#ifdef _WIN32
+#if defined(HAVE__CHMOD)
+#define chmod _chmod
+#endif
#if defined(HAVE__CLOSE)
#define close _close
#endif
#if !defined(HAVE_STRTOULL) && defined(HAVE__STRTOUI64)
#define strtoull _strtoui64
#endif
+#if defined(HAVE__UMASK)
+#define umask _umask
+#endif
+#if defined(HAVE__UNLINK)
+#define unlink _unlink
+#endif
#endif
#ifndef HAVE_FSEEKO
#include <errno.h>
#include <fcntl.h>
#ifdef _WIN32
+#include <process.h>
#include <io.h>
+#else
+#include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
/* 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 /* N 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_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 /* N 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 */
/* type of system error value */
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_REMOVE, /* remove file */
+ ZIP_SOURCE_GET_COMPRESSION_FLAGS /* get compression flags, internal only */
};
typedef enum zip_source_cmd zip_source_cmd_t;
-#define ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd) (1<<(cmd))
+#define ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd) (((zip_uint64_t)1)<<(cmd))
#define ZIP_SOURCE_SUPPORTS_READABLE (ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_OPEN) \
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_READ) \
typedef zip_uint32_t zip_flags_t;
typedef zip_int64_t (*zip_source_callback)(void *, void *, zip_uint64_t, zip_source_cmd_t);
-typedef void (*zip_progress_callback_t)(double);
-
+typedef void (*zip_progress_callback)(zip_t *, double, void *);
#ifndef ZIP_DISABLE_DEPRECATED
+typedef void (*zip_progress_callback_t)(double);
+ZIP_EXTERN void zip_register_progress_callback(zip_t *, zip_progress_callback_t);
+
ZIP_EXTERN zip_int64_t zip_add(zip_t *, const char *, zip_source_t *); /* use zip_file_add */
ZIP_EXTERN zip_int64_t zip_add_dir(zip_t *, const char *); /* use zip_dir_add */
ZIP_EXTERN const char *zip_get_file_comment(zip_t *, zip_uint64_t, int *, int); /* use zip_file_get_comment */
ZIP_EXTERN zip_int64_t zip_name_locate(zip_t *, const char *, zip_flags_t);
ZIP_EXTERN zip_t *zip_open(const char *, int, int *);
ZIP_EXTERN zip_t *zip_open_from_source(zip_source_t *, int, zip_error_t *);
-ZIP_EXTERN void zip_register_progress_callback(zip_t *, zip_progress_callback_t);
+ZIP_EXTERN int zip_register_progress_callback_with_state(zip_t *, double, zip_progress_callback, void (*)(void *), void *);
ZIP_EXTERN int zip_set_archive_comment(zip_t *, const char *, zip_uint16_t);
ZIP_EXTERN int zip_set_archive_flag(zip_t *, zip_flags_t, int);
ZIP_EXTERN int zip_set_default_password(zip_t *, const char *);
--- /dev/null
+/*
+ zip_algorithm_bzip2.c -- bzip2 (de)compression routines
+ Copyright (C) 2017 Dieter Baron and Thomas Klausner
+
+ This file is part of libzip, a library to manipulate ZIP archives.
+ The authors can be contacted at <libzip@nih.at>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "zipint.h"
+
+#if defined(HAVE_LIBBZ2)
+
+#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 void *
+allocate(bool compress, int 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;
+ ctx->compression_flags = compression_flags;
+ if (ctx->compression_flags < 1 || ctx->compression_flags > 9) {
+ 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, int compression_flags, zip_error_t *error) {
+ return allocate(true, compression_flags, error);
+}
+
+
+static void *
+decompress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
+ return allocate(false, compression_flags, error);
+}
+
+
+static void
+deallocate(void *ud) {
+ struct ctx *ctx = (struct ctx *)ud;
+
+ free(ctx);
+}
+
+
+static int
+compression_flags(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:
+ return ZIP_ER_INTERNAL;
+
+ default:
+ return ZIP_ER_INTERNAL;
+ }
+
+}
+
+static bool
+start(void *ud) {
+ struct ctx *ctx = (struct ctx *)ud;
+ int ret;
+
+ 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;
+
+ int ret;
+
+ if (ctx->zstr.avail_in == 0 && !ctx->end_of_input) {
+ *length = 0;
+ return ZIP_COMPRESSION_NEED_DATA;
+ }
+
+ ctx->zstr.avail_out = (unsigned int)ZIP_MIN(UINT_MAX, *length);
+ ctx->zstr.next_out = (char *)data;
+
+ if (ctx->compress) {
+ ret = BZ2_bzCompress(&ctx->zstr, ctx->end_of_input ? BZ_FINISH : BZ_RUN);
+ }
+ else {
+ ret = BZ2_bzDecompress(&ctx->zstr);
+ }
+
+ *length = *length - 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;
+ }
+}
+
+
+zip_compression_algorithm_t zip_algorithm_bzip2_compress = {
+ compress_allocate,
+ deallocate,
+ compression_flags,
+ start,
+ end,
+ input,
+ end_of_input,
+ process
+};
+
+
+zip_compression_algorithm_t zip_algorithm_bzip2_decompress = {
+ decompress_allocate,
+ deallocate,
+ compression_flags,
+ start,
+ end,
+ input,
+ end_of_input,
+ process
+};
+
+#else
+
+static int dummy;
+
+#endif /* HAVE_LIBBZ2 */
--- /dev/null
+/*
+ zip_algorithm_deflate.c -- deflate (de)compression routines
+ Copyright (C) 2017 Dieter Baron and Thomas Klausner
+
+ This file is part of libzip, a library to manipulate ZIP archives.
+ The authors can be contacted at <libzip@nih.at>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "zipint.h"
+
+#include <limits.h>
+#include <stdlib.h>
+#include <zlib.h>
+
+struct ctx {
+ zip_error_t *error;
+ bool compress;
+ int compression_flags;
+ bool end_of_input;
+ z_stream zstr;
+};
+
+
+static void *
+allocate(bool compress, int compression_flags, zip_error_t *error) {
+ struct ctx *ctx;
+
+ if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) {
+ return NULL;
+ }
+
+ ctx->error = error;
+ ctx->compress = compress;
+ ctx->compression_flags = compression_flags;
+ if (ctx->compression_flags < 1 || ctx->compression_flags > 9) {
+ ctx->compression_flags = Z_BEST_COMPRESSION;
+ }
+ ctx->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, int compression_flags, zip_error_t *error) {
+ return allocate(true, compression_flags, error);
+}
+
+
+static void *
+decompress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
+ return allocate(false, compression_flags, error);
+}
+
+
+static void
+deallocate(void *ud) {
+ struct ctx *ctx = (struct ctx *)ud;
+
+ free(ctx);
+}
+
+
+static int
+compression_flags(void *ud) {
+ struct ctx *ctx = (struct ctx *)ud;
+
+ if (!ctx->compress) {
+ return 0;
+ }
+
+ if (ctx->compression_flags < 3) {
+ return 2;
+ }
+ else if (ctx->compression_flags > 7) {
+ return 1;
+ }
+ return 0;
+}
+
+
+static bool
+start(void *ud) {
+ struct ctx *ctx = (struct ctx *)ud;
+ int ret;
+
+ 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->compression_flags, Z_DEFLATED, -MAX_WBITS, MAX_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;
+
+ int ret;
+
+ ctx->zstr.avail_out = (uInt)ZIP_MIN(UINT_MAX, *length);
+ 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 = *length - 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;
+ }
+}
+
+
+zip_compression_algorithm_t zip_algorithm_deflate_compress = {
+ compress_allocate,
+ deallocate,
+ compression_flags,
+ start,
+ end,
+ input,
+ end_of_input,
+ process
+};
+
+
+zip_compression_algorithm_t zip_algorithm_deflate_decompress = {
+ decompress_allocate,
+ deallocate,
+ compression_flags,
+ start,
+ end,
+ input,
+ end_of_input,
+ process
+};
#endif
-/* max deflate size increase: size + ceil(size/16k)*5+6 */
-#define MAX_DEFLATE_SIZE_32 4293656963u
-
static int add_data(zip_t *, zip_source_t *, zip_dirent_t *);
static int copy_data(zip_t *, zip_uint64_t);
-static int copy_source(zip_t *, zip_source_t *);
+static int copy_source(zip_t *, zip_source_t *, zip_int64_t);
static int write_cdir(zip_t *, const zip_filelist_t *, zip_uint64_t);
-
ZIP_EXTERN int
zip_close(zip_t *za)
{
free(filelist);
return -1;
}
-
+
+ _zip_progress_start(za->progress);
error = 0;
for (j=0; j<survivors; j++) {
int new_data;
zip_entry_t *entry;
zip_dirent_t *de;
- if (za->progress_callback) {
- za->progress_callback((double)j/survivors);
- }
+ _zip_progress_subrange(za->progress, (double)j / (double)survivors, (double)(j+1) / (double)survivors);
i = filelist[j].idx;
entry = za->entry+i;
return -1;
}
- if (za->progress_callback) {
- za->progress_callback(1);
- }
+ _zip_progress_end(za->progress);
zip_discard(za);
static int
add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de)
{
- zip_int64_t offstart, offdata, offend;
+ zip_int64_t offstart, offdata, offend, data_length;
struct zip_stat st;
zip_source_t *src_final, *src_tmp;
int ret;
int is_zip64;
zip_flags_t flags;
+ zip_int8_t compression_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;
flags = ZIP_EF_LOCAL;
- if ((st.valid & ZIP_STAT_SIZE) == 0)
+ if ((st.valid & ZIP_STAT_SIZE) == 0) {
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) {
- if (( ((de->comp_method == ZIP_CM_DEFLATE || ZIP_CM_IS_DEFAULT(de->comp_method)) && st.size > MAX_DEFLATE_SIZE_32)
- || (de->comp_method != ZIP_CM_STORE && de->comp_method != ZIP_CM_DEFLATE && !ZIP_CM_IS_DEFAULT(de->comp_method))))
+ zip_uint64_t max_size;
+
+ switch (ZIP_CM_ACTUAL(de->comp_method)) {
+ case ZIP_CM_BZIP2:
+ /* computed by looking at increase of 10 random files of size 1MB when
+ * compressed with bzip2, rounded up: 1.006 */
+ max_size = 4269351188u;
+ break;
+
+ case ZIP_CM_DEFLATE:
+ /* max deflate size increase: size + ceil(size/16k)*5+6 */
+ max_size = 4293656963u;
+ break;
+
+ case ZIP_CM_STORE:
+ max_size = 0xffffffffu;
+ break;
+
+ default:
+ max_size = 0;
+ }
+
+ if (st.size > max_size) {
flags |= ZIP_FL_FORCE_ZIP64;
+ }
}
else
de->comp_size = st.comp_size;
}
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)
+ if ((is_zip64=_zip_dirent_write(za, de, flags)) < 0) {
return -1;
+ }
- needs_recompress = !((st.comp_method == de->comp_method) || (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method == ZIP_CM_DEFLATE));
+ needs_recompress = st.comp_method != ZIP_CM_ACTUAL(de->comp_method);
needs_decompress = needs_recompress && (st.comp_method != ZIP_CM_STORE);
needs_crc = (st.comp_method == ZIP_CM_STORE) || needs_decompress;
needs_compress = needs_recompress && (de->comp_method != ZIP_CM_STORE);
}
if (needs_decompress) {
- zip_compression_implementation comp_impl;
-
- if ((comp_impl = _zip_get_compression_implementation(st.comp_method, ZIP_CODEC_DECODE)) == NULL) {
- zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
- zip_source_free(src_final);
- return -1;
- }
- if ((src_tmp = comp_impl(za, src_final, st.comp_method, ZIP_CODEC_DECODE)) == NULL) {
- /* error set by comp_impl */
+ if ((src_tmp = zip_source_decompress(za, src_final, st.comp_method)) == NULL) {
zip_source_free(src_final);
return -1;
}
}
if (needs_compress) {
- zip_compression_implementation comp_impl;
-
- if ((comp_impl = _zip_get_compression_implementation(de->comp_method, ZIP_CODEC_ENCODE)) == NULL) {
- zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
- zip_source_free(src_final);
- return -1;
- }
- if ((src_tmp = comp_impl(za, src_final, de->comp_method, ZIP_CODEC_ENCODE)) == NULL) {
+ if ((src_tmp = zip_source_compress(za, src_final, de->comp_method, de->compression_level)) == NULL) {
zip_source_free(src_final);
return -1;
}
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);
+ 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 ((compression_flags = zip_source_get_compression_flags(src_final)) < 0) {
+ _zip_error_set_from_source(&za->error, src_final);
ret = -1;
}
}
if ((offend = zip_source_tell_write(za->src)) < 0) {
+ _zip_error_set_from_source(&za->error, za->src);
return -1;
}
de->crc = st.crc;
de->uncomp_size = st.size;
de->comp_size = (zip_uint64_t)(offend - offdata);
-
+ de->bitflags = (zip_uint16_t)((de->bitflags & (zip_uint16_t)~6) | ((zip_uint8_t)compression_flags << 1));
+ _zip_dirent_set_version_needed(de, (flags & ZIP_FL_FORCE_ZIP64) != 0);
+
if ((ret=_zip_dirent_write(za, de, flags)) < 0)
return -1;
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);
{
zip_uint8_t buf[BUFSIZE];
size_t n;
+ double total = (double)len;
while (len > 0) {
n = len > sizeof(buf) ? sizeof(buf) : len;
}
len -= n;
+
+ _zip_progress_update(za->progress, (total - (double)len) / total);
}
return 0;
static int
-copy_source(zip_t *za, zip_source_t *src)
+copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length)
{
zip_uint8_t buf[BUFSIZE];
- zip_int64_t n;
+ zip_int64_t n, current;
int ret;
if (zip_source_open(src) < 0) {
}
ret = 0;
+ current = 0;
while ((n=zip_source_read(src, buf, sizeof(buf))) > 0) {
if (_zip_write(za, buf, (zip_uint64_t)n) < 0) {
ret = -1;
break;
}
+ if (n == sizeof(buf) && za->progress && data_length > 0) {
+ current += n;
+ _zip_progress_update(za->progress, (double)current/(double)data_length);
+ }
}
if (n < 0) {
return ret;
}
-
static int
write_cdir(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors)
{
de->cloned = 0;
de->crc_valid = true;
- de->version_madeby = 20 | (ZIP_OPSYS_DEFAULT << 8);
- de->version_needed = 20; /* 2.0 */
+ de->version_madeby = 63 | (ZIP_OPSYS_DEFAULT << 8);
+ de->version_needed = 10; /* 1.0 */
de->bitflags = 0;
de->comp_method = ZIP_CM_DEFAULT;
de->last_mod = 0;
de->int_attrib = 0;
de->ext_attrib = ZIP_EXT_ATTRIB_DEFAULT;
de->offset = 0;
+ de->compression_level = 0;
de->encryption_method = ZIP_EM_NONE;
de->password = NULL;
}
}
if (!_zip_dirent_process_winzip_aes(zde, error)) {
- if (!from_buffer) {
- _zip_buffer_free(buffer);
- }
return -1;
}
}
if (de->encryption_method == ZIP_EM_NONE) {
- de->bitflags &= ~ZIP_GPBF_ENCRYPTED;
+ de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCRYPTED;
}
else {
- de->bitflags |= ZIP_GPBF_ENCRYPTED;
+ de->bitflags |= (zip_uint16_t)ZIP_GPBF_ENCRYPTED;
}
is_really_zip64 = _zip_dirent_needs_zip64(de, flags);
_zip_buffer_put_16(ef_buffer, 2);
_zip_buffer_put(ef_buffer, "AE", 2);
- _zip_buffer_put_8(ef_buffer, (de->encryption_method & 0xff));
+ _zip_buffer_put_8(ef_buffer, (zip_uint8_t)(de->encryption_method & 0xff));
_zip_buffer_put_16(ef_buffer, (zip_uint16_t)de->comp_method);
if (!_zip_buffer_ok(ef_buffer)) {
_zip_buffer_put_16(buffer, (zip_uint16_t)(is_really_zip64 ? 45 : de->version_madeby));
}
_zip_buffer_put_16(buffer, (zip_uint16_t)(is_really_zip64 ? 45 : de->version_needed));
- _zip_buffer_put_16(buffer, de->bitflags&0xfff9); /* clear compression method specific flags */
+ _zip_buffer_put_16(buffer, de->bitflags);
if (is_winzip_aes) {
_zip_buffer_put_16(buffer, ZIP_CM_WINZIP_AES);
}
return;
}
+
+
+void
+_zip_dirent_set_version_needed(zip_dirent_t *de, bool force_zip64) {
+ zip_uint16_t length;
+
+ if (de->comp_method == ZIP_CM_LZMA) {
+ de->version_needed = 63;
+ return;
+ }
+
+ if (de->comp_method == ZIP_CM_BZIP2) {
+ de->version_needed = 46;
+ return;
+ }
+
+ if (force_zip64 || _zip_dirent_needs_zip64(de, 0)) {
+ de->version_needed = 45;
+ return;
+ }
+
+ if (de->comp_method == ZIP_CM_DEFLATE || de->encryption_method == ZIP_EM_TRAD_PKWARE) {
+ de->version_needed = 20;
+ return;
+ }
+
+ /* directory */
+ if ((length = _zip_string_length(de->filename)) > 0) {
+ if (de->filename->raw[length-1] == '/') {
+ de->version_needed = 20;
+ return;
+ }
+ }
+
+ de->version_needed = 10;
+}
}
free(za->open_source);
+ _zip_progress_free(za->progress);
+
zip_error_fini(&za->error);
free(za);
"Operation not supported",
"Resource still in use",
"Tell error",
+ "Compressed data invalid",
};
const int _zip_nerr_str = sizeof(_zip_err_str)/sizeof(_zip_err_str[0]);
N,
N,
S,
+ N,
};
zip_source_t *src;
struct zip_error error;
- if (_flags < 0 || (_flags & ZIP_TRUNCATE)) {
+ if (_flags < 0 || (_flags & ~(ZIP_CHECKCONS|ZIP_RDONLY))) {
_zip_set_open_error(zep, NULL, ZIP_ER_INVAL);
return NULL;
}
#include <string.h>
#include "zipint.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_uint16_t table_size;
+ zip_uint32_t table_size;
+ zip_uint64_t nentries;
zip_hash_entry_t **table;
};
-zip_hash_t *
-_zip_hash_new(zip_uint16_t table_size, zip_error_t *error)
+
+/* free list of entries */
+static void
+free_list(zip_hash_entry_t *entry)
{
- zip_hash_t *hash;
+ 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;
+ }
- if (table_size == 0) {
- zip_error_set(error, ZIP_ER_INTERNAL, 0);
- return NULL;
+ while (*name != 0) {
+ value = (zip_uint64_t)(((value * HASH_MULTIPLIER) + (zip_uint8_t)*name) % 0x100000000ul);
+ name++;
}
- if ((hash=(zip_hash_t *)malloc(sizeof(zip_hash_t))) == NULL) {
- zip_error_set(error, ZIP_ER_MEMORY, 0);
- return NULL;
+ 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;
}
- hash->table_size = table_size;
- if ((hash->table=(zip_hash_entry_t**)calloc(table_size, sizeof(zip_hash_entry_t *))) == NULL) {
- free(hash);
+
+ 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 NULL;
+ return false;
}
- return hash;
+ 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 void
-_free_list(zip_hash_entry_t *entry)
+
+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_entry_t *next;
- do {
- next = entry->next;
- free(entry);
- entry = next;
- } while (entry != NULL);
+ 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_uint16_t i;
+ zip_uint32_t i;
if (hash == NULL) {
return;
}
- for (i=0; i<hash->table_size; i++) {
- if (hash->table[i] != NULL) {
- _free_list(hash->table[i]);
+ 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->table);
free(hash);
}
-static zip_uint16_t
-_hash_string(const zip_uint8_t *name, zip_uint16_t size)
-{
-#define HASH_MULTIPLIER 33
- zip_uint16_t value = 5381;
-
- if (name == NULL)
- return 0;
-
- while (*name != 0) {
- value = (zip_uint16_t)(((value * HASH_MULTIPLIER) + (zip_uint8_t)*name) % size);
- name++;
- }
-
- return value;
-}
/* 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_uint16_t hash_value;
+ zip_uint32_t hash_value, table_index;
zip_hash_entry_t *entry;
if (hash == NULL || name == NULL || index > ZIP_INT64_MAX) {
return false;
}
- hash_value = _hash_string(name, hash->table_size);
- for (entry = hash->table[hash_value]; entry != NULL; entry = entry->next) {
- if (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 (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;
+ 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;
+ }
}
- entry->name = name;
- entry->next = hash->table[hash_value];
- hash->table[hash_value] = entry;
- entry->orig_index = -1;
}
if (flags & ZIP_FL_UNCHANGED) {
- entry->orig_index = (zip_int64_t)index;
+ entry->orig_index = (zip_int64_t)index;
}
entry->current_index = (zip_int64_t)index;
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_uint16_t hash_value;
+ zip_uint32_t hash_value, index;
zip_hash_entry_t *entry, *previous;
if (hash == NULL || name == NULL) {
return false;
}
- hash_value = _hash_string(name, hash->table_size);
- previous = NULL;
- entry = hash->table[hash_value];
- while (entry) {
- if (strcmp((const char *)name, (const char *)entry->name) == 0) {
- if (entry->orig_index == -1) {
- if (previous) {
- previous->next = entry->next;
+ 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 {
- hash->table[hash_value] = entry->next;
+ entry->current_index = -1;
}
- free(entry);
- }
- else {
- entry->current_index = -1;
+ return true;
}
- return true;
+ previous = entry;
+ entry = entry->next;
}
- 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_uint16_t hash_value;
+ 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;
+ zip_error_set(error, ZIP_ER_INVAL, 0);
+ return -1;
}
- hash_value = _hash_string(name, hash->table_size);
- for (entry = hash->table[hash_value]; 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;
+ 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;
+ else {
+ if (entry->current_index != -1) {
+ return entry->current_index;
+ }
}
+ break;
}
- break;
}
}
zip_error_set(error, ZIP_ER_NOENT, 0);
- return -1;
+ return -1;
}
-void
-_zip_hash_revert(zip_hash_t *hash)
+
+bool
+_zip_hash_reserve_capacity(zip_hash_t *hash, zip_uint64_t capacity, zip_error_t *error)
{
- zip_uint16_t i;
+ 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);
- }
- else {
- entry->current_index = entry->orig_index;
- previous = entry;
- entry = entry->next;
- }
+ previous = NULL;
+ entry = hash->table[i];
+ while (entry) {
+ if (entry->orig_index == -1) {
+ zip_hash_entry_t *p;
+ if (previous) {
+ previous->next = entry->next;
+ }
+ else {
+ hash->table[i] = entry->next;
+ }
+ p = entry;
+ entry = entry->next;
+ /* previous does not change */
+ free(p);
+ hash->nentries--;
+ }
+ else {
+ entry->current_index = entry->orig_index;
+ previous = entry;
+ entry = entry->next;
+ }
+ }
+ }
+
+ if (hash->nentries < hash->table_size * HASH_MIN_FILL && hash->table_size > HASH_MIN_SIZE) {
+ zip_uint32_t new_size = hash->table_size / 2;
+ while (hash->nentries < new_size * HASH_MIN_FILL && new_size > HASH_MIN_SIZE) {
+ new_size /= 2;
+ }
+ if (!hash_resize(hash, new_size, error)) {
+ return false;
}
}
+
+ return true;
}
return NULL;
}
- if ((za->names = _zip_hash_new(ZIP_HASH_TABLE_SIZE, error)) == NULL) {
+ if ((za->names = _zip_hash_new(error)) == NULL) {
free(za);
return NULL;
}
za->entry = NULL;
za->nopen_source = za->nopen_source_alloc = 0;
za->open_source = NULL;
- za->progress_callback = NULL;
+ za->progress = NULL;
return za;
}
}
}
-ZIP_EXTERN void
-zip_register_progress_callback(zip_t *za, zip_progress_callback_t progress_callback)
-{
- za->progress_callback = progress_callback;
-}
-
zip_t *
_zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error)
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) {
if (offset < 0) {
_zip_error_set_from_source(error, za->src);
- _zip_buffer_free(cd_buffer);
_zip_cdir_free(cd);
return NULL;
}
}
if ((flags & ZIP_CHECKCONS) && (eocd_disk != eocd_disk64 || num_disks != num_disks64)) {
zip_error_set(error, ZIP_ER_INCONS, 0);
+ if (free_buffer) {
+ _zip_buffer_free(buffer);
+ }
return NULL;
}
if (num_disks != 0 || eocd_disk != 0) {
zip_error_set(error, ZIP_ER_MULTIDISK, 0);
+ if (free_buffer) {
+ _zip_buffer_free(buffer);
+ }
return NULL;
}
zip_error_set(error, ZIP_ER_SEEK, EFBIG);
return NULL;
}
- if ((flags & ZIP_CHECKCONS) && offset+size != eocd_offset) {
+ if (offset+size > buf_offset + eocd_offset) {
+ /* cdir spans past EOCD record */
+ zip_error_set(error, ZIP_ER_INCONS, 0);
+ return NULL;
+ }
+ if ((flags & ZIP_CHECKCONS) && offset+size != buf_offset + eocd_offset) {
zip_error_set(error, ZIP_ER_INCONS, 0);
return NULL;
}
--- /dev/null
+/*
+ zip_progress.c -- progress reporting
+ Copyright (C) 2017 Dieter Baron and Thomas Klausner
+
+ This file is part of libzip, a library to manipulate ZIP archives.
+ The authors can be contacted at <libzip@nih.at>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <stdlib.h>
+
+
+#define _ZIP_COMPILING_DEPRECATED
+#include "zipint.h"
+
+struct zip_progress {
+ zip_t *za;
+ zip_progress_callback callback;
+ void (*ud_free)(void *);
+
+ void *ud;
+
+ 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 */
+};
+
+
+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;
+ }
+
+ if (progress->ud_free) {
+ progress->ud_free(progress->ud);
+ }
+
+ free(progress);
+}
+
+
+zip_progress_t *
+_zip_progress_new(zip_t *za, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud) {
+ 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 = callback;
+ progress->ud_free = ud_free;
+ progress->ud = ud;
+ progress->precision = precision;
+
+ return progress;
+}
+
+
+void
+_zip_progress_start(zip_progress_t *progress) {
+ if (progress == NULL) {
+ return;
+ }
+
+ progress->last_update = 0.0;
+ progress->callback(progress->za, 0.0, progress->ud);
+}
+
+
+void
+_zip_progress_subrange(zip_progress_t *progress, double start, double end) {
+ if (progress == NULL) {
+ return;
+ }
+
+ progress->start = start;
+ progress->end = end;
+
+ _zip_progress_update(progress, 0.0);
+}
+
+void
+_zip_progress_update(zip_progress_t *progress, double sub_current) {
+ double current;
+
+ if (progress == NULL) {
+ return;
+ }
+
+ 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->za, current, progress->ud);
+ progress->last_update = current;
+ }
+}
+
+
+ZIP_EXTERN int
+zip_register_progress_callback_with_state(zip_t *za, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud) {
+ zip_progress_t *progress = NULL;
+
+ if (callback != NULL) {
+ if ((progress = _zip_progress_new(za, precision, callback, ud_free, ud)) == NULL) {
+ return -1;
+ }
+ }
+
+ _zip_progress_free(za->progress);
+ za->progress = 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);
+ }
+}
#include "zipint.h"
#include <fcntl.h>
+#include <unistd.h>
bool
zip_random(zip_uint8_t *buffer, zip_uint16_t length)
zip_entry_t *e;
zip_int32_t old_method;
- if (idx >= za->nentry) {
+ if (idx >= za->nentry || flags > 9) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
return -1;
}
- if (method != ZIP_CM_DEFAULT && method != ZIP_CM_STORE && method != ZIP_CM_DEFLATE) {
+ if (!zip_compression_method_supported(method, true)) {
zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
return -1;
}
old_method = (e->orig == NULL ? ZIP_CM_DEFAULT : e->orig->comp_method);
- /* TODO: revisit this when flags are supported, since they may require a recompression */
+ /* 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;
}
e->changes->comp_method = method;
+ e->changes->compression_level = (zip_uint16_t)flags;
e->changes->changed |= ZIP_DIRENT_COMP_METHOD;
}
--- /dev/null
+/*
+ zip_source_compress.c -- (de)compression routines
+ Copyright (C) 2017 Dieter Baron and Thomas Klausner
+
+ This file is part of libzip, a library to manipulate ZIP archives.
+ The authors can be contacted at <libzip@nih.at>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include "zipint.h"
+
+struct context {
+ zip_error_t error;
+
+ bool end_of_input;
+ bool end_of_stream;
+ bool can_store;
+ bool is_stored;
+ bool compress;
+ zip_int32_t method;
+
+ zip_uint64_t size;
+ zip_int64_t first_read;
+ zip_uint8_t buffer[BUFSIZE];
+
+ zip_compression_algorithm_t *algorithm;
+ void *ud;
+};
+
+
+struct implementation {
+ zip_uint16_t method;
+ zip_compression_algorithm_t *compress;
+ zip_compression_algorithm_t *decompress;
+};
+
+static struct implementation implementations[] = {
+ { ZIP_CM_DEFLATE, &zip_algorithm_deflate_compress, &zip_algorithm_deflate_decompress },
+#if defined(HAVE_LIBBZ2)
+ { ZIP_CM_BZIP2, &zip_algorithm_bzip2_compress, &zip_algorithm_bzip2_decompress },
+#endif
+};
+
+static size_t implementations_size = sizeof(implementations) / sizeof(implementations[0]);
+
+static zip_source_t *compression_source_new(zip_t *za, zip_source_t *src, zip_int32_t method, bool compress, int compression_flags);
+static zip_int64_t compress_callback(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t);
+static void context_free(struct context *ctx);
+static struct context *context_new(zip_int32_t method, bool compress, int compression_flags, zip_compression_algorithm_t *algorithm);
+static zip_int64_t compress_read(zip_source_t *, struct context *, void *, zip_uint64_t);
+
+static zip_compression_algorithm_t *
+get_algorithm(zip_int32_t method, bool compress) {
+ size_t i;
+ zip_uint16_t real_method = ZIP_CM_ACTUAL(method);
+
+ for (i = 0; i < implementations_size; i++) {
+ if (implementations[i].method == real_method) {
+ if (compress) {
+ return implementations[i].compress;
+ }
+ else {
+ return implementations[i].decompress;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+bool
+zip_compression_method_supported(zip_int32_t method, bool compress) {
+ if (method == ZIP_CM_STORE) {
+ return true;
+ }
+ return get_algorithm(method, compress) != NULL;
+}
+
+zip_source_t *
+zip_source_compress(zip_t *za, zip_source_t *src, zip_int32_t method, int compression_flags) {
+ return compression_source_new(za, src, method, true, compression_flags);
+}
+
+zip_source_t *
+zip_source_decompress(zip_t *za, zip_source_t *src, zip_int32_t method) {
+ return compression_source_new(za, src, method, false, 0);
+}
+
+
+static zip_source_t *
+compression_source_new(zip_t *za, zip_source_t *src, zip_int32_t method, bool compress, int compression_flags)
+{
+ struct context *ctx;
+ zip_source_t *s2;
+ zip_compression_algorithm_t *algorithm = NULL;
+
+ if (src == NULL) {
+ zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+ return NULL;
+ }
+
+ if ((algorithm = get_algorithm(method, compress)) == NULL) {
+ zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
+ return NULL;
+ }
+
+ if ((ctx = context_new(method, compress, compression_flags, algorithm)) == NULL) {
+ zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+ return NULL;
+ }
+
+ if ((s2 = zip_source_layered(za, src, compress_callback, ctx)) == NULL) {
+ context_free(ctx);
+ return NULL;
+ }
+
+ return s2;
+}
+
+
+static struct context *
+context_new(zip_int32_t method, bool compress, int compression_flags, zip_compression_algorithm_t *algorithm) {
+ struct context *ctx;
+
+ if ((ctx = (struct context *)malloc(sizeof(*ctx))) == NULL) {
+ return NULL;
+ }
+ zip_error_init(&ctx->error);
+ ctx->can_store = compress ? ZIP_CM_IS_DEFAULT(method) : false;
+ ctx->algorithm = algorithm;
+ ctx->method = method;
+ ctx->compress = compress;
+
+ if ((ctx->ud = ctx->algorithm->allocate(ZIP_CM_ACTUAL(method), compression_flags, &ctx->error)) == NULL) {
+ zip_error_fini(&ctx->error);
+ free(ctx);
+ return NULL;
+ }
+
+ return ctx;
+}
+
+
+static void
+context_free(struct context *ctx) {
+ if (ctx == NULL) {
+ return;
+ }
+
+ ctx->algorithm->deallocate(ctx->ud);
+ zip_error_fini(&ctx->error);
+
+ free(ctx);
+}
+
+
+static zip_int64_t
+compress_read(zip_source_t *src, struct context *ctx, void *data, zip_uint64_t len)
+{
+ zip_compression_status_t ret;
+ bool end;
+ zip_int64_t n;
+ zip_uint64_t out_offset;
+ zip_uint64_t out_len;
+
+ if (zip_error_code_zip(&ctx->error) != ZIP_ER_OK) {
+ return -1;
+ }
+
+ if (len == 0 || ctx->end_of_stream) {
+ return 0;
+ }
+
+ out_offset = 0;
+
+ end = false;
+ while (!end && out_offset < len) {
+ out_len = len - out_offset;
+ ret = ctx->algorithm->process(ctx->ud, (zip_uint8_t *)data + out_offset, &out_len);
+
+ if (ret != ZIP_COMPRESSION_ERROR) {
+ out_offset += out_len;
+ }
+
+ switch (ret) {
+ case ZIP_COMPRESSION_END:
+ ctx->end_of_stream = true;
+
+ if (!ctx->end_of_input) {
+ /* TODO: garbage after stream, or compression ended before all data read */
+ }
+
+ if (ctx->first_read < 0) {
+ /* we got end of processed stream before reading any input data */
+ zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
+ end = true;
+ break;
+ }
+ if (ctx->can_store && (zip_uint64_t)ctx->first_read <= out_offset) {
+ ctx->is_stored = true;
+ ctx->size = (zip_uint64_t)ctx->first_read;
+ memcpy(data, ctx->buffer, ctx->size);
+ return (zip_int64_t)ctx->size;
+ }
+ end = true;
+ break;
+
+ case ZIP_COMPRESSION_OK:
+ break;
+
+ case ZIP_COMPRESSION_NEED_DATA:
+ if (ctx->end_of_input) {
+ /* TODO: error: stream not ended, but no more input */
+ end = true;
+ break;
+ }
+
+ if ((n = zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
+ _zip_error_set_from_source(&ctx->error, src);
+ end = true;
+ break;
+ }
+ else if (n == 0) {
+ ctx->end_of_input = true;
+ ctx->algorithm->end_of_input(ctx->ud);
+ if (ctx->first_read < 0) {
+ ctx->first_read = 0;
+ }
+ }
+ else {
+ if (ctx->first_read >= 0) {
+ /* we overwrote a previously filled ctx->buffer */
+ ctx->can_store = false;
+ }
+ else {
+ ctx->first_read = n;
+ }
+
+ ctx->algorithm->input(ctx->ud, ctx->buffer, (zip_uint64_t)n);
+ }
+ break;
+
+ case ZIP_COMPRESSION_ERROR:
+ /* error set by algorithm */
+ if (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) {
+ zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
+ }
+ end = true;
+ break;
+ }
+ }
+
+ if (out_offset > 0) {
+ ctx->can_store = false;
+ ctx->size += out_offset;
+ return (zip_int64_t)out_offset;
+ }
+
+ return (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) ? 0 : -1;
+}
+
+
+static zip_int64_t
+compress_callback(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
+{
+ struct context *ctx;
+
+ ctx = (struct context *)ud;
+
+ switch (cmd) {
+ case ZIP_SOURCE_OPEN:
+ ctx->size = 0;
+ ctx->end_of_input = false;
+ ctx->end_of_stream = false;
+ ctx->is_stored = false;
+ ctx->first_read = -1;
+
+ if (!ctx->algorithm->start(ctx->ud)) {
+ return -1;
+ }
+
+ return 0;
+
+ case ZIP_SOURCE_READ:
+ return compress_read(src, ctx, data, len);
+
+ case ZIP_SOURCE_CLOSE:
+ if (!ctx->algorithm->end(ctx->ud)) {
+ return -1;
+ }
+ return 0;
+
+ case ZIP_SOURCE_STAT:
+ {
+ zip_stat_t *st;
+
+ st = (zip_stat_t *)data;
+
+ if (ctx->compress) {
+ st->comp_method = ctx->is_stored ? ZIP_CM_STORE : ZIP_CM_ACTUAL(ctx->method);
+ if (ctx->end_of_stream) {
+ st->comp_size = ctx->size;
+ st->valid |= ZIP_STAT_COMP_SIZE;
+ }
+ else {
+ st->valid &= ~ZIP_STAT_COMP_SIZE;
+ }
+ }
+ else {
+ st->comp_method = ZIP_CM_STORE;
+ if (ctx->end_of_stream) {
+ st->size = ctx->size;
+ st->valid |= ZIP_STAT_SIZE;
+ }
+ else {
+ st->valid &= ~ZIP_STAT_SIZE;
+ }
+ }
+ st->valid |= ZIP_STAT_COMP_METHOD;
+ }
+ return 0;
+
+ case ZIP_SOURCE_GET_COMPRESSION_FLAGS:
+ return ctx->is_stored ? 0 : ctx->algorithm->compression_flags(ctx->ud);
+
+ case ZIP_SOURCE_ERROR:
+ return zip_error_to_data(&ctx->error, data, len);
+
+ case ZIP_SOURCE_FREE:
+ context_free(ctx);
+ return 0;
+
+ case ZIP_SOURCE_SUPPORTS:
+ return ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_GET_COMPRESSION_FLAGS, -1);
+
+ default:
+ zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
+ return -1;
+ }
+}
return -1;
}
- return mask & ~zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, -1);
+ return mask & ~zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, ZIP_SOURCE_GET_COMPRESSION_FLAGS, -1);
}
case ZIP_SOURCE_SEEK:
+++ /dev/null
-/*
- zip_source_deflate.c -- deflate (de)compressoin routines
- Copyright (C) 2009-2015 Dieter Baron and Thomas Klausner
-
- This file is part of libzip, a library to manipulate ZIP archives.
- The authors can be contacted at <libzip@nih.at>
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
- 3. The names of the authors may not be used to endorse or promote
- products derived from this software without specific prior
- written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
- OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-
-#include "zipint.h"
-
-struct deflate {
- zip_error_t error;
-
- bool eof;
- bool can_store;
- bool is_stored;
- int mem_level;
- zip_uint64_t size;
- zip_uint8_t buffer[BUFSIZE];
- z_stream zstr;
-};
-
-static zip_int64_t compress_read(zip_source_t *, struct deflate *, void *, zip_uint64_t);
-static zip_int64_t decompress_read(zip_source_t *, struct deflate *, void *, zip_uint64_t);
-static zip_int64_t deflate_compress(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t);
-static zip_int64_t deflate_decompress(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t);
-static void deflate_free(struct deflate *);
-
-
-zip_source_t *
-zip_source_deflate(zip_t *za, zip_source_t *src, zip_int32_t cm, int flags)
-{
- struct deflate *ctx;
- zip_source_t *s2;
-
- if (src == NULL || (cm != ZIP_CM_DEFLATE && !ZIP_CM_IS_DEFAULT(cm))) {
- zip_error_set(&za->error, ZIP_ER_INVAL, 0);
- return NULL;
- }
-
- if ((ctx=(struct deflate *)malloc(sizeof(*ctx))) == NULL) {
- zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
- return NULL;
- }
-
- zip_error_init(&ctx->error);
- ctx->eof = false;
- ctx->is_stored = false;
- ctx->can_store = ZIP_CM_IS_DEFAULT(cm);
- if (flags & ZIP_CODEC_ENCODE) {
- ctx->mem_level = MAX_MEM_LEVEL;
- }
-
- if ((s2=zip_source_layered(za, src,
- ((flags & ZIP_CODEC_ENCODE)
- ? deflate_compress : deflate_decompress),
- ctx)) == NULL) {
- deflate_free(ctx);
- return NULL;
- }
-
- return s2;
-}
-
-
-static zip_int64_t
-compress_read(zip_source_t *src, struct deflate *ctx, void *data, zip_uint64_t len)
-{
- int end, ret;
- zip_int64_t n;
- zip_uint64_t out_offset;
- uInt out_len;
-
- if (zip_error_code_zip(&ctx->error) != ZIP_ER_OK)
- return -1;
-
- if (len == 0 || ctx->is_stored) {
- return 0;
- }
-
- out_offset = 0;
- out_len = (uInt)ZIP_MIN(UINT_MAX, len);
- ctx->zstr.next_out = (Bytef *)data;
- ctx->zstr.avail_out = out_len;
-
- end = 0;
- while (!end) {
- ret = deflate(&ctx->zstr, ctx->eof ? Z_FINISH : 0);
-
- switch (ret) {
- case Z_STREAM_END:
- if (ctx->can_store && ctx->zstr.total_in <= ctx->zstr.total_out) {
- ctx->is_stored = true;
- ctx->size = ctx->zstr.total_in;
- memcpy(data, ctx->buffer, ctx->size);
- return (zip_int64_t)ctx->size;
- }
- /* fallthrough */
- case Z_OK:
- /* all ok */
-
- if (ctx->zstr.avail_out == 0) {
- out_offset += out_len;
- if (out_offset < len) {
- out_len = (uInt)ZIP_MIN(UINT_MAX, len-out_offset);
- ctx->zstr.next_out = (Bytef *)data+out_offset;
- ctx->zstr.avail_out = out_len;
- }
- else {
- ctx->can_store = false;
- end = 1;
- }
- }
- else if (ctx->eof && ctx->zstr.avail_in == 0)
- end = 1;
- break;
-
- case Z_BUF_ERROR:
- if (ctx->zstr.avail_in == 0) {
- if (ctx->eof) {
- end = 1;
- break;
- }
-
- if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
- _zip_error_set_from_source(&ctx->error, src);
- end = 1;
- break;
- }
- else if (n == 0) {
- ctx->eof = true;
- /* TODO: check against stat of src? */
- ctx->size = ctx->zstr.total_in;
- }
- else {
- if (ctx->zstr.total_in > 0) {
- /* we overwrote a previously filled ctx->buffer */
- ctx->can_store = false;
- }
- ctx->zstr.next_in = (Bytef *)ctx->buffer;
- ctx->zstr.avail_in = (uInt)n;
- }
- continue;
- }
- /* fallthrough */
- case Z_NEED_DICT:
- case Z_DATA_ERROR:
- case Z_STREAM_ERROR:
- case Z_MEM_ERROR:
- zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret);
-
- end = 1;
- break;
- }
- }
-
- if (ctx->zstr.avail_out < len) {
- ctx->can_store = false;
- return (zip_int64_t)(len - ctx->zstr.avail_out);
- }
-
- return (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) ? 0 : -1;
-}
-
-
-static zip_int64_t
-decompress_read(zip_source_t *src, struct deflate *ctx, void *data, zip_uint64_t len)
-{
- int end, ret;
- zip_int64_t n;
- zip_uint64_t out_offset;
- uInt out_len;
-
- if (zip_error_code_zip(&ctx->error) != ZIP_ER_OK)
- return -1;
-
- if (len == 0)
- return 0;
-
- out_offset = 0;
- out_len = (uInt)ZIP_MIN(UINT_MAX, len);
- ctx->zstr.next_out = (Bytef *)data;
- ctx->zstr.avail_out = out_len;
-
- end = 0;
- while (!end) {
- ret = inflate(&ctx->zstr, Z_SYNC_FLUSH);
-
- switch (ret) {
- case Z_OK:
- if (ctx->zstr.avail_out == 0) {
- out_offset += out_len;
- if (out_offset < len) {
- out_len = (uInt)ZIP_MIN(UINT_MAX, len-out_offset);
- ctx->zstr.next_out = (Bytef *)data+out_offset;
- ctx->zstr.avail_out = out_len;
- }
- else {
- end = 1;
- }
- }
- break;
-
- case Z_STREAM_END:
- ctx->eof = 1;
- end = 1;
- break;
-
- case Z_BUF_ERROR:
- if (ctx->zstr.avail_in == 0) {
- if (ctx->eof) {
- end = 1;
- break;
- }
-
- if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
- _zip_error_set_from_source(&ctx->error, src);
- end = 1;
- break;
- }
- else if (n == 0) {
- ctx->eof = 1;
- }
- else {
- ctx->zstr.next_in = (Bytef *)ctx->buffer;
- ctx->zstr.avail_in = (uInt)n;
- }
- continue;
- }
- /* fallthrough */
- case Z_NEED_DICT:
- case Z_DATA_ERROR:
- case Z_STREAM_ERROR:
- case Z_MEM_ERROR:
- zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret);
- end = 1;
- break;
- }
- }
-
- if (ctx->zstr.avail_out < len)
- return (zip_int64_t)(len - ctx->zstr.avail_out);
-
- return (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) ? 0 : -1;
-}
-
-
-static zip_int64_t
-deflate_compress(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
-{
- struct deflate *ctx;
- int ret;
-
- ctx = (struct deflate *)ud;
-
- switch (cmd) {
- case ZIP_SOURCE_OPEN:
- ctx->zstr.zalloc = Z_NULL;
- ctx->zstr.zfree = Z_NULL;
- ctx->zstr.opaque = NULL;
- ctx->zstr.avail_in = 0;
- ctx->zstr.next_in = NULL;
- ctx->zstr.avail_out = 0;
- ctx->zstr.next_out = NULL;
-
- /* negative value to tell zlib not to write a header */
- if ((ret=deflateInit2(&ctx->zstr, Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS, ctx->mem_level, Z_DEFAULT_STRATEGY)) != Z_OK) {
- zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret);
- return -1;
- }
-
- return 0;
-
- case ZIP_SOURCE_READ:
- return compress_read(src, ctx, data, len);
-
- case ZIP_SOURCE_CLOSE:
- deflateEnd(&ctx->zstr);
- return 0;
-
- case ZIP_SOURCE_STAT:
- {
- zip_stat_t *st;
-
- st = (zip_stat_t *)data;
-
- st->comp_method = ctx->is_stored ? ZIP_CM_STORE : ZIP_CM_DEFLATE;
- st->valid |= ZIP_STAT_COMP_METHOD;
- if (ctx->eof) {
- st->comp_size = ctx->size;
- st->valid |= ZIP_STAT_COMP_SIZE;
- }
- else
- st->valid &= ~ZIP_STAT_COMP_SIZE;
- }
- return 0;
-
- case ZIP_SOURCE_ERROR:
- return zip_error_to_data(&ctx->error, data, len);
-
- case ZIP_SOURCE_FREE:
- deflate_free(ctx);
- return 0;
-
- case ZIP_SOURCE_SUPPORTS:
- return ZIP_SOURCE_SUPPORTS_READABLE;
-
- default:
- zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
- return -1;
- }
-}
-
-
-static zip_int64_t
-deflate_decompress(zip_source_t *src, void *ud, void *data,
- zip_uint64_t len, zip_source_cmd_t cmd)
-{
- struct deflate *ctx;
- zip_int64_t n;
- int ret;
-
- ctx = (struct deflate *)ud;
-
- switch (cmd) {
- case ZIP_SOURCE_OPEN:
- if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
- _zip_error_set_from_source(&ctx->error, src);
- return -1;
- }
-
- ctx->zstr.zalloc = Z_NULL;
- ctx->zstr.zfree = Z_NULL;
- ctx->zstr.opaque = NULL;
- ctx->zstr.next_in = (Bytef *)ctx->buffer;
- ctx->zstr.avail_in = (uInt)n;
-
- /* negative value to tell zlib that there is no header */
- if ((ret=inflateInit2(&ctx->zstr, -MAX_WBITS)) != Z_OK) {
- zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret);
- return -1;
- }
- return 0;
-
- case ZIP_SOURCE_READ:
- return decompress_read(src, ctx, data, len);
-
- case ZIP_SOURCE_CLOSE:
- inflateEnd(&ctx->zstr);
- return 0;
-
- case ZIP_SOURCE_STAT:
- {
- zip_stat_t *st;
-
- st = (zip_stat_t *)data;
-
- st->comp_method = ZIP_CM_STORE;
- if (st->comp_size > 0 && st->size > 0)
- st->comp_size = st->size;
-
- return 0;
- }
-
- case ZIP_SOURCE_ERROR:
- return zip_error_to_data(&ctx->error, data, len);
-
- case ZIP_SOURCE_FREE:
- free(ctx);
- return 0;
-
- case ZIP_SOURCE_SUPPORTS:
- return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1);
-
- default:
- zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
- return -1;
- }
-}
-
-
-static void
-deflate_free(struct deflate *ctx)
-{
- free(ctx);
-}
{
struct read_file *ctx;
zip_source_t *zs;
+ struct stat sb;
+ bool stat_valid;
if (file == NULL && fname == NULL) {
zip_error_set(error, ZIP_ER_INVAL, 0);
ctx->supports = ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1);
if (ctx->fname) {
- struct stat sb;
- if (stat(ctx->fname, &sb) < 0) {
- zip_error_set(&ctx->stat_error, ZIP_ER_READ, errno);
+ stat_valid = stat(ctx->fname, &sb) >= 0;
+
+ if (!stat_valid) {
if (ctx->start == 0 && ctx->end == 0) {
ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE;
}
}
- else {
- if ((ctx->st.valid & ZIP_STAT_MTIME) == 0) {
- ctx->st.mtime = sb.st_mtime;
- ctx->st.valid |= ZIP_STAT_MTIME;
- }
- if (S_ISREG(sb.st_mode)) {
- ctx->supports = ZIP_SOURCE_SUPPORTS_SEEKABLE;
-
- if (ctx->start + ctx->end > (zip_uint64_t)sb.st_size) {
- zip_error_set(error, ZIP_ER_INVAL, 0);
- free(ctx->fname);
- free(ctx);
- return NULL;
- }
+ }
+ else {
+ stat_valid = fstat(fileno(ctx->f), &sb) >= 0;
+ }
- if (ctx->end == 0) {
- ctx->st.size = (zip_uint64_t)sb.st_size - ctx->start;
- ctx->st.valid |= ZIP_STAT_SIZE;
+ if (!stat_valid) {
+ zip_error_set(&ctx->stat_error, ZIP_ER_READ, errno);
+ }
+ else {
+ if ((ctx->st.valid & ZIP_STAT_MTIME) == 0) {
+ ctx->st.mtime = sb.st_mtime;
+ ctx->st.valid |= ZIP_STAT_MTIME;
+ }
+ if (S_ISREG(sb.st_mode)) {
+ ctx->supports = ZIP_SOURCE_SUPPORTS_SEEKABLE;
+
+ if (ctx->start + ctx->end > (zip_uint64_t)sb.st_size) {
+ zip_error_set(error, ZIP_ER_INVAL, 0);
+ free(ctx->fname);
+ free(ctx);
+ return NULL;
+ }
- if (start == 0) {
- ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE;
- }
+ if (ctx->end == 0) {
+ ctx->st.size = (zip_uint64_t)sb.st_size - ctx->start;
+ ctx->st.valid |= ZIP_STAT_SIZE;
+
+ if (ctx->fname && start == 0) {
+ ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE;
}
}
}
}
- else if (fseeko(ctx->f, 0, SEEK_CUR) == 0) {
- ctx->supports = ZIP_SOURCE_SUPPORTS_SEEKABLE;
- }
if ((zs=zip_source_function_create(read_file, ctx, error)) == NULL) {
free(ctx->fname);
/*
- zip_get_compression_implementation.c -- get compression implementation
- Copyright (C) 2009-2016 Dieter Baron and Thomas Klausner
+ zip_source_get_compression_flags.c -- get compression flags for entry
+ Copyright (C) 2017 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
#include "zipint.h"
+#define ZIP_COMPRESSION_BITFLAG_MAX 3
-zip_compression_implementation
-_zip_get_compression_implementation(zip_int32_t cm, int operation)
+zip_int8_t
+zip_source_get_compression_flags(zip_source_t *src)
{
- if (cm == ZIP_CM_DEFLATE || ZIP_CM_IS_DEFAULT(cm))
- return zip_source_deflate;
- return NULL;
+ while (src) {
+ if ((src->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_GET_COMPRESSION_FLAGS))) {
+ zip_int64_t ret = _zip_source_call(src, NULL, 0, ZIP_SOURCE_GET_COMPRESSION_FLAGS);
+ if (ret < 0) {
+ return -1;
+ }
+ if (ret > ZIP_COMPRESSION_BITFLAG_MAX) {
+ zip_error_set(&src->error, ZIP_ER_INTERNAL, 0);
+ return -1;
+ }
+ return (zip_int8_t)ret;
+ }
+ src = src->src;
+ }
+
+ return 0;
}
static HANDLE
_win32_create_temp_a(_zip_source_win32_read_file_t *ctx, void **temp, zip_uint32_t value, PSECURITY_ATTRIBUTES sa)
{
- int len;
+ size_t len;
len = strlen((const char *)ctx->fname) + 10;
if (*temp == NULL) {
static HANDLE
_win32_create_temp_w(_zip_source_win32_read_file_t *ctx, void **temp, zip_uint32_t value, PSECURITY_ATTRIBUTES sa)
{
- int len;
+ size_t len;
len = wcslen((const wchar_t *)ctx->fname) + 10;
if (*temp == NULL) {
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
#include "zipint.h"
struct window {
- zip_uint64_t start;
- zip_uint64_t end;
- zip_uint64_t offset;
+ zip_uint64_t start; /* where in file we start reading */
+ zip_uint64_t end; /* where in file we stop reading */
+
+ /* if not NULL, read file data for this file */
+ zip_t *source_archive;
+ zip_uint64_t source_index;
+
+ zip_uint64_t offset; /* offset in src for next read */
+
zip_stat_t stat;
+ zip_int8_t compression_flags;
zip_error_t error;
zip_int64_t supports;
bool needs_seek;
zip_source_t *
zip_source_window(zip_t *za, zip_source_t *src, zip_uint64_t start, zip_uint64_t len)
{
- return _zip_source_window_new(src, start, len, NULL, &za->error);
+ return _zip_source_window_new(src, start, len, NULL, 0, NULL, 0, &za->error);
}
zip_source_t *
-_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_error_t *error)
+_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_int8_t compression_flags, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error)
{
struct window *ctx;
-
- if (src == NULL || start + length < start) {
+
+ if (src == NULL || start + length < start || (source_archive == NULL && source_index != 0)) {
zip_error_set(error, ZIP_ER_INVAL, 0);
return NULL;
}
-
+
if ((ctx=(struct window *)malloc(sizeof(*ctx))) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
-
+
ctx->start = start;
ctx->end = start + length;
zip_stat_init(&ctx->stat);
+ ctx->compression_flags = compression_flags;
+ ctx->source_archive = source_archive;
+ ctx->source_index = source_index;
zip_error_init(&ctx->error);
- ctx->supports = (zip_source_supports(src) & ZIP_SOURCE_SUPPORTS_SEEKABLE) | (zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1));
+ ctx->supports = (zip_source_supports(src) & ZIP_SOURCE_SUPPORTS_SEEKABLE) | (zip_source_make_command_bitmap(ZIP_SOURCE_GET_COMPRESSION_FLAGS, ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1));
ctx->needs_seek = (ctx->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK)) ? true : false;
-
+
if (st) {
if (_zip_stat_merge(&ctx->stat, st, error) < 0) {
free(ctx);
return NULL;
}
}
-
+
return zip_source_layered_create(src, window_read, ctx, error);
}
switch (cmd) {
case ZIP_SOURCE_CLOSE:
return 0;
-
+
case ZIP_SOURCE_ERROR:
return zip_error_to_data(&ctx->error, data, len);
-
+
case ZIP_SOURCE_FREE:
free(ctx);
return 0;
case ZIP_SOURCE_OPEN:
+ if (ctx->source_archive) {
+ zip_int64_t offset;
+
+ if ((offset = _zip_file_get_offset(ctx->source_archive, ctx->source_index, &ctx->error)) == 0) {
+ return -1;
+ }
+ if (ctx->end + offset < ctx->end) {
+ /* zip archive data claims end of data past zip64 limits */
+ zip_error_set(&ctx->error, ZIP_ER_INCONS, 0);
+ return -1;
+ }
+ ctx->start += offset;
+ ctx->end += offset;
+ ctx->source_archive = NULL;
+ }
+
if (!ctx->needs_seek) {
for (n=0; n<ctx->start; n+=(zip_uint64_t)ret) {
i = (ctx->start-n > sizeof(b) ? sizeof(b) : ctx->start-n);
return -1;
}
}
-
+
}
ctx->offset = ctx->start;
return 0;
case ZIP_SOURCE_READ:
if (len > ctx->end - ctx->offset)
len = ctx->end - ctx->offset;
-
+
if (len == 0)
return 0;
-
+
if (ctx->needs_seek) {
if (zip_source_seek(src, (zip_int64_t)ctx->offset, SEEK_SET) < 0) {
_zip_error_set_from_source(&ctx->error, src);
return -1;
}
}
-
+
if ((ret=zip_source_read(src, data, len)) < 0) {
zip_error_set(&ctx->error, ZIP_ER_EOF, 0);
return -1;
}
}
return ret;
-
+
case ZIP_SOURCE_SEEK:
{
zip_int64_t new_offset = zip_source_seek_compute_offset(ctx->offset - ctx->start, ctx->end - ctx->start, data, len, &ctx->error);
if (new_offset < 0) {
return -1;
}
-
+
ctx->offset = (zip_uint64_t)new_offset + ctx->start;
return 0;
}
case ZIP_SOURCE_STAT:
{
zip_stat_t *st;
-
+
st = (zip_stat_t *)data;
-
+
if (_zip_stat_merge(st, &ctx->stat, &ctx->error) < 0) {
return -1;
}
return 0;
}
-
+
+ case ZIP_SOURCE_GET_COMPRESSION_FLAGS:
+ return ctx->compression_flags;
+
case ZIP_SOURCE_SUPPORTS:
return ctx->supports;
-
+
case ZIP_SOURCE_TELL:
return (zip_int64_t)(ctx->offset - ctx->start);
-
+
default:
zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
_zip_deregister_source(zip_t *za, zip_source_t *src)
{
unsigned int i;
-
+
for (i=0; i<za->nopen_source; i++) {
if (za->open_source[i] == src) {
za->open_source[i] = za->open_source[za->nopen_source-1];
_zip_register_source(zip_t *za, zip_source_t *src)
{
zip_source_t **open_source;
-
+
if (za->nopen_source+1 >= za->nopen_source_alloc) {
unsigned int n;
n = za->nopen_source_alloc + 10;
za->nopen_source_alloc = n;
za->open_source = open_source;
}
-
+
za->open_source[za->nopen_source++] = src;
-
+
return 0;
}
zip_source_t *
_zip_source_zip_new(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_uint64_t len, const char *password)
{
- zip_compression_implementation comp_impl;
- zip_encryption_implementation enc_impl;
zip_source_t *src, *s2;
- zip_uint64_t offset;
struct zip_stat st;
+ bool partial_data, needs_crc, needs_decrypt, needs_decompress;
if (za == NULL)
return NULL;
}
/* overflow or past end of file */
- if ((start > 0 || len > 0) && (start+len < start || start+len > st.size)) {
+ if ((start > 0 || len > 0) && (start + len < start || start + len > st.size)) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return NULL;
}
- enc_impl = NULL;
- if (((flags & ZIP_FL_ENCRYPTED) == 0) && (st.encryption_method != ZIP_EM_NONE)) {
+ if (len == 0) {
+ len = st.size - start;
+ }
+
+ partial_data = len < st.size;
+ needs_decrypt = ((flags & ZIP_FL_ENCRYPTED) == 0) && (st.encryption_method != ZIP_EM_NONE);
+ needs_decompress = ((flags & ZIP_FL_COMPRESSED) == 0) && (st.comp_method != ZIP_CM_STORE);
+ /* when reading the whole file, check for CRC errors */
+ needs_crc = ((flags & ZIP_FL_COMPRESSED) == 0 || st.comp_method == ZIP_CM_STORE) && !partial_data;
+
+ if (needs_decrypt) {
if (password == NULL) {
password = za->default_password;
}
zip_error_set(&za->error, ZIP_ER_NOPASSWD, 0);
return NULL;
}
- if ((enc_impl=_zip_get_encryption_implementation(st.encryption_method, ZIP_CODEC_DECODE)) == NULL) {
- zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
- return NULL;
- }
}
- comp_impl = NULL;
- if ((flags & ZIP_FL_COMPRESSED) == 0) {
- if (st.comp_method != ZIP_CM_STORE) {
- if ((comp_impl=_zip_get_compression_implementation(st.comp_method, ZIP_CODEC_DECODE)) == NULL) {
- zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
- return NULL;
- }
- }
- }
-
- if ((offset=_zip_file_get_offset(srcza, srcidx, &za->error)) == 0)
- return NULL;
-
if (st.comp_size == 0) {
return zip_source_buffer(za, NULL, 0, 0);
}
- if (start+len > 0 && enc_impl == NULL && comp_impl == NULL) {
+ if (partial_data && !needs_decrypt && !needs_decompress) {
struct zip_stat st2;
- st2.size = len ? len : st.size-start;
- st2.comp_size = st2.size;
+ st2.size = len;
+ st2.comp_size = len;
st2.comp_method = ZIP_CM_STORE;
st2.mtime = st.mtime;
st2.valid = ZIP_STAT_SIZE|ZIP_STAT_COMP_SIZE|ZIP_STAT_COMP_METHOD|ZIP_STAT_MTIME;
- if ((src = _zip_source_window_new(srcza->src, offset+start, st2.size, &st2, &za->error)) == NULL) {
+ if ((src = _zip_source_window_new(srcza->src, start, len, &st2, 0, srcza, srcidx, &za->error)) == NULL) {
return NULL;
}
}
else {
- if ((src = _zip_source_window_new(srcza->src, offset, st.comp_size, &st, &za->error)) == NULL) {
+ zip_dirent_t *de;
+
+ if ((de = _zip_get_dirent(srcza, srcidx, flags, &za->error)) == NULL) {
+ return NULL;
+ }
+ if ((src = _zip_source_window_new(srcza->src, 0, st.comp_size, &st, (de->bitflags >> 1) & 3, srcza, srcidx, &za->error)) == NULL) {
return NULL;
}
}
-
+
if (_zip_source_set_source_archive(src, srcza) < 0) {
zip_source_free(src);
return NULL;
/* creating a layered source calls zip_keep() on the lower layer, so we free it */
- if (enc_impl) {
+ if (needs_decrypt) {
+ zip_encryption_implementation enc_impl;
+
+ if ((enc_impl = _zip_get_encryption_implementation(st.encryption_method, ZIP_CODEC_DECODE)) == NULL) {
+ zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
+ return NULL;
+ }
+
s2 = enc_impl(za, src, st.encryption_method, 0, password);
zip_source_free(src);
if (s2 == NULL) {
}
src = s2;
}
- if (comp_impl) {
- s2 = comp_impl(za, src, st.comp_method, 0);
+ if (needs_decompress) {
+ s2 = zip_source_decompress(za, src, st.comp_method);
zip_source_free(src);
if (s2 == NULL) {
return NULL;
}
src = s2;
}
- if (((flags & ZIP_FL_COMPRESSED) == 0 || st.comp_method == ZIP_CM_STORE) && (len == 0 || len == st.comp_size)) {
- /* when reading the whole file, check for CRC errors */
+ if (needs_crc) {
s2 = zip_source_crc(za, src, 1);
zip_source_free(src);
if (s2 == NULL) {
src = s2;
}
- if (start+len > 0 && (comp_impl || enc_impl)) {
- s2 = zip_source_window(za, src, start, len ? len : st.size-start);
+ if (partial_data && (needs_decrypt || needs_decompress)) {
+ s2 = zip_source_window(za, src, start, len);
zip_source_free(src);
if (s2 == NULL) {
return NULL;
int ret;
zip_uint64_t i;
- _zip_hash_revert(za->names);
+ if (!_zip_hash_revert(za->names, &za->error)) {
+ return -1;
+ }
ret = 0;
for (i=0; i<za->nentry; i++)
#define ZIP_CM_WINZIP_AES 99 /* Winzip AES encrypted */
#define ZIP_CM_IS_DEFAULT(x) ((x) == ZIP_CM_DEFAULT || (x) == ZIP_CM_REPLACED_DEFAULT)
+#define ZIP_CM_ACTUAL(x) ((zip_uint16_t)(ZIP_CM_IS_DEFAULT(x) ? ZIP_CM_DEFLATE : (x)))
#define ZIP_EF_UTF_8_COMMENT 0x6375
#define ZIP_EF_UTF_8_NAME 0x7075
#define ZIP_CODEC_DECODE 0 /* decompress/decrypt (encode flag not set) */
#define ZIP_CODEC_ENCODE 1 /* compress/encrypt */
-
-typedef zip_source_t *(*zip_compression_implementation)(zip_t *, zip_source_t *, zip_int32_t, int);
typedef zip_source_t *(*zip_encryption_implementation)(zip_t *, zip_source_t *, zip_uint16_t, int, const char *);
-zip_compression_implementation _zip_get_compression_implementation(zip_int32_t method, int operation);
zip_encryption_implementation _zip_get_encryption_implementation(zip_uint16_t method, int operation);
+enum zip_compression_status {
+ ZIP_COMPRESSION_OK,
+ ZIP_COMPRESSION_END,
+ ZIP_COMPRESSION_ERROR,
+ ZIP_COMPRESSION_NEED_DATA
+};
+typedef enum zip_compression_status zip_compression_status_t;
+
+struct zip_compression_algorithm {
+ /* called once to create new context */
+ void *(*allocate)(zip_uint16_t method, int compression_flags, zip_error_t *error);
+ /* called once to free context */
+ void (*deallocate)(void *ctx);
+
+ /* get compression specific general purpose bitflags */
+ int (*compression_flags)(void *ctx);
+ /* start processing */
+ bool (*start)(void *ctx);
+ /* stop processing */
+ bool (*end)(void *ctx);
+
+ /* provide new input data, remains valid until next call to input or end */
+ bool (*input)(void *ctx, zip_uint8_t *data, zip_uint64_t length);
+
+ /* all input data has been provided */
+ void (*end_of_input)(void *ctx);
+
+ /* process input data, writing to data, which has room for length bytes, update length to number of bytes written */
+ zip_compression_status_t (*process)(void *ctx, zip_uint8_t *data, zip_uint64_t *length);
+};
+typedef struct zip_compression_algorithm zip_compression_algorithm_t;
+
+extern zip_compression_algorithm_t zip_algorithm_bzip2_compress;
+extern zip_compression_algorithm_t zip_algorithm_bzip2_decompress;
+extern zip_compression_algorithm_t zip_algorithm_deflate_compress;
+extern zip_compression_algorithm_t zip_algorithm_deflate_decompress;
+
+bool zip_compression_method_supported(zip_int32_t method, bool compress);
/* This API is not final yet, but we need it internally, so it's private for now. */
Thus we will keep it private for now. */
typedef zip_int64_t (*zip_source_layered_callback)(zip_source_t *, void *, void *, zip_uint64_t, enum zip_source_cmd);
+zip_source_t *zip_source_compress(zip_t *za, zip_source_t *src, zip_int32_t cm, int compression_flags);
zip_source_t *zip_source_crc(zip_t *, zip_source_t *, int);
-zip_source_t *zip_source_deflate(zip_t *, zip_source_t *, zip_int32_t, int);
+zip_source_t *zip_source_decompress(zip_t *za, zip_source_t *src, zip_int32_t cm);
zip_source_t *zip_source_layered(zip_t *, zip_source_t *, zip_source_layered_callback, void *);
zip_source_t *zip_source_layered_create(zip_source_t *src, zip_source_layered_callback cb, void *ud, zip_error_t *error);
zip_source_t *zip_source_pkware(zip_t *, zip_source_t *, zip_uint16_t, int, const char *);
/* directory entry: general purpose bit flags */
-#define ZIP_GPBF_ENCRYPTED 0x0001 /* is encrypted */
-#define ZIP_GPBF_DATA_DESCRIPTOR 0x0008 /* crc/size after file data */
-#define ZIP_GPBF_STRONG_ENCRYPTION 0x0040 /* uses strong encryption */
-#define ZIP_GPBF_ENCODING_UTF_8 0x0800 /* file name encoding is UTF-8 */
+#define ZIP_GPBF_ENCRYPTED 0x0001u /* is encrypted */
+#define ZIP_GPBF_DATA_DESCRIPTOR 0x0008u /* crc/size after file data */
+#define ZIP_GPBF_STRONG_ENCRYPTION 0x0040u /* uses strong encryption */
+#define ZIP_GPBF_ENCODING_UTF_8 0x0800u /* file name encoding is UTF-8 */
/* extra fields */
typedef enum zip_encoding_type zip_encoding_type_t;
-#ifndef ZIP_HASH_TABLE_SIZE
-#define ZIP_HASH_TABLE_SIZE 8192
-#endif
-
struct zip_hash;
+struct zip_progress;
typedef struct zip_cdir zip_cdir_t;
typedef struct zip_dirent zip_dirent_t;
typedef struct zip_string zip_string_t;
typedef struct zip_buffer zip_buffer_t;
typedef struct zip_hash zip_hash_t;
+typedef struct zip_progress zip_progress_t;
/* zip archive, part of API */
zip_hash_t *names; /* hash table for name lookup */
- zip_progress_callback_t progress_callback; /* progress callback for zip_close() */
+ zip_progress_t *progress; /* progress callback for zip_close() */
};
/* file in zip archive, part of API */
zip_uint32_t ext_attrib; /* (c) external file attributes */
zip_uint64_t offset; /* (c) offset of local header */
+ zip_uint16_t compression_level; /* level of compression to use (never valid in orig) */
zip_uint16_t encryption_method; /* encryption method, computed from other fields */
char *password; /* file specific encryption password */
};
bool _zip_dirent_needs_zip64(const zip_dirent_t *, zip_flags_t);
zip_dirent_t *_zip_dirent_new(void);
zip_int64_t _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, bool local, zip_error_t *error);
+void _zip_dirent_set_version_needed(zip_dirent_t *de, bool force_zip64);
zip_int32_t _zip_dirent_size(zip_source_t *src, zip_uint16_t, zip_error_t *);
int _zip_dirent_write(zip_t *za, zip_dirent_t *dirent, zip_flags_t flags);
bool _zip_hash_delete(zip_hash_t *hash, const zip_uint8_t *key, zip_error_t *error);
void _zip_hash_free(zip_hash_t *hash);
zip_int64_t _zip_hash_lookup(zip_hash_t *hash, const zip_uint8_t *name, zip_flags_t flags, zip_error_t *error);
-zip_hash_t *_zip_hash_new(zip_uint16_t hash_size, zip_error_t *error);
-void _zip_hash_revert(zip_hash_t *hash);
+zip_hash_t *_zip_hash_new(zip_error_t *error);
+bool _zip_hash_reserve_capacity(zip_hash_t *hash, zip_uint64_t capacity, zip_error_t *error);
+bool _zip_hash_revert(zip_hash_t *hash, zip_error_t *error);
zip_t *_zip_open(zip_source_t *, unsigned int, zip_error_t *);
+void _zip_progress_end(zip_progress_t *progress);
+void _zip_progress_free(zip_progress_t *progress);
+zip_progress_t *_zip_progress_new(zip_t *za, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud);
+void _zip_progress_start(zip_progress_t *progress);
+void _zip_progress_subrange(zip_progress_t *progress, double start, double end);
+void _zip_progress_update(zip_progress_t *progress, double value);
+
bool zip_random(zip_uint8_t *buffer, zip_uint16_t length);
int _zip_read(zip_source_t *src, zip_uint8_t *data, zip_uint64_t length, zip_error_t *error);
zip_int64_t _zip_source_call(zip_source_t *src, void *data, zip_uint64_t length, zip_source_cmd_t command);
bool _zip_source_eof(zip_source_t *);
zip_source_t *_zip_source_file_or_p(const char *, FILE *, zip_uint64_t, zip_int64_t, const zip_stat_t *, zip_error_t *error);
-void _zip_source_invalidate(zip_source_t *src);
+zip_int8_t zip_source_get_compression_flags(zip_source_t *);
bool _zip_source_had_error(zip_source_t *);
+void _zip_source_invalidate(zip_source_t *src);
zip_source_t *_zip_source_new(zip_error_t *error);
int _zip_source_set_source_archive(zip_source_t *, zip_t *);
-zip_source_t *_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_error_t *error);
+zip_source_t *_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_int8_t compression_flags, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error);
zip_source_t *_zip_source_zip_new(zip_t *, zip_t *, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_uint64_t, const char *);
int _zip_stat_merge(zip_stat_t *dst, const zip_stat_t *src, zip_error_t *error);
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd July 21, 2012
+.Dd April 25, 2017
.Dt ZIP_NAME_LOCATE 3
.Os
.Sh NAME
.It Dv ZIP_FL_NOCASE
Ignore case distinctions.
(Will only work well if the file names are ASCII.)
+With this flag,
+.Fn zip_name_locate
+will be slow for archives with many files.
.It Dv ZIP_FL_NODIR
Ignore directory part of file name in archive.
+With this flag,
+.Fn zip_name_locate
+will be slow for archives with many files.
.It Dv ZIP_FL_ENC_RAW
Compare against the unmodified names as it is in the ZIP archive.
.It Dv ZIP_FL_ENC_GUESS
.\" zip_set_file_compression.mdoc -- set compression method and its flags
-.\" Copyright (C) 2012-2016 Dieter Baron and Thomas Klausner
+.\" Copyright (C) 2012-2017 Dieter Baron and Thomas Klausner
.\"
.\" This file is part of libzip, a library to manipulate ZIP files.
.\" The authors can be contacted at <libzip@nih.at>
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd May 1, 2012
+.Dd April 6, 2017
.Dt ZIP_SET_FILE_COMPRESSION 3
.Os
.Sh NAME
.Dv ZIP_CM_DEFLATE .
.It Dv ZIP_CM_STORE
Store the file uncompressed.
+.It Dv ZIP_CM_BZIP2
+Compress the file using the
+.Xr bzip2 1
+algorithm.
.It Dv ZIP_CM_DEFLATE
Deflate the file with the
.Xr zlib 3
algorithm and default options
.El
.Pp
+.Em NOTE :
+Only the deflate and store methods can be assumed to be universally
+supported.
+.Pp
The
.Ar comp_flags
-argument is currently ignored.
-.\" For the comp_flags argument, the lower 4 bits define the compression
-.\" level.
-.\" 0 is fastest compression, 15 is highest compression
-.\" .Dv ZIP_COMP_FL_DEFAULT
-.\" can be used to specify that the default shall be used.
-.\" Further compression method specific flags will be added over time.
+argument defines the compression level, 1 being fastest compression
+and 9 highest.
+Allowed values are 1-9, other values are undefined.
+Further compression method specific flags might be added over time.
.Pp
The current compression method for a file in a zip archive can be
determined using
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd January 19, 2016
+.Dd April 25, 2017
.Dt ZIPMERGE 1
.Os
.Sh NAME
.Bl -tag -width MMM
.It Fl D
Ignore directory components in file name comparisons.
+This option is slow for archives with many files.
.It Fl h
Display a short help message and exit.
.It Fl I
Ignore case in file name comparisons
+This option is slow for archives with many files.
.It Fl i
Ask before overwriting files.
See also
${CMAKE_CURRENT_SOURCE_DIR}/../src)
ENDIF(NOT HAVE_GETOPT)
-SET(STANDALONE_TEST_PROGRAMS
+SET(TEST_PROGRAMS
add_from_filep
fopen_unchanged
fseek
)
-SET(HELPER_TEST_PROGRAMS
-# tryopen
-)
-
SET(GETOPT_USERS
fread
tryopen
)
-SET(DISABLED_TESTS
- encryption-nonrandom-aes128.test
- encryption-nonrandom-aes192.test
- encryption-nonrandom-aes256.test
-)
-
SET(EXTRA_TESTS
add_dir.test
add_from_buffer.test
add_from_stdin.test
add_from_zip_closed.test
add_from_zip_deflated.test
+ add_from_zip_deflated2.test
add_from_zip_partial_deflated.test
add_from_zip_partial_stored.test
add_from_zip_stored.test
add_stored.test
add_stored_in_memory.test
+ cm-default.test
count_entries.test
+ decrypt-correct-password-aes128.test
+ decrypt-correct-password-aes192.test
decrypt-correct-password-aes256.test
decrypt-correct-password-pkware.test
decrypt-no-password-aes256.test
+ decrypt-wrong-password-aes128.test
+ decrypt-wrong-password-aes192.test
decrypt-wrong-password-aes256.test
decrypt-wrong-password-pkware.test
delete_add_same.test
delete_multiple_partial.test
delete_renamed_rename.test
encrypt.test
+# TODO: the tests need nonrandomopen.so, which is not hooked into the CMake build
+# encryption-nonrandom-aes128.test
+# encryption-nonrandom-aes192.test
+# encryption-nonrandom-aes256.test
encryption-remove.test
extra_add.test
extra_add_multiple.test
extra_set.test
extra_set_modify_c.test
extra_set_modify_l.test
+ fdopen_ok.test
file_comment_encmismatch.test
fopen_unchanged.test
fread.test
fseek_fail.test
fseek_ok.test
get_comment.test
+ junk_at_end.test
+ junk_at_start.test
name_locate.test
open_cons_extrabytes.test
open_empty.test
open_empty_2.test
open_extrabytes.test
+ open_file_count.test
+ open_filename_duplicate.test
+ open_filename_duplicate_consistency.test
+ open_filename_duplicate_empty.test
+ open_filename_duplicate_empty_consistency.test
open_filename_empty.test
open_incons.test
+ open_many_fail.test
open_many_ok.test
open_multidisk.test
open_new_but_exists.test
set_comment_localonly.test
set_comment_removeglobal.test
set_comment_revert.test
+ set_compression_bzip2_to_deflate.test
+ set_compression_deflate_to_bzip2.test
set_compression_deflate_to_deflate.test
set_compression_deflate_to_store.test
+ set_compression_store_to_bzip2.test
set_compression_store_to_deflate.test
set_compression_store_to_store.test
set_compression_unknown.test
stat_index_utf8_unmarked_strict.test
stat_index_zip64.test
utf-8-standardization.test
+ zip-in-archive-comment.test
zip64_creation.test
zip64_stored_creation.test
)
SET(ENV{srcdir} ${CMAKE_CURRENT_SOURCE_DIR})
-FOREACH(PROGRAM ${STANDALONE_TEST_PROGRAMS})
+FOREACH(PROGRAM ${TEST_PROGRAMS})
ADD_EXECUTABLE(${PROGRAM} ${PROGRAM}.c)
TARGET_LINK_LIBRARIES(${PROGRAM} zip)
- ADD_TEST(${PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/runtest ${CMAKE_CURRENT_SOURCE_DIR}/${PROGRAM})
ENDFOREACH(PROGRAM ${STANDALONE_TEST_PROGRAMS})
-FOREACH(PROGRAM ${HELPER_TEST_PROGRAMS})
- ADD_EXECUTABLE(${PROGRAM} ${PROGRAM}.c)
- TARGET_LINK_LIBRARIES(${PROGRAM} zip)
-ENDFOREACH(PROGRAM ${HELPER_TEST_PROGRAMS})
-
FOREACH(PROGRAM ${GETOPT_USERS})
ADD_EXECUTABLE(${PROGRAM} ${PROGRAM}.c ${SRC_EXTRA_FILES})
TARGET_LINK_LIBRARIES(${PROGRAM} zip)
ENDFOREACH(PROGRAM ${GETOPT_USERS})
-ADD_TEST(fread ${CMAKE_CURRENT_SOURCE_DIR}/runtest ${CMAKE_CURRENT_SOURCE_DIR}/fread)
+# for appveyor builds
+#SET(CMAKE_MSVCIDE_RUN_PATH C:/projects/libzip/vstudio/zlib/installed/bin;C:/projects/libzip/vstudio/zlib/installed/lib;C:/projects/libzip/build/lib/Release)
+
+ADD_CUSTOM_TARGET(
+ testinput
+ # ALL
+ VERBATIM
+ COMMAND ziptool ${CMAKE_CURRENT_SOURCE_DIR}/manyfiles-zip.zip cat 0 > manyfiles.zip
+ COMMAND ziptool ${CMAKE_CURRENT_SOURCE_DIR}/manyfiles-zip.zip cat 1 > manyfiles-133000.zip
+ COMMAND ziptool ${CMAKE_CURRENT_SOURCE_DIR}/manyfiles-zip.zip cat 2 > manyfiles-65536.zip
+ COMMAND ziptool ${CMAKE_CURRENT_SOURCE_DIR}/manyfiles-zip.zip cat 3 > manyfiles-zip64-modulo.zip
+ COMMAND ziptool ${CMAKE_CURRENT_SOURCE_DIR}/manyfiles-zip.zip cat 4 > manyfiles-zip64.zip
+ COMMAND ziptool ${CMAKE_CURRENT_SOURCE_DIR}/manyfiles-zip.zip cat 5 > manyfiles-fewer.zip
+ COMMAND ziptool ${CMAKE_CURRENT_SOURCE_DIR}/manyfiles-zip.zip cat 6 > manyfiles-more.zip
+ COMMAND ziptool ${CMAKE_CURRENT_SOURCE_DIR}/bigzero-zip.zip cat 0 > bigzero.zip
+ DEPENDS ziptool ${CMAKE_CURRENT_SOURCE_DIR}/manyfiles-zip.zip ${CMAKE_CURRENT_SOURCE_DIR}/bigzero-zip.zip
+)
+SET_PROPERTY(DIRECTORY PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
+ bigzero.zip
+ manyfiles-133000.zip
+ manyfiles-65536.zip
+ manyfiles-fewer.zip
+ manyfiles-more.zip
+ manyfiles-zip64-modulo.zip
+ manyfiles-zip64.zip
+ manyfiles.zip
+)
FOREACH(CASE ${EXTRA_TESTS})
- ADD_TEST(${CASE} ${CMAKE_CURRENT_SOURCE_DIR}/runtest ${CMAKE_CURRENT_SOURCE_DIR}/${CASE})
+ ADD_TEST(${CASE} perl ${CMAKE_BINARY_DIR}/regress/runtest ${CMAKE_CURRENT_SOURCE_DIR}/${CASE})
ENDFOREACH(CASE ${EXTRA_TESTS})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../lib
test-utf8.zip \
test-utf8-unmarked.zip \
testbuffer.zip \
+ testbzip2.zip \
testdir.zip \
testchanged.zip \
testchangedlocal.zip \
delete_multiple_partial.test \
delete_renamed_rename.test \
encrypt.test \
+ encryption-nonrandom-aes128.test \
+ encryption-nonrandom-aes192.test \
+ encryption-nonrandom-aes256.test \
encryption-remove.test \
extra_add.test \
extra_add_multiple.test \
extra_set.test \
extra_set_modify_c.test \
extra_set_modify_l.test \
+ fdopen_ok.test \
file_comment_encmismatch.test \
fopen_unchanged.test \
fread.test \
set_comment_localonly.test \
set_comment_removeglobal.test \
set_comment_revert.test \
+ set_compression_bzip2_to_deflate.test \
+ set_compression_deflate_to_bzip2.test \
set_compression_deflate_to_deflate.test \
set_compression_deflate_to_store.test \
+ set_compression_store_to_bzip2.test \
set_compression_store_to_deflate.test \
set_compression_store_to_store.test \
set_compression_unknown.test \
zip64_creation.test \
zip64_stored_creation.test
-DISABLED_TESTS= \
- encryption-nonrandom-aes128.test \
- encryption-nonrandom-aes192.test \
- encryption-nonrandom-aes256.test
-
#XFAIL_TESTS=
${top_builddir}/src/ziptool ${srcdir}/manyfiles-zip.zip cat 4 > ${builddir}/$@
runtest: runtest.in
- sed -e 's!@[s]rcdir@!${srcdir}!g' -e 's!@[a]bs_srcdir@!${abs_srcdir}!g' ${srcdir}/runtest.in > runtest
+ sed -e 's!@[s]rcdir@!${srcdir}!g' -e 's!@[a]bs_srcdir@!${abs_srcdir}!g' -e 's!@[t]op_builddir@!${top_builddir}!g' ${srcdir}/runtest.in > runtest
chmod +x runtest
cleanup:
use File::Path qw(mkpath remove_tree);
use Getopt::Long qw(:config posix_default bundling no_ignore_case);
use IPC::Open3;
+use Storable qw(dclone);
use Symbol 'gensym';
use UNIVERSAL;
-use Data::Dumper qw(Dumper);
+#use Data::Dumper qw(Dumper);
# NiHTest -- package to run regression tests
# Copyright (C) 2002-2016 Dieter Baron and Thomas Klausner
# mkdir MODE NAME
# create directory NAME with permissions MODE.
#
+# pipefile FILE
+# pipe FILE to program's stdin.
+#
# pipein COMMAND ARGS ...
# pipe output of running COMMAND to program's stdin.
#
ERROR => 99
);
+# MARK: - Public API
+
sub new {
my $class = UNIVERSAL::isa ($_[0], __PACKAGE__) ? shift : __PACKAGE__;
my $self = bless {}, $class;
-
+
my ($opts) = @_;
$self->{default_program} = $opts->{default_program};
$self->{zipcmp} = $opts->{zipcmp} // 'zipcmp';
- $self->{zipcmp_flags} = $opts->{zipcmp_flags};
+ $self->{zipcmp_flags} = $opts->{zipcmp_flags} // '-p';
$self->{directives} = {
args => { type => 'string...', once => 1, required => 1 },
'file-del' => { type => 'string string' },
'file-new' => { type => 'string string' },
mkdir => { type => 'string string' },
+ pipefile => { type => 'string', once => 1 },
pipein => { type => 'string', once => 1 },
preload => { type => 'string', once => 1 },
program => { type => 'string', once => 1 },
touch => { type => 'int string' },
ulimit => { type => 'char string' }
};
-
+
$self->{compare_by_type} = {};
$self->{copy_by_type} = {};
$self->{hooks} = {};
- $self->add_comparator('zip/zip', \&comparator_zip);
-
- $self->{srcdir} = $opts->{srcdir} // $ENV{srcdir};
-
- if (!defined($self->{srcdir}) || $self->{srcdir} eq '') {
- $self->{srcdir} = `sed -n 's/^srcdir = \(.*\)/\1/p' Makefile`;
- chomp($self->{srcdir});
- }
-
+ $self->get_variable('srcdir', $opts);
+ $self->get_variable('top_builddir', $opts);
+
$self->{in_sandbox} = 0;
-
+
$self->{verbose} = $ENV{VERBOSE};
$self->{keep_broken} = $ENV{KEEP_BROKEN};
$self->{no_cleanup} = $ENV{NO_CLEANUP};
sub add_comparator {
my ($self, $ext, $sub) = @_;
-
+
return $self->add_file_proc('compare_by_type', $ext, $sub);
}
sub add_directive {
my ($self, $name, $def) = @_;
-
+
if (exists($self->{directives}->{$name})) {
$self->die("directive $name already defined");
}
-
+
# TODO: validate $def
-
+
$self->{directives}->{$name} = $def;
-
+
return 1;
}
sub add_hook {
my ($self, $hook, $sub) = @_;
-
+
$self->{hooks}->{$hook} = [] unless (defined($self->{hooks}->{$hook}));
push @{$self->{hooks}->{$hook}}, $sub;
}
+sub add_variant {
+ my ($self, $name, $hooks) = @_;
+
+ if (!defined($self->{variants})) {
+ $self->{variants} = [];
+ $self->add_directive('variants' => { type => 'string...', once => 1 });
+ }
+ for my $variant (@{$self->{variants}}) {
+ if ($variant->{name} eq $name) {
+ $self->die("variant $name already defined");
+ }
+ }
+
+ push @{$self->{variants}}, { name => $name, hooks => $hooks };
+
+ return 1;
+}
+
+
sub end {
my ($self, @results) = @_;
sub runtest {
+ my ($self) = @_;
+
+ if (defined($self->{variants})) {
+ my @results = ();
+ $self->{original_test} = $self->{test};
+
+ my %variants;
+
+ if (defined($self->{test}->{variants})) {
+ %variants = map { $_ => 1; } @{$self->{test}->{variants}};
+ }
+
+ for my $variant (@{$self->{variants}}) {
+ next if (defined($self->{test}->{variants}) && !exists($variants{$variant->{name}}));
+
+ $self->{variant_hooks} = $variant->{hooks};
+ $self->{test} = dclone($self->{original_test});
+ $self->{variant} = $variant->{name};
+ $self->mangle_test_for_variant();
+ push @results, $self->runtest_one($variant->{name});
+ }
+
+ return @results;
+ }
+ else {
+ return $self->runtest_one();
+ }
+}
+
+
+sub runtest_one {
my ($self, $tag) = @_;
$ENV{TZ} = "UTC";
$ENV{POSIXLY_CORRECT} = 1;
$self->sandbox_create($tag);
$self->sandbox_enter();
-
+
my $ok = 1;
$ok &= $self->copy_files();
$ok &= $self->run_hook('post_copy_files');
$preload_env_var = 'DYLD_INSERT_LIBRARIES';
}
if (defined($self->{test}->{'preload'})) {
- print "preloading: $preload_env_var = $self->{test}->{preload}\n";
$ENV{$preload_env_var} = cwd() . "/../.libs/$self->{test}->{'preload'}";
}
$self->run_hook('post_run_program');
my @failed = ();
-
+
if ($self->{exit_status} != ($self->{test}->{return} // 0)) {
push @failed, 'exit status';
if ($self->{verbose}) {
print "-" . ($self->{test}->{return} // 0) . "\n+$self->{exit_status}\n";
}
}
-
+
if (!$self->compare_arrays($self->{expected_stdout}, $self->{stdout}, 'output')) {
push @failed, 'output';
}
if (!$self->compare_files()) {
push @failed, 'files';
}
-
+
$self->{failed} = \@failed;
-
+
$self->run_hook('checks');
-
+
my $result = scalar(@{$self->{failed}}) == 0 ? 'PASS' : 'FAIL';
$self->sandbox_leave();
@ARGV = @argv;
my $ok = GetOptions(
'help|h' => \my $help,
- 'keep-broken' => \$self->{keep_broken},
+ 'keep-broken|k' => \$self->{keep_broken},
'no-cleanup' => \$self->{no_cleanup},
# 'run-gdb' => \$self->{run_gdb},
'setup-only' => \$self->{setup_only},
$testcase .= '.test' unless ($testcase =~ m/\.test$/);
my $testcase_file = $self->find_file($testcase);
-
+
$self->die("cannot find test case $testcase") unless ($testcase_file);
-
+
$testcase =~ s,^(?:.*/)?([^/]*)\.test$,$1,;
$self->{testname} = $testcase;
$self->die("error in test case definition") unless $self->parse_case($testcase_file);
-
+
$self->check_features_requirement() if ($self->{test}->{features});
$self->end_test('SKIP') if ($self->{test}->{preload} && $^O eq 'darwin');
}
-#
-# internal methods
-#
+# MARK: - Internal Methods
sub add_file {
my ($self, $file) = @_;
-
+
if (defined($self->{files}->{$file->{destination}})) {
$self->warn("duplicate specification for input file $file->{destination}");
return undef;
}
-
+
$self->{files}->{$file->{destination}} = $file;
-
+
return 1;
}
sub check_features_requirement() {
my ($self) = @_;
-
- ### TODO: implement
-
+
+ my %features;
+
+ my $fh;
+ unless (open($fh, '<', "$self->{top_builddir}/config.h")) {
+ $self->die("cannot open config.h in top builddir $self->{top_builddir}");
+ }
+ while (my $line = <$fh>) {
+ if ($line =~ m/^#define HAVE_([A-Z0-9_a-z]*)/) {
+ $features{$1} = 1;
+ }
+ }
+ close($fh);
+
+ my @missing = ();
+ for my $feature (@{$self->{test}->{features}}) {
+ if (!$features{$feature}) {
+ push @missing, $feature;
+ }
+ }
+
+ if (scalar @missing > 0) {
+ my $reason = "missing features";
+ if (scalar(@missing) == 1) {
+ $reason = "missing feature";
+ }
+ $self->print_test_result('SKIP', "$reason: " . (join ' ', @missing));
+ $self->end_test('SKIP');
+ }
+
return 1;
}
sub comparator_zip {
my ($self, $got, $expected) = @_;
- my @args = ($self->{zipcmp}, $self->{verbose} ? '-pv' : '-pq');
+ my @args = ($self->{zipcmp}, $self->{verbose} ? '-v' : '-q');
push @args, $self->{zipcmp_flags} if ($self->{zipcmp_flags});
push @args, ($expected, $got);
-
+
my $ret = system(@args);
-
+
return $ret == 0;
}
sub compare_arrays() {
my ($self, $a, $b, $tag) = @_;
-
+
my $ok = 1;
-
+
if (scalar(@$a) != scalar(@$b)) {
$ok = 0;
}
}
}
}
-
+
if (!$ok && $self->{verbose}) {
print "Unexpected $tag:\n";
print "--- expected\n+++ got\n";
diff_arrays($a, $b);
}
-
+
return $ok;
}
sub compare_file($$$) {
my ($self, $got, $expected) = @_;
-
+
my $real_expected = $self->find_file($expected);
unless ($real_expected) {
$self->warn("cannot find expected result file $expected");
return $ok;
}
+sub list_files {
+ my ($root) = @_;
+ my $ls;
+
+ my @files = ();
+ my @dirs = ($root);
+
+ while (scalar(@dirs) > 0) {
+ my $dir = shift @dirs;
+
+ opendir($ls, $dir);
+ unless ($ls) {
+ # TODO: handle error
+ }
+ while (my $entry = readdir($ls)) {
+ my $file = "$dir/$entry";
+ if ($dir eq '.') {
+ $file = $entry;
+ }
+
+ if (-f $file) {
+ push @files, "$file";
+ }
+ if (-d $file && $entry ne '.' && $entry ne '..') {
+ push @dirs, "$file";
+ }
+ }
+ closedir($ls);
+ }
+
+ return @files;
+}
sub compare_files() {
my ($self) = @_;
-
+
my $ok = 1;
-
- opendir(my $ls, '.');
- unless ($ls) {
- # TODO: handle error
- }
- my @files_got = grep { -f } readdir($ls);
- closedir($ls);
- @files_got = sort @files_got;
+
+ my @files_got = sort(list_files("."));
my @files_should = ();
-
+
for my $file (sort keys %{$self->{files}}) {
push @files_should, $file if ($self->{files}->{$file}->{result} || $self->{files}->{$file}->{ignore});
}
unless ($self->run_hook('post_list_files')) {
return 0;
}
-
+
$ok = $self->compare_arrays($self->{files_should}, $self->{files_got}, 'files');
-
+
for my $file (@{$self->{files_got}}) {
my $file_def = $self->{files}->{$file};
next unless ($file_def && $file_def->{result});
-
+
$ok &= $self->compare_file($file, $file_def->{result});
}
-
+
return $ok;
}
sub copy_files {
my ($self) = @_;
-
+
my $ok = 1;
-
+
for my $filename (sort keys %{$self->{files}}) {
my $file = $self->{files}->{$filename};
next unless ($file->{source});
}
}
}
-
+
$self->die("failed to copy input files") unless ($ok);
}
sub die() {
my ($self, $msg) = @_;
-
+
print STDERR "$0: $msg\n" if ($msg);
-
+
$self->end_test('ERROR');
}
sub end_test {
my ($self, $status) = @_;
-
+
my $exit_code = $EXIT_CODES{$status} // $EXIT_CODES{ERROR};
-
+
$self->exit($exit_code);
}
sub exit() {
my ($self, $status) = @_;
### TODO: cleanup
-
+
exit($status);
}
sub find_file() {
my ($self, $fname) = @_;
-
+
for my $dir (('', "$self->{srcdir}/")) {
my $f = "$dir$fname";
$f = "../$f" if ($self->{in_sandbox} && $dir !~ m,^/,);
-
+
return $f if (-f $f);
}
-
+
return undef;
}
}
+sub get_variable {
+ my ($self, $name, $opts) = @_;
+
+ $self->{$name} = $opts->{$name} // $ENV{$name};
+ if (!defined($self->{$name}) || $self->{$name} eq '') {
+ my $fh;
+ unless (open($fh, '<', 'Makefile')) {
+ $self->die("cannot open Makefile: $!");
+ }
+ while (my $line = <$fh>) {
+ chomp $line;
+ if ($line =~ m/^$name = (.*)/) {
+ $self->{$name} = $1;
+ last;
+ }
+ }
+ close ($fh);
+ }
+ if (!defined($self->{$name} || $self->{$name} eq '')) {
+ $self->die("cannot get variable $name");
+ }
+}
+
+
+sub mangle_test_for_variant {
+ my ($self) = @_;
+
+ $self->{test}->{stdout} = $self->strip_tags($self->{variant}, $self->{test}->{stdout});
+ $self->{test}->{stderr} = $self->strip_tags($self->{variant}, $self->{test}->{stderr});
+ $self->run_hook('mangle_test');
+
+ return 1;
+}
+
sub parse_args {
my ($self, $type, $str) = @_;
$self->warn_file_line("expected $expected arguments, got " . (scalar(@strs)));
return undef;
}
-
+
my $args = [];
-
+
my $n = scalar(@types);
for (my $i=0; $i<scalar(@strs); $i++) {
my $val = $self->parse_args(($i >= $n ? $types[$n-1] : $types[$i]), $strs[$i]);
return undef unless (defined($val));
push @$args, $val;
}
-
+
return $args;
}
else {
sub parse_case() {
my ($self, $fname) = @_;
-
+
my $ok = 1;
-
+
open TST, "< $fname" or $self->die("cannot open test case $fname: $!");
-
+
$self->{testcase_fname} = $fname;
-
+
my %test = ();
-
+
while (my $line = <TST>) {
chomp $line;
-
+
next if ($line =~ m/^\#/);
-
+
unless ($line =~ m/(\S*)(?:\s(.*))?/) {
$self->warn_file_line("cannot parse line $line");
$ok = 0;
next;
}
my ($cmd, $argstring) = ($1, $2//"");
-
+
my $def = $self->{directives}->{$cmd};
-
+
unless ($def) {
$self->warn_file_line("unknown directive $cmd in test file");
$ok = 0;
next;
}
-
+
my $args = $self->parse_args($def->{type}, $argstring);
-
+
unless (defined($args)) {
$ok = 0;
next;
}
-
+
if ($def->{once}) {
if (defined($test{$cmd})) {
$self->warn_file_line("directive $cmd appeared twice in test file");
}
close TST;
-
+
return undef unless ($ok);
-
+
for my $cmd (sort keys %test) {
if ($self->{directives}->{$cmd}->{required} && !defined($test{$cmd})) {
$self->warn_file("required directive $cmd missing in test file");
$ok = 0;
}
}
-
+
+ if ($test{pipefile} && $test{pipein}) {
+ $self->warn_file("both pipefile and pipein set, choose one");
+ $ok = 0;
+ }
+
+ if (defined($self->{variants})) {
+ if (defined($test{variants})) {
+ for my $name (@{$test{variants}}) {
+ my $found = 0;
+ for my $variant (@{$self->{variants}}) {
+ if ($name eq $variant->{name}) {
+ $found = 1;
+ last;
+ }
+ }
+ if ($found == 0) {
+ $self->warn_file("unknown variant $name");
+ $ok = 0;
+ }
+ }
+ }
+ }
+
return undef unless ($ok);
if (defined($test{'stderr-replace'}) && defined($test{stderr})) {
$self->{test} = \%test;
$self->run_hook('mangle_program');
-
+
if (!$self->parse_postprocess_files()) {
return 0;
}
sub parse_postprocess_files {
my ($self) = @_;
-
+
$self->{files} = {};
-
+
my $ok = 1;
-
+
for my $file (@{$self->{test}->{file}}) {
$ok = 0 unless ($self->add_file({ source => $file->[1], destination => $file->[0], result => $file->[2] }));
}
-
+
for my $file (@{$self->{test}->{'file-del'}}) {
$ok = 0 unless ($self->add_file({ source => $file->[1], destination => $file->[0], result => undef }));
}
-
+
for my $file (@{$self->{test}->{'file-new'}}) {
$ok = 0 unless ($self->add_file({ source => undef, destination => $file->[0], result => $file->[1] }));
}
-
+
return $ok;
}
my $ext = ($self->get_extension($got)) . '/' . ($self->get_extension($expected));
+ if ($self->{variant}) {
+ if (defined($self->{$proc}->{"$self->{variant}/$ext"})) {
+ for my $sub (@{$self->{$proc}->{"$self->{variant}/$ext"}}) {
+ my $ret = $sub->($self, $got, $expected);
+ return $ret if (defined($ret));
+ }
+ }
+ }
if (defined($self->{$proc}->{$ext})) {
for my $sub (@{$self->{$proc}->{$ext}}) {
my $ret = $sub->($self, $got, $expected);
sub run_hook {
my ($self, $hook) = @_;
-
+
my $ok = 1;
-
+
+ my @hooks = ();
+
+ if (defined($self->{variant_hooks}) && defined($self->{variant_hooks}->{$hook})) {
+ push @hooks, $self->{variant_hooks}->{$hook};
+ }
if (defined($self->{hooks}->{$hook})) {
- for my $sub (@{$self->{hooks}->{$hook}}) {
- unless ($sub->($self, $hook)) {
- $self->warn("hook $hook failed");
- $ok = 0;
- }
+ push @hooks, @{$self->{hooks}->{$hook}};
+ }
+
+ for my $sub (@hooks) {
+ unless ($sub->($self, $hook, $self->{variant})) {
+ $self->warn("hook $hook failed");
+ $ok = 0;
}
}
-
+
return $ok;
}
sub args_decode {
my @cmd = ('../' . $self->{test}->{program}, map ({ args_decode($_, $self->{srcdir}); } @{$self->{test}->{args}}));
### TODO: catch errors?
-
- my $pid = open3($stdin, $stdout, $stderr, @cmd);
-
+
+ my $pid;
+ if ($self->{test}->{pipefile}) {
+ open(SPLAT, '<', $self->{test}->{pipefile});
+ my $is_marked = eof SPLAT; # mark used
+ $pid = open3("<&SPLAT", $stdout, $stderr, @cmd);
+ }
+ else {
+ $pid = open3($stdin, $stdout, $stderr, @cmd);
+ }
$self->{stdout} = [];
$self->{stderr} = [];
-
- if ($self->{test}->{pipein}) {
+
+ if ($self->{test}->{pipein}) {
my $fh;
open($fh, "$self->{test}->{pipein} |");
if (!defined($fh)) {
close($fh);
close($stdin);
}
-
+
while (my $line = <$stdout>) {
if ($^O eq 'MSWin32') {
$line =~ s/[\r\n]+$//;
}
push @{$self->{stderr}}, $line;
}
-
+
waitpid($pid, 0);
-
+
$self->{exit_status} = $? >> 8;
}
sub sandbox_create {
my ($self, $tag) = @_;
-
+
$tag = ($tag ? "-$tag" : "");
$self->{sandbox_dir} = "sandbox-$self->{testname}$tag.d$$";
-
+
$self->die("sandbox $self->{sandbox_dir} already exists") if (-e $self->{sandbox_dir});
-
+
mkdir($self->{sandbox_dir}) or $self->die("cannot create sandbox $self->{sandbox_dir}: $!");
-
+
return 1;
}
sub sandbox_enter {
my ($self) = @_;
-
+
$self->die("internal error: cannot enter sandbox before creating it") unless (defined($self->{sandbox_dir}));
return if ($self->{in_sandbox});
- chdir($self->{sandbox_dir}) or $self->die("cant cd into sandbox $self->{sandbox_dir}: $!");
-
+ chdir($self->{sandbox_dir}) or $self->die("cannot cd into sandbox $self->{sandbox_dir}: $!");
+
$self->{in_sandbox} = 1;
}
sub sandbox_leave {
my ($self) = @_;
-
+
return if (!$self->{in_sandbox});
-
+
chdir('..') or $self->die("cannot leave sandbox: $!");
-
+
$self->{in_sandbox} = 0;
}
}
+sub strip_tags {
+ my ($self, $tag, $lines) = @_;
+
+ my @stripped = ();
+
+ for my $line (@$lines) {
+ if ($line =~ m/^<([a-zA-Z0-9_]*)> (.*)/) {
+ if ($1 eq $tag) {
+ push @stripped, $2;
+ }
+ }
+ else {
+ push @stripped, $line;
+ }
+ }
+
+ return \@stripped;
+}
+
+
sub touch_files {
my ($self) = @_;
-
+
my $ok = 1;
-
+
if (defined($self->{test}->{touch})) {
for my $args (@{$self->{test}->{touch}}) {
my ($mtime, $fname) = @$args;
-
+
if (!-f $fname) {
my $fh;
unless (open($fh, "> $fname") and close($fh)) {
}
}
}
-
+
return $ok;
}
sub warn {
my ($self, $msg) = @_;
-
+
print STDERR "$0: $msg\n";
}
sub warn_file {
my ($self, $msg) = @_;
-
+
$self->warn("$self->{testcase_fname}: $msg");
}
sub warn_file_line {
my ($self, $msg) = @_;
-
+
$self->warn("$self->{testcase_fname}:$.: $msg");
}
if (!defined($best_a)) {
return (scalar(@$a) - $i, scalar(@$b) - $j);
}
-
+
return ($best_a, $best_b);
}
--- /dev/null
+# zip_fdopen: stdin opens fine
+program ../src/ziptool
+args /dev/stdin stat 0
+pipefile test.zip
+return 0
+file test.zip test.zip test.zip
+stdout name: 'test'
+stdout index: '0'
+stdout size: '5'
+stdout compressed size: '5'
+stdout mtime: 'Mon Oct 06 2003 15:46:42'
+stdout crc: '3bb935c6'
+stdout compression method: '0'
+stdout encryption method: '0'
+stdout
\ No newline at end of file
static void
init(void)
{
- char *foo;
real_open = dlsym(RTLD_NEXT, "open");
if (!real_open)
abort();
use NiHTest;
-my $test = NiHTest::new({ default_program => '../src/ziptool', srcdir => '@srcdir@', zipcmp => '../../src/zipcmp', zipcmp_flags => '-p' });
+my $test = NiHTest::new({ default_program => '../src/ziptool', srcdir => '@srcdir@', top_builddir => '@top_builddir@', zipcmp => '../../src/zipcmp', zipcmp_flags => '-p' });
+
+sub mangle_test {
+ my ($test, $variant) = @_;
+
+ if (defined($test->{test}->{preload})) {
+ if (!defined($test->{test}->{features})) {
+ $test->{test}->{features} = [];
+ }
+ push @{$test->{test}->{features}}, 'SHARED';
+ }
+
+ return 1;
+}
+
+
+$test->add_comparator('zip/zip', \&NiHTest::comparator_zip);
+$test->add_hook('post_parse', \&mangle_test);
$test->run(@ARGV);
--- /dev/null
+# change method from bzip2 to deflated
+features LIBBZ2
+return 0
+args test.zip set_file_compression 0 deflate 0
+file test.zip testbzip2.zip testdeflated.zip
--- /dev/null
+# change method from deflated to bzip2
+features LIBBZ2
+return 0
+args test.zip set_file_compression 0 bzip2 0
+file test.zip testdeflated.zip testbzip2.zip
--- /dev/null
+# change method from stored to bzip2
+features LIBBZ2
+return 0
+args test.zip set_file_compression 0 bzip2 0
+file test.zip teststored.zip testbzip2.zip
#include "getopt.h"
#endif
-#include "zip.h"
#include "compat.h"
+#include "zip.h"
const char *usage = "usage: %s [-cent] file\n\n"
"\t-c\tcheck consistency\n"
# replace file contents and make UTF-8 name
return 0
-args testfile replace_file_contents 0 "Some new content for the file." set_file_mtime 0 1406885162
-file testfile utf-8-standardization-input.zip utf-8-standardization-output.zip
+args testfile.zzip replace_file_contents 0 "Some new content for the file." set_file_mtime 0 1406885162
+file testfile.zzip utf-8-standardization-input.zip utf-8-standardization-output.zip
#include "getopt.h"
#endif
-#include "zip.h"
#include "compat.h"
+#include "zip.h"
struct archive {
const char *name;
FTS *fts;
FTSENT *ent;
zip_uint64_t nalloc;
+ size_t prefix_length;
char * const names[2] = { (char *)name, NULL };
fprintf(stderr, "%s: can't open directory '%s': %s\n", prg, name, strerror(errno));
return -1;
}
- size_t prefix_length = strlen(name)+1;
+ prefix_length = strlen(name)+1;
nalloc = 0;
#include "getopt.h"
#endif
-#include "zip.h"
#include "compat.h"
+#include "zip.h"
char *prg;
#endif
extern int optopt;
-#include "zip.h"
#include "compat.h"
+#include "zip.h"
zip_source_t *source_hole_create(const char *, int flags, zip_error_t *);
}
static void
-progress_callback(double percentage) {
+progress_callback(zip_t *za, double percentage, void *ud) {
printf("%.1lf%% done\n", percentage*100);
}
static int
print_progress(int argc, char *argv[]) {
- zip_register_progress_callback(za, progress_callback);
+ zip_register_progress_callback_with_state(za, 0.001, progress_callback, NULL, NULL);
return 0;
}
return ZIP_CM_STORE;
else if (strcmp(arg, "deflate") == 0)
return ZIP_CM_DEFLATE;
+#if defined(HAVE_LIBBZ2)
+ else if (strcmp(arg, "bzip2") == 0)
+ return ZIP_CM_BZIP2;
+#endif
else if (strcmp(arg, "unknown") == 0)
return 100;
return 0; /* TODO: error handling */
int err;
if (offset == 0 && length == 0) {
- if ((zaa = zip_open(archive, flags, &err)) == NULL) {
+ if (strcmp(archive, "/dev/stdin") == 0) {
+ zaa = zip_fdopen(STDIN_FILENO, flags & ~ZIP_CREATE, &err);
+ }
+ else {
+ zaa = zip_open(archive, flags, &err);
+ }
+ if (zaa == NULL) {
zip_error_set(error, err, errno);
return NULL;
}
zip_source_t *src = NULL;
zip_t *zs = NULL;
+ if (strcmp(archive, "/dev/stdin") == 0) {
+ zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
+ return NULL;
+ }
+
if ((src = source_hole_create(archive, flags, error)) == NULL
|| (zs = zip_open_from_source(src, flags, error)) == NULL) {
zip_source_free(src);
zip_source_t *src;
zip_t *zb;
+ if (strcmp(archive, "/dev/stdin") == 0) {
+ zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
+ return NULL;
+ }
+
if (stat(archive, &st) < 0) {
if (errno == ENOENT) {
src = zip_source_buffer_create(NULL, 0, 0, error);
"\tu\tZIP_FL_UNCHANGED\n");
fprintf(out, "\nSupported compression methods are:\n"
"\tdefault\n"
+#if defined(HAVE_LIBBZ2)
+ "\tbzip2\n"
+#endif
"\tdeflate\n"
"\tstore\n");
fprintf(out, "\nSupported compression methods are:\n"
if errorlevel 1 goto exit_failure
if exist ..\regress\manyfiles.zip del ..\regress\manyfiles.zip
if errorlevel 1 goto exit_failure
+ if exist ..\regress\manyfiles-133000.zip del ..\regress\manyfiles-133000.zip
+ if errorlevel 1 goto exit_failure
+ if exist ..\regress\manyfiles-65536.zip del ..\regress\manyfiles-65536.zip
+ if errorlevel 1 goto exit_failure
+ if exist ..\regress\manyfiles-zip64-modulo.zip del ..\regress\manyfiles-zip64-modulo.zip
+ if errorlevel 1 goto exit_failure
+ if exist ..\regress\manyfiles-zip64.zip del ..\regress\manyfiles-zip64.zip
+ if errorlevel 1 goto exit_failure
+ if exist ..\regress\manyfiles-fewer.zip del ..\regress\manyfiles-fewer.zip
+ if errorlevel 1 goto exit_failure
+ if exist ..\regress\manyfiles-more.zip del ..\regress\manyfiles-more.zip
+ if errorlevel 1 goto exit_failure
echo Done
exit /b 0
) else if "%1"=="build" (
popd
rem ---------------------------------------------------------------------------
-rem regress/CMakeLists.txt thinks the Perl script to run a test is called
-rem runtest, but on Windows we have to explicitly start the Perl interpreter
-rem because cmd.exe doesn't do "shebang".
-rem Fix this up before configuring libzip.
-rem ---------------------------------------------------------------------------
-if "%LIBZIP_RUN_TESTS%"=="true" (
- echo Fixing up runtest script for Windows
- pushd ..\regress
- rem Get the full path to the Perl interpreter, with backslashes replaced by
- rem forward slashes.
- for /f "usebackq tokens=*" %%a in (`where perl.exe`) do set PERL_PATH=%%a
- set PERL_PATH=!PERL_PATH:\=/!
- echo Path to Perl interpreter is !PERL_PATH!
-
- rem Fix up the CMakeLists.txt file.
- perl -p -e "s|\$\{CMAKE_CURRENT_SOURCE_DIR\}/runtest|!PERL_PATH! \$\{CMAKE_CURRENT_BINARY_DIR\}/runtest|;" CMakeLists.txt > CMakeLists.fixed.txt
- if errorlevel 1 popd & goto exit_failure
- rename CMakeLists.txt CMakeLists.orig.txt
- if errorlevel 1 popd & goto exit_failure
- rename CMakeLists.fixed.txt CMakeLists.txt
- if errorlevel 1 popd & goto exit_failure
- popd
-)
-
-rem ---------------------------------------------------------------------------
rem Prepare the build directory and run CMake to configure the project.
rem ---------------------------------------------------------------------------
pushd ..
if errorlevel 1 popd & goto exit_failure
cmake .. -G %CMAKE_GENERATOR% -T %CMAKE_TOOLSET% -DCMAKE_PREFIX_PATH="%ZLIB_INSTALL_PATH%"
if errorlevel 1 popd & goto exit_failure
-call :revert_cmakelists
+goto :EOF
rem ---------------------------------------------------------------------------
rem Build libzip.
if errorlevel 1 popd & goto exit_failure
copy Release\*.exe .
if errorlevel 1 popd & goto exit_failure
+ copy ..\src\Release\*.exe .
+ if errorlevel 1 popd & goto exit_failure
echo Extracting test files
if not exist ..\..\regress\bigzero.zip ziptool ..\..\regress\bigzero-zip.zip cat 0 > ..\..\regress\bigzero.zip
if errorlevel 1 popd & goto exit_failure
if not exist ..\..\regress\manyfiles.zip ziptool ..\..\regress\manyfiles-zip.zip cat 0 > ..\..\regress\manyfiles.zip
if errorlevel 1 popd & goto exit_failure
+ if not exist ..\..\regress\manyfiles-133000.zip ziptool ..\..\regress\manyfiles-zip.zip cat 1 > ..\..\regress\manyfiles-133000.zip
+ if errorlevel 1 popd & goto exit_failure
+ if not exist ..\..\regress\manyfiles-65536.zip ziptool ..\..\regress\manyfiles-zip.zip cat 2 > ..\..\regress\manyfiles-65536.zip
+ if errorlevel 1 popd & goto exit_failure
+ if not exist ..\..\regress\manyfiles-zip64-modulo.zip ziptool ..\..\regress\manyfiles-zip.zip cat 3 > ..\..\regress\manyfiles-zip64-modulo.zip
+ if errorlevel 1 popd & goto exit_failure
+ if not exist ..\..\regress\manyfiles-zip64.zip ziptool ..\..\regress\manyfiles-zip.zip cat 4 > ..\..\regress\manyfiles-zip64.zip
+ if errorlevel 1 popd & goto exit_failure
+ if not exist ..\..\regress\manyfiles-fewer.zip ziptool ..\..\regress\manyfiles-zip.zip cat 5 > ..\..\regress\manyfiles-fewer.zip
+ if errorlevel 1 popd & goto exit_failure
+ if not exist ..\..\regress\manyfiles-more.zip ziptool ..\..\regress\manyfiles-zip.zip cat 6 > ..\..\regress\manyfiles-more.zip
+ if errorlevel 1 popd & goto exit_failure
echo Generating runtest script
for /f %%p in ("..\..\regress") do set ABS_SRCDIR=%%~fp
set ABS_SRCDIR=!ABS_SRCDIR:\=\\!
if errorlevel 1 popd & goto exit_failure
echo Running tests
ctest
- if errorlevel 1 popd & goto exit_failure
popd
+ if errorlevel 1 goto exit_failure
)
goto :EOF
)
goto :EOF
-:revert_cmakelists
-if exist ..\regress\CMakeLists.orig.txt (
- del ..\regress\CMakeLists.txt
- rename ..\regress\CMakeLists.orig.txt CMakeLists.txt
-)
-goto :EOF
-
:exit_failure
-call :revert_cmakelists
echo Build failed.
exit /b 1
#define PACKAGE_URL ""
/* Define to the version of this package. */
-#define PACKAGE_VERSION "1.2.0"
+#define PACKAGE_VERSION "1.3.0"
/* The size of `int', as computed by sizeof. */
#define SIZEOF_INT 4
/* #undef TM_IN_SYS_TIME */
/* Version number of package */
-#define VERSION "1.2.0"
+#define VERSION "1.3.0"
/* Enable large inode numbers on Mac OS X 10.5. */
#ifndef _DARWIN_USE_64_BIT_INODE
4B01D6C815B2F46B002D5007 /* zip_fread.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC721315B1B25E00236D3C /* zip_fread.c */; };
4B01D6C915B2F46B002D5007 /* zip_get_archive_comment.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC721415B1B25E00236D3C /* zip_get_archive_comment.c */; };
4B01D6CA15B2F46B002D5007 /* zip_get_archive_flag.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC721515B1B25E00236D3C /* zip_get_archive_flag.c */; };
- 4B01D6CB15B2F46B002D5007 /* zip_get_compression_implementation.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC721615B1B25E00236D3C /* zip_get_compression_implementation.c */; };
4B01D6CC15B2F46B002D5007 /* zip_get_encryption_implementation.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC721715B1B25E00236D3C /* zip_get_encryption_implementation.c */; };
4B01D6CD15B2F46B002D5007 /* zip_get_file_comment.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC721815B1B25E00236D3C /* zip_get_file_comment.c */; };
4B01D6CE15B2F46B002D5007 /* zip_get_name.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC721915B1B25E00236D3C /* zip_get_name.c */; };
4B01D6DD15B2F46B002D5007 /* zip_source_buffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC722815B1B25E00236D3C /* zip_source_buffer.c */; };
4B01D6DE15B2F46B002D5007 /* zip_source_close.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC722915B1B25E00236D3C /* zip_source_close.c */; };
4B01D6DF15B2F46B002D5007 /* zip_source_crc.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC722A15B1B25E00236D3C /* zip_source_crc.c */; };
- 4B01D6E015B2F46B002D5007 /* zip_source_deflate.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC722B15B1B25E00236D3C /* zip_source_deflate.c */; };
4B01D6E115B2F46B002D5007 /* zip_source_error.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC722C15B1B25E00236D3C /* zip_source_error.c */; };
4B01D6E215B2F46B002D5007 /* zip_source_file.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC722D15B1B25E00236D3C /* zip_source_file.c */; };
4B01D6E315B2F46B002D5007 /* zip_source_filep.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC722E15B1B25E00236D3C /* zip_source_filep.c */; };
4B01D73215B2F5EE002D5007 /* zipconf.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BDC729E15B1B4E900236D3C /* zipconf.h */; settings = {ATTRIBUTES = (Public, ); }; };
4B01D73415B2F5F4002D5007 /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BDC72A015B1B56400236D3C /* config.h */; };
4B01D73C15B2F6AF002D5007 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B01D70815B2F4CF002D5007 /* libz.dylib */; };
+ 4B0454B81E8E3E02002FA1F9 /* zip_source_get_compression_flags.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B0454B71E8E3DF7002FA1F9 /* zip_source_get_compression_flags.c */; };
+ 4B0454B91E8E3E03002FA1F9 /* zip_source_get_compression_flags.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B0454B71E8E3DF7002FA1F9 /* zip_source_get_compression_flags.c */; };
+ 4B0454BA1E8E3E08002FA1F9 /* zip_source_compress.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B0454B61E8E3DF7002FA1F9 /* zip_source_compress.c */; };
+ 4B0454BB1E8E3E09002FA1F9 /* zip_source_compress.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B0454B61E8E3DF7002FA1F9 /* zip_source_compress.c */; };
+ 4B0454BC1E8E3E24002FA1F9 /* zip_algorithm_bzip2.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B0454B41E8E3DF7002FA1F9 /* zip_algorithm_bzip2.c */; };
+ 4B0454BD1E8E3E24002FA1F9 /* zip_algorithm_deflate.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B0454B51E8E3DF7002FA1F9 /* zip_algorithm_deflate.c */; };
+ 4B0454BE1E8E3E25002FA1F9 /* zip_algorithm_bzip2.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B0454B41E8E3DF7002FA1F9 /* zip_algorithm_bzip2.c */; };
+ 4B0454BF1E8E3E25002FA1F9 /* zip_algorithm_deflate.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B0454B51E8E3DF7002FA1F9 /* zip_algorithm_deflate.c */; };
4B3A5F501DF96EA8005A53A1 /* gladman-fcrypt.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B3A5F4B1DF96D83005A53A1 /* gladman-fcrypt.c */; };
4B3A5F511DF96EA9005A53A1 /* gladman-fcrypt.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B3A5F4B1DF96D83005A53A1 /* gladman-fcrypt.c */; };
4B3A5F521DF96EB4005A53A1 /* zip_fseek.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B3A5F4D1DF96D83005A53A1 /* zip_fseek.c */; };
4BD6CB6619E71CD100710654 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B01D70815B2F4CF002D5007 /* libz.dylib */; };
4BD6CB6719E71CD100710654 /* libzip.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B01D68B15B2F3F1002D5007 /* libzip.framework */; };
4BD6CB6F19E71D6900710654 /* hole.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BD6CB5E19E71B3B00710654 /* hole.c */; };
+ 4BD708791EB1CF73003F351F /* zip_progress.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BD708781EB1CF73003F351F /* zip_progress.c */; };
+ 4BD7087A1EB1CF73003F351F /* zip_progress.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BD708781EB1CF73003F351F /* zip_progress.c */; };
4BDC724415B1B25E00236D3C /* zip_add_dir.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC71F115B1B25E00236D3C /* zip_add_dir.c */; };
4BDC724515B1B25E00236D3C /* zip_add_entry.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC71F215B1B25E00236D3C /* zip_add_entry.c */; };
4BDC724615B1B25E00236D3C /* zip_add.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC71F315B1B25E00236D3C /* zip_add.c */; };
4BDC726615B1B25E00236D3C /* zip_fread.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC721315B1B25E00236D3C /* zip_fread.c */; };
4BDC726715B1B25E00236D3C /* zip_get_archive_comment.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC721415B1B25E00236D3C /* zip_get_archive_comment.c */; };
4BDC726815B1B25E00236D3C /* zip_get_archive_flag.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC721515B1B25E00236D3C /* zip_get_archive_flag.c */; };
- 4BDC726915B1B25E00236D3C /* zip_get_compression_implementation.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC721615B1B25E00236D3C /* zip_get_compression_implementation.c */; };
4BDC726A15B1B25E00236D3C /* zip_get_encryption_implementation.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC721715B1B25E00236D3C /* zip_get_encryption_implementation.c */; };
4BDC726B15B1B25E00236D3C /* zip_get_file_comment.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC721815B1B25E00236D3C /* zip_get_file_comment.c */; };
4BDC726C15B1B25E00236D3C /* zip_get_name.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC721915B1B25E00236D3C /* zip_get_name.c */; };
4BDC727B15B1B25E00236D3C /* zip_source_buffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC722815B1B25E00236D3C /* zip_source_buffer.c */; };
4BDC727C15B1B25E00236D3C /* zip_source_close.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC722915B1B25E00236D3C /* zip_source_close.c */; };
4BDC727D15B1B25E00236D3C /* zip_source_crc.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC722A15B1B25E00236D3C /* zip_source_crc.c */; };
- 4BDC727E15B1B25E00236D3C /* zip_source_deflate.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC722B15B1B25E00236D3C /* zip_source_deflate.c */; };
4BDC727F15B1B25E00236D3C /* zip_source_error.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC722C15B1B25E00236D3C /* zip_source_error.c */; };
4BDC728015B1B25E00236D3C /* zip_source_file.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC722D15B1B25E00236D3C /* zip_source_file.c */; };
4BDC728115B1B25E00236D3C /* zip_source_filep.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BDC722E15B1B25E00236D3C /* zip_source_filep.c */; };
3D7E35401B33063600022624 /* in-memory.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "in-memory.c"; sourceTree = "<group>"; };
3D7E35421B33063600022624 /* windows-open.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "windows-open.c"; sourceTree = "<group>"; };
3D7E35471B33076C00022624 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
- 3D9284801C309510001EABA7 /* zip_hash.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip_hash.c; sourceTree = "<group>"; };
+ 3D9284801C309510001EABA7 /* zip_hash.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip_hash.c; sourceTree = "<group>"; usesTabs = 1; };
4B01D68B15B2F3F1002D5007 /* libzip.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = libzip.framework; sourceTree = BUILT_PRODUCTS_DIR; };
4B01D6FD15B2F4B1002D5007 /* zipmerge */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = zipmerge; sourceTree = BUILT_PRODUCTS_DIR; };
4B01D70815B2F4CF002D5007 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk/usr/lib/libz.dylib; sourceTree = DEVELOPER_DIR; };
4B01D72115B2F572002D5007 /* zipcmp.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = zipcmp.c; sourceTree = "<group>"; };
4B01D72215B2F572002D5007 /* zipmerge.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = zipmerge.c; sourceTree = "<group>"; };
4B01D73D15B2FB6B002D5007 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; };
+ 4B0454B41E8E3DF7002FA1F9 /* zip_algorithm_bzip2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip_algorithm_bzip2.c; sourceTree = "<group>"; };
+ 4B0454B51E8E3DF7002FA1F9 /* zip_algorithm_deflate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip_algorithm_deflate.c; sourceTree = "<group>"; };
+ 4B0454B61E8E3DF7002FA1F9 /* zip_source_compress.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip_source_compress.c; sourceTree = "<group>"; };
+ 4B0454B71E8E3DF7002FA1F9 /* zip_source_get_compression_flags.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip_source_get_compression_flags.c; sourceTree = "<group>"; };
4B1ABD1A1A2E5DA700C93867 /* links */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = links; sourceTree = "<group>"; };
4B1ABD1B1A2E5E4D00C93867 /* handle_links */ = {isa = PBXFileReference; explicitFileType = text.script.perl; fileEncoding = 4; path = handle_links; sourceTree = "<group>"; };
4B1E46E51A08CB7600A376D2 /* zip_error_code_system.mdoc */ = {isa = PBXFileReference; lastKnownFileType = text; path = zip_error_code_system.mdoc; sourceTree = "<group>"; };
4B28AA2115BACC3900D0C17D /* ziptorrent.mdoc */ = {isa = PBXFileReference; lastKnownFileType = text; path = ziptorrent.mdoc; sourceTree = "<group>"; };
4B28AA2215BAD4E200D0C17D /* API-CHANGES */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "API-CHANGES"; sourceTree = "<group>"; };
4B28AA2315BAD4E200D0C17D /* AUTHORS */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = AUTHORS; sourceTree = "<group>"; };
- 4B28AA2415BAD4E200D0C17D /* NEWS */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = NEWS; sourceTree = "<group>"; };
- 4B28AA2515BAD4E200D0C17D /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ 4B28AA2415BAD4E200D0C17D /* NEWS.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = NEWS.md; sourceTree = "<group>"; };
+ 4B28AA2515BAD4E200D0C17D /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
4B28AA2615BAD4E200D0C17D /* THANKS */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = THANKS; sourceTree = "<group>"; };
- 4B28AA2715BAD4E200D0C17D /* TODO */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = TODO; sourceTree = "<group>"; };
+ 4B28AA2715BAD4E200D0C17D /* TODO.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = TODO.md; sourceTree = "<group>"; };
4B3A5F4A1DF96D83005A53A1 /* gladman-fcrypt */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "gladman-fcrypt"; sourceTree = "<group>"; };
4B3A5F4B1DF96D83005A53A1 /* gladman-fcrypt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "gladman-fcrypt.c"; sourceTree = "<group>"; };
4B3A5F4C1DF96D83005A53A1 /* gladman-fcrypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gladman-fcrypt.h"; sourceTree = "<group>"; };
4BD6CB5C19E6A5D900710654 /* source_hole.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = source_hole.c; sourceTree = "<group>"; };
4BD6CB5E19E71B3B00710654 /* hole.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = hole.c; sourceTree = "<group>"; };
4BD6CB6C19E71CD100710654 /* hole */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = hole; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4BD708781EB1CF73003F351F /* zip_progress.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip_progress.c; sourceTree = "<group>"; };
4BDC71E015B182B200236D3C /* libzip_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = libzip_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
4BDC71F115B1B25E00236D3C /* zip_add_dir.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_add_dir.c; path = ../lib/zip_add_dir.c; sourceTree = "<group>"; };
4BDC71F215B1B25E00236D3C /* zip_add_entry.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_add_entry.c; path = ../lib/zip_add_entry.c; sourceTree = "<group>"; };
4BDC721315B1B25E00236D3C /* zip_fread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_fread.c; path = ../lib/zip_fread.c; sourceTree = "<group>"; };
4BDC721415B1B25E00236D3C /* zip_get_archive_comment.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_get_archive_comment.c; path = ../lib/zip_get_archive_comment.c; sourceTree = "<group>"; };
4BDC721515B1B25E00236D3C /* zip_get_archive_flag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_get_archive_flag.c; path = ../lib/zip_get_archive_flag.c; sourceTree = "<group>"; };
- 4BDC721615B1B25E00236D3C /* zip_get_compression_implementation.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_get_compression_implementation.c; path = ../lib/zip_get_compression_implementation.c; sourceTree = "<group>"; };
4BDC721715B1B25E00236D3C /* zip_get_encryption_implementation.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_get_encryption_implementation.c; path = ../lib/zip_get_encryption_implementation.c; sourceTree = "<group>"; };
4BDC721815B1B25E00236D3C /* zip_get_file_comment.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_get_file_comment.c; path = ../lib/zip_get_file_comment.c; sourceTree = "<group>"; };
4BDC721915B1B25E00236D3C /* zip_get_name.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_get_name.c; path = ../lib/zip_get_name.c; sourceTree = "<group>"; };
4BDC721C15B1B25E00236D3C /* zip_memdup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_memdup.c; path = ../lib/zip_memdup.c; sourceTree = "<group>"; };
4BDC721D15B1B25E00236D3C /* zip_name_locate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_name_locate.c; path = ../lib/zip_name_locate.c; sourceTree = "<group>"; };
4BDC721E15B1B25E00236D3C /* zip_new.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_new.c; path = ../lib/zip_new.c; sourceTree = "<group>"; };
- 4BDC721F15B1B25E00236D3C /* zip_open.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_open.c; path = ../lib/zip_open.c; sourceTree = "<group>"; };
+ 4BDC721F15B1B25E00236D3C /* zip_open.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_open.c; path = ../lib/zip_open.c; sourceTree = "<group>"; usesTabs = 1; };
4BDC722015B1B25E00236D3C /* zip_rename.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_rename.c; path = ../lib/zip_rename.c; sourceTree = "<group>"; };
4BDC722115B1B25E00236D3C /* zip_replace.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_replace.c; path = ../lib/zip_replace.c; sourceTree = "<group>"; };
4BDC722215B1B25E00236D3C /* zip_set_archive_comment.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_set_archive_comment.c; path = ../lib/zip_set_archive_comment.c; sourceTree = "<group>"; };
4BDC722815B1B25E00236D3C /* zip_source_buffer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_source_buffer.c; path = ../lib/zip_source_buffer.c; sourceTree = "<group>"; };
4BDC722915B1B25E00236D3C /* zip_source_close.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_source_close.c; path = ../lib/zip_source_close.c; sourceTree = "<group>"; };
4BDC722A15B1B25E00236D3C /* zip_source_crc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_source_crc.c; path = ../lib/zip_source_crc.c; sourceTree = "<group>"; };
- 4BDC722B15B1B25E00236D3C /* zip_source_deflate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_source_deflate.c; path = ../lib/zip_source_deflate.c; sourceTree = "<group>"; };
4BDC722C15B1B25E00236D3C /* zip_source_error.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_source_error.c; path = ../lib/zip_source_error.c; sourceTree = "<group>"; };
4BDC722D15B1B25E00236D3C /* zip_source_file.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_source_file.c; path = ../lib/zip_source_file.c; sourceTree = "<group>"; };
4BDC722E15B1B25E00236D3C /* zip_source_filep.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_source_filep.c; path = ../lib/zip_source_filep.c; sourceTree = "<group>"; };
children = (
4B28AA2215BAD4E200D0C17D /* API-CHANGES */,
4B28AA2315BAD4E200D0C17D /* AUTHORS */,
- 4B28AA2415BAD4E200D0C17D /* NEWS */,
- 4B28AA2515BAD4E200D0C17D /* README */,
+ 4B28AA2415BAD4E200D0C17D /* NEWS.md */,
+ 4B28AA2515BAD4E200D0C17D /* README.md */,
4B28AA2615BAD4E200D0C17D /* THANKS */,
- 4B28AA2715BAD4E200D0C17D /* TODO */,
+ 4B28AA2715BAD4E200D0C17D /* TODO.md */,
);
name = info;
path = ..;
4BDC71F115B1B25E00236D3C /* zip_add_dir.c */,
4BDC71F215B1B25E00236D3C /* zip_add_entry.c */,
4BDC71F315B1B25E00236D3C /* zip_add.c */,
+ 4B0454B41E8E3DF7002FA1F9 /* zip_algorithm_bzip2.c */,
+ 4B0454B51E8E3DF7002FA1F9 /* zip_algorithm_deflate.c */,
4BCB434119E9347E0067FAA3 /* zip_buffer.c */,
4BDC71F415B1B25E00236D3C /* zip_close.c */,
4BDC71F515B1B25E00236D3C /* zip_delete.c */,
4B3A5F4E1DF96D83005A53A1 /* zip_ftell.c */,
4BDC721415B1B25E00236D3C /* zip_get_archive_comment.c */,
4BDC721515B1B25E00236D3C /* zip_get_archive_flag.c */,
- 4BDC721615B1B25E00236D3C /* zip_get_compression_implementation.c */,
4BDC721715B1B25E00236D3C /* zip_get_encryption_implementation.c */,
4BDC721815B1B25E00236D3C /* zip_get_file_comment.c */,
4BDC721915B1B25E00236D3C /* zip_get_name.c */,
4BDC721D15B1B25E00236D3C /* zip_name_locate.c */,
4BDC721E15B1B25E00236D3C /* zip_new.c */,
4BDC721F15B1B25E00236D3C /* zip_open.c */,
+ 4BD708781EB1CF73003F351F /* zip_progress.c */,
736ED9B81E3D688C00C36873 /* zip_random_unix.c */,
4BDC722015B1B25E00236D3C /* zip_rename.c */,
4BDC722115B1B25E00236D3C /* zip_replace.c */,
4BD5053219A0116D007DD28A /* zip_source_call.c */,
4BDC722915B1B25E00236D3C /* zip_source_close.c */,
4BCF301B199A2F820064207B /* zip_source_commit_write.c */,
+ 4B0454B61E8E3DF7002FA1F9 /* zip_source_compress.c */,
4BDC722A15B1B25E00236D3C /* zip_source_crc.c */,
- 4BDC722B15B1B25E00236D3C /* zip_source_deflate.c */,
4BDC722C15B1B25E00236D3C /* zip_source_error.c */,
4BDC722D15B1B25E00236D3C /* zip_source_file.c */,
4BDC722E15B1B25E00236D3C /* zip_source_filep.c */,
4BDC722F15B1B25E00236D3C /* zip_source_free.c */,
4BDC723015B1B25E00236D3C /* zip_source_function.c */,
+ 4B0454B71E8E3DF7002FA1F9 /* zip_source_get_compression_flags.c */,
4BE402AC19D94AE400298248 /* zip_source_is_deleted.c */,
4BDC723115B1B25E00236D3C /* zip_source_layered.c */,
4BDC723215B1B25E00236D3C /* zip_source_open.c */,
4BCF3039199ABDDA0064207B /* zip_source_tell_write.c in Sources */,
4B01D6A615B2F46B002D5007 /* zip_add_dir.c in Sources */,
4B972052188EBE85002FAFAD /* zip_file_set_external_attributes.c in Sources */,
+ 4B0454BA1E8E3E08002FA1F9 /* zip_source_compress.c in Sources */,
4BCF3024199A2F820064207B /* zip_source_begin_write.c in Sources */,
4B01D6A715B2F46B002D5007 /* zip_add_entry.c in Sources */,
4B01D6A815B2F46B002D5007 /* zip_add.c in Sources */,
4B01D6A915B2F46B002D5007 /* zip_close.c in Sources */,
4B01D6AA15B2F46B002D5007 /* zip_delete.c in Sources */,
4B01D6AB15B2F46B002D5007 /* zip_dir_add.c in Sources */,
+ 4BD7087A1EB1CF73003F351F /* zip_progress.c in Sources */,
4B01D6AC15B2F46B002D5007 /* zip_dirent.c in Sources */,
4B01D6AD15B2F46B002D5007 /* zip_discard.c in Sources */,
+ 4B0454B81E8E3E02002FA1F9 /* zip_source_get_compression_flags.c in Sources */,
4B01D6AE15B2F46B002D5007 /* zip_entry.c in Sources */,
4B01D6AF15B2F46B002D5007 /* zip_err_str.c in Sources */,
4B3A5F521DF96EB4005A53A1 /* zip_fseek.c in Sources */,
4B01D6BD15B2F46B002D5007 /* zip_file_get_comment.c in Sources */,
4B01D6BE15B2F46B002D5007 /* zip_file_get_offset.c in Sources */,
4B01D6BF15B2F46B002D5007 /* zip_file_rename.c in Sources */,
+ 4B0454BD1E8E3E24002FA1F9 /* zip_algorithm_deflate.c in Sources */,
4B01D6C015B2F46B002D5007 /* zip_file_replace.c in Sources */,
4B01D6C115B2F46B002D5007 /* zip_file_set_comment.c in Sources */,
4BCF3033199ABD3A0064207B /* zip_source_remove.c in Sources */,
736ED9BF1E3D6B7C00C36873 /* zip_file_set_encryption.c in Sources */,
4B01D6C915B2F46B002D5007 /* zip_get_archive_comment.c in Sources */,
4B01D6CA15B2F46B002D5007 /* zip_get_archive_flag.c in Sources */,
+ 4B0454BC1E8E3E24002FA1F9 /* zip_algorithm_bzip2.c in Sources */,
736ED9BC1E3D6B6F00C36873 /* zip_source_winzip_aes_encode.c in Sources */,
- 4B01D6CB15B2F46B002D5007 /* zip_get_compression_implementation.c in Sources */,
4BD5053419A01BB0007DD28A /* zip_source_call.c in Sources */,
4BCF3030199A2F820064207B /* zip_source_write.c in Sources */,
4B01D6CC15B2F46B002D5007 /* zip_get_encryption_implementation.c in Sources */,
4BCB434319E9347E0067FAA3 /* zip_buffer.c in Sources */,
4B01D6DE15B2F46B002D5007 /* zip_source_close.c in Sources */,
4B01D6DF15B2F46B002D5007 /* zip_source_crc.c in Sources */,
- 4B01D6E015B2F46B002D5007 /* zip_source_deflate.c in Sources */,
4B01D6E115B2F46B002D5007 /* zip_source_error.c in Sources */,
4B01D6E215B2F46B002D5007 /* zip_source_file.c in Sources */,
4B01D6E315B2F46B002D5007 /* zip_source_filep.c in Sources */,
4BCF3038199ABDDA0064207B /* zip_source_tell_write.c in Sources */,
4BDC724415B1B25E00236D3C /* zip_add_dir.c in Sources */,
4B972051188EBE85002FAFAD /* zip_file_set_external_attributes.c in Sources */,
+ 4B0454BB1E8E3E09002FA1F9 /* zip_source_compress.c in Sources */,
4BCF3023199A2F820064207B /* zip_source_begin_write.c in Sources */,
4BDC724515B1B25E00236D3C /* zip_add_entry.c in Sources */,
4BDC724615B1B25E00236D3C /* zip_add.c in Sources */,
736ED9C11E3D6B8300C36873 /* zip_source_winzip_aes_decode.c in Sources */,
4BDC724715B1B25E00236D3C /* zip_close.c in Sources */,
4BDC724815B1B25E00236D3C /* zip_delete.c in Sources */,
+ 4BD708791EB1CF73003F351F /* zip_progress.c in Sources */,
736ED9C21E3D6B8600C36873 /* zip_source_winzip_aes_encode.c in Sources */,
4BDC724915B1B25E00236D3C /* zip_dir_add.c in Sources */,
+ 4B0454B91E8E3E03002FA1F9 /* zip_source_get_compression_flags.c in Sources */,
4BDC724A15B1B25E00236D3C /* zip_dirent.c in Sources */,
4BDC724B15B1B25E00236D3C /* zip_discard.c in Sources */,
4BDC724C15B1B25E00236D3C /* zip_entry.c in Sources */,
4BDC725B15B1B25E00236D3C /* zip_file_get_comment.c in Sources */,
4BDC725C15B1B25E00236D3C /* zip_file_get_offset.c in Sources */,
4BDC725D15B1B25E00236D3C /* zip_file_rename.c in Sources */,
+ 4B0454BF1E8E3E25002FA1F9 /* zip_algorithm_deflate.c in Sources */,
4BDC725E15B1B25E00236D3C /* zip_file_replace.c in Sources */,
4BDC725F15B1B25E00236D3C /* zip_file_set_comment.c in Sources */,
4BCF3032199ABD3A0064207B /* zip_source_remove.c in Sources */,
4BDC726615B1B25E00236D3C /* zip_fread.c in Sources */,
4BDC726715B1B25E00236D3C /* zip_get_archive_comment.c in Sources */,
4BDC726815B1B25E00236D3C /* zip_get_archive_flag.c in Sources */,
- 4BDC726915B1B25E00236D3C /* zip_get_compression_implementation.c in Sources */,
736ED9C01E3D6B8000C36873 /* zip_random_unix.c in Sources */,
+ 4B0454BE1E8E3E25002FA1F9 /* zip_algorithm_bzip2.c in Sources */,
4BD5053319A0116D007DD28A /* zip_source_call.c in Sources */,
4BCF302F199A2F820064207B /* zip_source_write.c in Sources */,
4BDC726A15B1B25E00236D3C /* zip_get_encryption_implementation.c in Sources */,
4BCB434219E9347E0067FAA3 /* zip_buffer.c in Sources */,
4BDC727C15B1B25E00236D3C /* zip_source_close.c in Sources */,
4BDC727D15B1B25E00236D3C /* zip_source_crc.c in Sources */,
- 4BDC727E15B1B25E00236D3C /* zip_source_deflate.c in Sources */,
4BDC727F15B1B25E00236D3C /* zip_source_error.c in Sources */,
4BDC728015B1B25E00236D3C /* zip_source_file.c in Sources */,
4BDC728115B1B25E00236D3C /* zip_source_filep.c in Sources */,