Implement I/O abstraction layer. Finally.
diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a55636..643869e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -2,8 +2,7 @@ # 1. pkgconfig file not yet built. # 2. installation not tested. # 3. Problems generating html pages. -# 4. distribution tarball not checked for unwanted/missing content. -# 5. create usable libtool .la file +# 4. create usable libtool .la file CMAKE_MINIMUM_REQUIRED(VERSION 2.6) @@ -93,60 +92,14 @@ ADD_SUBDIRECTORY(src) ADD_SUBDIRECTORY(regress) - # TODO: pkgconfig file -# installation - -# TODO: pkgconfig file - -# packaging - -SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "library for manipulating zip archives") -SET(CPACK_PACKAGE_VENDOR "Dieter Baron <dillo@giga.or.at> and Thomas Klausner <tk@giga.or.at>") -SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README") -SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") -SET(CPACK_PACKAGE_VERSION_MAJOR ${PACKAGE_VERSION_MAJOR}) -SET(CPACK_PACKAGE_VERSION_MINOR ${PACKAGE_VERSION_MINOR}) -SET(CPACK_PACKAGE_VERSION_PATCH ${PACKAGE_VERSION_PATCH}) -SET(CPACK_SOURCE_PACKAGE_FILE_NAME ${PACKAGE_NAME}-${PACKAGE_VERSION}) -SET(CPACK_GENERATOR "TGZ") -SET(CPACK_SOURCE_GENERATOR "TGZ") -SET(CPACK_SOURCE_IGNORE_FILES - ".a$" - ".cmake$" - ".o$" - ".so$" - "/.deps/" - "/.libs/" - "/CMakeFiles/" - "/CVS/" - "/autom4te.cache/" - "/build" - "/broken" - "/docs/" - "AdditionalInfo.txt$" - "CMakeCache.txt$" - "Makefile$" - "\\\\.sh$" - "_CPack_" - "config.h$" - "config.log$" - "config.status$" - "html$" - "install_manifest.txt$" - "stamp-h1$" - "tar.bz2" - "tar.gz" - "~$" -) -SET(CPACK_SOURCE_STRIP_FILES "") -INCLUDE(CPack) - # write out config file CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/cmake-config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/cmake-zipconf.h.in ${CMAKE_CURRENT_BINARY_DIR}/zipconf.h) +# installation + INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/zipconf.h DESTINATION lib/libzip/include)
diff --git a/Makefile.am b/Makefile.am index 4c1db88..09da711 100644 --- a/Makefile.am +++ b/Makefile.am
@@ -3,7 +3,7 @@ ACLOCAL_AMFLAGS= -I m4 -SUBDIRS=lib src man regress +SUBDIRS=lib man src regress examples pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libzip.pc
diff --git a/TODO b/TODO index 133e970..1733d7e 100644 --- a/TODO +++ b/TODO
@@ -48,7 +48,6 @@ . local headers come before central dir - support for old compression methods????? -- append to files (for self-extracting files) Bugs @@ -124,6 +123,10 @@ * (strerror) * (unchange) * (unchange_all) +* open(ZIP_RDONLY) +* I/O abstraction layer + zip_open_from_source +* read two zip entries interleaved I/O Methods @@ -155,14 +158,23 @@ Used after all data has been written successfully. (On POSIX systems, this will replace the original file with the temporary file, adapting permissions etc.) + +ZIP_SOURCE_REMOVE + Zip archive is empty. Is responsible for removing file, if + appropriate. + ZIP_SOURCE_ROLLBACK_WRITE + Used to reset the zip archive to the previous state (e.g. because writing failed) to restore original data if possible; - return an errohis will + return an error otherwise. (On POSIX systems, this will delete the temporary file.) ZIP_SOURCE_SEEK Set position for next read or write, a la fseek(3). +ZIP_SOURCE_TELL + Report current position, a la ftell(3). + ZIP_SOURCE_SUPPORTS Query which commands are supported for this stream. If a file cannot be written to, this will report ZIP_SOURCE_BEGIN_WRITE @@ -179,3 +191,64 @@ Once the details are finalized, we'll ask for volunteers for writing a Windows specific implementation. + +zip_source_XXX -> [I] +[I] -> OPEN -> [R] +[R] -> (SEEK|TELL|READ|STAT)* -> [R] +[R] -> CLOSE -> [I] +[I] -> BEGIN_WRITE -> [W] +[W] -> (SEEK|TELL|WRITE)* -> [W] +[W] -> (COMMIT_WRITE|ROLLBACK_WRITE) -> [I] +[IR] -> REMOVE -> [X] +[I] -> STAT -> [I] + +(no state change in case of error) + +always: +* -> ERROR -> \1 +* -> SUPPORTS -> \1 +* -> FREE + + +[-,-] +[R,-] +[-,W] +[R,W] + +zip_source_XXX -> [-,-] +[-,y] -> OPEN -> [R,y] +[R,y] -> (SEEK|TELL|READ|STAT)* -> [R,y] +[R,y] -> CLOSE -> [-,y] +[x,-] -> BEGIN_WRITE -> [x,W] +[x,W] -> (SEEK_WRITE|TELL_WRITE|WRITE)* -> [x,W] +[x,W] -> (COMMIT_WRITE|ROLLBACK_WRITE) -> [x,-] +[x,y] -> REMOVE -> [-,-] +[x,y] -> STAT -> [x,y] +[x,y] -> ERROR -> [x,y] +[x,y] -> SUPPORTS -> [x,y] +[x,y] -> FREE + +- document: zip_source_write: length can't be > ZIP_INT64_MAX +- document: ZIP_SOURCE_CLOSE implementation can't return error + + +- check for INT_MAX, UINT_MAX + +plan for merge: + +after merge: +- direct reference to source and from upper layer are equivalent: only close/free if all are gone. +- only allow multiple upper layers for sources that support seek +- cache supported state in struct zip_source and check in _zip_source_call before calling +- style cleanup (xxx_t instead of struct xxx) +- adapt man pages + - zip_source_is_deleted + - zip_source_stat + - zip_source_open + - zip_source_close + - zip_source_read + - zip_source_make_command_bitmap + - zip_error_set + - zip_error_to_data +- ask on libzip-discuss whether Windows backend will use stdio, make plan for avoiding code duplication with Unix backend +- re-implement fix for OS X sandboxing (zip_archive_set_tempdir).
diff --git a/configure.ac b/configure.ac index c3e5f4a..ee2a636 100644 --- a/configure.ac +++ b/configure.ac
@@ -115,6 +115,7 @@ AC_CONFIG_FILES([Makefile libzip.pc libzip-uninstalled.pc + examples/Makefile man/Makefile lib/Makefile regress/Makefile
diff --git a/examples/Makefile.am b/examples/Makefile.am new file mode 100644 index 0000000..dc674a0 --- /dev/null +++ b/examples/Makefile.am
@@ -0,0 +1 @@ +EXTRA_DIST=in-memory.c
diff --git a/examples/in-memory.c b/examples/in-memory.c new file mode 100644 index 0000000..2c76f2c --- /dev/null +++ b/examples/in-memory.c
@@ -0,0 +1,218 @@ +/* + in-memory.c -- modify zip file in memory + Copyright (C) 2014 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 <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> + +#include <zip.h> + +static int +get_data(void **datap, size_t *sizep, const char *archive) +{ + /* example implementation that reads data from file */ + struct stat st; + FILE *fp; + + if (stat(archive, &st) < 0) { + if (errno != ENOENT) { + fprintf(stderr, "can't stat %s: %s\n", archive, strerror(errno)); + return -1; + } + + *datap = NULL; + *sizep = 0; + + return 0; + } + + if ((*datap = malloc(st.st_size)) == NULL) { + fprintf(stderr, "can't allocate buffer\n"); + return -1; + } + + if ((fp=fopen(archive, "r")) == NULL) { + free(*datap); + fprintf(stderr, "can't open %s: %s\n", archive, strerror(errno)); + return -1; + } + + if (fread(*datap, 1, st.st_size, fp) < st.st_size) { + free(*datap); + fprintf(stderr, "can't read %s: %s\n", archive, strerror(errno)); + return -1; + } + + fclose(fp); + + *sizep = st.st_size; + return 0; +} + +static int +modify_archive(zip_t *za) +{ + /* modify the archive */ + return 0; +} + + +static int +use_data(void *data, size_t size, const char *archive) +{ + /* example implementation that writes data to file */ + FILE *fp; + + if (data == NULL) { + if (remove(archive) < 0 && errno != ENOENT) { + fprintf(stderr, "can't remove %s: %s\n", archive, strerror(errno)); + return -1; + } + return 0; + } + + if ((fp = fopen(archive, "wb")) == NULL) { + fprintf(stderr, "can't open %s: %s\n", archive, strerror(errno)); + return -1; + } + if (fwrite(data, 1, size, fp) < size) { + fprintf(stderr, "can't write %s: %s\n", archive, strerror(errno)); + return -1; + } + if (fclose(fp) < 0) { + fprintf(stderr, "can't write %s: %s\n", archive, strerror(errno)); + return -1; + } + + return 0; +} + + +int +main(int argc, char *argv[]) +{ + const char *archive; + zip_source_t *src; + zip_t *za; + zip_error_t error; + void *data; + size_t size; + + if (argc < 2) { + fprintf(stderr, "usage: %s archive\n", argv[0]); + return 1; + } + archive = argv[1]; + + /* get buffer with zip archive inside */ + if (get_data(&data, &size, archive) < 0) { + return 1; + } + + zip_error_init(&error); + /* create source from buffer */ + if ((src = zip_source_buffer_create(data, size, 1, &error)) == NULL) { + fprintf(stderr, "can't create source: %s\n", zip_error_strerror(&error)); + free(data); + zip_error_fini(&error); + return 1; + } + + /* open zip archive from source */ + if ((za = zip_open_from_source(src, 0, &error)) == NULL) { + fprintf(stderr, "can't open zip from source: %s\n", zip_error_strerror(&error)); + zip_source_free(src); + zip_error_fini(&error); + return 1; + } + zip_error_fini(&error); + + /* we'll want to read the data back after zip_close */ + zip_source_keep(src); + + /* modify archive */ + modify_archive(za); + + /* close archive */ + if (zip_close(za) < 0) { + fprintf(stderr, "can't close zip archive '%s': %s\n", archive, zip_strerror(za)); + return 1; + } + + + /* copy new archive to buffer */ + + if (zip_source_is_deleted(src)) { + /* new archive is empty, thus no data */ + data = NULL; + } + else { + zip_stat_t zst; + + if (zip_source_stat(src, &zst) < 0) { + fprintf(stderr, "can't stat source: %s\n", zip_error_strerror(zip_source_error(src))); + return 1; + } + + size = zst.size; + + if (zip_source_open(src) < 0) { + fprintf(stderr, "can't open source: %s\n", zip_error_strerror(zip_source_error(src))); + return 1; + } + if ((data = malloc(size)) == NULL) { + fprintf(stderr, "malloc failed: %s\n", strerror(errno)); + zip_source_close(src); + return 1; + } + if (zip_source_read(src, data, size) < size) { + fprintf(stderr, "can't read data from source: %s\n", zip_error_strerror(zip_source_error(src))); + zip_source_close(src); + free(data); + return 1; + } + zip_source_close(src); + } + + /* we're done with src */ + zip_source_free(src); + + /* use new data */ + use_data(data, size, archive); + + free(data); + + return 0; +}
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index b145230..d6867d0 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt
@@ -99,6 +99,7 @@ zip_get_name.c zip_get_num_entries.c zip_get_num_files.c + zip_io_util.c zip_memdup.c zip_name_locate.c zip_new.c @@ -111,8 +112,11 @@ zip_set_file_comment.c zip_set_file_compression.c zip_set_name.c + zip_source_begin_write.c zip_source_buffer.c + zip_source_call.c zip_source_close.c + zip_source_commit_write.c zip_source_crc.c zip_source_deflate.c zip_source_error.c @@ -120,13 +124,22 @@ zip_source_filep.c zip_source_free.c zip_source_function.c + zip_source_is_deleted.c zip_source_layered.c zip_source_open.c zip_source_pkware.c zip_source_pop.c zip_source_read.c + zip_source_remove.c + zip_source_rollback_write.c + zip_source_seek.c + zip_source_seek_write.c zip_source_stat.c + zip_source_supports.c + zip_source_tell.c + zip_source_tell_write.c zip_source_window.c + zip_source_write.c zip_source_zip.c zip_source_zip_new.c zip_stat.c @@ -161,6 +174,6 @@ SET_TARGET_PROPERTIES(zip PROPERTIES VERSION 3.0 SOVERSION 3 ) TARGET_LINK_LIBRARIES(zip ${ZLIB_LIBRARY}) INSTALL(TARGETS zip - ARCHIVE DESTINATION lib - LIBRARY DESTINATION lib) + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib) #CREATE_LIBTOOL_FILE(zip lib)
diff --git a/lib/Makefile.am b/lib/Makefile.am index c258f0c..b76d897 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am
@@ -57,6 +57,7 @@ zip_get_num_entries.c \ zip_get_num_files.c \ zip_get_name.c \ + zip_io_util.c \ zip_memdup.c \ zip_name_locate.c \ zip_new.c \ @@ -69,8 +70,11 @@ zip_set_file_comment.c \ zip_set_file_compression.c \ zip_set_name.c \ + zip_source_begin_write.c \ zip_source_buffer.c \ + zip_source_call.c \ zip_source_close.c \ + zip_source_commit_write.c \ zip_source_crc.c \ zip_source_deflate.c \ zip_source_error.c \ @@ -78,13 +82,22 @@ zip_source_filep.c \ zip_source_free.c \ zip_source_function.c \ + zip_source_is_deleted.c \ zip_source_layered.c \ zip_source_open.c \ zip_source_pkware.c \ zip_source_pop.c \ zip_source_read.c \ + zip_source_remove.c \ + zip_source_rollback_write.c \ + zip_source_seek.c \ + zip_source_seek_write.c \ zip_source_stat.c \ + zip_source_supports.c \ + zip_source_tell.c \ + zip_source_tell_write.c \ zip_source_window.c \ + zip_source_write.c \ zip_source_zip.c \ zip_source_zip_new.c \ zip_stat.c \
diff --git a/lib/zip.h b/lib/zip.h index 644af2f..3b51208 100644 --- a/lib/zip.h +++ b/lib/zip.h
@@ -51,6 +51,9 @@ #ifdef __cplusplus extern "C" { +#if 0 +} /* fix autoindent */ +#endif #endif #include <zipconf.h> @@ -65,6 +68,7 @@ #define ZIP_EXCL 2 #define ZIP_CHECKCONS 4 #define ZIP_TRUNCATE 8 +#define ZIP_RDONLY 16 /* flags for zip_name_locate, zip_fopen, zip_stat, ... */ @@ -121,7 +125,7 @@ #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 EOF */ +#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 */ @@ -132,6 +136,9 @@ #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 */ /* type of system error value */ @@ -205,15 +212,41 @@ enum zip_source_cmd { - ZIP_SOURCE_OPEN, /* prepare for reading */ - ZIP_SOURCE_READ, /* read data */ - ZIP_SOURCE_CLOSE, /* reading is done */ - ZIP_SOURCE_STAT, /* get meta information */ - ZIP_SOURCE_ERROR, /* get error information */ - ZIP_SOURCE_FREE /* cleanup and free resources */ + ZIP_SOURCE_OPEN, /* prepare for reading */ + ZIP_SOURCE_READ, /* read data */ + ZIP_SOURCE_CLOSE, /* reading is done */ + ZIP_SOURCE_STAT, /* get meta information */ + ZIP_SOURCE_ERROR, /* get error information */ + ZIP_SOURCE_FREE, /* cleanup and free resources */ + ZIP_SOURCE_SEEK, /* set position for reading */ + ZIP_SOURCE_TELL, /* get read position */ + ZIP_SOURCE_BEGIN_WRITE, /* prepare for writing */ + ZIP_SOURCE_COMMIT_WRITE, /* writing is done */ + ZIP_SOURCE_ROLLBACK_WRITE, /* discard written changes */ + ZIP_SOURCE_WRITE, /* write data */ + ZIP_SOURCE_SEEK_WRITE, /* set position for writing */ + ZIP_SOURCE_TELL_WRITE, /* get write position */ + ZIP_SOURCE_SUPPORTS, /* check whether source supports command */ + ZIP_SOURCE_REMOVE /* remove file */ }; +typedef enum zip_source_cmd zip_source_cmd_t; -#define ZIP_SOURCE_ERR_LOWER -2 +/* for use by sources */ +struct zip_source_args_seek { + zip_int64_t offset; + int whence; +}; +typedef struct zip_source_args_seek zip_source_args_seek_t; +#define ZIP_SOURCE_GET_ARGS(type, data, len, error) ((len) < sizeof(type) ? zip_error_set((error), ZIP_ER_INVAL, 0), NULL : (type *)(data)) + + +/* error information */ +/* use zip_error_*() to access */ +struct zip_error { + int zip_err; /* libzip error code (ZIP_ER_*) */ + int sys_err; /* copy of errno (E*) or zlib error code */ + char *str; /* string representation or NULL */ +}; #define ZIP_STAT_NAME 0x0001u #define ZIP_STAT_INDEX 0x0002u @@ -242,6 +275,12 @@ struct zip_file; struct zip_source; +typedef struct zip zip_t; +typedef struct zip_error zip_error_t; +typedef struct zip_file zip_file_t; +typedef struct zip_source zip_source_t; +typedef struct zip_stat zip_stat_t; + typedef zip_uint32_t zip_flags_t; typedef zip_int64_t (*zip_source_callback)(void *, void *, zip_uint64_t, @@ -249,13 +288,16 @@ #ifndef ZIP_DISABLE_DEPRECATED -ZIP_EXTERN zip_int64_t zip_add(struct zip *, const char *, struct zip_source *); /* use zip_file_add */ +ZIP_EXTERN zip_int64_t zip_add(struct zip *, const char *, zip_source_t *); /* use zip_file_add */ ZIP_EXTERN zip_int64_t zip_add_dir(struct zip *, const char *); /* use zip_dir_add */ ZIP_EXTERN const char *zip_get_file_comment(struct zip *, zip_uint64_t, int *, int); /* use zip_file_get_comment */ ZIP_EXTERN int zip_get_num_files(struct zip *); /* use zip_get_num_entries instead */ ZIP_EXTERN int zip_rename(struct zip *, zip_uint64_t, const char *); /* use zip_file_rename */ -ZIP_EXTERN int zip_replace(struct zip *, zip_uint64_t, struct zip_source *); /* use zip_file_replace */ +ZIP_EXTERN int zip_replace(struct zip *, zip_uint64_t, zip_source_t *); /* use zip_file_replace */ ZIP_EXTERN int zip_set_file_comment(struct zip *, zip_uint64_t, const char *, int); /* use zip_file_set_comment */ +ZIP_EXTERN int zip_error_get_sys_type(int); /* use zip_error_system_type */ +ZIP_EXTERN void zip_error_get(struct zip *, int *, int *); /* use zip_get_error, zip_error_code_zip / zip_error_code_system */ +ZIP_EXTERN void zip_file_error_get(struct zip_file *, int *, int *); /* use zip_file_get_error, zip_error_code_zip / zip_error_code_system */ #endif ZIP_EXTERN int zip_archive_set_tempdir(struct zip *, const char *); @@ -263,15 +305,23 @@ ZIP_EXTERN int zip_delete(struct zip *, zip_uint64_t); ZIP_EXTERN zip_int64_t zip_dir_add(struct zip *, const char *, zip_flags_t); ZIP_EXTERN void zip_discard(struct zip *); + +ZIP_EXTERN struct zip_error *zip_get_error(struct zip *); ZIP_EXTERN void zip_error_clear(struct zip *); -ZIP_EXTERN void zip_error_get(struct zip *, int *, int *); -ZIP_EXTERN int zip_error_get_sys_type(int); +ZIP_EXTERN int zip_error_code_zip(const struct zip_error *); +ZIP_EXTERN int zip_error_code_system(const struct zip_error *); +ZIP_EXTERN void zip_error_fini(struct zip_error *); +ZIP_EXTERN void zip_error_init(struct zip_error *); +ZIP_EXTERN void zip_error_set(zip_error_t *, int, int); +ZIP_EXTERN const char *zip_error_strerror(struct zip_error *); +ZIP_EXTERN int zip_error_system_type(const struct zip_error *); +ZIP_EXTERN zip_int64_t zip_error_to_data(const zip_error_t *, void *, zip_uint64_t); ZIP_EXTERN int zip_error_to_str(char *, zip_uint64_t, int, int); + ZIP_EXTERN int zip_fclose(struct zip_file *); ZIP_EXTERN struct zip *zip_fdopen(int, int, int *); -ZIP_EXTERN zip_int64_t zip_file_add(struct zip *, const char *, struct zip_source *, zip_flags_t); +ZIP_EXTERN zip_int64_t zip_file_add(struct zip *, const char *, zip_source_t *, zip_flags_t); ZIP_EXTERN void zip_file_error_clear(struct zip_file *); -ZIP_EXTERN void zip_file_error_get(struct zip_file *, int *, int *); ZIP_EXTERN int zip_file_extra_field_delete(struct zip *, zip_uint64_t, zip_uint16_t, zip_flags_t); ZIP_EXTERN int zip_file_extra_field_delete_by_id(struct zip *, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_flags_t); ZIP_EXTERN int zip_file_extra_field_set(struct zip *, zip_uint64_t, zip_uint16_t, zip_uint16_t, const zip_uint8_t *, zip_uint16_t, zip_flags_t); @@ -280,9 +330,10 @@ ZIP_EXTERN const zip_uint8_t *zip_file_extra_field_get(struct zip *, zip_uint64_t, zip_uint16_t, zip_uint16_t *, zip_uint16_t *, zip_flags_t); ZIP_EXTERN const zip_uint8_t *zip_file_extra_field_get_by_id(struct zip *, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_uint16_t *, zip_flags_t); ZIP_EXTERN const char *zip_file_get_comment(struct zip *, zip_uint64_t, zip_uint32_t *, zip_flags_t); +ZIP_EXTERN struct zip_error *zip_file_get_error(struct zip_file *); ZIP_EXTERN int zip_file_get_external_attributes(struct zip *, zip_uint64_t, zip_flags_t, zip_uint8_t *, zip_uint32_t *); ZIP_EXTERN int zip_file_rename(struct zip *, zip_uint64_t, const char *, zip_flags_t); -ZIP_EXTERN int zip_file_replace(struct zip *, zip_uint64_t, struct zip_source *, zip_flags_t); +ZIP_EXTERN int zip_file_replace(struct zip *, zip_uint64_t, zip_source_t *, zip_flags_t); ZIP_EXTERN int zip_file_set_comment(struct zip *, zip_uint64_t, const char *, zip_uint16_t, zip_flags_t); ZIP_EXTERN int zip_file_set_external_attributes(struct zip *, zip_uint64_t, zip_flags_t, zip_uint8_t, zip_uint32_t); ZIP_EXTERN int zip_file_set_mtime(struct zip *, zip_uint64_t, time_t, zip_flags_t); @@ -298,16 +349,29 @@ ZIP_EXTERN zip_int64_t zip_get_num_entries(struct zip *, zip_flags_t); ZIP_EXTERN zip_int64_t zip_name_locate(struct zip *, const char *, zip_flags_t); ZIP_EXTERN struct zip *zip_open(const char *, int, int *); +ZIP_EXTERN struct zip *zip_open_from_source(zip_source_t *, int, struct zip_error *); ZIP_EXTERN int zip_set_archive_comment(struct zip *, const char *, zip_uint16_t); ZIP_EXTERN int zip_set_archive_flag(struct zip *, zip_flags_t, int); ZIP_EXTERN int zip_set_default_password(struct zip *, const char *); ZIP_EXTERN int zip_set_file_compression(struct zip *, zip_uint64_t, zip_int32_t, zip_uint32_t); -ZIP_EXTERN struct zip_source *zip_source_buffer(struct zip *, const void *, zip_uint64_t, int); -ZIP_EXTERN struct zip_source *zip_source_file(struct zip *, const char *, zip_uint64_t, zip_int64_t); -ZIP_EXTERN struct zip_source *zip_source_filep(struct zip *, FILE *, zip_uint64_t, zip_int64_t); -ZIP_EXTERN void zip_source_free(struct zip_source *); -ZIP_EXTERN struct zip_source *zip_source_function(struct zip *, zip_source_callback, void *); -ZIP_EXTERN struct zip_source *zip_source_zip(struct zip *, struct zip *, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t); +ZIP_EXTERN zip_source_t *zip_source_buffer(struct zip *, const void *, zip_uint64_t, int); +ZIP_EXTERN zip_source_t *zip_source_buffer_create(const void *, zip_uint64_t, int, zip_error_t *); +ZIP_EXTERN int zip_source_close(zip_source_t *); +ZIP_EXTERN zip_error_t *zip_source_error(zip_source_t *src); +ZIP_EXTERN zip_source_t *zip_source_file(struct zip *, const char *, zip_uint64_t, zip_int64_t); +ZIP_EXTERN zip_source_t *zip_source_file_create(const char *, zip_uint64_t, zip_int64_t, struct zip_error *); +ZIP_EXTERN zip_source_t *zip_source_filep(struct zip *, FILE *, zip_uint64_t, zip_int64_t); +ZIP_EXTERN zip_source_t *zip_source_filep_create(FILE *, zip_uint64_t, zip_int64_t, struct zip_error *); +ZIP_EXTERN void zip_source_free(zip_source_t *); +ZIP_EXTERN zip_source_t *zip_source_function(struct zip *, zip_source_callback, void *); +ZIP_EXTERN zip_source_t *zip_source_function_create(zip_source_callback, void *, zip_error_t *); +ZIP_EXTERN int zip_source_is_deleted(zip_source_t *); +ZIP_EXTERN void zip_source_keep(zip_source_t *); +ZIP_EXTERN zip_int64_t zip_source_make_command_bitmap(enum zip_source_cmd, ...); +ZIP_EXTERN int zip_source_open(zip_source_t *); +ZIP_EXTERN zip_int64_t zip_source_read(zip_source_t *, void *, zip_uint64_t); +ZIP_EXTERN int zip_source_stat(zip_source_t *, struct zip_stat *); +ZIP_EXTERN zip_source_t *zip_source_zip(struct zip *, struct zip *, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t); ZIP_EXTERN int zip_stat(struct zip *, const char *, zip_flags_t, struct zip_stat *); ZIP_EXTERN int zip_stat_index(struct zip *, zip_uint64_t, zip_flags_t, struct zip_stat *); ZIP_EXTERN void zip_stat_init(struct zip_stat *);
diff --git a/lib/zip_add.c b/lib/zip_add.c index 75cd79d..7574762 100644 --- a/lib/zip_add.c +++ b/lib/zip_add.c
@@ -1,6 +1,6 @@ /* zip_add.c -- add file via callback function - Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/lib/zip_add_dir.c b/lib/zip_add_dir.c index d2450bf..65abceb 100644 --- a/lib/zip_add_dir.c +++ b/lib/zip_add_dir.c
@@ -1,6 +1,6 @@ /* zip_add_dir.c -- add directory - Copyright (C) 1999-2013 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/lib/zip_add_entry.c b/lib/zip_add_entry.c index 688046b..4ead9be 100644 --- a/lib/zip_add_entry.c +++ b/lib/zip_add_entry.c
@@ -1,6 +1,6 @@ /* zip_add_entry.c -- create and init struct zip_entry - Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -47,10 +47,15 @@ if (za->nentry+1 >= za->nentry_alloc) { struct zip_entry *rentries; zip_uint64_t nalloc = za->nentry_alloc + 16; - /* TODO check for overflow */ + zip_uint64_t realloc_size = sizeof(struct zip_entry) * (size_t)nalloc; + + if (sizeof(struct zip_entry) * (size_t)za->nentry_alloc > realloc_size) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } rentries = (struct zip_entry *)realloc(za->entry, sizeof(struct zip_entry) * (size_t)nalloc); if (!rentries) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); return -1; } za->entry = rentries;
diff --git a/lib/zip_close.c b/lib/zip_close.c index 84ff9f9..1188aa6 100644 --- a/lib/zip_close.c +++ b/lib/zip_close.c
@@ -1,6 +1,6 @@ /* zip_close.c -- close zip archive and update changes - Copyright (C) 1999-2013 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -55,11 +55,10 @@ /* max deflate size increase: size + ceil(size/16k)*5+6 */ #define MAX_DEFLATE_SIZE_32 4293656963u -static int add_data(struct zip *, struct zip_source *, struct zip_dirent *, FILE *); -static int copy_data(FILE *, zip_uint64_t, FILE *, struct zip_error *); -static int copy_source(struct zip *, struct zip_source *, FILE *); -static int write_cdir(struct zip *, const struct zip_filelist *, zip_uint64_t, FILE *); -static char *_zip_create_temp_output(struct zip *, FILE **); +static int add_data(struct zip *, struct zip_source *, struct zip_dirent *); +static int copy_data(struct zip *, zip_uint64_t); +static int copy_source(struct zip *, struct zip_source *); +static int write_cdir(struct zip *, const struct zip_filelist *, zip_uint64_t); static int _zip_torrentzip_cmp(const void *, const void *); @@ -67,19 +66,12 @@ zip_close(struct zip *za) { zip_uint64_t i, j, survivors; + zip_int64_t off; int error; - char *temp; - FILE *out; -#ifndef _WIN32 - mode_t mask; -#endif struct zip_filelist *filelist; - int reopen_on_error; int new_torrentzip; int changed; - reopen_on_error = 0; - if (za == NULL) return -1; @@ -87,17 +79,9 @@ /* don't create zip files with no entries */ if (survivors == 0) { - if (za->zn && ((za->open_flags & ZIP_TRUNCATE) || (changed && za->zp))) { - int reopen = 0; - if (za->zp) { - reopen = 1; - fclose(za->zp); - za->zp = NULL; - } - if (remove(za->zn) != 0) { - _zip_error_set(&za->error, ZIP_ER_REMOVE, errno); - if (reopen) - za->zp = fopen(za->zn, "rb"); + if ((za->open_flags & ZIP_TRUNCATE) || changed) { + if (zip_source_remove(za->src) < 0) { + zip_error_set_from_source(&za->error, za->src); return -1; } } @@ -111,7 +95,7 @@ } if (survivors > za->nentry) { - _zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); return -1; } @@ -136,7 +120,7 @@ if (j >= survivors) { free(filelist); - _zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); return -1; } @@ -146,17 +130,16 @@ } if (j < survivors) { free(filelist); - _zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); return -1; } - - if ((temp=_zip_create_temp_output(za, &out)) == NULL) { + if (zip_source_begin_write(za->src) < 0) { + zip_error_set_from_source(&za->error, za->src); free(filelist); return -1; } - if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0)) qsort(filelist, (size_t)survivors, sizeof(filelist[0]), _zip_torrentzip_cmp); @@ -178,7 +161,7 @@ /* create new local directory entry */ if (entry->changes == NULL) { if ((entry->changes=_zip_dirent_clone(entry->orig)) == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); error = 1; break; } @@ -193,8 +176,11 @@ if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0)) _zip_dirent_torrent_normalize(entry->changes); - - de->offset = (zip_uint64_t)ftello(out); /* TODO: check for errors */ + if ((off = zip_source_tell_write(za->src)) < 0) { + error = 1; + break; + } + de->offset = (zip_uint64_t)off; if (new_data) { struct zip_source *zs; @@ -208,7 +194,7 @@ } /* add_data writes dirent */ - if (add_data(za, zs ? zs : entry->source, de, out) < 0) { + if (add_data(za, zs ? zs : entry->source, de) < 0) { error = 1; if (zs) zip_source_free(zs); @@ -222,7 +208,7 @@ /* when copying data, all sizes are known -> no data descriptor needed */ de->bitflags &= ~ZIP_GPBF_DATA_DESCRIPTOR; - if (_zip_dirent_write(de, out, ZIP_FL_LOCAL, &za->error) < 0) { + if (_zip_dirent_write(za, de, ZIP_FL_LOCAL) < 0) { error = 1; break; } @@ -230,12 +216,12 @@ error = 1; break; } - if ((fseeko(za->zp, (off_t)offset, SEEK_SET) < 0)) { - _zip_error_set(&za->error, ZIP_ER_SEEK, errno); + if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) { + zip_error_set_from_source(&za->error, za->src); error = 1; break; } - if (copy_data(za->zp, de->comp_size, out, &za->error) < 0) { + if (copy_data(za, de->comp_size) < 0) { error = 1; break; } @@ -243,58 +229,34 @@ } if (!error) { - if (write_cdir(za, filelist, survivors, out) < 0) + if (write_cdir(za, filelist, survivors) < 0) error = 1; } free(filelist); - if (error) { - fclose(out); - (void)remove(temp); - free(temp); - return -1; + if (!error) { + if (zip_source_commit_write(za->src) != 0) { + zip_error_set_from_source(&za->error, za->src); + error = 1; + } } - if (fclose(out) != 0) { - _zip_error_set(&za->error, ZIP_ER_CLOSE, errno); - (void)remove(temp); - free(temp); + if (error) { + zip_source_rollback_write(za->src); return -1; } - - if (za->zp) { - fclose(za->zp); - za->zp = NULL; - reopen_on_error = 1; - } - if (_zip_rename(temp, za->zn) != 0) { - _zip_error_set(&za->error, ZIP_ER_RENAME, errno); - (void)remove(temp); - free(temp); - if (reopen_on_error) { - /* ignore errors, since we're already in an error case */ - za->zp = fopen(za->zn, "rb"); - } - return -1; - } -#ifndef _WIN32 - mask = umask(0); - umask(mask); - chmod(za->zn, 0666&~mask); -#endif zip_discard(za); - free(temp); return 0; } static int -add_data(struct zip *za, struct zip_source *src, struct zip_dirent *de, FILE *ft) +add_data(struct zip *za, struct zip_source *src, struct zip_dirent *de) { - off_t offstart, offdata, offend; + zip_int64_t offstart, offdata, offend; struct zip_stat st; struct zip_source *s2; int ret; @@ -302,7 +264,7 @@ zip_flags_t flags; if (zip_source_stat(src, &st) < 0) { - _zip_error_set_from_source(&za->error, src); + zip_error_set_from_source(&za->error, src); return -1; } @@ -339,12 +301,13 @@ de->comp_size = st.comp_size; } - - offstart = ftello(ft); + if ((offstart = zip_source_tell_write(za->src)) < 0) { + return -1; + } /* as long as we don't support non-seekable output, clear data descriptor bit */ de->bitflags &= ~ZIP_GPBF_DATA_DESCRIPTOR; - if ((is_zip64=_zip_dirent_write(de, ft, flags, &za->error)) < 0) + if ((is_zip64=_zip_dirent_write(za, de, flags)) < 0) return -1; @@ -354,7 +317,7 @@ if (st.comp_method != ZIP_CM_STORE) { if ((comp_impl=_zip_get_compression_implementation(st.comp_method)) == NULL) { - _zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); + zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); return -1; } if ((s_store=comp_impl(za, src, st.comp_method, ZIP_CODEC_DECODE)) == NULL) { @@ -374,7 +337,7 @@ /* TODO: deflate 0-byte files for torrentzip? */ if (de->comp_method != ZIP_CM_STORE && ((st.valid & ZIP_STAT_SIZE) == 0 || st.size != 0)) { if ((comp_impl=_zip_get_compression_implementation(de->comp_method)) == NULL) { - _zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); + zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); zip_source_pop(s_crc); if (s_store != src) zip_source_pop(s_store); @@ -393,33 +356,40 @@ else s2 = src; - offdata = ftello(ft); - - ret = copy_source(za, s2, ft); + if ((offdata = zip_source_tell_write(za->src)) < 0) { + return -1; + } + + ret = copy_source(za, s2); if (zip_source_stat(s2, &st) < 0) ret = -1; while (s2 != src) { - if ((s2=zip_source_pop(s2)) == NULL) { - /* TODO: set erorr */ + zip_source_t *tmp = zip_source_pop(s2); + + if (tmp == NULL) { + zip_error_set_from_source(&za->error, s2); ret = -1; break; } + s2 = tmp; } if (ret < 0) return -1; - offend = ftello(ft); + if ((offend = zip_source_tell_write(za->src)) < 0) { + return -1; + } - if (fseeko(ft, offstart, SEEK_SET) < 0) { - _zip_error_set(&za->error, ZIP_ER_SEEK, errno); + if (zip_source_seek_write(za->src, offstart, SEEK_SET) < 0) { + zip_error_set_from_source(&za->error, za->src); return -1; } if ((st.valid & (ZIP_STAT_COMP_METHOD|ZIP_STAT_CRC|ZIP_STAT_SIZE)) != (ZIP_STAT_COMP_METHOD|ZIP_STAT_CRC|ZIP_STAT_SIZE)) { - _zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); return -1; } @@ -432,23 +402,23 @@ de->comp_method = st.comp_method; de->crc = st.crc; de->uncomp_size = st.size; - de->comp_size = (zip_uint64_t)(offend - offdata); + de->comp_size = (zip_uint8_t)(offend - offdata); if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0)) _zip_dirent_torrent_normalize(de); - if ((ret=_zip_dirent_write(de, ft, flags, &za->error)) < 0) + if ((ret=_zip_dirent_write(za, de, flags)) < 0) return -1; if (is_zip64 != ret) { /* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */ - _zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); return -1; } - if (fseeko(ft, offend, SEEK_SET) < 0) { - _zip_error_set(&za->error, ZIP_ER_SEEK, errno); + if (zip_source_seek_write(za->src, offend, SEEK_SET) < 0) { + zip_error_set_from_source(&za->error, za->src); return -1; } @@ -457,29 +427,18 @@ static int -copy_data(FILE *fs, zip_uint64_t len, FILE *ft, struct zip_error *error) +copy_data(struct zip *za, zip_uint64_t len) { - char buf[BUFSIZE]; - size_t n, nn; - - if (len == 0) - return 0; + zip_uint8_t buf[BUFSIZE]; + size_t n; while (len > 0) { - nn = len > sizeof(buf) ? sizeof(buf) : len > SIZE_MAX ? SIZE_MAX : (size_t)len; - if ((n=fread(buf, 1, nn, fs)) == 0) { - if (ferror(fs)) { - _zip_error_set(error, ZIP_ER_READ, errno); - return -1; - } - else { - _zip_error_set(error, ZIP_ER_EOF, 0); - return -1; - } - } + n = len > sizeof(buf) ? sizeof(buf) : len; + if (_zip_read(za->src, buf, n, &za->error) < 0) { + return -1; + } - if (fwrite(buf, 1, n, ft) != (size_t)n) { - _zip_error_set(error, ZIP_ER_WRITE, errno); + if (_zip_write(za, buf, n) < 0) { return -1; } @@ -491,31 +450,29 @@ static int -copy_source(struct zip *za, struct zip_source *src, FILE *ft) +copy_source(struct zip *za, struct zip_source *src) { - char buf[BUFSIZE]; + zip_uint8_t buf[BUFSIZE]; zip_int64_t n; int ret; if (zip_source_open(src) < 0) { - _zip_error_set_from_source(&za->error, src); + zip_error_set_from_source(&za->error, src); return -1; } ret = 0; while ((n=zip_source_read(src, buf, sizeof(buf))) > 0) { - if (fwrite(buf, 1, (size_t)n, ft) != (size_t)n) { - _zip_error_set(&za->error, ZIP_ER_WRITE, errno); + if (_zip_write(za, buf, (zip_uint64_t)n) < 0) { ret = -1; break; } } if (n < 0) { - if (ret == 0) - _zip_error_set_from_source(&za->error, src); + zip_error_set_from_source(&za->error, src); ret = -1; - } + } zip_source_close(src); @@ -524,38 +481,39 @@ static int -write_cdir(struct zip *za, const struct zip_filelist *filelist, zip_uint64_t survivors, FILE *out) +write_cdir(struct zip *za, const struct zip_filelist *filelist, zip_uint64_t survivors) { - off_t cd_start, end; - zip_int64_t size; + zip_int64_t cd_start, end, size; uLong crc; - char buf[TORRENT_CRC_LEN+1]; + zip_uint8_t buf[TORRENT_CRC_LEN+1]; - cd_start = ftello(out); + if ((cd_start = zip_source_tell_write(za->src)) < 0) { + return -1; + } - if ((size=_zip_cdir_write(za, filelist, survivors, out)) < 0) + if ((size=_zip_cdir_write(za, filelist, survivors)) < 0) { return -1; + } - end = ftello(out); + if ((end = zip_source_tell_write(za->src)) < 0) { + return -1; + } if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0) == 0) return 0; - /* fix up torrentzip comment */ - - if (_zip_filerange_crc(out, cd_start, size, &crc, &za->error) < 0) + if (_zip_filerange_crc(za->src, (zip_uint64_t)cd_start, (zip_uint64_t)size, &crc, &za->error) < 0) return -1; - snprintf(buf, sizeof(buf), "%08lX", (long)crc); + snprintf((char *)buf, sizeof(buf), "%08lX", (long)crc); - if (fseeko(out, end-TORRENT_CRC_LEN, SEEK_SET) < 0) { - _zip_error_set(&za->error, ZIP_ER_SEEK, errno); + if (zip_source_seek_write(za->src, end-TORRENT_CRC_LEN, SEEK_SET) < 0) { + zip_error_set_from_source(&za->error, za->src); return -1; } - if (fwrite(buf, TORRENT_CRC_LEN, 1, out) != 1) { - _zip_error_set(&za->error, ZIP_ER_WRITE, errno); + if (_zip_write(za, buf, TORRENT_CRC_LEN) < 0) { return -1; } @@ -589,54 +547,6 @@ } -static char * -_zip_create_temp_output(struct zip *za, FILE **outp) -{ - char *temp; - int tfd; - FILE *tfp; - - if (za->tempdir) { - if ((temp=(char *)malloc(strlen(za->tempdir)+13)) == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return NULL; - } - sprintf(temp, "%s/.zip.XXXXXX", za->tempdir); - } - else { - if ((temp=(char *)malloc(strlen(za->zn)+8)) == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return NULL; - } - sprintf(temp, "%s.XXXXXX", za->zn); - } - - if ((tfd=mkstemp(temp)) == -1) { - _zip_error_set(&za->error, ZIP_ER_TMPOPEN, errno); - free(temp); - return NULL; - } - - if ((tfp=fdopen(tfd, "r+b")) == NULL) { - _zip_error_set(&za->error, ZIP_ER_TMPOPEN, errno); - close(tfd); - (void)remove(temp); - free(temp); - return NULL; - } - -#ifdef _WIN32 - /* - According to Pierre Joye, Windows in some environments per - default creates text files, so force binary mode. - */ - _setmode(_fileno(tfp), _O_BINARY ); -#endif - - *outp = tfp; - return temp; -} - static int _zip_torrentzip_cmp(const void *a, const void *b)
diff --git a/lib/zip_delete.c b/lib/zip_delete.c index db30157..668e8b9 100644 --- a/lib/zip_delete.c +++ b/lib/zip_delete.c
@@ -1,6 +1,6 @@ /* zip_delete.c -- delete file from zip archive - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -39,12 +39,12 @@ zip_delete(struct zip *za, zip_uint64_t idx) { if (idx >= za->nentry) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } if (ZIP_IS_RDONLY(za)) { - _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); return -1; }
diff --git a/lib/zip_dir_add.c b/lib/zip_dir_add.c index d7f4ef6..a68337c 100644 --- a/lib/zip_dir_add.c +++ b/lib/zip_dir_add.c
@@ -1,6 +1,6 @@ /* zip_dir_add.c -- add directory - Copyright (C) 1999-2013 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -49,12 +49,12 @@ struct zip_source *source; if (ZIP_IS_RDONLY(za)) { - _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); return -1; } if (name == NULL) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } @@ -63,7 +63,7 @@ if (name[len-1] != '/') { if ((s=(char *)malloc(len+2)) == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); return -1; } strcpy(s, name);
diff --git a/lib/zip_dirent.c b/lib/zip_dirent.c index db051b5..c20eda2 100644 --- a/lib/zip_dirent.c +++ b/lib/zip_dirent.c
@@ -1,6 +1,6 @@ /* zip_dirent.c -- read directory entry (local or central), clean dirent - Copyright (C) 1999-2013 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -42,7 +42,6 @@ #include "zipint.h" static time_t _zip_d2u_time(zip_uint16_t, zip_uint16_t); -static struct zip_string *_zip_read_string(const unsigned char **, FILE *, zip_uint16_t, int, struct zip_error *); static struct zip_string *_zip_dirent_process_ef_utf_8(const struct zip_dirent *, zip_uint16_t, struct zip_string *); static struct zip_extra_field *_zip_ef_utf8(zip_uint16_t, struct zip_string *, struct zip_error *); @@ -70,7 +69,7 @@ zip_uint64_t i; if (nentry < cd->nentry_alloc) { - _zip_error_set(error, ZIP_ER_INTERNAL, 0); + zip_error_set(error, ZIP_ER_INTERNAL, 0); return -1; } @@ -79,7 +78,7 @@ if ((entry=((struct zip_entry *) realloc(cd->entry, sizeof(*(cd->entry))*(size_t)nentry))) == NULL) { - _zip_error_set(error, ZIP_ER_MEMORY, 0); + zip_error_set(error, ZIP_ER_MEMORY, 0); return -1; } @@ -100,14 +99,14 @@ zip_uint64_t i; if ((cd=(struct zip_cdir *)malloc(sizeof(*cd))) == NULL) { - _zip_error_set(error, ZIP_ER_MEMORY, 0); + zip_error_set(error, ZIP_ER_MEMORY, 0); return NULL; } if (nentry == 0) cd->entry = NULL; else if ((cd->entry=(struct zip_entry *)malloc(sizeof(*(cd->entry))*(size_t)nentry)) == NULL) { - _zip_error_set(error, ZIP_ER_MEMORY, 0); + zip_error_set(error, ZIP_ER_MEMORY, 0); free(cd); return NULL; } @@ -124,17 +123,18 @@ zip_int64_t -_zip_cdir_write(struct zip *za, const struct zip_filelist *filelist, zip_uint64_t survivors, FILE *fp) +_zip_cdir_write(struct zip *za, const struct zip_filelist *filelist, zip_uint64_t survivors) { - off_t off; zip_uint64_t offset, size; struct zip_string *comment; + zip_uint8_t buf[EOCDLEN + EOCD64LEN], *p; + zip_int64_t off; zip_uint64_t i; int is_zip64; int ret; - if ((off=ftello(fp)) < 0) { - _zip_error_set(&za->error, ZIP_ER_READ, errno); + if ((off = zip_source_tell_write(za->src)) < 0) { + zip_error_set_from_source(&za->error, za->src); return -1; } offset = (zip_uint64_t)off; @@ -144,14 +144,14 @@ for (i=0; i<survivors; i++) { struct zip_entry *entry = za->entry+filelist[i].idx; - if ((ret=_zip_dirent_write(entry->changes ? entry->changes : entry->orig, fp, ZIP_FL_CENTRAL, &za->error)) < 0) + if ((ret=_zip_dirent_write(za, entry->changes ? entry->changes : entry->orig, ZIP_FL_CENTRAL)) < 0) return -1; if (ret) is_zip64 = 1; } - if ((off=ftello(fp)) < 0) { - _zip_error_set(&za->error, ZIP_ER_READ, errno); + if ((off = zip_source_tell_write(za->src)) < 0) { + zip_error_set_from_source(&za->error, za->src); return -1; } size = (zip_uint64_t)off - offset; @@ -159,44 +159,45 @@ if (offset > ZIP_UINT32_MAX || survivors > ZIP_UINT16_MAX) is_zip64 = 1; + p = buf; if (is_zip64) { - fwrite(EOCD64_MAGIC, 1, 4, fp); - _zip_write8(EOCD64LEN-12, fp); - _zip_write2(45, fp); - _zip_write2(45, fp); - _zip_write4(0, fp); - _zip_write4(0, fp); - _zip_write8(survivors, fp); - _zip_write8(survivors, fp); - _zip_write8(size, fp); - _zip_write8(offset, fp); - - fwrite(EOCD64LOC_MAGIC, 1, 4, fp); - _zip_write4(0, fp); - _zip_write8(offset+size, fp); - _zip_write4(1, fp); - + _zip_put_data(&p, EOCD64_MAGIC, 4); + _zip_put_64(&p, EOCD64LEN-12); + _zip_put_16(&p, 45); + _zip_put_16(&p, 45); + _zip_put_32(&p, 0); + _zip_put_32(&p, 0); + _zip_put_64(&p, survivors); + _zip_put_64(&p, survivors); + _zip_put_64(&p, size); + _zip_put_64(&p, offset); + _zip_put_data(&p, EOCD64LOC_MAGIC, 4); + _zip_put_32(&p, 0); + _zip_put_64(&p, offset+size); + _zip_put_32(&p, 1); } - - /* clearerr(fp); */ - fwrite(EOCD_MAGIC, 1, 4, fp); - _zip_write4(0, fp); - _zip_write2(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : (zip_uint16_t)survivors, fp); - _zip_write2(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : (zip_uint16_t)survivors, fp); - _zip_write4(size >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : (zip_uint32_t)size, fp); - _zip_write4(offset >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : (zip_uint32_t)offset, fp); + + _zip_put_data(&p, EOCD_MAGIC, 4); + _zip_put_32(&p, 0); + _zip_put_16(&p, survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : (zip_uint16_t)survivors); + _zip_put_16(&p, survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : (zip_uint16_t)survivors); + _zip_put_32(&p, size >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : (zip_uint32_t)size); + _zip_put_32(&p, offset >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : (zip_uint32_t)offset); comment = za->comment_changed ? za->comment_changes : za->comment_orig; - _zip_write2(comment ? comment->length : 0, fp); - if (comment) - fwrite(comment->raw, 1, comment->length, fp); + _zip_put_16(&p, comment ? comment->length : 0); - if (ferror(fp)) { - _zip_error_set(&za->error, ZIP_ER_WRITE, errno); + if (_zip_write(za, buf, (zip_uint64_t)(p-buf)) < 0) { return -1; } + if (comment) { + if (_zip_write(za, comment->raw, comment->length) < 0) { + return -1; + } + } + return (zip_int64_t)size; } @@ -312,7 +313,7 @@ */ int -_zip_dirent_read(struct zip_dirent *zde, FILE *fp, +_zip_dirent_read(struct zip_dirent *zde, struct zip_source *src, const unsigned char **bufp, zip_uint64_t *leftp, int local, struct zip_error *error) { @@ -328,7 +329,7 @@ size = CDENTRYSIZE; if (leftp && (*leftp < size)) { - _zip_error_set(error, ZIP_ER_NOZIP, 0); + zip_error_set(error, ZIP_ER_NOZIP, 0); return -1; } @@ -337,16 +338,21 @@ cur = *bufp; } else { - /* read entry from disk */ - if ((fread(buf, 1, size, fp)<size)) { - _zip_error_set(error, ZIP_ER_READ, errno); + zip_int64_t n; + + if ((n = zip_source_read(src, buf, size)) < 0) { + zip_error_set_from_source(error, src); + return -1; + } + if ((zip_uint64_t)n != size) { + zip_error_set(error, ZIP_ER_NOZIP, errno); return -1; } cur = buf; } if (memcmp(cur, (local ? LOCAL_MAGIC : CENTRAL_MAGIC), 4) != 0) { - _zip_error_set(error, ZIP_ER_NOZIP, 0); + zip_error_set(error, ZIP_ER_NOZIP, 0); return -1; } cur += 4; @@ -356,24 +362,24 @@ _zip_dirent_init(zde); if (!local) - zde->version_madeby = _zip_read2(&cur); + zde->version_madeby = _zip_get_16(&cur); else zde->version_madeby = 0; - zde->version_needed = _zip_read2(&cur); - zde->bitflags = _zip_read2(&cur); - zde->comp_method = _zip_read2(&cur); + zde->version_needed = _zip_get_16(&cur); + zde->bitflags = _zip_get_16(&cur); + zde->comp_method = _zip_get_16(&cur); /* convert to time_t */ - dostime = _zip_read2(&cur); - dosdate = _zip_read2(&cur); + dostime = _zip_get_16(&cur); + dosdate = _zip_get_16(&cur); zde->last_mod = _zip_d2u_time(dostime, dosdate); - zde->crc = _zip_read4(&cur); - zde->comp_size = _zip_read4(&cur); - zde->uncomp_size = _zip_read4(&cur); + zde->crc = _zip_get_32(&cur); + zde->comp_size = _zip_get_32(&cur); + zde->uncomp_size = _zip_get_32(&cur); - filename_len = _zip_read2(&cur); - ef_len = _zip_read2(&cur); + filename_len = _zip_get_16(&cur); + ef_len = _zip_get_16(&cur); if (local) { comment_len = 0; @@ -382,11 +388,11 @@ zde->ext_attrib = 0; zde->offset = 0; } else { - comment_len = _zip_read2(&cur); - zde->disk_number = _zip_read2(&cur); - zde->int_attrib = _zip_read2(&cur); - zde->ext_attrib = _zip_read4(&cur); - zde->offset = _zip_read4(&cur); + comment_len = _zip_get_16(&cur); + zde->disk_number = _zip_get_16(&cur); + zde->int_attrib = _zip_get_16(&cur); + zde->ext_attrib = _zip_get_32(&cur); + zde->offset = _zip_get_32(&cur); } zde->filename = NULL; @@ -396,25 +402,29 @@ size += filename_len+ef_len+comment_len; if (leftp && (*leftp < size)) { - _zip_error_set(error, ZIP_ER_INCONS, 0); + zip_error_set(error, ZIP_ER_INCONS, 0); return -1; } if (filename_len) { - zde->filename = _zip_read_string(bufp ? &cur : NULL, fp, filename_len, 1, error); - if (!zde->filename) + zde->filename = _zip_read_string(bufp ? &cur : NULL, src, filename_len, 1, error); + if (!zde->filename) { + if (zip_error_code_zip(error) == ZIP_ER_EOF) { + zip_error_set(error, ZIP_ER_INCONS, 0); + } return -1; + } if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) { if (_zip_guess_encoding(zde->filename, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) { - _zip_error_set(error, ZIP_ER_INCONS, 0); + zip_error_set(error, ZIP_ER_INCONS, 0); return -1; } } } if (ef_len) { - zip_uint8_t *ef = _zip_read_data(bufp ? &cur : NULL, fp, ef_len, 0, error); + zip_uint8_t *ef = _zip_read_data(bufp ? &cur : NULL, src, ef_len, 0, error); if (ef == NULL) return -1; @@ -428,13 +438,13 @@ } if (comment_len) { - zde->comment = _zip_read_string(bufp ? &cur : NULL, fp, comment_len, 0, error); + zde->comment = _zip_read_string(bufp ? &cur : NULL, src, comment_len, 0, error); if (!zde->comment) return -1; if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) { if (_zip_guess_encoding(zde->comment, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) { - _zip_error_set(error, ZIP_ER_INCONS, 0); + zip_error_set(error, ZIP_ER_INCONS, 0); return -1; } } @@ -460,29 +470,28 @@ + (zde->disk_number == ZIP_UINT16_MAX) * 4; if (got_len != needed_len) { - _zip_error_set(error, ZIP_ER_INCONS, 0); + zip_error_set(error, ZIP_ER_INCONS, 0); return -1; } if (zde->uncomp_size == ZIP_UINT32_MAX) - zde->uncomp_size = _zip_read8(&ef); + zde->uncomp_size = _zip_get_64(&ef); else if (local) ef += 8; if (zde->comp_size == ZIP_UINT32_MAX) - zde->comp_size = _zip_read8(&ef); + zde->comp_size = _zip_get_64(&ef); if (!local) { if (zde->offset == ZIP_UINT32_MAX) - zde->offset = _zip_read8(&ef); + zde->offset = _zip_get_64(&ef); if (zde->disk_number == ZIP_UINT16_MAX) - zde->disk_number = _zip_read4(&ef); + zde->disk_number = _zip_get_32(&ef); } } - if (!local) { - if (zde->offset > ZIP_OFF_MAX) { - _zip_error_set(error, ZIP_ER_SEEK, EFBIG); - return -1; - } + /* zip_source_seek / zip_source_tell don't support values > ZIP_INT64_MAX */ + if (zde->offset > ZIP_INT64_MAX) { + zip_error_set(error, ZIP_ER_SEEK, EFBIG); + return -1; } zde->extra_fields = _zip_ef_remove_internal(zde->extra_fields); @@ -508,7 +517,7 @@ return str; ef++; - ef_crc = _zip_read4(&ef); + ef_crc = _zip_get_32(&ef); if (_zip_string_crc32(str) == ef_crc) { struct zip_string *ef_str = _zip_string_new(ef, ef_len-5, ZIP_FL_ENC_UTF_8, NULL); @@ -524,7 +533,7 @@ zip_int32_t -_zip_dirent_size(FILE *f, zip_uint16_t flags, struct zip_error *error) +_zip_dirent_size(zip_source_t *src, zip_uint16_t flags, zip_error_t *error) { zip_int32_t size; int local = (flags & ZIP_EF_LOCAL); @@ -534,19 +543,18 @@ size = local ? LENTRYSIZE : CDENTRYSIZE; - if (fseek(f, local ? 26 : 28, SEEK_CUR) < 0) { - _zip_error_set(error, ZIP_ER_SEEK, errno); + if (zip_source_seek(src, local ? 26 : 28, SEEK_CUR) < 0) { + zip_error_set_from_source(error, src); return -1; } - if (fread(b, (local ? 4 : 6), 1, f) != 1) { - _zip_error_set(error, ZIP_ER_READ, errno); + if (_zip_read(src, b, local ? 4 : 6, error) < 0) { return -1; } p = b; for (i=0; i<(local ? 2 : 3); i++) { - size += _zip_read2(&p); + size += _zip_get_16(&p); } return size; @@ -606,8 +614,8 @@ } -/* _zip_dirent_write(zde, fp, flags, error): - Writes zip directory entry zde to file fp. +/* _zip_dirent_write + Writes zip directory entry. If flags & ZIP_EF_LOCAL, it writes a local header instead of a central directory entry. If flags & ZIP_EF_FORCE_ZIP64, a ZIP64 extra field is written, even if not needed. @@ -617,20 +625,23 @@ */ int -_zip_dirent_write(struct zip_dirent *de, FILE *fp, zip_flags_t flags, struct zip_error *error) +_zip_dirent_write(struct zip *za, struct zip_dirent *de, zip_flags_t flags) { - unsigned short dostime, dosdate; + zip_uint16_t dostime, dosdate; enum zip_encoding_type com_enc, name_enc; struct zip_extra_field *ef; zip_uint8_t ef_zip64[24], *ef_zip64_p; int is_zip64; int is_really_zip64; + zip_uint8_t buf[CDENTRYSIZE], *p; ef = NULL; is_zip64 = 0; - fwrite((flags & ZIP_FL_LOCAL) ? LOCAL_MAGIC : CENTRAL_MAGIC, 1, 4, fp); + p = buf; + + _zip_put_data(&p, (flags & ZIP_FL_LOCAL) ? LOCAL_MAGIC : CENTRAL_MAGIC, 4); name_enc = _zip_guess_encoding(de->filename, ZIP_ENCODING_UNKNOWN); com_enc = _zip_guess_encoding(de->comment, ZIP_ENCODING_UNKNOWN); @@ -642,12 +653,12 @@ else { de->bitflags &= ~ZIP_GPBF_ENCODING_UTF_8; if (name_enc == ZIP_ENCODING_UTF8_KNOWN) { - ef = _zip_ef_utf8(ZIP_EF_UTF_8_NAME, de->filename, error); + ef = _zip_ef_utf8(ZIP_EF_UTF_8_NAME, de->filename, &za->error); if (ef == NULL) return -1; } if ((flags & ZIP_FL_LOCAL) == 0 && com_enc == ZIP_ENCODING_UTF8_KNOWN){ - struct zip_extra_field *ef2 = _zip_ef_utf8(ZIP_EF_UTF_8_COMMENT, de->comment, error); + struct zip_extra_field *ef2 = _zip_ef_utf8(ZIP_EF_UTF_8_COMMENT, de->comment, &za->error); if (ef2 == NULL) { _zip_ef_free(ef); return -1; @@ -660,18 +671,18 @@ ef_zip64_p = ef_zip64; if (flags & ZIP_FL_LOCAL) { if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX) { - _zip_poke8(de->uncomp_size, &ef_zip64_p); - _zip_poke8(de->comp_size, &ef_zip64_p); + _zip_put_64(&ef_zip64_p, de->uncomp_size); + _zip_put_64(&ef_zip64_p, de->comp_size); } } else { if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX || de->offset > ZIP_UINT32_MAX) { if (de->uncomp_size >= ZIP_UINT32_MAX) - _zip_poke8(de->uncomp_size, &ef_zip64_p); + _zip_put_64(&ef_zip64_p, de->uncomp_size); if (de->comp_size >= ZIP_UINT32_MAX) - _zip_poke8(de->comp_size, &ef_zip64_p); + _zip_put_64(&ef_zip64_p, de->comp_size); if (de->offset >= ZIP_UINT32_MAX) - _zip_poke8(de->offset, &ef_zip64_p); + _zip_put_64(&ef_zip64_p, de->offset); } } @@ -688,59 +699,70 @@ is_really_zip64 = is_zip64; if ((flags & ZIP_FL_LOCAL) == 0) - _zip_write2(is_really_zip64 ? 45 : de->version_madeby, fp); - _zip_write2(is_really_zip64 ? 45 : de->version_needed, fp); - _zip_write2(de->bitflags&0xfff9, fp); /* clear compression method specific flags */ - _zip_write2((zip_uint16_t)de->comp_method, fp); /* TODO: can it be ZIP_CM_DEFAULT? */ + _zip_put_16(&p, is_really_zip64 ? 45 : de->version_madeby); + _zip_put_16(&p, is_really_zip64 ? 45 : de->version_needed); + _zip_put_16(&p, de->bitflags&0xfff9); /* clear compression method specific flags */ + _zip_put_16(&p, (zip_uint16_t)de->comp_method); _zip_u2d_time(de->last_mod, &dostime, &dosdate); - _zip_write2(dostime, fp); - _zip_write2(dosdate, fp); + _zip_put_16(&p, dostime); + _zip_put_16(&p, dosdate); - _zip_write4(de->crc, fp); + _zip_put_32(&p, de->crc); if (de->comp_size < ZIP_UINT32_MAX) - _zip_write4((zip_uint32_t)de->comp_size, fp); + _zip_put_32(&p, (zip_uint32_t)de->comp_size); else - _zip_write4(ZIP_UINT32_MAX, fp); + _zip_put_32(&p, ZIP_UINT32_MAX); if (de->uncomp_size < ZIP_UINT32_MAX) - _zip_write4((zip_uint32_t)de->uncomp_size, fp); + _zip_put_32(&p, (zip_uint32_t)de->uncomp_size); else - _zip_write4(ZIP_UINT32_MAX, fp); + _zip_put_32(&p, ZIP_UINT32_MAX); - _zip_write2(_zip_string_length(de->filename), fp); - _zip_write2(_zip_ef_size(de->extra_fields, flags) + _zip_ef_size(ef, ZIP_EF_BOTH), fp); + _zip_put_16(&p, _zip_string_length(de->filename)); + _zip_put_16(&p, _zip_ef_size(de->extra_fields, flags) + _zip_ef_size(ef, ZIP_EF_BOTH)); if ((flags & ZIP_FL_LOCAL) == 0) { - _zip_write2(_zip_string_length(de->comment), fp); - _zip_write2((zip_uint16_t)de->disk_number, fp); - _zip_write2(de->int_attrib, fp); - _zip_write4(de->ext_attrib, fp); + _zip_put_16(&p, _zip_string_length(de->comment)); + _zip_put_16(&p, (zip_uint16_t)de->disk_number); + _zip_put_16(&p, de->int_attrib); + _zip_put_32(&p, de->ext_attrib); if (de->offset < ZIP_UINT32_MAX) - _zip_write4((zip_uint32_t)de->offset, fp); + _zip_put_32(&p, (zip_uint32_t)de->offset); else - _zip_write4(ZIP_UINT32_MAX, fp); + _zip_put_32(&p, ZIP_UINT32_MAX); } - if (de->filename) - _zip_string_write(de->filename, fp); + if (_zip_write(za, buf, (zip_uint64_t)(p-buf)) < 0) { + return -1; + } - if (ef) - _zip_ef_write(ef, ZIP_EF_BOTH, fp); - if (de->extra_fields) - _zip_ef_write(de->extra_fields, flags, fp); + if (de->filename) { + if (_zip_string_write(za, de->filename) < 0) { + return -1; + } + } + + if (ef) { + if (_zip_ef_write(za, ef, ZIP_EF_BOTH) < 0) { + return -1; + } + } + if (de->extra_fields) { + if (_zip_ef_write(za, de->extra_fields, flags) < 0) { + return -1; + } + } if ((flags & ZIP_FL_LOCAL) == 0) { - if (de->comment) - _zip_string_write(de->comment, fp); + if (de->comment) { + if (_zip_string_write(za, de->comment) < 0) { + return -1; + } + } } _zip_ef_free(ef); - if (ferror(fp)) { - _zip_error_set(error, ZIP_ER_WRITE, errno); - return -1; - } - return is_zip64; } @@ -782,13 +804,13 @@ } if ((data=(zip_uint8_t *)malloc(len+5)) == NULL) { - _zip_error_set(error, ZIP_ER_MEMORY, 0); + zip_error_set(error, ZIP_ER_MEMORY, 0); return NULL; } p = data; *(p++) = 1; - _zip_poke4(_zip_string_crc32(str), &p); + _zip_put_32(&p, _zip_string_crc32(str)); memcpy(p, raw, len); p += len; @@ -805,17 +827,17 @@ error = &za->error; if (idx >= za->nentry) { - _zip_error_set(error, ZIP_ER_INVAL, 0); + zip_error_set(error, ZIP_ER_INVAL, 0); return NULL; } if ((flags & ZIP_FL_UNCHANGED) || za->entry[idx].changes == NULL) { if (za->entry[idx].orig == NULL) { - _zip_error_set(error, ZIP_ER_INVAL, 0); + zip_error_set(error, ZIP_ER_INVAL, 0); return NULL; } if (za->entry[idx].deleted && (flags & ZIP_FL_UNCHANGED) == 0) { - _zip_error_set(error, ZIP_ER_DELETED, 0); + zip_error_set(error, ZIP_ER_DELETED, 0); return NULL; } return za->entry[idx].orig; @@ -825,161 +847,6 @@ } -zip_uint16_t -_zip_read2(const zip_uint8_t **a) -{ - zip_uint16_t ret; - - ret = (zip_uint16_t)((*a)[0]+((*a)[1]<<8)); - *a += 2; - - return ret; -} - - -zip_uint32_t -_zip_read4(const zip_uint8_t **a) -{ - zip_uint32_t ret; - - ret = ((((((zip_uint32_t)(*a)[3]<<8)+(*a)[2])<<8)+(*a)[1])<<8)+(*a)[0]; - *a += 4; - - return ret; -} - - -zip_uint64_t -_zip_read8(const zip_uint8_t **a) -{ - zip_uint64_t x, y; - - x = ((((((zip_uint64_t)(*a)[3]<<8)+(*a)[2])<<8)+(*a)[1])<<8)+(*a)[0]; - *a += 4; - y = ((((((zip_uint64_t)(*a)[3]<<8)+(*a)[2])<<8)+(*a)[1])<<8)+(*a)[0]; - *a += 4; - - return x+(y<<32); -} - - -zip_uint8_t * -_zip_read_data(const zip_uint8_t **buf, FILE *fp, size_t len, int nulp, struct zip_error *error) -{ - zip_uint8_t *r; - - if (len == 0 && nulp == 0) - return NULL; - - r = (zip_uint8_t *)malloc(nulp ? len+1 : len); - if (!r) { - _zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; - } - - if (buf) { - memcpy(r, *buf, len); - *buf += len; - } - else { - if (fread(r, 1, len, fp)<len) { - free(r); - if (ferror(fp)) - _zip_error_set(error, ZIP_ER_READ, errno); - else - _zip_error_set(error, ZIP_ER_INCONS, 0); - return NULL; - } - } - - if (nulp) { - zip_uint8_t *o; - /* replace any in-string NUL characters with spaces */ - r[len] = 0; - for (o=r; o<r+len; o++) - if (*o == '\0') - *o = ' '; - } - - return r; -} - - -static struct zip_string * -_zip_read_string(const zip_uint8_t **buf, FILE *fp, zip_uint16_t len, int nulp, struct zip_error *error) -{ - zip_uint8_t *raw; - struct zip_string *s; - - if ((raw=_zip_read_data(buf, fp, len, nulp, error)) == NULL) - return NULL; - - s = _zip_string_new(raw, len, ZIP_FL_ENC_GUESS, error); - free(raw); - return s; -} - - -void -_zip_poke4(zip_uint32_t i, zip_uint8_t **p) -{ - *((*p)++) = i&0xff; - *((*p)++) = (i>>8)&0xff; - *((*p)++) = (i>>16)&0xff; - *((*p)++) = (i>>24)&0xff; -} - - -void -_zip_poke8(zip_uint64_t i, zip_uint8_t **p) -{ - *((*p)++) = i&0xff; - *((*p)++) = (i>>8)&0xff; - *((*p)++) = (i>>16)&0xff; - *((*p)++) = (i>>24)&0xff; - *((*p)++) = (i>>32)&0xff; - *((*p)++) = (i>>40)&0xff; - *((*p)++) = (i>>48)&0xff; - *((*p)++) = (i>>56)&0xff; -} - - -void -_zip_write2(zip_uint16_t i, FILE *fp) -{ - putc(i&0xff, fp); - putc((i>>8)&0xff, fp); - - return; -} - - -void -_zip_write4(zip_uint32_t i, FILE *fp) -{ - putc(i&0xff, fp); - putc((i>>8)&0xff, fp); - putc((i>>16)&0xff, fp); - putc((i>>24)&0xff, fp); - - return; -} - - -void -_zip_write8(zip_uint64_t i, FILE *fp) -{ - putc(i&0xff, fp); - putc((i>>8)&0xff, fp); - putc((i>>16)&0xff, fp); - putc((i>>24)&0xff, fp); - putc((i>>32)&0xff, fp); - putc((i>>40)&0xff, fp); - putc((i>>48)&0xff, fp); - putc((i>>56)&0xff, fp); - - return; -} void
diff --git a/lib/zip_discard.c b/lib/zip_discard.c index 3fc6d8f..2ca11df 100644 --- a/lib/zip_discard.c +++ b/lib/zip_discard.c
@@ -49,11 +49,10 @@ if (za == NULL) return; - if (za->zn) - free(za->zn); - - if (za->zp) - fclose(za->zp); + if (za->src) { + zip_source_close(za->src); + zip_source_free(za->src); + } free(za->default_password); _zip_string_free(za->comment_orig); @@ -65,12 +64,12 @@ free(za->entry); } - for (i=0; i<za->nsource; i++) { - _zip_source_filep_invalidate(za->source[i]); + for (i=0; i<za->nopen_source; i++) { + _zip_source_invalidate(za->open_source[i]); } + free(za->open_source); - _zip_error_fini(&za->error); - free(za->source); + zip_error_fini(&za->error); free(za);
diff --git a/lib/zip_entry.c b/lib/zip_entry.c index acce311..73a1f50 100644 --- a/lib/zip_entry.c +++ b/lib/zip_entry.c
@@ -1,6 +1,6 @@ /* zip_entry.c -- struct zip_entry helper functions - Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/lib/zip_err_str.c b/lib/zip_err_str.c index 830eb1c..65698be 100644 --- a/lib/zip_err_str.c +++ b/lib/zip_err_str.c
@@ -23,7 +23,7 @@ "Malloc failure", "Entry has been changed", "Compression method not supported", - "Premature EOF", + "Premature end of file", "Invalid argument", "Not a zip archive", "Internal error", @@ -34,6 +34,9 @@ "Read-only archive", "No password provided", "Wrong password provided", + "Operation not supported", + "Resource still in use", + "Tell error", }; const int _zip_nerr_str = sizeof(_zip_err_str)/sizeof(_zip_err_str[0]); @@ -71,4 +74,7 @@ N, N, N, + N, + N, + S, };
diff --git a/lib/zip_error.c b/lib/zip_error.c index ca95c2f..6ccf397 100644 --- a/lib/zip_error.c +++ b/lib/zip_error.c
@@ -1,6 +1,6 @@ /* - zip_error.c -- struct zip_error helper functions - Copyright (C) 1999-2013 Dieter Baron and Thomas Klausner + zip_error.c -- zip_error_t helper functions + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -37,8 +37,46 @@ #include "zipint.h" +ZIP_EXTERN int +zip_error_code_system(const zip_error_t *error) { + return error->sys_err; +} + + +ZIP_EXTERN int +zip_error_code_zip(const zip_error_t *error) { + return error->zip_err; +} + + +ZIP_EXTERN void +zip_error_fini(zip_error_t *err) +{ + free(err->str); + err->str = NULL; +} + + +ZIP_EXTERN void +zip_error_init(zip_error_t *err) +{ + err->zip_err = ZIP_ER_OK; + err->sys_err = 0; + err->str = NULL; +} + + +ZIP_EXTERN int +zip_error_system_type(const zip_error_t *error) { + if (error->zip_err < 0 || error->zip_err >= _zip_nerr_str) + return ZIP_ET_NONE; + + return _zip_err_type[error->zip_err]; +} + + void -_zip_error_clear(struct zip_error *err) +_zip_error_clear(zip_error_t *err) { if (err == NULL) return; @@ -49,7 +87,7 @@ void -_zip_error_copy(struct zip_error *dst, const struct zip_error *src) +_zip_error_copy(zip_error_t *dst, const zip_error_t *src) { dst->zip_err = src->zip_err; dst->sys_err = src->sys_err; @@ -57,20 +95,12 @@ void -_zip_error_fini(struct zip_error *err) -{ - free(err->str); - err->str = NULL; -} - - -void -_zip_error_get(const struct zip_error *err, int *zep, int *sep) +_zip_error_get(const zip_error_t *err, int *zep, int *sep) { if (zep) *zep = err->zip_err; if (sep) { - if (zip_error_get_sys_type(err->zip_err) != ZIP_ET_NONE) + if (zip_error_system_type(err) != ZIP_ET_NONE) *sep = err->sys_err; else *sep = 0; @@ -79,16 +109,7 @@ void -_zip_error_init(struct zip_error *err) -{ - err->zip_err = ZIP_ER_OK; - err->sys_err = 0; - err->str = NULL; -} - - -void -_zip_error_set(struct zip_error *err, int ze, int se) +zip_error_set(zip_error_t *err, int ze, int se) { if (err) { err->zip_err = ze; @@ -98,10 +119,22 @@ void -_zip_error_set_from_source(struct zip_error *err, struct zip_source *src) +zip_error_set_from_source(zip_error_t *err, struct zip_source *src) { - int ze, se; + _zip_error_copy(err, zip_source_error(src)); +} + + +zip_int64_t +zip_error_to_data(const zip_error_t *error, void *data, zip_uint64_t length) +{ + int *e = (int *)data; - zip_source_error(src, &ze, &se); - _zip_error_set(err, ze, se); + if (length < sizeof(int)*2) { + return -1; + } + + e[0] = zip_error_code_zip(error); + e[1] = zip_error_code_system(error); + return sizeof(int)*2; }
diff --git a/lib/zip_error_clear.c b/lib/zip_error_clear.c index a0ceda5..3e6e482 100644 --- a/lib/zip_error_clear.c +++ b/lib/zip_error_clear.c
@@ -1,6 +1,6 @@ /* zip_error_clear.c -- clear zip error - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/lib/zip_error_get.c b/lib/zip_error_get.c index 80fd2ba..ef98b0a 100644 --- a/lib/zip_error_get.c +++ b/lib/zip_error_get.c
@@ -1,6 +1,6 @@ /* zip_error_get.c -- get zip error - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 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> @@ -32,6 +32,7 @@ */ +#define _ZIP_COMPILING_DEPRECATED #include "zipint.h"
diff --git a/lib/zip_error_get_sys_type.c b/lib/zip_error_get_sys_type.c index e96a676..7e27bbf 100644 --- a/lib/zip_error_get_sys_type.c +++ b/lib/zip_error_get_sys_type.c
@@ -1,6 +1,6 @@ /* zip_error_get_sys_type.c -- return type of system error code - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -31,7 +31,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - +#define _ZIP_COMPILING_DEPRECATED #include "zipint.h"
diff --git a/lib/zip_error_strerror.c b/lib/zip_error_strerror.c index dd871d3..a4e603d 100644 --- a/lib/zip_error_strerror.c +++ b/lib/zip_error_strerror.c
@@ -1,6 +1,6 @@ /* zip_error_sterror.c -- get string representation of struct zip_error - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -40,13 +40,13 @@ #include "zipint.h" -const char * -_zip_error_strerror(struct zip_error *err) +ZIP_EXTERN const char * +zip_error_strerror(struct zip_error *err) { const char *zs, *ss; char buf[128], *s; - _zip_error_fini(err); + zip_error_fini(err); if (err->zip_err < 0 || err->zip_err >= _zip_nerr_str) { sprintf(buf, "Unknown error %d", err->zip_err);
diff --git a/lib/zip_error_to_str.c b/lib/zip_error_to_str.c index 8d2b4fd..77af776 100644 --- a/lib/zip_error_to_str.c +++ b/lib/zip_error_to_str.c
@@ -1,6 +1,6 @@ /* zip_error_to_str.c -- get string representation of zip error code - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/lib/zip_extra_field.c b/lib/zip_extra_field.c index 6ec2db3..4095613 100644 --- a/lib/zip_extra_field.c +++ b/lib/zip_extra_field.c
@@ -1,6 +1,6 @@ /* zip_extra_field.c -- manipulate extra fields - Copyright (C) 2012-2013 Dieter Baron and Thomas Klausner + Copyright (C) 2012-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -48,7 +48,7 @@ while (ef) { if ((def=_zip_ef_new(ef->id, ef->size, ef->data, ef->flags)) == NULL) { - _zip_error_set(error, ZIP_ER_MEMORY, 0); + zip_error_set(error, ZIP_ER_MEMORY, 0); _zip_ef_free(head); return NULL; } @@ -142,7 +142,7 @@ } } - _zip_error_set(error, ZIP_ER_NOENT, 0); + zip_error_set(error, ZIP_ER_NOENT, 0); return NULL; } @@ -217,22 +217,22 @@ ef_head = ef = NULL; for (p=data; p<data+len; p+=flen) { if (p+4 > data+len) { - _zip_error_set(error, ZIP_ER_INCONS, 0); + zip_error_set(error, ZIP_ER_INCONS, 0); _zip_ef_free(ef_head); return NULL; } - fid = _zip_read2(&p); - flen = _zip_read2(&p); + fid = _zip_get_16(&p); + flen = _zip_get_16(&p); if (p+flen > data+len) { - _zip_error_set(error, ZIP_ER_INCONS, 0); + zip_error_set(error, ZIP_ER_INCONS, 0); _zip_ef_free(ef_head); return NULL; } if ((ef2=_zip_ef_new(fid, flen, p, flags)) == NULL) { - _zip_error_set(error, ZIP_ER_MEMORY, 0); + zip_error_set(error, ZIP_ER_MEMORY, 0); _zip_ef_free(ef_head); return NULL; } @@ -294,17 +294,27 @@ } -void -_zip_ef_write(const struct zip_extra_field *ef, zip_flags_t flags, FILE *f) +int +_zip_ef_write(struct zip *za, const struct zip_extra_field *ef, zip_flags_t flags) { + zip_uint8_t b[4], *p; + for (; ef; ef=ef->next) { if (ef->flags & flags & ZIP_EF_BOTH) { - _zip_write2(ef->id, f); - _zip_write2(ef->size, f); - if (ef->size > 0) - fwrite(ef->data, ef->size, 1, f); + p = b; + _zip_put_16(&p, ef->id); + _zip_put_16(&p, ef->size); + if (_zip_write(za, b, 4) < 0) { + return -1; + } + if (ef->size > 0) { + if (_zip_write(za, ef->data, ef->size) < 0) { + return -1; + } + } } } + return 0; } @@ -317,7 +327,7 @@ zip_uint16_t fname_len, ef_len; if (idx >= za->nentry) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } @@ -326,31 +336,34 @@ if (e->orig == NULL || e->orig->local_extra_fields_read) return 0; + if (e->orig->offset + 26 > ZIP_INT64_MAX) { + zip_error_set(&za->error, ZIP_ER_SEEK, EFBIG); + return -1; + } - if (fseeko(za->zp, (off_t)(e->orig->offset + 26), SEEK_SET) < 0) { - _zip_error_set(&za->error, ZIP_ER_SEEK, errno); + if (zip_source_seek(za->src, (zip_int64_t)(e->orig->offset + 26), SEEK_SET) < 0) { + zip_error_set_from_source(&za->error, za->src); return -1; } - if (fread(b, sizeof(b), 1, za->zp) != 1) { - _zip_error_set(&za->error, ZIP_ER_READ, errno); + if (_zip_read(za->src, b, sizeof(b), &za->error) < 0) { return -1; } p = b; - fname_len = _zip_read2(&p); - ef_len = _zip_read2(&p); + fname_len = _zip_get_16(&p); + ef_len = _zip_get_16(&p); if (ef_len > 0) { struct zip_extra_field *ef; zip_uint8_t *ef_raw; - if (fseek(za->zp, fname_len, SEEK_CUR) < 0) { - _zip_error_set(&za->error, ZIP_ER_SEEK, errno); + if (zip_source_seek(za->src, fname_len, SEEK_CUR) < 0) { + zip_error_set(&za->error, ZIP_ER_SEEK, errno); return -1; } - ef_raw = _zip_read_data(NULL, za->zp, ef_len, 0, &za->error); + ef_raw = _zip_read_data(NULL, za->src, ef_len, 0, &za->error); if (ef_raw == NULL) return -1;
diff --git a/lib/zip_extra_field_api.c b/lib/zip_extra_field_api.c index 357674b..f567c28 100644 --- a/lib/zip_extra_field_api.c +++ b/lib/zip_extra_field_api.c
@@ -1,6 +1,6 @@ /* zip_extra_field_api.c -- public extra fields API functions - Copyright (C) 2012-2013 Dieter Baron and Thomas Klausner + Copyright (C) 2012-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -41,12 +41,12 @@ struct zip_dirent *de; if ((flags & ZIP_EF_BOTH) == 0) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } if (((flags & ZIP_EF_BOTH) == ZIP_EF_BOTH) && (ef_idx != ZIP_EXTRA_FIELD_ALL)) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } @@ -54,7 +54,7 @@ return -1; if (ZIP_IS_RDONLY(za)) { - _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); return -1; } @@ -74,12 +74,12 @@ struct zip_dirent *de; if ((flags & ZIP_EF_BOTH) == 0) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } if (((flags & ZIP_EF_BOTH) == ZIP_EF_BOTH) && (ef_idx != ZIP_EXTRA_FIELD_ALL)) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } @@ -87,7 +87,7 @@ return -1; if (ZIP_IS_RDONLY(za)) { - _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); return -1; } @@ -111,7 +111,7 @@ int i; if ((flags & ZIP_EF_BOTH) == 0) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return NULL; } @@ -141,7 +141,7 @@ } } - _zip_error_set(&za->error, ZIP_ER_NOENT, 0); + zip_error_set(&za->error, ZIP_ER_NOENT, 0); return NULL; } @@ -153,7 +153,7 @@ struct zip_dirent *de; if ((flags & ZIP_EF_BOTH) == 0) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return NULL; } @@ -176,7 +176,7 @@ zip_uint16_t n; if ((flags & ZIP_EF_BOTH) == 0) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } @@ -204,7 +204,7 @@ zip_uint16_t n; if ((flags & ZIP_EF_BOTH) == 0) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } @@ -233,7 +233,7 @@ int i, found, new_len; if ((flags & ZIP_EF_BOTH) == 0) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } @@ -241,12 +241,12 @@ return -1; if (ZIP_IS_RDONLY(za)) { - _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); return -1; } if (ZIP_EF_IS_INTERNAL(ef_id)) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } @@ -272,7 +272,7 @@ } if (i < ef_idx && ef_idx != ZIP_EXTRA_FIELD_NEW) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } @@ -291,12 +291,12 @@ new_len += len + 4; if (new_len > ZIP_UINT16_MAX) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } if ((ef_new=_zip_ef_new(ef_id, len, data, flags)) == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); return -1; } @@ -334,7 +334,7 @@ struct zip_entry *e; if (idx >= za->nentry) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } @@ -350,7 +350,7 @@ if (e->changes == NULL) { if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); return -1; } }
diff --git a/lib/zip_fclose.c b/lib/zip_fclose.c index 00265cd..d5148c7 100644 --- a/lib/zip_fclose.c +++ b/lib/zip_fclose.c
@@ -49,7 +49,7 @@ if (zf->error.zip_err) ret = zf->error.zip_err; - _zip_error_fini(&zf->error); + zip_error_fini(&zf->error); free(zf); return ret; }
diff --git a/lib/zip_fdopen.c b/lib/zip_fdopen.c index eb4d7ec..ac11316 100644 --- a/lib/zip_fdopen.c +++ b/lib/zip_fdopen.c
@@ -1,6 +1,6 @@ /* zip_fdopen.c -- open read-only archive from file descriptor - Copyright (C) 2009-2010 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -40,34 +40,43 @@ { int fd; FILE *fp; - unsigned int flags; + struct zip *za; + struct zip_source *src; + struct zip_error error; - if (_flags < 0) { - if (zep) - *zep = ZIP_ER_INVAL; + if (_flags < 0 || (_flags & ZIP_TRUNCATE)) { + _zip_set_open_error(zep, NULL, ZIP_ER_INVAL); return NULL; } - flags = (unsigned int)_flags; - if (flags & ZIP_TRUNCATE) { - *zep = ZIP_ER_INVAL; - return NULL; - } - /* We dup() here to avoid messing with the passed in fd. We could not restore it to the original state in case of error. */ if ((fd=dup(fd_orig)) < 0) { - *zep = ZIP_ER_OPEN; + _zip_set_open_error(zep, NULL, ZIP_ER_OPEN); return NULL; } if ((fp=fdopen(fd, "rb")) == NULL) { close(fd); - *zep = ZIP_ER_OPEN; + _zip_set_open_error(zep, NULL, ZIP_ER_OPEN); return NULL; } + zip_error_init(&error); + if ((src = zip_source_filep_create(fp, 0, -1, &error)) == NULL) { + _zip_set_open_error(zep, &error, 0); + zip_error_fini(&error); + return NULL; + } + + if ((za = zip_open_from_source(src, _flags, &error)) == NULL) { + _zip_set_open_error(zep, &error, 0); + zip_error_fini(&error); + return NULL; + } + + zip_error_fini(&error); close(fd_orig); - return _zip_open(NULL, fp, flags, zep); + return za; }
diff --git a/lib/zip_file_add.c b/lib/zip_file_add.c index 35e2e6f..fe95287 100644 --- a/lib/zip_file_add.c +++ b/lib/zip_file_add.c
@@ -1,6 +1,6 @@ /* zip_file_add.c -- add file via callback function - Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -45,7 +45,7 @@ zip_file_add(struct zip *za, const char *name, struct zip_source *source, zip_flags_t flags) { if (name == NULL || source == NULL) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; }
diff --git a/lib/zip_file_error_clear.c b/lib/zip_file_error_clear.c index d4fc1db..927bad9 100644 --- a/lib/zip_file_error_clear.c +++ b/lib/zip_file_error_clear.c
@@ -1,6 +1,6 @@ /* zip_file_error_clear.c -- clear zip file error - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/lib/zip_file_error_get.c b/lib/zip_file_error_get.c index c2f8145..1ef56bc 100644 --- a/lib/zip_file_error_get.c +++ b/lib/zip_file_error_get.c
@@ -1,6 +1,6 @@ /* zip_file_error_get.c -- get zip file error - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -31,7 +31,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - +#define _ZIP_COMPILING_DEPRECATED #include "zipint.h"
diff --git a/lib/zip_file_get_comment.c b/lib/zip_file_get_comment.c index fc48b1d..4473aa0 100644 --- a/lib/zip_file_get_comment.c +++ b/lib/zip_file_get_comment.c
@@ -1,6 +1,6 @@ /* zip_file_get_comment.c -- get file comment - Copyright (C) 2006-2012 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/lib/zip_file_get_external_attributes.c b/lib/zip_file_get_external_attributes.c index 6d09889..bf8bf02 100644 --- a/lib/zip_file_get_external_attributes.c +++ b/lib/zip_file_get_external_attributes.c
@@ -1,6 +1,6 @@ /* zip_file_get_external_attributes.c -- get opsys/external attributes - Copyright (C) 2013 Dieter Baron and Thomas Klausner + Copyright (C) 2013-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/lib/zip_file_get_offset.c b/lib/zip_file_get_offset.c index 38c456b..feb5c6e 100644 --- a/lib/zip_file_get_offset.c +++ b/lib/zip_file_get_offset.c
@@ -1,6 +1,6 @@ /* zip_file_get_offset.c -- get offset of file data in archive. - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -56,17 +56,17 @@ offset = za->entry[idx].orig->offset; - if (fseeko(za->zp, (off_t)offset, SEEK_SET) != 0) { - _zip_error_set(error, ZIP_ER_SEEK, errno); + if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) { + zip_error_set_from_source(error, za->src); return 0; } /* TODO: cache? */ - if ((size=_zip_dirent_size(za->zp, ZIP_EF_LOCAL, error)) < 0) + if ((size=_zip_dirent_size(za->src, ZIP_EF_LOCAL, error)) < 0) return 0; - if (offset+(zip_uint32_t)size > ZIP_OFF_MAX) { - _zip_error_set(error, ZIP_ER_SEEK, EFBIG); + if (offset+(zip_uint32_t)size > ZIP_INT64_MAX) { + zip_error_set(error, ZIP_ER_SEEK, EFBIG); return 0; }
diff --git a/lib/zip_file_rename.c b/lib/zip_file_rename.c index 64c1642..17d8ff8 100644 --- a/lib/zip_file_rename.c +++ b/lib/zip_file_rename.c
@@ -1,6 +1,6 @@ /* zip_file_rename.c -- rename file in zip archive - Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -44,12 +44,12 @@ int old_is_dir, new_is_dir; if (idx >= za->nentry || (name != NULL && strlen(name) > ZIP_UINT16_MAX)) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } if (ZIP_IS_RDONLY(za)) { - _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); return -1; } @@ -60,7 +60,7 @@ old_is_dir = (old_name[strlen(old_name)-1] == '/'); if (new_is_dir != old_is_dir) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; }
diff --git a/lib/zip_file_replace.c b/lib/zip_file_replace.c index 24cf3f0..01a0916 100644 --- a/lib/zip_file_replace.c +++ b/lib/zip_file_replace.c
@@ -1,6 +1,6 @@ /* zip_file_replace.c -- replace file via callback function - Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -39,7 +39,7 @@ zip_file_replace(struct zip *za, zip_uint64_t idx, struct zip_source *source, zip_flags_t flags) { if (idx >= za->nentry || source == NULL) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } @@ -59,7 +59,7 @@ zip_uint64_t za_nentry_prev; if (ZIP_IS_RDONLY(za)) { - _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); return -1; } @@ -93,7 +93,7 @@ if (za->entry[idx].orig != NULL && (za->entry[idx].changes == NULL || (za->entry[idx].changes->changed & ZIP_DIRENT_COMP_METHOD) == 0)) { if (za->entry[idx].changes == NULL) { if ((za->entry[idx].changes=_zip_dirent_clone(za->entry[idx].orig)) == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); return -1; } }
diff --git a/lib/zip_file_set_comment.c b/lib/zip_file_set_comment.c index 6947818..cdc3a35 100644 --- a/lib/zip_file_set_comment.c +++ b/lib/zip_file_set_comment.c
@@ -1,6 +1,6 @@ /* zip_file_set_comment.c -- set comment for file in archive - Copyright (C) 2006-2012 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -49,12 +49,12 @@ return -1; if (ZIP_IS_RDONLY(za)) { - _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); return -1; } if (len > 0 && comment == NULL) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } @@ -83,7 +83,7 @@ if (changed) { if (e->changes == NULL) { if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); _zip_string_free(cstr); return -1; }
diff --git a/lib/zip_file_set_external_attributes.c b/lib/zip_file_set_external_attributes.c index 0ae15b2..61623d2 100644 --- a/lib/zip_file_set_external_attributes.c +++ b/lib/zip_file_set_external_attributes.c
@@ -1,6 +1,6 @@ /* zip_file_set_external_attributes.c -- set external attributes for entry - Copyright (C) 2013 Dieter Baron and Thomas Klausner + Copyright (C) 2013-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -45,7 +45,7 @@ return -1; if (ZIP_IS_RDONLY(za)) { - _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); return -1; } @@ -59,7 +59,7 @@ if (changed) { if (e->changes == NULL) { if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); return -1; } }
diff --git a/lib/zip_file_set_mtime.c b/lib/zip_file_set_mtime.c index f5ea0e8..59c3aff 100644 --- a/lib/zip_file_set_mtime.c +++ b/lib/zip_file_set_mtime.c
@@ -42,7 +42,7 @@ return -1; if (ZIP_IS_RDONLY(za)) { - _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); return -1; } @@ -53,7 +53,7 @@ if (changed) { if (e->changes == NULL) { if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); return -1; } }
diff --git a/lib/zip_file_strerror.c b/lib/zip_file_strerror.c index 834435c..95c5923 100644 --- a/lib/zip_file_strerror.c +++ b/lib/zip_file_strerror.c
@@ -1,6 +1,6 @@ /* zip_file_sterror.c -- get string representation of zip file error - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -38,5 +38,5 @@ ZIP_EXTERN const char * zip_file_strerror(struct zip_file *zf) { - return _zip_error_strerror(&zf->error); + return zip_error_strerror(&zf->error); }
diff --git a/lib/zip_filerange_crc.c b/lib/zip_filerange_crc.c index 5c7ebef..5702aa8 100644 --- a/lib/zip_filerange_crc.c +++ b/lib/zip_filerange_crc.c
@@ -1,6 +1,6 @@ /* zip_filerange_crc.c -- compute CRC32 for a range of a file - Copyright (C) 2008-2013 Dieter Baron and Thomas Klausner + Copyright (C) 2008-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -40,29 +40,37 @@ int -_zip_filerange_crc(FILE *fp, off_t start, off_t len, uLong *crcp, - struct zip_error *errp) +_zip_filerange_crc(zip_source_t *src, zip_uint64_t start, zip_uint64_t len, uLong *crcp, zip_error_t *error) { Bytef buf[BUFSIZE]; - size_t n; + zip_int64_t n; *crcp = crc32(0L, Z_NULL, 0); - if (fseeko(fp, start, SEEK_SET) != 0) { - _zip_error_set(errp, ZIP_ER_SEEK, errno); + if (start > ZIP_INT64_MAX) { + zip_error_set(error, ZIP_ER_SEEK, EFBIG); + return -1; + } + + if (zip_source_seek(src, (zip_int64_t)start, SEEK_SET) != 0) { + zip_error_set_from_source(error, src); return -1; } while (len > 0) { - n = len > BUFSIZE ? BUFSIZE : (size_t)len; - if ((n=fread(buf, 1, n, fp)) == 0) { - _zip_error_set(errp, ZIP_ER_READ, errno); + n = (zip_int64_t)(len > BUFSIZE ? BUFSIZE : len); + if ((n = zip_source_read(src, buf, (zip_uint64_t)n)) < 0) { + zip_error_set_from_source(error, src); + return -1; + } + if (n == 0) { + zip_error_set(error, ZIP_ER_EOF, 0); return -1; } *crcp = crc32(*crcp, buf, (uInt)n); - len-= n; + len -= (zip_uint64_t)n; } return 0;
diff --git a/lib/zip_fopen.c b/lib/zip_fopen.c index 2656f8e..ad7c416 100644 --- a/lib/zip_fopen.c +++ b/lib/zip_fopen.c
@@ -1,6 +1,6 @@ /* zip_fopen.c -- open file in zip archive for reading - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/lib/zip_fopen_encrypted.c b/lib/zip_fopen_encrypted.c index 3bbb3b6..8b2d05e 100644 --- a/lib/zip_fopen_encrypted.c +++ b/lib/zip_fopen_encrypted.c
@@ -1,6 +1,6 @@ /* zip_fopen_encrypted.c -- open file for reading with password - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/lib/zip_fopen_index.c b/lib/zip_fopen_index.c index fa8feff..7887eef 100644 --- a/lib/zip_fopen_index.c +++ b/lib/zip_fopen_index.c
@@ -1,6 +1,6 @@ /* zip_fopen_index.c -- open file in zip archive for reading by index - Copyright (C) 1999-2013 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/lib/zip_fopen_index_encrypted.c b/lib/zip_fopen_index_encrypted.c index a640610..70b035f 100644 --- a/lib/zip_fopen_index_encrypted.c +++ b/lib/zip_fopen_index_encrypted.c
@@ -52,7 +52,7 @@ return NULL; if (zip_source_open(src) < 0) { - _zip_error_set_from_source(&za->error, src); + zip_error_set_from_source(&za->error, src); zip_source_free(src); return NULL; } @@ -74,12 +74,12 @@ struct zip_file *zf; if ((zf=(struct zip_file *)malloc(sizeof(struct zip_file))) == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); return NULL; } zf->za = za; - _zip_error_init(&zf->error); + zip_error_init(&zf->error); zf->eof = 0; zf->src = NULL;
diff --git a/lib/zip_fread.c b/lib/zip_fread.c index a226a14..88af7f3 100644 --- a/lib/zip_fread.c +++ b/lib/zip_fread.c
@@ -1,6 +1,6 @@ /* zip_fread.c -- read from file - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -47,7 +47,7 @@ return -1; if (toread > ZIP_INT64_MAX) { - _zip_error_set(&zf->error, ZIP_ER_INVAL, 0); + zip_error_set(&zf->error, ZIP_ER_INVAL, 0); return -1; } @@ -55,7 +55,7 @@ return 0; if ((n=zip_source_read(zf->src, outbuf, toread)) < 0) { - _zip_error_set_from_source(&zf->error, zf->src); + zip_error_set_from_source(&zf->error, zf->src); return -1; }
diff --git a/lib/zip_get_archive_comment.c b/lib/zip_get_archive_comment.c index f419342..971883f 100644 --- a/lib/zip_get_archive_comment.c +++ b/lib/zip_get_archive_comment.c
@@ -1,6 +1,6 @@ /* zip_get_archive_comment.c -- get archive comment - Copyright (C) 2006-2012 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/lib/zip_get_archive_flag.c b/lib/zip_get_archive_flag.c index 330ba80..6e87126 100644 --- a/lib/zip_get_archive_flag.c +++ b/lib/zip_get_archive_flag.c
@@ -1,6 +1,6 @@ /* zip_get_archive_flag.c -- get archive global flag - Copyright (C) 2008 Dieter Baron and Thomas Klausner + Copyright (C) 2008-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/lib/zip_get_compression_implementation.c b/lib/zip_get_compression_implementation.c index 8a2cd4d..c1120d3 100644 --- a/lib/zip_get_compression_implementation.c +++ b/lib/zip_get_compression_implementation.c
@@ -1,6 +1,6 @@ /* zip_get_compression_implementation.c -- get compression implementation - Copyright (C) 2009 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/lib/zip_get_encryption_implementation.c b/lib/zip_get_encryption_implementation.c index cbcb644..e2f833b 100644 --- a/lib/zip_get_encryption_implementation.c +++ b/lib/zip_get_encryption_implementation.c
@@ -1,6 +1,6 @@ /* zip_get_encryption_implementation.c -- get encryption implementation - Copyright (C) 2009 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/lib/zip_get_file_comment.c b/lib/zip_get_file_comment.c index bd59a0f..20bbf99 100644 --- a/lib/zip_get_file_comment.c +++ b/lib/zip_get_file_comment.c
@@ -1,6 +1,6 @@ /* zip_get_file_comment.c -- get file comment - Copyright (C) 2006-2012 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/lib/zip_get_name.c b/lib/zip_get_name.c index 205b326..0ae78de 100644 --- a/lib/zip_get_name.c +++ b/lib/zip_get_name.c
@@ -1,6 +1,6 @@ /* zip_get_name.c -- get filename for a file in zip file - Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/lib/zip_get_num_entries.c b/lib/zip_get_num_entries.c index f528734..9a70375 100644 --- a/lib/zip_get_num_entries.c +++ b/lib/zip_get_num_entries.c
@@ -1,6 +1,6 @@ /* zip_get_num_entries.c -- get number of entries in archive - Copyright (C) 1999-2011 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/lib/zip_get_num_files.c b/lib/zip_get_num_files.c index 6b28d99..224b975 100644 --- a/lib/zip_get_num_files.c +++ b/lib/zip_get_num_files.c
@@ -1,6 +1,6 @@ /* zip_get_num_files.c -- get number of files in archive - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -34,6 +34,7 @@ #define _ZIP_COMPILING_DEPRECATED #include "zipint.h" +#include <limits.h> ZIP_EXTERN int @@ -42,6 +43,10 @@ if (za == NULL) return -1; - /* TODO: check for overflow */ + if (za->nentry > INT_MAX) { + zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 0); + return -1; + } + return (int)za->nentry; }
diff --git a/lib/zip_io_util.c b/lib/zip_io_util.c new file mode 100644 index 0000000..3f4970c --- /dev/null +++ b/lib/zip_io_util.c
@@ -0,0 +1,211 @@ +/* + zip_io_util.c -- I/O helper functions + Copyright (C) 1999-2014 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 <errno.h> +#include <stdlib.h> +#include <string.h> + +#include "zipint.h" + +zip_uint16_t +_zip_get_16(const zip_uint8_t **a) +{ + zip_uint16_t ret; + + ret = (zip_uint16_t)((*a)[0]+((*a)[1]<<8)); + *a += 2; + + return ret; +} + + +zip_uint32_t +_zip_get_32(const zip_uint8_t **a) +{ + zip_uint32_t ret; + + ret = ((((((zip_uint32_t)(*a)[3]<<8)+(*a)[2])<<8)+(*a)[1])<<8)+(*a)[0]; + *a += 4; + + return ret; +} + + +zip_uint64_t +_zip_get_64(const zip_uint8_t **a) +{ + zip_uint64_t x, y; + + x = ((((((zip_uint64_t)(*a)[3]<<8)+(*a)[2])<<8)+(*a)[1])<<8)+(*a)[0]; + *a += 4; + y = ((((((zip_uint64_t)(*a)[3]<<8)+(*a)[2])<<8)+(*a)[1])<<8)+(*a)[0]; + *a += 4; + + return x+(y<<32); +} + +int +_zip_read(struct zip_source *src, zip_uint8_t *b, zip_uint64_t length, struct zip_error *error) +{ + zip_int64_t n; + + if (length > ZIP_INT64_MAX) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + return -1; + } + + if ((n = zip_source_read(src, b, length)) < 0) { + zip_error_set_from_source(error, src); + return -1; + } + + if (n < (zip_int64_t)length) { + zip_error_set(error, ZIP_ER_EOF, 0); + return -1; + } + + return 0; +} + + +zip_uint8_t * +_zip_read_data(const zip_uint8_t **buf, struct zip_source *src, size_t len, int nulp, struct zip_error *error) +{ + zip_uint8_t *r; + + if (len == 0 && nulp == 0) + return NULL; + + r = (zip_uint8_t *)malloc(nulp ? len+1 : len); + if (!r) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if (buf) { + memcpy(r, *buf, len); + *buf += len; + } + else { + if (_zip_read(src, r, len, error) < 0) { + free(r); + return NULL; + } + } + + if (nulp) { + zip_uint8_t *o; + /* replace any in-string NUL characters with spaces */ + r[len] = 0; + for (o=r; o<r+len; o++) + if (*o == '\0') + *o = ' '; + } + + return r; +} + + +struct zip_string * +_zip_read_string(const zip_uint8_t **buf, struct zip_source *src, zip_uint16_t len, int nulp, struct zip_error *error) +{ + zip_uint8_t *raw; + struct zip_string *s; + + if ((raw=_zip_read_data(buf, src, len, nulp, error)) == NULL) + return NULL; + + s = _zip_string_new(raw, len, ZIP_FL_ENC_GUESS, error); + free(raw); + return s; +} + + + + +void +_zip_put_16(zip_uint8_t **p, zip_uint16_t i) +{ + *((*p)++) = i&0xff; + *((*p)++) = (i>>8)&0xff; +} + + +void +_zip_put_32(zip_uint8_t **p, zip_uint32_t i) +{ + *((*p)++) = i&0xff; + *((*p)++) = (i>>8)&0xff; + *((*p)++) = (i>>16)&0xff; + *((*p)++) = (i>>24)&0xff; +} + + +void +_zip_put_64(zip_uint8_t **p, zip_uint64_t i) +{ + *((*p)++) = i&0xff; + *((*p)++) = (i>>8)&0xff; + *((*p)++) = (i>>16)&0xff; + *((*p)++) = (i>>24)&0xff; + *((*p)++) = (i>>32)&0xff; + *((*p)++) = (i>>40)&0xff; + *((*p)++) = (i>>48)&0xff; + *((*p)++) = (i>>56)&0xff; +} + + +void +_zip_put_data(zip_uint8_t **p, const char *s, size_t len) +{ + memcpy(*p, s, len); + *p += len; +} + + +int +_zip_write(struct zip *za, const void *data, zip_uint64_t length) +{ + zip_int64_t n; + + if ((n = zip_source_write(za->src, data, length)) < 0) { + zip_error_set_from_source(&za->error, za->src); + return -1; + } + if ((zip_uint64_t)n != length) { + zip_error_set(&za->error, ZIP_ER_WRITE, EINTR); + return -1; + } + + return 0; +}
diff --git a/lib/zip_memdup.c b/lib/zip_memdup.c index 11bdfe7..758b946 100644 --- a/lib/zip_memdup.c +++ b/lib/zip_memdup.c
@@ -1,6 +1,6 @@ /* zip_memdup.c -- internal zip function, "strdup" with len - Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -47,7 +47,7 @@ ret = malloc(len); if (!ret) { - _zip_error_set(error, ZIP_ER_MEMORY, 0); + zip_error_set(error, ZIP_ER_MEMORY, 0); return NULL; }
diff --git a/lib/zip_name_locate.c b/lib/zip_name_locate.c index dd011cc..3435e14 100644 --- a/lib/zip_name_locate.c +++ b/lib/zip_name_locate.c
@@ -1,6 +1,6 @@ /* zip_name_locate.c -- get index by name - Copyright (C) 1999-2011 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -58,7 +58,7 @@ return -1; if (fname == NULL) { - _zip_error_set(error, ZIP_ER_INVAL, 0); + zip_error_set(error, ZIP_ER_INVAL, 0); return -1; } @@ -83,6 +83,6 @@ } } - _zip_error_set(error, ZIP_ER_NOENT, 0); + zip_error_set(error, ZIP_ER_NOENT, 0); return -1; }
diff --git a/lib/zip_new.c b/lib/zip_new.c index db64be3..484ee75 100644 --- a/lib/zip_new.c +++ b/lib/zip_new.c
@@ -48,22 +48,21 @@ za = (struct zip *)malloc(sizeof(struct zip)); if (!za) { - _zip_error_set(error, ZIP_ER_MEMORY, 0); + zip_error_set(error, ZIP_ER_MEMORY, 0); return NULL; } - za->zn = NULL; - za->zp = NULL; + za->src = NULL; za->open_flags = 0; - _zip_error_init(&za->error); + zip_error_init(&za->error); za->flags = za->ch_flags = 0; za->default_password = NULL; za->comment_orig = za->comment_changes = NULL; za->comment_changed = 0; za->nentry = za->nentry_alloc = 0; za->entry = NULL; - za->nsource = za->nsource_alloc = 0; - za->source = NULL; + za->nopen_source = za->nopen_source_alloc = 0; + za->open_source = NULL; za->tempdir = NULL; return za;
diff --git a/lib/zip_open.c b/lib/zip_open.c index 30afde9..553a37e 100644 --- a/lib/zip_open.c +++ b/lib/zip_open.c
@@ -1,6 +1,6 @@ /* zip_open.c -- open zip archive by name - Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -41,68 +41,126 @@ #include "zipint.h" -static void set_error(int *, const struct zip_error *, int); -static struct zip *_zip_allocate_new(const char *, unsigned int, int *); -static zip_int64_t _zip_checkcons(FILE *, struct zip_cdir *, struct zip_error *); -static void _zip_check_torrentzip(struct zip *, const struct zip_cdir *); -static struct zip_cdir *_zip_find_central_dir(FILE *, unsigned int, int *, off_t); -static int _zip_file_exists(const char *, unsigned int, int *); +typedef enum { + EXISTS_ERROR = -1, + EXISTS_NOT = 0, + EXISTS_EMPTY, + EXISTS_NONEMPTY, +} exists_t; +static struct zip *_zip_allocate_new(struct zip_source *src, unsigned int flags, struct zip_error *error); +static zip_int64_t _zip_checkcons(struct zip *za, struct zip_cdir *cdir, struct zip_error *error); +static void _zip_check_torrentzip(struct zip *za, const struct zip_cdir *cdir); +static struct zip_cdir *_zip_find_central_dir(struct zip *za, zip_uint64_t len); +static exists_t _zip_file_exists(struct zip_source *src, struct zip_error *error); static int _zip_headercomp(const struct zip_dirent *, const struct zip_dirent *); static unsigned char *_zip_memmem(const unsigned char *, size_t, const unsigned char *, size_t); -static struct zip_cdir *_zip_readcdir(FILE *, off_t, unsigned char *, const unsigned char *, - size_t, unsigned int, struct zip_error *); -static struct zip_cdir *_zip_read_eocd(const unsigned char *, const unsigned char *, off_t, +static struct zip_cdir *_zip_read_cdir(zip_t *za, zip_uint64_t buf_offset, zip_uint8_t *buf, const zip_uint8_t *eocd, size_t buflen, struct zip_error *error); +static struct zip_cdir *_zip_read_eocd(const unsigned char *, const unsigned char *, zip_uint64_t, size_t, unsigned int, struct zip_error *); -static struct zip_cdir *_zip_read_eocd64(FILE *, const unsigned char *, const unsigned char *, - off_t, size_t, unsigned int, struct zip_error *); +static struct zip_cdir *_zip_read_eocd64(struct zip_source *, const zip_uint8_t *, const zip_uint8_t *, + zip_uint64_t, size_t, unsigned int, struct zip_error *); ZIP_EXTERN struct zip * zip_open(const char *fn, int _flags, int *zep) { - FILE *fp; - unsigned int flags; + struct zip *za; + struct zip_source *src; + struct zip_error error; + + zip_error_init(&error); + if ((src = zip_source_file_create(fn, 0, -1, &error)) == NULL) { + _zip_set_open_error(zep, &error, 0); + zip_error_fini(&error); + return NULL; + } + + if ((za = zip_open_from_source(src, _flags, &error)) == NULL) { + _zip_set_open_error(zep, &error, 0); + zip_error_fini(&error); + return NULL; + } + + zip_error_fini(&error); + return za; +} + + +ZIP_EXTERN struct zip * +zip_open_from_source(struct zip_source *src, int _flags, struct zip_error *error) +{ + static zip_int64_t needed_support_read = -1; + static zip_int64_t needed_support_write = -1; - if (_flags < 0 || fn == NULL) { - if (zep) - *zep = ZIP_ER_INVAL; + unsigned int flags; + zip_int64_t supported; + exists_t exists; + + if (_flags < 0 || src == NULL) { + zip_error_set(error, ZIP_ER_INVAL, 0); return NULL; } flags = (unsigned int)_flags; + + supported = zip_source_supports(src); + if (needed_support_read == -1) { + needed_support_read = zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_SEEK, ZIP_SOURCE_TELL, ZIP_SOURCE_STAT, -1); + needed_support_write = zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, -1); + } + if ((supported & needed_support_read) != needed_support_read) { + zip_error_set(error, ZIP_ER_OPNOTSUPP, 0); + return NULL; + } + if ((supported & needed_support_write) != needed_support_write) { + flags |= ZIP_RDONLY; + } - switch (_zip_file_exists(fn, flags, zep)) { - case -1: + if ((flags & (ZIP_RDONLY|ZIP_TRUNCATE)) == (ZIP_RDONLY|ZIP_TRUNCATE)) { + zip_error_set(error, ZIP_ER_RDONLY, 0); + return NULL; + } + + exists = _zip_file_exists(src, error); + switch (exists) { + case EXISTS_ERROR: return NULL; - case 0: + case EXISTS_NOT: if ((flags & ZIP_CREATE) == 0) { - set_error(zep, NULL, ZIP_ER_NOENT); + zip_error_set(error, ZIP_ER_NOENT, 0); return NULL; } - return _zip_allocate_new(fn, flags, zep); + return _zip_allocate_new(src, flags, error); - default: + default: { + zip_t *za; if (flags & ZIP_EXCL) { - set_error(zep, NULL, ZIP_ER_EXISTS); + zip_error_set(error, ZIP_ER_EXISTS, 0); + return NULL; + } + if (zip_source_open(src) < 0) { + zip_error_set_from_source(error, src); return NULL; } - if ((fp = fopen(fn, "rb")) == NULL) { - set_error(zep, NULL, ZIP_ER_OPEN); + if (flags & ZIP_TRUNCATE) { + za = _zip_allocate_new(src, flags, error); + } + else { + /* ZIP_CREATE gets ignored if file exists and not ZIP_EXCL, just like open() */ + za = _zip_open(src, flags, error); + } + + if (za == NULL) { + zip_source_close(src); return NULL; } - if (flags & ZIP_TRUNCATE) { - fclose(fp); - return _zip_allocate_new(fn, flags, zep); - } - /* ZIP_CREATE gets ignored if file exists and not ZIP_EXCL, - just like open() */ - return _zip_open(fn, fp, flags, zep); + return za; + } } } - ZIP_EXTERN int zip_archive_set_tempdir(struct zip *za, const char *tempdir) { @@ -110,7 +168,7 @@ if (tempdir) { if ((new_tempdir = strdup(tempdir)) == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, errno); + zip_error_set(&za->error, ZIP_ER_MEMORY, errno); return -1; } } @@ -124,36 +182,40 @@ } struct zip * -_zip_open(const char *fn, FILE *fp, unsigned int flags, int *zep) +_zip_open(struct zip_source *src, unsigned int flags, struct zip_error *error) { struct zip *za; struct zip_cdir *cdir; - off_t len; + struct zip_stat st; + zip_uint64_t len; - if (fseeko(fp, 0, SEEK_END) < 0) { - *zep = ZIP_ER_SEEK; + zip_stat_init(&st); + if (zip_source_stat(src, &st) < 0) { + zip_error_set_from_source(error, src); return NULL; } - len = ftello(fp); + if ((st.valid & ZIP_STAT_SIZE) == 0) { + zip_error_set(error, ZIP_ER_SEEK, EOPNOTSUPP); + return NULL; + } + len = st.size; /* treat empty files as empty archives */ if (len == 0) { - if ((za=_zip_allocate_new(fn, flags, zep)) == NULL) - fclose(fp); - else - za->zp = fp; + if ((za=_zip_allocate_new(src, flags, error)) == NULL) { + zip_source_free(src); + return NULL; + } + return za; } - cdir = _zip_find_central_dir(fp, flags, zep, len); - if (cdir == NULL) { - fclose(fp); - return NULL; + if ((za=_zip_allocate_new(src, flags, error)) == NULL) { + return NULL; } - - if ((za=_zip_allocate_new(fn, flags, zep)) == NULL) { - _zip_cdir_free(cdir); - fclose(fp); + + if ((cdir = _zip_find_central_dir(za, len)) == NULL) { + _zip_error_copy(error, &za->error); return NULL; } @@ -162,8 +224,6 @@ za->nentry_alloc = cdir->nentry_alloc; za->comment_orig = cdir->comment; - za->zp = fp; - _zip_check_torrentzip(za, cdir); za->ch_flags = za->flags; @@ -174,15 +234,14 @@ } -static void -set_error(int *zep, const struct zip_error *err, int ze) +void +_zip_set_open_error(int *zep, const struct zip_error *err, int ze) { - int se; - if (err) { - _zip_error_get(err, &ze, &se); - if (zip_error_get_sys_type(ze) == ZIP_ET_SYS) - errno = se; + ze = zip_error_code_zip(err); + if (zip_error_system_type(err) == ZIP_ET_SYS) { + errno = zip_error_code_system(err); + } } if (zep) @@ -197,8 +256,7 @@ entries, or NULL if unsuccessful. */ static struct zip_cdir * -_zip_readcdir(FILE *fp, off_t buf_offset, unsigned char *buf, const unsigned char *eocd, size_t buflen, - unsigned int flags, struct zip_error *error) +_zip_read_cdir(zip_t *za, zip_uint64_t buf_offset, zip_uint8_t *buf, const zip_uint8_t *eocd, size_t buflen, struct zip_error *error) { struct zip_cdir *cd; const unsigned char *cdp; @@ -209,41 +267,41 @@ tail_len = buf + buflen - eocd - EOCDLEN; if (tail_len < 0) { /* not enough bytes left for comment */ - _zip_error_set(error, ZIP_ER_NOZIP, 0); + zip_error_set(error, ZIP_ER_NOZIP, 0); return NULL; } /* check for end-of-central-dir magic */ if (memcmp(eocd, EOCD_MAGIC, 4) != 0) { - _zip_error_set(error, ZIP_ER_NOZIP, 0); + zip_error_set(error, ZIP_ER_NOZIP, 0); return NULL; } if (memcmp(eocd+4, "\0\0\0\0", 4) != 0) { - _zip_error_set(error, ZIP_ER_MULTIDISK, 0); + zip_error_set(error, ZIP_ER_MULTIDISK, 0); return NULL; } if (eocd-EOCD64LOCLEN >= buf && memcmp(eocd-EOCD64LOCLEN, EOCD64LOC_MAGIC, 4) == 0) - cd = _zip_read_eocd64(fp, eocd-EOCD64LOCLEN, buf, buf_offset, buflen, flags, error); + cd = _zip_read_eocd64(za->src, eocd-EOCD64LOCLEN, buf, buf_offset, buflen, za->flags, error); else - cd = _zip_read_eocd(eocd, buf, buf_offset, buflen, flags, error); + cd = _zip_read_eocd(eocd, buf, buf_offset, buflen, za->flags, error); if (cd == NULL) return NULL; cdp = eocd + 20; - comment_len = _zip_read2(&cdp); + comment_len = _zip_get_16(&cdp); if ((zip_uint64_t)cd->offset+(zip_uint64_t)cd->size > (zip_uint64_t)buf_offset + (zip_uint64_t)(eocd-buf)) { /* cdir spans past EOCD record */ - _zip_error_set(error, ZIP_ER_INCONS, 0); + zip_error_set(error, ZIP_ER_INCONS, 0); _zip_cdir_free(cd); return NULL; } - if (tail_len < comment_len || ((flags & ZIP_CHECKCONS) && tail_len != comment_len)) { - _zip_error_set(error, ZIP_ER_INCONS, 0); + if (tail_len < comment_len || ((za->open_flags & ZIP_CHECKCONS) && tail_len != comment_len)) { + zip_error_set(error, ZIP_ER_INCONS, 0); _zip_cdir_free(cd); return NULL; } @@ -263,16 +321,16 @@ else { /* go to start of cdir and read it entry by entry */ bufp = NULL; - clearerr(fp); - fseeko(fp, cd->offset, SEEK_SET); - /* possible consistency check: cd->offset = - len-(cd->size+cd->comment_len+EOCDLEN) ? */ - if (ferror(fp) || (ftello(fp) != cd->offset)) { - /* seek error or offset of cdir wrong */ - if (ferror(fp)) - _zip_error_set(error, ZIP_ER_SEEK, errno); - else - _zip_error_set(error, ZIP_ER_NOZIP, 0); + + if (zip_source_seek(za->src, (zip_int64_t)cd->offset, SEEK_SET) < 0) { + zip_error_set_from_source(error, za->src); + _zip_cdir_free(cd); + return NULL; + } + + /* possible consistency check: cd->offset = len-(cd->size+cd->comment_len+EOCDLEN) ? */ + if (zip_source_tell(za->src) != (zip_int64_t)cd->offset) { + zip_error_set(error, ZIP_ER_NOZIP, 0); _zip_cdir_free(cd); return NULL; } @@ -282,14 +340,14 @@ i=0; while (i<cd->nentry && left > 0) { if ((cd->entry[i].orig=_zip_dirent_new()) == NULL - || (_zip_dirent_read(cd->entry[i].orig, fp, bufp, &left, 0, error)) < 0) { + || (_zip_dirent_read(cd->entry[i].orig, za->src, bufp, &left, 0, error)) < 0) { _zip_cdir_free(cd); return NULL; } i++; } - if (i != cd->nentry || ((flags & ZIP_CHECKCONS) && left != 0)) { - _zip_error_set(error, ZIP_ER_INCONS, 0); + if (i != cd->nentry || ((za->open_flags & ZIP_CHECKCONS) && left != 0)) { + zip_error_set(error, ZIP_ER_INCONS, 0); _zip_cdir_free(cd); return NULL; } @@ -305,7 +363,7 @@ difference between the lowest and the highest fileposition reached */ static zip_int64_t -_zip_checkcons(FILE *fp, struct zip_cdir *cd, struct zip_error *error) +_zip_checkcons(struct zip *za, struct zip_cdir *cd, struct zip_error *error) { zip_uint64_t i; zip_uint64_t min, max, j; @@ -322,7 +380,7 @@ if (cd->entry[i].orig->offset < min) min = cd->entry[i].orig->offset; if (min > (zip_uint64_t)cd->offset) { - _zip_error_set(error, ZIP_ER_NOZIP, 0); + zip_error_set(error, ZIP_ER_NOZIP, 0); return -1; } @@ -331,20 +389,20 @@ if (j > max) max = j; if (max > (zip_uint64_t)cd->offset) { - _zip_error_set(error, ZIP_ER_NOZIP, 0); + zip_error_set(error, ZIP_ER_NOZIP, 0); return -1; } - if (fseeko(fp, (off_t)cd->entry[i].orig->offset, SEEK_SET) != 0) { - _zip_error_set(error, ZIP_ER_SEEK, errno); - return -1; + if (zip_source_seek(za->src, (zip_int64_t)cd->entry[i].orig->offset, SEEK_SET) < 0) { + zip_error_set_from_source(error, za->src); + return -1; } - if (_zip_dirent_read(&temp, fp, NULL, NULL, 1, error) == -1) + if (_zip_dirent_read(&temp, za->src, NULL, NULL, 1, error) == -1) return -1; if (_zip_headercomp(cd->entry[i].orig, &temp) != 0) { - _zip_error_set(error, ZIP_ER_INCONS, 0); + zip_error_set(error, ZIP_ER_INCONS, 0); _zip_dirent_finalize(&temp); return -1; } @@ -370,7 +428,7 @@ char buf[8+1]; char *end; - if (za->zp == NULL || cdir == NULL) + if (cdir == NULL) return; if (_zip_string_length(cdir->comment) != TORRENT_SIG_LEN+8 @@ -384,7 +442,7 @@ if ((crc_should == UINT_MAX && errno != 0) || (end && *end)) return; - if (_zip_filerange_crc(za->zp, cdir->offset, cdir->size, &crc_got, NULL) < 0) + if (_zip_filerange_crc(za->src, cdir->offset, cdir->size, &crc_got, NULL) < 0) return; if (crc_got == crc_should) @@ -426,116 +484,103 @@ static struct zip * -_zip_allocate_new(const char *fn, unsigned int flags, int *zep) +_zip_allocate_new(struct zip_source *src, unsigned int flags, struct zip_error *error) { struct zip *za; - struct zip_error error; - if ((za=_zip_new(&error)) == NULL) { - set_error(zep, &error, 0); + if ((za = _zip_new(error)) == NULL) { return NULL; } - if (fn == NULL) - za->zn = NULL; - else { - za->zn = strdup(fn); - if (!za->zn) { - zip_discard(za); - set_error(zep, NULL, ZIP_ER_MEMORY); - return NULL; - } - } + za->src = src; za->open_flags = flags; + if (flags & ZIP_RDONLY) { + za->flags |= ZIP_AFL_RDONLY; + za->ch_flags |= ZIP_AFL_RDONLY; + } return za; } /* * tests for file existence - * 1: file exists and is stat()able - * 0: file does not exist - * -1: error */ -static int -_zip_file_exists(const char *fn, unsigned int flags, int *zep) +static exists_t +_zip_file_exists(struct zip_source *src, struct zip_error *error) { - struct stat st; + struct zip_stat st; - if (fn == NULL) { - set_error(zep, NULL, ZIP_ER_INVAL); - return -1; - } - - if (stat(fn, &st) != 0) { - if (errno == ENOENT) { - return 0; + zip_stat_init(&st); + if (zip_source_stat(src, &st) != 0) { + zip_error_t *src_error = zip_source_error(src); + if (zip_error_code_zip(src_error) == ZIP_ER_READ && zip_error_code_system(src_error) == ENOENT) { + return EXISTS_NOT; } - set_error(zep, NULL, ZIP_ER_OPEN); - return -1; + _zip_error_copy(error, src_error); + return EXISTS_ERROR; } - return 1; + return (st.valid & ZIP_STAT_SIZE) && st.size == 0 ? EXISTS_EMPTY : EXISTS_NONEMPTY; } static struct zip_cdir * -_zip_find_central_dir(FILE *fp, unsigned int flags, int *zep, off_t len) +_zip_find_central_dir(struct zip *za, zip_uint64_t len) { struct zip_cdir *cdir, *cdirnew; unsigned char *buf, *match; - off_t buf_offset; - size_t buflen; - zip_int64_t a, i; + zip_int64_t buf_offset; + zip_uint64_t buflen; + zip_int64_t a; zip_int64_t best; struct zip_error zerr; - if (len < (off_t)EOCDLEN) { - set_error(zep, NULL, ZIP_ER_NOZIP); + if (len < EOCDLEN) { + zip_error_set(&za->error, ZIP_ER_NOZIP, 0); + return NULL; + } + + buflen = (len < CDBUFSIZE ? len : CDBUFSIZE); + if (zip_source_seek(za->src, -(zip_int64_t)buflen, SEEK_END) < 0) { + struct zip_error *src_error = zip_source_error(za->src); + if (zip_error_code_zip(src_error) != ZIP_ER_SEEK || zip_error_code_system(src_error) != EFBIG) { + /* seek before start of file on my machine */ + _zip_error_copy(&za->error, src_error); + return NULL; + } + } + if ((buf_offset = zip_source_tell(za->src)) < 0) { + zip_error_set_from_source(&za->error, za->src); return NULL; } - i = fseeko(fp, -(len < CDBUFSIZE ? len : CDBUFSIZE), SEEK_END); - if (i == -1 && errno != EFBIG) { - /* seek before start of file on my machine */ - set_error(zep, NULL, ZIP_ER_SEEK); - return NULL; - } - buf_offset = ftello(fp); - /* 64k is too much for stack */ - if ((buf=(unsigned char *)malloc(CDBUFSIZE)) == NULL) { - set_error(zep, NULL, ZIP_ER_MEMORY); + if ((buf=(unsigned char *)malloc(buflen)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); return NULL; } - - clearerr(fp); - buflen = fread(buf, 1, CDBUFSIZE, fp); - - if (ferror(fp)) { - set_error(zep, NULL, ZIP_ER_READ); - free(buf); + + if (_zip_read(za->src, buf, buflen, &za->error) < 0) { return NULL; } best = -1; cdir = NULL; - match = buf+ (buflen < CDBUFSIZE ? 0 : EOCD64LOCLEN); - _zip_error_set(&zerr, ZIP_ER_NOZIP, 0); + match = buf + (buflen < CDBUFSIZE ? 0 : EOCD64LOCLEN); + zip_error_set(&zerr, ZIP_ER_NOZIP, 0); while ((match=_zip_memmem(match, buflen-(size_t)(match-buf)-(EOCDLEN-4), (const unsigned char *)EOCD_MAGIC, 4))!=NULL) { /* found match -- check, if good */ /* to avoid finding the same match all over again */ match++; - if ((cdirnew=_zip_readcdir(fp, buf_offset, buf, match-1, buflen, flags, - &zerr)) == NULL) + if ((cdirnew=_zip_read_cdir(za, (zip_uint64_t)buf_offset, buf, match-1, buflen, &zerr)) == NULL) continue; if (cdir) { if (best <= 0) - best = _zip_checkcons(fp, cdir, &zerr); - a = _zip_checkcons(fp, cdirnew, &zerr); + best = _zip_checkcons(za, cdir, &zerr); + a = _zip_checkcons(za, cdirnew, &zerr); if (best < a) { _zip_cdir_free(cdir); cdir = cdirnew; @@ -546,8 +591,8 @@ } else { cdir = cdirnew; - if (flags & ZIP_CHECKCONS) - best = _zip_checkcons(fp, cdir, &zerr); + if (za->open_flags & ZIP_CHECKCONS) + best = _zip_checkcons(za, cdir, &zerr); else best = 0; } @@ -557,7 +602,7 @@ free(buf); if (best < 0) { - set_error(zep, &zerr, 0); + _zip_error_copy(&za->error, &zerr); _zip_cdir_free(cdir); return NULL; } @@ -585,7 +630,7 @@ static struct zip_cdir * -_zip_read_eocd(const unsigned char *eocd, const unsigned char *buf, off_t buf_offset, size_t buflen, +_zip_read_eocd(const unsigned char *eocd, const unsigned char *buf, zip_uint64_t buf_offset, size_t buflen, unsigned int flags, struct zip_error *error) { struct zip_cdir *cd; @@ -593,54 +638,54 @@ zip_uint64_t i, nentry, size, offset; if (eocd+EOCDLEN > buf+buflen) { - _zip_error_set(error, ZIP_ER_INCONS, 0); + zip_error_set(error, ZIP_ER_INCONS, 0); return NULL; } cdp = eocd + 8; /* number of cdir-entries on this disk */ - i = _zip_read2(&cdp); + i = _zip_get_16(&cdp); /* number of cdir-entries */ - nentry = _zip_read2(&cdp); + nentry = _zip_get_16(&cdp); if (nentry != i) { - _zip_error_set(error, ZIP_ER_NOZIP, 0); + zip_error_set(error, ZIP_ER_NOZIP, 0); return NULL; } - size = _zip_read4(&cdp); - offset = _zip_read4(&cdp); + size = _zip_get_32(&cdp); + offset = _zip_get_32(&cdp); - if (size > ZIP_OFF_MAX || offset > ZIP_OFF_MAX || offset+size > ZIP_OFF_MAX) { - _zip_error_set(error, ZIP_ER_SEEK, EFBIG); + if (offset+size < offset) { + zip_error_set(error, ZIP_ER_SEEK, EFBIG); return NULL; } - if (offset+size > (zip_uint64_t)(buf_offset + (eocd-buf))) { + if (offset+size > buf_offset + (zip_uint64_t)(eocd-buf)) { /* cdir spans past EOCD record */ - _zip_error_set(error, ZIP_ER_INCONS, 0); + zip_error_set(error, ZIP_ER_INCONS, 0); return NULL; } - if ((flags & ZIP_CHECKCONS) && offset+size != (zip_uint64_t)(buf_offset + (eocd-buf))) { - _zip_error_set(error, ZIP_ER_INCONS, 0); + if ((flags & ZIP_CHECKCONS) && offset+size != buf_offset + (zip_uint64_t)(eocd-buf)) { + zip_error_set(error, ZIP_ER_INCONS, 0); return NULL; } if ((cd=_zip_cdir_new(nentry, error)) == NULL) return NULL; - cd->size = (off_t)size; - cd->offset = (off_t)offset; + cd->size = size; + cd->offset = offset; return cd; } static struct zip_cdir * -_zip_read_eocd64(FILE *f, const zip_uint8_t *eocd64loc, const zip_uint8_t *buf, - off_t buf_offset, size_t buflen, unsigned int flags, struct zip_error *error) +_zip_read_eocd64(struct zip_source *src, const zip_uint8_t *eocd64loc, const zip_uint8_t *buf, + zip_uint64_t buf_offset, size_t buflen, unsigned int flags, struct zip_error *error) { struct zip_cdir *cd; zip_uint64_t offset; @@ -650,73 +695,73 @@ zip_uint64_t size, nentry, i; cdp = eocd64loc+8; - eocd_offset = _zip_read8(&cdp); + eocd_offset = _zip_get_64(&cdp); - if (eocd_offset > ZIP_OFF_MAX || eocd_offset + EOCD64LEN > ZIP_OFF_MAX) { - _zip_error_set(error, ZIP_ER_SEEK, EFBIG); + if (eocd_offset > ZIP_INT64_MAX || eocd_offset + EOCD64LEN < eocd_offset) { + zip_error_set(error, ZIP_ER_SEEK, EFBIG); return NULL; } - if (eocd64loc < buf || (off_t)eocd_offset+EOCD64LEN > (buf_offset+(eocd64loc-buf))) { - _zip_error_set(error, ZIP_ER_INCONS, 0); + if (eocd64loc < buf || eocd_offset+EOCD64LEN > buf_offset+(zip_uint64_t)(eocd64loc-buf)) { + zip_error_set(error, ZIP_ER_INCONS, 0); return NULL; } - if ((off_t)eocd_offset >= buf_offset && (off_t)eocd_offset+EOCD64LEN <= buf_offset+(ssize_t)buflen) - cdp = buf+((off_t)eocd_offset-buf_offset); + if (eocd_offset >= buf_offset && eocd_offset+EOCD64LEN <= buf_offset+buflen) + cdp = buf+(eocd_offset-buf_offset); else { - if (fseeko(f, (off_t)eocd_offset, SEEK_SET) != 0) { - _zip_error_set(error, ZIP_ER_SEEK, errno); + zip_int64_t n; + + if (zip_source_seek(src, (zip_int64_t)eocd_offset, SEEK_SET) < 0) { + zip_error_set_from_source(error, src); return NULL; } - clearerr(f); - if (fread(eocd, 1, EOCD64LEN, f) < EOCD64LEN) { - _zip_error_set(error, ZIP_ER_READ, errno); + if ((n = zip_source_read(src, eocd, EOCD64LEN)) < 0) { + zip_error_set_from_source(error, src); + return NULL; + } + if (n < EOCD64LEN) { + zip_error_set(error, ZIP_ER_READ, EIO); return NULL; } - if (ferror(f)) { - _zip_error_set(error, ZIP_ER_READ, errno); - return NULL; - } - cdp = eocd; } if (memcmp(cdp, EOCD64_MAGIC, 4) != 0) { - _zip_error_set(error, ZIP_ER_INCONS, 0); + zip_error_set(error, ZIP_ER_INCONS, 0); return NULL; } cdp += 4; - size = _zip_read8(&cdp); + size = _zip_get_64(&cdp); - if ((flags & ZIP_CHECKCONS) && size+eocd_offset+12 != (zip_uint64_t)(buf_offset+(eocd64loc-buf))) { - _zip_error_set(error, ZIP_ER_INCONS, 0); + if ((flags & ZIP_CHECKCONS) && size+eocd_offset+12 != buf_offset+(zip_uint64_t)(eocd64loc-buf)) { + zip_error_set(error, ZIP_ER_INCONS, 0); return NULL; } cdp += 4; /* skip version made by/needed */ cdp += 8; /* skip num disks */ - nentry = _zip_read8(&cdp); - i = _zip_read8(&cdp); + nentry = _zip_get_64(&cdp); + i = _zip_get_64(&cdp); if (nentry != i) { - _zip_error_set(error, ZIP_ER_MULTIDISK, 0); + zip_error_set(error, ZIP_ER_MULTIDISK, 0); return NULL; } - size = _zip_read8(&cdp); - offset = _zip_read8(&cdp); + size = _zip_get_64(&cdp); + offset = _zip_get_64(&cdp); - if (size > ZIP_OFF_MAX || offset > ZIP_OFF_MAX || offset+size > ZIP_OFF_MAX) { - _zip_error_set(error, ZIP_ER_SEEK, EFBIG); + if (offset > ZIP_INT64_MAX || offset+size < offset) { + zip_error_set(error, ZIP_ER_SEEK, EFBIG); return NULL; } if ((flags & ZIP_CHECKCONS) && offset+size != eocd_offset) { - _zip_error_set(error, ZIP_ER_INCONS, 0); + zip_error_set(error, ZIP_ER_INCONS, 0); return NULL; } @@ -724,8 +769,8 @@ return NULL; - cd->size = (off_t)size; - cd->offset = (off_t)offset; + cd->size = size; + cd->offset = offset; return cd; }
diff --git a/lib/zip_rename.c b/lib/zip_rename.c index 1c77b0d..ecc7705 100644 --- a/lib/zip_rename.c +++ b/lib/zip_rename.c
@@ -1,6 +1,6 @@ /* zip_rename.c -- rename file in zip archive - Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/lib/zip_replace.c b/lib/zip_replace.c index 2d699ad..5838252 100644 --- a/lib/zip_replace.c +++ b/lib/zip_replace.c
@@ -1,6 +1,6 @@ /* zip_replace.c -- replace file via callback function - Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/lib/zip_set_archive_comment.c b/lib/zip_set_archive_comment.c index 7b8b24b..2153138 100644 --- a/lib/zip_set_archive_comment.c +++ b/lib/zip_set_archive_comment.c
@@ -1,6 +1,6 @@ /* zip_set_archive_comment.c -- set archive comment - Copyright (C) 2006-2013 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -43,12 +43,12 @@ struct zip_string *cstr; if (ZIP_IS_RDONLY(za)) { - _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); return -1; } if (len > 0 && comment == NULL) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } @@ -58,7 +58,7 @@ if (_zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_CP437) { _zip_string_free(cstr); - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } }
diff --git a/lib/zip_set_archive_flag.c b/lib/zip_set_archive_flag.c index 8e4622d..7f555c3 100644 --- a/lib/zip_set_archive_flag.c +++ b/lib/zip_set_archive_flag.c
@@ -1,6 +1,6 @@ /* zip_get_archive_flag.c -- set archive global flag - Copyright (C) 2008-2009 Dieter Baron and Thomas Klausner + Copyright (C) 2008-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -49,14 +49,14 @@ return 0; if (ZIP_IS_RDONLY(za)) { - _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); return -1; } if ((flag & ZIP_AFL_RDONLY) && value && (za->ch_flags & ZIP_AFL_RDONLY) == 0) { if (_zip_changed(za, NULL)) { - _zip_error_set(&za->error, ZIP_ER_CHANGED, 0); + zip_error_set(&za->error, ZIP_ER_CHANGED, 0); return -1; } }
diff --git a/lib/zip_set_default_password.c b/lib/zip_set_default_password.c index f41e8f8..f45d580 100644 --- a/lib/zip_set_default_password.c +++ b/lib/zip_set_default_password.c
@@ -1,6 +1,6 @@ /* zip_set_default_password.c -- set default password for decryption - Copyright (C) 2009 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -49,7 +49,7 @@ if (passwd) { if ((za->default_password=strdup(passwd)) == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); return -1; } }
diff --git a/lib/zip_set_file_comment.c b/lib/zip_set_file_comment.c index e4a7d3e..fffff46 100644 --- a/lib/zip_set_file_comment.c +++ b/lib/zip_set_file_comment.c
@@ -1,6 +1,6 @@ /* zip_set_file_comment.c -- set comment for file in archive - Copyright (C) 2006-2012 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -42,7 +42,7 @@ zip_set_file_comment(struct zip *za, zip_uint64_t idx, const char *comment, int len) { if (len < 0 || len > ZIP_UINT16_MAX) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } return zip_file_set_comment(za, idx, comment, (zip_uint16_t)len, 0);
diff --git a/lib/zip_set_file_compression.c b/lib/zip_set_file_compression.c index 3322106..41aaa67 100644 --- a/lib/zip_set_file_compression.c +++ b/lib/zip_set_file_compression.c
@@ -1,6 +1,6 @@ /* zip_set_file_compression.c -- set compression for file in archive - Copyright (C) 2012 Dieter Baron and Thomas Klausner + Copyright (C) 2012-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -43,17 +43,17 @@ zip_int32_t old_method; if (idx >= za->nentry) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } if (ZIP_IS_RDONLY(za)) { - _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); return -1; } if (method != ZIP_CM_DEFAULT && method != ZIP_CM_STORE && method != ZIP_CM_DEFLATE) { - _zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); + zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); return -1; } @@ -75,7 +75,7 @@ else { if (e->changes == NULL) { if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); return -1; } }
diff --git a/lib/zip_set_name.c b/lib/zip_set_name.c index f92fe90..87d372f 100644 --- a/lib/zip_set_name.c +++ b/lib/zip_set_name.c
@@ -1,6 +1,6 @@ /* zip_set_name.c -- rename helper function - Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -47,12 +47,12 @@ zip_int64_t i; if (idx >= za->nentry) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } if (ZIP_IS_RDONLY(za)) { - _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); return -1; } @@ -69,7 +69,7 @@ /* TODO: encoding flags needed for CP437? */ if ((i=_zip_name_locate(za, name, 0, NULL)) >= 0 && (zip_uint64_t)i != idx) { _zip_string_free(str); - _zip_error_set(&za->error, ZIP_ER_EXISTS, 0); + zip_error_set(&za->error, ZIP_ER_EXISTS, 0); return -1; } @@ -95,7 +95,7 @@ if (changed) { if (e->changes == NULL) { if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); _zip_string_free(str); return -1; }
diff --git a/lib/zip_source_begin_write.c b/lib/zip_source_begin_write.c new file mode 100644 index 0000000..a6a8563 --- /dev/null +++ b/lib/zip_source_begin_write.c
@@ -0,0 +1,53 @@ +/* + zip_source_begin_write.c -- start a new file for writing + Copyright (C) 2014 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" + + +int +zip_source_begin_write(struct zip_source *src) +{ + if (ZIP_SOURCE_IS_OPEN_WRITING(src)) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_BEGIN_WRITE) < 0) { + return -1; + } + + src->write_state = ZIP_SOURCE_WRITE_OPEN; + + return 0; +}
diff --git a/lib/zip_source_buffer.c b/lib/zip_source_buffer.c index bc6a6cb..85631ad 100644 --- a/lib/zip_source_buffer.c +++ b/lib/zip_source_buffer.c
@@ -1,6 +1,6 @@ /* zip_source_buffer.c -- create zip data source from buffer - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -37,41 +37,80 @@ #include "zipint.h" -struct read_data { - const char *buf, *data, *end; - time_t mtime; - int freep; +#ifndef WRITE_FRAGMENT_SIZE +#define WRITE_FRAGMENT_SIZE 64*1024 +#endif + +struct buffer { + zip_uint64_t fragment_size; /* size of each fragment */ + + zip_uint8_t **fragments; /* pointers to fragments */ + zip_uint64_t nfragments; /* number of allocated fragments */ + zip_uint64_t fragments_capacity; /* size of fragments (number of pointers) */ + zip_uint64_t size; /* size of data in bytes */ + zip_uint64_t offset; /* current offset */ + int free_data; }; +typedef struct buffer buffer_t; + +struct read_data { + zip_error_t error; + time_t mtime; + buffer_t *in; + buffer_t *out; +}; + +static void buffer_free(buffer_t *buffer); +static buffer_t *buffer_new(zip_uint64_t fragment_size); +static buffer_t *buffer_new_read(const void *data, zip_uint64_t length, int free_data); +static buffer_t *buffer_new_write(zip_uint64_t fragment_size); +static zip_int64_t buffer_read(buffer_t *buffer, void *data, zip_uint64_t length); +static int buffer_seek(buffer_t *buffer, void *data, zip_uint64_t len, zip_error_t *error); +static zip_int64_t buffer_write(buffer_t *buffer, const void *data, zip_uint64_t length, zip_error_t *); + static zip_int64_t read_data(void *, void *, zip_uint64_t, enum zip_source_cmd); ZIP_EXTERN struct zip_source * zip_source_buffer(struct zip *za, const void *data, zip_uint64_t len, int freep) { - struct read_data *f; - struct zip_source *zs; - if (za == NULL) return NULL; + return zip_source_buffer_create(data, len, freep, &za->error); +} + + +ZIP_EXTERN struct zip_source * +zip_source_buffer_create(const void *data, zip_uint64_t len, int freep, zip_error_t *error) +{ + struct read_data *ctx; + struct zip_source *zs; + if (data == NULL && len > 0) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(error, ZIP_ER_INVAL, 0); return NULL; } - if ((f=(struct read_data *)malloc(sizeof(*f))) == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + if ((ctx=(struct read_data *)malloc(sizeof(*ctx))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); return NULL; } - f->data = (const char *)data; - f->end = ((const char *)data)+len; - f->freep = freep; - f->mtime = time(NULL); + if ((ctx->in = buffer_new_read(data, len, freep)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + free(ctx); + return NULL; + } + + ctx->out = NULL; + ctx->mtime = time(NULL); + zip_error_init(&ctx->error); - if ((zs=zip_source_function(za, read_data, f)) == NULL) { - free(f); + if ((zs=zip_source_function_create(read_data, ctx, error)) == NULL) { + buffer_free(ctx->in); + free(ctx); return NULL; } @@ -82,77 +121,316 @@ static zip_int64_t read_data(void *state, void *data, zip_uint64_t len, enum zip_source_cmd cmd) { - struct read_data *z; + struct read_data *ctx = (struct read_data *)state; char *buf; zip_uint64_t n; - z = (struct read_data *)state; - buf = (char *)data; - switch (cmd) { - case ZIP_SOURCE_OPEN: - z->buf = z->data; - return 0; - - case ZIP_SOURCE_READ: - n = (zip_uint64_t)(z->end - z->buf); - if (n > len) - n = len; + case ZIP_SOURCE_BEGIN_WRITE: + if ((ctx->out = buffer_new_write(WRITE_FRAGMENT_SIZE)) == NULL) { + zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); + return -1; + } + return 0; - if (n) { - memcpy(buf, z->buf, n); - z->buf += n; + case ZIP_SOURCE_CLOSE: + return 0; + + case ZIP_SOURCE_COMMIT_WRITE: + buffer_free(ctx->in); + ctx->in = ctx->out; + ctx->out = NULL; + return 0; + + case ZIP_SOURCE_ERROR: + return zip_error_to_data(&ctx->error, data, len); + + case ZIP_SOURCE_FREE: + buffer_free(ctx->in); + buffer_free(ctx->out); + free(ctx); + return 0; + + case ZIP_SOURCE_OPEN: + ctx->in->offset = 0; + return 0; + + case ZIP_SOURCE_READ: + return buffer_read(ctx->in, data, len); + + case ZIP_SOURCE_REMOVE: + { + buffer_t *empty = buffer_new_read(NULL, 0, 0); + if (empty == 0) { + zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); + return -1; + } + + buffer_free(ctx->in); + ctx->in = empty; + return 0; } - return (zip_int64_t)n; - - case ZIP_SOURCE_CLOSE: - return 0; + case ZIP_SOURCE_ROLLBACK_WRITE: + buffer_free(ctx->out); + ctx->out = NULL; + return 0; - case ZIP_SOURCE_STAT: + case ZIP_SOURCE_SEEK: + return buffer_seek(ctx->in, data, len, &ctx->error); + + case ZIP_SOURCE_SEEK_WRITE: + return buffer_seek(ctx->out, data, len, &ctx->error); + + case ZIP_SOURCE_STAT: { - struct zip_stat *st; + struct zip_stat *st; - if (len < sizeof(*st)) + if (len < sizeof(*st)) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); return -1; + } st = (struct zip_stat *)data; zip_stat_init(st); - st->mtime = z->mtime; - st->size = (zip_uint64_t)(z->end - z->data); + st->mtime = ctx->mtime; + st->size = ctx->in->size; st->comp_size = st->size; st->comp_method = ZIP_CM_STORE; st->encryption_method = ZIP_EM_NONE; - st->valid = ZIP_STAT_MTIME|ZIP_STAT_SIZE|ZIP_STAT_COMP_SIZE - |ZIP_STAT_COMP_METHOD|ZIP_STAT_ENCRYPTION_METHOD; + st->valid = ZIP_STAT_MTIME|ZIP_STAT_SIZE|ZIP_STAT_COMP_SIZE|ZIP_STAT_COMP_METHOD|ZIP_STAT_ENCRYPTION_METHOD; return sizeof(*st); } - case ZIP_SOURCE_ERROR: - { - int *e; + case ZIP_SOURCE_SUPPORTS: + return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_SEEK, ZIP_SOURCE_TELL, ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_REMOVE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_WRITE, -1); + + case ZIP_SOURCE_TELL: + return ctx->in->offset; + + case ZIP_SOURCE_TELL_WRITE: + return ctx->out->offset; - if (len < sizeof(int)*2) - return -1; + case ZIP_SOURCE_WRITE: + return buffer_write(ctx->out, data, len, &ctx->error); - e = (int *)data; - e[0] = e[1] = 0; - } - return sizeof(int)*2; + default: + zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); + return -1; + } +} - case ZIP_SOURCE_FREE: - if (z->freep) { - free((void *)z->data); - z->data = NULL; - } - free(z); - return 0; - default: - ; +static void +buffer_free(buffer_t *buffer) +{ + if (buffer == NULL) { + return; } - return -1; + if (buffer->free_data) { + zip_uint64_t i; + + for (i=0; i < buffer->nfragments; i++) { + free(buffer->fragments[i]); + } + } + free(buffer->fragments); + free(buffer); +} + + +static buffer_t * +buffer_new(zip_uint64_t fragment_size) +{ + buffer_t *buffer; + + if ((buffer = malloc(sizeof(*buffer))) == NULL) { + return NULL; + } + + buffer->fragment_size = fragment_size; + buffer->offset = 0; + buffer->free_data = 0; + buffer->nfragments = 0; + buffer->fragments_capacity = 0; + buffer->fragments = NULL; + buffer->size = 0; + + return buffer; +} + + +static buffer_t * +buffer_new_read(const void *data, zip_uint64_t length, int free_data) +{ + buffer_t *buffer; + + if ((buffer = buffer_new(length)) == NULL) { + return NULL; + } + + buffer->size = length; + + if (length > 0) { + if ((buffer->fragments = malloc(sizeof(*(buffer->fragments)))) == NULL) { + buffer_free(buffer); + return NULL; + } + buffer->fragments_capacity = 1; + + buffer->nfragments = 1; + buffer->fragments[0] = (zip_uint8_t *)data; + buffer->free_data = free_data; + } + + return buffer; +} + + +static buffer_t * +buffer_new_write(zip_uint64_t fragment_size) +{ + buffer_t *buffer; + + if ((buffer = buffer_new(fragment_size)) == NULL) { + return NULL; + } + + if ((buffer->fragments = malloc(sizeof(*(buffer->fragments)))) == NULL) { + buffer_free(buffer); + return NULL; + } + buffer->fragments_capacity = 1; + buffer->nfragments = 0; + buffer->free_data = 1; + + return buffer; +} + + +static zip_int64_t +buffer_read(buffer_t *buffer, void *data, zip_uint64_t length) +{ + zip_uint64_t n, i, fragment_offset; + + length = ZIP_MIN(length, buffer->size - buffer->offset); + + if (length == 0) { + return 0; + } + + i = buffer->offset / buffer->fragment_size; + fragment_offset = buffer->offset % buffer->fragment_size; + n = 0; + while (n < length) { + zip_uint64_t left = ZIP_MIN(length - n, buffer->fragment_size - fragment_offset); + + memcpy(data + n, buffer->fragments[i] + fragment_offset, left); + + n += left; + i++; + fragment_offset = 0; + } + + buffer->offset += n; + return n; +} + + +static int +buffer_seek(buffer_t *buffer, void *data, zip_uint64_t len, zip_error_t *error) +{ + zip_uint64_t offset; + zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, error); + + if (args == NULL) + return -1; + + switch (args->whence) { + case SEEK_CUR: + offset = buffer->offset + args->offset; + break; + + case SEEK_END: + offset = buffer->size + args->offset; + break; + + case SEEK_SET: + offset = args->offset; + break; + } + + if (offset < 0 || (zip_uint64_t)offset > buffer->size) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return -1; + } + + buffer->offset = offset; + return 0; +} + + +static zip_int64_t +buffer_write(buffer_t *buffer, const void *data, zip_uint64_t length, zip_error_t *error) +{ + zip_uint64_t n, i, fragment_offset; + + if (buffer->offset + length + buffer->fragment_size - 1 < length) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return -1; + } + + /* grow buffer if needed */ + if (buffer->offset + length > buffer->nfragments * buffer->fragment_size) { + zip_uint64_t needed_fragments = (buffer->offset + length + buffer->fragment_size - 1) / buffer->fragment_size; + + if (needed_fragments > buffer->fragments_capacity) { + zip_uint64_t new_capacity = buffer->fragments_capacity; + + while (new_capacity < needed_fragments) { + new_capacity *= 2; + } + + zip_uint8_t **fragments = realloc(buffer->fragments, new_capacity * sizeof(*fragments)); + + if (fragments == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return -1; + } + + buffer->fragments = fragments; + buffer->fragments_capacity = new_capacity; + } + + while (buffer->nfragments < needed_fragments) { + if ((buffer->fragments[buffer->nfragments] = malloc(buffer->fragment_size)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return -1; + } + buffer->nfragments++; + } + } + + i = buffer->offset / buffer->fragment_size; + fragment_offset = buffer->offset % buffer->fragment_size; + n = 0; + while (n < length) { + zip_uint64_t left = ZIP_MIN(length - n, buffer->fragment_size - fragment_offset); + + memcpy(buffer->fragments[i] + fragment_offset, data + n, left); + + n += left; + i++; + fragment_offset = 0; + } + + buffer->offset += n; + if (buffer->offset > buffer->size) { + buffer->size = buffer->offset; + } + + return n; }
diff --git a/lib/zip_source_call.c b/lib/zip_source_call.c new file mode 100644 index 0000000..e0a1a63 --- /dev/null +++ b/lib/zip_source_call.c
@@ -0,0 +1,64 @@ +/* + zip_source_call.c -- invoke callback command on zip_source + Copyright (C) 2009-2014 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" + + +zip_int64_t +_zip_source_call(zip_source_t *src, void *data, zip_uint64_t length, enum zip_source_cmd command) +{ + zip_int64_t ret; + + if (src->src == NULL) { + ret = src->cb.f(src->ud, data, length, command); + } + else { + ret = src->cb.l(src->src, src->ud, data, length, command); + } + + if (ret < 0) { + if (command != ZIP_SOURCE_ERROR && command != ZIP_SOURCE_SUPPORTS) { + int e[2]; + + if (_zip_source_call(src, e, sizeof(e), ZIP_SOURCE_ERROR) < 0) { + zip_error_set(&src->error, ZIP_ER_INTERNAL, 0); + } + else { + zip_error_set(&src->error, e[0], e[1]); + } + } + } + + return ret; +}
diff --git a/lib/zip_source_close.c b/lib/zip_source_close.c index 0075503..cbc69c4 100644 --- a/lib/zip_source_close.c +++ b/lib/zip_source_close.c
@@ -1,6 +1,6 @@ /* zip_source_close.c -- close zip_source (stop reading) - Copyright (C) 2009 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -35,18 +35,24 @@ #include "zipint.h" -void +int zip_source_close(struct zip_source *src) { - if (!src->is_open) - return; - - if (src->src == NULL) - (void)src->cb.f(src->ud, NULL, 0, ZIP_SOURCE_CLOSE); - else { - (void)src->cb.l(src->src, src->ud, NULL, 0, ZIP_SOURCE_CLOSE); - zip_source_close(src->src); + if (!ZIP_SOURCE_IS_OPEN_READING(src)) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; } - src->is_open = 0; + src->open_count--; + if (src->open_count == 0) { + _zip_source_call(src, NULL, 0, ZIP_SOURCE_CLOSE); + } + + if (ZIP_SOURCE_IS_LAYERED(src)) { + if (zip_source_close(src->src) < 0) { + zip_error_set(&src->error, ZIP_ER_INTERNAL, 0); + } + } + + return 0; }
diff --git a/lib/zip_source_commit_write.c b/lib/zip_source_commit_write.c new file mode 100644 index 0000000..09fe3da --- /dev/null +++ b/lib/zip_source_commit_write.c
@@ -0,0 +1,64 @@ +/* + zip_source_commit_write.c -- commit changes to file + Copyright (C) 2014 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" + + +int +zip_source_commit_write(struct zip_source *src) +{ + if (!ZIP_SOURCE_IS_OPEN_WRITING(src)) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (src->open_count > 1) { + zip_error_set(&src->error, ZIP_ER_INUSE, 0); + return -1; + } + else if (ZIP_SOURCE_IS_OPEN_READING(src)) { + if (zip_source_close(src) < 0) { + return -1; + } + } + + if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_COMMIT_WRITE) < 0) { + src->write_state = ZIP_SOURCE_WRITE_FAILED; + return -1; + } + + src->write_state = ZIP_SOURCE_WRITE_CLOSED; + + return 0; +}
diff --git a/lib/zip_source_crc.c b/lib/zip_source_crc.c index fda2caa..f3d5048 100644 --- a/lib/zip_source_crc.c +++ b/lib/zip_source_crc.c
@@ -1,6 +1,6 @@ /* zip_source_crc.c -- pass-through source that calculates CRC32 and size - Copyright (C) 2009 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -34,19 +34,19 @@ #include <stdlib.h> #include <string.h> +#include <limits.h> #include "zipint.h" struct crc_context { int eof; int validate; - int e[2]; + zip_error_t error; zip_uint64_t size; zip_uint32_t crc; }; -static zip_int64_t crc_read(struct zip_source *, void *, void * - , zip_uint64_t, enum zip_source_cmd); +static zip_int64_t crc_read(struct zip_source *, void *, void *, zip_uint64_t, enum zip_source_cmd); struct zip_source * @@ -55,18 +55,18 @@ struct crc_context *ctx; if (src == NULL) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return NULL; } if ((ctx=(struct crc_context *)malloc(sizeof(*ctx))) == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); return NULL; } ctx->eof = 0; ctx->validate = validate; - ctx->e[0] = ctx->e[1] = 0; + zip_error_init(&ctx->error); ctx->size = 0; ctx->crc = 0; @@ -75,8 +75,7 @@ static zip_int64_t -crc_read(struct zip_source *src, void *_ctx, void *data, - zip_uint64_t len, enum zip_source_cmd cmd) +crc_read(struct zip_source *src, void *_ctx, void *data, zip_uint64_t len, enum zip_source_cmd cmd) { struct crc_context *ctx; zip_int64_t n; @@ -84,54 +83,60 @@ ctx = (struct crc_context *)_ctx; switch (cmd) { - case ZIP_SOURCE_OPEN: - ctx->eof = 0; - ctx->crc = (zip_uint32_t)crc32(0, NULL, 0); - ctx->size = 0; + case ZIP_SOURCE_OPEN: + ctx->eof = 0; + ctx->crc = (zip_uint32_t)crc32(0, NULL, 0); + ctx->size = 0; + + return 0; + + case ZIP_SOURCE_READ: + if (ctx->eof || len == 0) + return 0; + + if ((n=zip_source_read(src, data, len)) < 0) { + zip_error_set_from_source(&ctx->error, src); + return -1; + } + + if (n == 0) { + ctx->eof = 1; + if (ctx->validate) { + struct zip_stat st; + + if (zip_source_stat(src, &st) < 0) { + zip_error_set_from_source(&ctx->error, src); + return -1; + } + + if ((st.valid & ZIP_STAT_CRC) && st.crc != ctx->crc) { + zip_error_set(&ctx->error, ZIP_ER_CRC, 0); + return -1; + } + if ((st.valid & ZIP_STAT_SIZE) && st.size != ctx->size) { + zip_error_set(&ctx->error, ZIP_ER_INCONS, 0); + return -1; + } + } + } + else { + zip_uint64_t i, nn; - return 0; + for (i=0; i < n; i += nn) { + nn = ZIP_MIN(UINT_MAX, n-i); - case ZIP_SOURCE_READ: - if (ctx->eof || len == 0) - return 0; - - if ((n=zip_source_read(src, data, len)) < 0) - return ZIP_SOURCE_ERR_LOWER; - - if (n == 0) { - ctx->eof = 1; - if (ctx->validate) { - struct zip_stat st; - - if (zip_source_stat(src, &st) < 0) - return ZIP_SOURCE_ERR_LOWER; - - if ((st.valid & ZIP_STAT_CRC) && st.crc != ctx->crc) { - ctx->e[0] = ZIP_ER_CRC; - ctx->e[1] = 0; - - return -1; + ctx->crc = (zip_uint32_t)crc32(ctx->crc, (const Bytef *)data+i, (uInt)nn); } - if ((st.valid & ZIP_STAT_SIZE) && st.size != ctx->size) { - ctx->e[0] = ZIP_ER_INCONS; - ctx->e[1] = 0; - - return -1; - } - } - } - else { - ctx->size += (zip_uint64_t)n; - ctx->crc = (zip_uint32_t)crc32(ctx->crc, (const Bytef *)data, (uInt)n); /* TODO: check for overflow, use multiple crc calls if needed */ - } - return n; + ctx->size += (zip_uint64_t)n; + } + return n; - case ZIP_SOURCE_CLOSE: - return 0; + case ZIP_SOURCE_CLOSE: + return 0; - case ZIP_SOURCE_STAT: - { - struct zip_stat *st; + case ZIP_SOURCE_STAT: + { + struct zip_stat *st; st = (struct zip_stat *)data; @@ -145,19 +150,21 @@ st->encryption_method = ZIP_EM_NONE; st->valid |= ZIP_STAT_SIZE|ZIP_STAT_CRC|ZIP_STAT_COMP_SIZE|ZIP_STAT_COMP_METHOD|ZIP_STAT_ENCRYPTION_METHOD;; } - } - return 0; - - case ZIP_SOURCE_ERROR: - memcpy(data, ctx->e, sizeof(ctx->e)); - return 0; + return 0; + } + + case ZIP_SOURCE_ERROR: + return zip_error_to_data(&ctx->error, data, len); - case ZIP_SOURCE_FREE: - free(ctx); - return 0; - - default: - return -1; + 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; } - }
diff --git a/lib/zip_source_deflate.c b/lib/zip_source_deflate.c index 4950d4e..344ccd9 100644 --- a/lib/zip_source_deflate.c +++ b/lib/zip_source_deflate.c
@@ -1,6 +1,6 @@ /* zip_source_deflate.c -- deflate (de)compressoin routines - Copyright (C) 2009 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -34,12 +34,13 @@ #include <stdlib.h> #include <string.h> +#include <limits.h> #include "zipint.h" struct deflate { - int e[2]; - + zip_error_t error; + int eof; int mem_level; zip_uint64_t size; @@ -47,35 +48,30 @@ z_stream zstr; }; -static zip_int64_t compress_read(struct zip_source *, struct deflate *, - void *, zip_uint64_t); -static zip_int64_t decompress_read(struct zip_source *, struct deflate *, - void *, zip_uint64_t); -static zip_int64_t deflate_compress(struct zip_source *, void *, void *, - zip_uint64_t, enum zip_source_cmd); -static zip_int64_t deflate_decompress(struct zip_source *, void *, void *, - zip_uint64_t, enum zip_source_cmd); +static zip_int64_t compress_read(struct zip_source *, struct deflate *, void *, zip_uint64_t); +static zip_int64_t decompress_read(struct zip_source *, struct deflate *, void *, zip_uint64_t); +static zip_int64_t deflate_compress(struct zip_source *, void *, void *, zip_uint64_t, enum zip_source_cmd); +static zip_int64_t deflate_decompress(struct zip_source *, void *, void *, zip_uint64_t, enum zip_source_cmd); static void deflate_free(struct deflate *); struct zip_source * -zip_source_deflate(struct zip *za, struct zip_source *src, - zip_int32_t cm, int flags) +zip_source_deflate(struct zip *za, struct zip_source *src, zip_int32_t cm, int flags) { struct deflate *ctx; struct zip_source *s2; if (src == NULL || (cm != ZIP_CM_DEFLATE && !ZIP_CM_IS_DEFAULT(cm))) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + 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); + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); return NULL; } - ctx->e[0] = ctx->e[1] = 0; + zip_error_init(&ctx->error); ctx->eof = 0; if (flags & ZIP_CODEC_ENCODE) { if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0)) @@ -97,20 +93,23 @@ static zip_int64_t -compress_read(struct zip_source *src, struct deflate *ctx, - void *data, zip_uint64_t len) +compress_read(struct zip_source *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 (ctx->e[0] != 0) + 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 = (uInt)len; /* TODO: check for overflow */ + ctx->zstr.avail_out = out_len; end = 0; while (!end) { @@ -121,8 +120,18 @@ case Z_STREAM_END: /* all ok */ - if (ctx->zstr.avail_out == 0 - || (ctx->eof && ctx->zstr.avail_in == 0)) + 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; + } + } + else if (ctx->eof && ctx->zstr.avail_in == 0) end = 1; break; @@ -134,7 +143,7 @@ } if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) { - zip_source_error(src, ctx->e, ctx->e+1); + zip_error_set_from_source(&ctx->error, src); end = 1; break; } @@ -154,8 +163,7 @@ case Z_DATA_ERROR: case Z_STREAM_ERROR: case Z_MEM_ERROR: - ctx->e[0] = ZIP_ER_ZLIB; - ctx->e[1] = ret; + zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret); end = 1; break; @@ -165,32 +173,46 @@ if (ctx->zstr.avail_out < len) return (zip_int64_t)(len - ctx->zstr.avail_out); - return (ctx->e[0] == 0) ? 0 : -1; + return (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) ? 0 : -1; } static zip_int64_t -decompress_read(struct zip_source *src, struct deflate *ctx, - void *data, zip_uint64_t len) +decompress_read(struct zip_source *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 (ctx->e[0] != 0) + if (zip_error_code_zip(&ctx->error) != ZIP_ER_OK) return -1; if (len == 0) return 0; - + + out_offset = 0; + out_len = ZIP_MIN(UINT_MAX, len); ctx->zstr.next_out = (Bytef *)data; - ctx->zstr.avail_out = (uInt)len; /* TODO: check for overflow */ + ctx->zstr.avail_out = out_len; end = 0; - while (!end && ctx->zstr.avail_out) { + 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: @@ -206,7 +228,7 @@ } if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) { - zip_source_error(src, ctx->e, ctx->e+1); + zip_error_set_from_source(&ctx->error, src); end = 1; break; } @@ -223,8 +245,7 @@ case Z_DATA_ERROR: case Z_STREAM_ERROR: case Z_MEM_ERROR: - ctx->e[0] = ZIP_ER_ZLIB; - ctx->e[1] = ret; + zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret); end = 1; break; } @@ -233,13 +254,12 @@ if (ctx->zstr.avail_out < len) return (zip_int64_t)(len - ctx->zstr.avail_out); - return (ctx->e[0] == 0) ? 0 : -1; + return (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) ? 0 : -1; } static zip_int64_t -deflate_compress(struct zip_source *src, void *ud, void *data, - zip_uint64_t len, enum zip_source_cmd cmd) +deflate_compress(struct zip_source *src, void *ud, void *data, zip_uint64_t len, enum zip_source_cmd cmd) { struct deflate *ctx; int ret; @@ -257,11 +277,8 @@ 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) { - ctx->e[0] = ZIP_ER_ZLIB; - ctx->e[1] = ret; + 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; } @@ -292,16 +309,14 @@ return 0; case ZIP_SOURCE_ERROR: - memcpy(data, ctx->e, sizeof(int)*2); - return sizeof(int)*2; + return zip_error_to_data(&ctx->error, data, len); case ZIP_SOURCE_FREE: deflate_free(ctx); return 0; default: - ctx->e[0] = ZIP_ER_INVAL; - ctx->e[1] = 0; + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); return -1; } } @@ -318,68 +333,64 @@ ctx = (struct deflate *)ud; switch (cmd) { - case ZIP_SOURCE_OPEN: - if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) - return ZIP_SOURCE_ERR_LOWER; + 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 /* TODO: check for overflow */; + 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) { - ctx->e[0] = ZIP_ER_ZLIB; - ctx->e[1] = ret; + /* 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; - return -1; - } - return 0; + case ZIP_SOURCE_READ: + return decompress_read(src, ctx, data, len); - case ZIP_SOURCE_READ: - return decompress_read(src, ctx, data, len); + case ZIP_SOURCE_CLOSE: + inflateEnd(&ctx->zstr); + return 0; - case ZIP_SOURCE_CLOSE: - inflateEnd(&ctx->zstr); - return 0; + case ZIP_SOURCE_STAT: + { + struct zip_stat *st; + + st = (struct zip_stat *)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_STAT: - { - struct zip_stat *st; + case ZIP_SOURCE_ERROR: + return zip_error_to_data(&ctx->error, data, len); - st = (struct zip_stat *)data; + 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); - 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: - if (len < sizeof(int)*2) - return -1; - - memcpy(data, ctx->e, sizeof(int)*2); - return sizeof(int)*2; - - case ZIP_SOURCE_FREE: - /* TODO: inflateEnd if close was not called */ - free(ctx); - return 0; - - default: - ctx->e[0] = ZIP_ER_INVAL; - ctx->e[1] = 0; - return -1; + default: + zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); + return -1; } - } static void deflate_free(struct deflate *ctx) { - /* TODO: deflateEnd if close was not called */ free(ctx); }
diff --git a/lib/zip_source_error.c b/lib/zip_source_error.c index 4999491..401a32e 100644 --- a/lib/zip_source_error.c +++ b/lib/zip_source_error.c
@@ -1,6 +1,6 @@ /* zip_source_error.c -- get last error from zip_source - Copyright (C) 2009-2013 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -35,48 +35,8 @@ #include "zipint.h" -void -zip_source_error(struct zip_source *src, int *ze, int *se) +struct zip_error * +zip_source_error(struct zip_source *src) { - int e[2]; - - if (src->src == NULL) { - if (src->cb.f(src->ud, e, sizeof(e), ZIP_SOURCE_ERROR) < 0) { - e[0] = ZIP_ER_INTERNAL; - e[1] = 0; - } - } - else { - switch (src->error_source) { - case ZIP_LES_NONE: - e[0] = e[1] = 0; - break; - - case ZIP_LES_INVAL: - e[0] = ZIP_ER_INVAL; - e[1] = 0; - break; - - case ZIP_LES_LOWER: - zip_source_error(src->src, ze, se); - return; - - case ZIP_LES_UPPER: - if (src->cb.l(src->src, src->ud, e, sizeof(e), ZIP_SOURCE_ERROR) < 0) { - e[0] = ZIP_ER_INTERNAL; - e[1] = 0; - } - break; - - default: - e[0] = ZIP_ER_INTERNAL; - e[1] = 0; - break; - } - } - - if (ze) - *ze = e[0]; - if (se) - *se = e[1]; + return &src->error; }
diff --git a/lib/zip_source_file.c b/lib/zip_source_file.c index 4a6824a..0fddfbd 100644 --- a/lib/zip_source_file.c +++ b/lib/zip_source_file.c
@@ -1,6 +1,6 @@ /* zip_source_file.c -- create data source from file - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -39,16 +39,22 @@ ZIP_EXTERN struct zip_source * -zip_source_file(struct zip *za, const char *fname, zip_uint64_t start, - zip_int64_t len) +zip_source_file(struct zip *za, const char *fname, zip_uint64_t start, zip_int64_t len) { if (za == NULL) return NULL; + + return zip_source_file_create(fname, start, len, &za->error); +} - if (fname == NULL || len < -1) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + +ZIP_EXTERN zip_source_t * +zip_source_file_create(const char *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error) +{ + if (fname == NULL || length < -1) { + zip_error_set(error, ZIP_ER_INVAL, 0); return NULL; } - return _zip_source_file_or_p(za, fname, NULL, start, len, 1, NULL); + return _zip_source_file_or_p(fname, NULL, start, length, 1, NULL, error); }
diff --git a/lib/zip_source_filep.c b/lib/zip_source_filep.c index b05e960..9fabf81 100644 --- a/lib/zip_source_filep.c +++ b/lib/zip_source_filep.c
@@ -41,79 +41,105 @@ #include "zipint.h" struct read_file { - char *fname; /* name of file to copy from */ - FILE *f; /* file to copy from */ - int closep; /* close f */ - struct zip_stat st; /* stat information passed in */ + zip_error_t error; /* last error information */ + zip_int64_t supports; - zip_uint64_t off; /* start offset of */ - zip_int64_t len; /* length of data to copy */ - zip_int64_t remain; /* bytes remaining to be copied */ - int e[2]; /* error codes */ - int source_closed; /* set if source archive is closed */ - struct zip *source_archive; /* zip archive we're reading from, NULL if not from archive */ + /* reading */ + char *fname; /* name of file to read from */ + FILE *f; /* file to read from */ + int closep; /* whether to close f on ZIP_CMD_FREE */ + struct zip_stat st; /* stat information passed in */ + zip_uint64_t start; /* start offset of data to read */ + zip_uint64_t end; /* end offset of data to read, 0 for up to EOF */ + zip_uint64_t current; /* current offset */ + + /* writing */ + char *tmpname; + FILE *fout; }; static zip_int64_t read_file(void *state, void *data, zip_uint64_t len, enum zip_source_cmd cmd); -static void _zip_deregister_source(struct zip *za, void *ud); -static int _zip_register_source(struct zip *za, struct zip_source *src); +static int create_temp_output(struct read_file *ctx); ZIP_EXTERN struct zip_source * -zip_source_filep(struct zip *za, FILE *file, zip_uint64_t start, - zip_int64_t len) +zip_source_filep(struct zip *za, FILE *file, zip_uint64_t start, zip_int64_t len) { if (za == NULL) return NULL; + + return zip_source_filep_create(file, start, len, &za->error); +} - if (file == NULL || len < -1) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + +ZIP_EXTERN zip_source_t * +zip_source_filep_create(FILE *file, zip_uint64_t start, zip_int64_t length, zip_error_t *error) +{ + if (file == NULL || length < -1) { + zip_error_set(error, ZIP_ER_INVAL, 0); return NULL; } - return _zip_source_file_or_p(za, NULL, file, start, len, 1, NULL); + return _zip_source_file_or_p(NULL, file, start, length, 1, NULL, error); } struct zip_source * -_zip_source_file_or_p(struct zip *za, const char *fname, FILE *file, - zip_uint64_t start, zip_int64_t len, int closep, - const struct zip_stat *st) +_zip_source_file_or_p(const char *fname, FILE *file, zip_uint64_t start, zip_int64_t len, int closep, const zip_stat_t *st, zip_error_t *error) { - struct read_file *f; + struct read_file *ctx; struct zip_source *zs; - + if (file == NULL && fname == NULL) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((ctx=(struct read_file *)malloc(sizeof(struct read_file))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); return NULL; } - if ((f=(struct read_file *)malloc(sizeof(struct read_file))) == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return NULL; - } - - f->fname = NULL; + ctx->fname = NULL; if (fname) { - if ((f->fname=strdup(fname)) == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - free(f); + if ((ctx->fname=strdup(fname)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + free(ctx); return NULL; } } - f->f = file; - f->off = start; - f->len = (len ? len : -1); - f->closep = f->fname ? 1 : closep; - f->source_closed = 0; - f->source_archive = NULL; - if (st) - memcpy(&f->st, st, sizeof(f->st)); - else - zip_stat_init(&f->st); + ctx->f = file; + ctx->start = start; + ctx->end = (len < 0 ? 0 : start+(zip_uint64_t)len); + ctx->closep = ctx->fname ? 1 : closep; + if (st) { + memcpy(&ctx->st, st, sizeof(ctx->st)); + ctx->st.name = NULL; + ctx->st.valid &= ~ZIP_STAT_NAME; + } + else { + zip_stat_init(&ctx->st); + } + + ctx->tmpname = NULL; + ctx->fout = NULL; + + zip_error_init(&ctx->error); - if ((zs=zip_source_function(za, read_file, f)) == NULL) { - free(f); + ctx->supports = zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_TELL, -1); + if (ctx->fname) { + struct stat sb; + + if (stat(ctx->fname, &sb) < 0 || S_ISREG(sb.st_mode)) { + ctx->supports |= zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_REMOVE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_WRITE, -1); + } + } + else if (fseek(ctx->f, 0, SEEK_CUR) == 0) { + ctx->supports |= zip_source_make_command_bitmap(ZIP_SOURCE_SEEK, -1); + } + + if ((zs=zip_source_function_create(read_file, ctx, error)) == NULL) { + free(ctx); return NULL; } @@ -121,132 +147,257 @@ } -int -_zip_source_filep_set_source_archive(struct zip_source *src, struct zip *za) +static int +create_temp_output(struct read_file *ctx) { - struct read_file *z = (struct read_file *)src->ud; - - z->source_archive = za; - return _zip_register_source(za, src); -} - - -/* called by zip_discard to avoid operating on file from closed archive */ -void -_zip_source_filep_invalidate(struct zip_source *src) -{ - struct read_file *z = (struct read_file *)src->ud; - - z->source_closed = 1; - z->f = NULL; - if (z->e[0] == ZIP_ER_OK) { - z->e[0] = ZIP_ER_ZIPCLOSED; - z->e[1] = 0; + char *temp; + int tfd; + FILE *tfp; + + if ((temp=(char *)malloc(strlen(ctx->fname)+8)) == NULL) { + zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); + return -1; } + sprintf(temp, "%s.XXXXXX", ctx->fname); + + if ((tfd=mkstemp(temp)) == -1) { + zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); + free(temp); + return -1; + } + + if ((tfp=fdopen(tfd, "r+b")) == NULL) { + zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); + close(tfd); + (void)remove(temp); + free(temp); + return -1; + } + +#ifdef _WIN32 + /* + According to Pierre Joye, Windows in some environments per + default creates text files, so force binary mode. + */ + _setmode(_fileno(tfp), _O_BINARY ); +#endif + + ctx->fout = tfp; + ctx->tmpname = temp; + + return 0; } static zip_int64_t -read_file(void *state, void *data, zip_uint64_t len, enum zip_source_cmd cmd) +read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) { - struct read_file *z; + struct read_file *ctx; char *buf; zip_uint64_t n; size_t i; - z = (struct read_file *)state; + ctx = (struct read_file *)state; buf = (char *)data; switch (cmd) { - case ZIP_SOURCE_OPEN: - if (z->source_closed) - return -1; - - if (z->fname) { - if ((z->f=fopen(z->fname, "rb")) == NULL) { - z->e[0] = ZIP_ER_OPEN; - z->e[1] = errno; - return -1; - } - } - - if (z->closep && z->off > 0) { - if (fseeko(z->f, (off_t)z->off, SEEK_SET) < 0) { - z->e[0] = ZIP_ER_SEEK; - z->e[1] = errno; - return -1; - } - } - z->remain = z->len; - return 0; - - case ZIP_SOURCE_READ: - if (z->source_closed) - return -1; - - if (z->remain != -1) - n = len > (zip_uint64_t)z->remain ? (zip_uint64_t)z->remain : len; - else - n = len; - - if (n > SIZE_MAX) - n = SIZE_MAX; - - if (!z->closep) { - /* we might share this file with others, so let's be safe */ - if (fseeko(z->f, (off_t)(z->off + (zip_uint64_t)(z->len-z->remain)), SEEK_SET) < 0) { - z->e[0] = ZIP_ER_SEEK; - z->e[1] = errno; - return -1; - } - } - - if ((i=fread(buf, 1, (size_t)n, z->f)) == 0) { - if (ferror(z->f)) { - z->e[0] = ZIP_ER_READ; - z->e[1] = errno; + case ZIP_SOURCE_BEGIN_WRITE: + if (ctx->fname == NULL) { + zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); return -1; } + return create_temp_output(ctx); + + case ZIP_SOURCE_COMMIT_WRITE: { + mode_t mask; + + if (fclose(ctx->fout) < 0) { + ctx->fout = NULL; + zip_error_set(&ctx->error, ZIP_ER_WRITE, errno); + } + ctx->fout = NULL; + if (rename(ctx->tmpname, ctx->fname) < 0) { + zip_error_set(&ctx->error, ZIP_ER_RENAME, errno); + return -1; + } + mask = umask(022); + umask(mask); + chmod(ctx->fname, 0666&~mask); + return 0; } + + case ZIP_SOURCE_CLOSE: + if (ctx->fname) { + fclose(ctx->f); + ctx->f = NULL; + } + return 0; + + case ZIP_SOURCE_ERROR: + return zip_error_to_data(&ctx->error, data, len); + + case ZIP_SOURCE_FREE: + free(ctx->fname); + if (ctx->closep && ctx->f) + fclose(ctx->f); + free(ctx); + return 0; + + case ZIP_SOURCE_OPEN: + if (ctx->fname) { + if ((ctx->f=fopen(ctx->fname, "rb")) == NULL) { + zip_error_set(&ctx->error, ZIP_ER_OPEN, errno); + return -1; + } + } + + if (ctx->closep && ctx->start > 0) { + if (fseeko(ctx->f, (off_t)ctx->start, SEEK_SET) < 0) { + zip_error_set(&ctx->error, ZIP_ER_SEEK, errno); + return -1; + } + } + ctx->current = ctx->start; + return 0; + + case ZIP_SOURCE_READ: + if (ctx->end > 0) { + n = ctx->end-ctx->current; + if (n > len) { + n = len; + } + } + else { + n = len; + } + + if (n > SIZE_MAX) + n = SIZE_MAX; - if (z->remain != -1) - z->remain -= i; + if (!ctx->closep) { + if (fseeko(ctx->f, (off_t)ctx->current, SEEK_SET) < 0) { + zip_error_set(&ctx->error, ZIP_ER_SEEK, errno); + return -1; + } + } - return (zip_int64_t)i; + if ((i=fread(buf, 1, (size_t)n, ctx->f)) == 0) { + if (ferror(ctx->f)) { + zip_error_set(&ctx->error, ZIP_ER_READ, errno); + return -1; + } + } + ctx->current += i; + + return (zip_int64_t)i; + + case ZIP_SOURCE_REMOVE: + if (remove(ctx->fname) < 0) { + zip_error_set(&ctx->error, ZIP_ER_REMOVE, errno); + return -1; + } + return 0; + + case ZIP_SOURCE_ROLLBACK_WRITE: + if (ctx->fout) { + fclose(ctx->fout); + ctx->fout = NULL; + } + remove(ctx->tmpname); + ctx->tmpname = NULL; + return 0; - case ZIP_SOURCE_CLOSE: - if (z->source_closed) - return -1; + case ZIP_SOURCE_SEEK: { + zip_int64_t new_current; + int need_seek; + zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error); - if (z->fname) { - fclose(z->f); - z->f = NULL; - } - return 0; + if (args == NULL) + return -1; + + need_seek = ctx->closep; + + switch (args->whence) { + case SEEK_SET: + new_current = args->offset; + break; + + case SEEK_END: + if (ctx->end == 0) { + if (fseeko(ctx->f, args->offset, SEEK_END) < 0) { + zip_error_set(&ctx->error, ZIP_ER_SEEK, errno); + return -1; + } + if ((new_current = ftello(ctx->f)) < 0) { + zip_error_set(&ctx->error, ZIP_ER_SEEK, errno); + return -1; + } + need_seek = 0; + } + else { + new_current = (zip_int64_t)ctx->end + args->offset; + } + break; + case SEEK_CUR: + new_current = (zip_int64_t)ctx->current + args->offset; + break; - case ZIP_SOURCE_STAT: - if (z->source_closed) - return -1; + default: + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } - { - if (len < sizeof(z->st)) + if (new_current < 0 || (zip_uint64_t)new_current < ctx->start || (ctx->end != 0 && (zip_uint64_t)new_current > ctx->end)) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } + + ctx->current = (zip_uint64_t)new_current; + + if (need_seek) { + if (fseeko(ctx->f, (off_t)ctx->current, SEEK_SET) < 0) { + zip_error_set(&ctx->error, ZIP_ER_SEEK, errno); + return -1; + } + } + return 0; + } + + case ZIP_SOURCE_SEEK_WRITE: { + zip_int64_t offset, whence; + + if (len < sizeof(zip_int64_t)*2) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } + offset = ((zip_int64_t *)data)[0]; + whence = ((zip_int64_t *)data)[1]; + + if (fseeko(ctx->fout, offset, (int)whence) < 0) { + zip_error_set(&ctx->error, ZIP_ER_SEEK, errno); + return -1; + } + return 0; + } + + case ZIP_SOURCE_STAT: { + if (len < sizeof(ctx->st)) return -1; - if (z->st.valid != 0) - memcpy(data, &z->st, sizeof(z->st)); + if (ctx->st.valid != 0) + memcpy(data, &ctx->st, sizeof(ctx->st)); else { struct zip_stat *st; struct stat fst; int err; - if (z->f) - err = fstat(fileno(z->f), &fst); + if (ctx->f) + err = fstat(fileno(ctx->f), &fst); else - err = stat(z->fname, &fst); + err = stat(ctx->fname, &fst); if (err != 0) { - z->e[0] = ZIP_ER_READ; /* best match */ - z->e[1] = errno; + zip_error_set(&ctx->error, ZIP_ER_READ, errno); return -1; } @@ -255,8 +406,8 @@ zip_stat_init(st); st->mtime = fst.st_mtime; st->valid |= ZIP_STAT_MTIME; - if (z->len != -1) { - st->size = (zip_uint64_t)z->len; + if (ctx->end != 0) { + st->size = ctx->end - ctx->start; st->valid |= ZIP_STAT_SIZE; } else if ((fst.st_mode&S_IFMT) == S_IFREG) { @@ -264,67 +415,42 @@ st->valid |= ZIP_STAT_SIZE; } } - return sizeof(z->st); + return sizeof(ctx->st); } - case ZIP_SOURCE_ERROR: - if (len < sizeof(int)*2) - return -1; + case ZIP_SOURCE_SUPPORTS: + return ctx->supports; + + case ZIP_SOURCE_TELL: + return (zip_int64_t)ctx->current; + + case ZIP_SOURCE_TELL_WRITE: + { + off_t ret = ftello(ctx->fout); + + if (ret < 0) { + zip_error_set(&ctx->error, ZIP_ER_TELL, errno); + return -1; + } + return ret; + } + + case ZIP_SOURCE_WRITE: + { + size_t ret; + + clearerr(ctx->fout); + ret = fwrite(data, 1, len, ctx->fout); + if (ret != len || ferror(ctx->fout)) { + zip_error_set(&ctx->error, ZIP_ER_WRITE, errno); + return -1; + } + + return (zip_int64_t)ret; + } - memcpy(data, z->e, sizeof(int)*2); - return sizeof(int)*2; - - case ZIP_SOURCE_FREE: - if (z->source_archive && !z->source_closed) { - _zip_deregister_source(z->source_archive, state); - } - free(z->fname); - if (z->closep && z->f) - fclose(z->f); - free(z); - return 0; - - default: - ; + default: + zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); + return -1; } - - return -1; -} - - -static void -_zip_deregister_source(struct zip *za, void *ud) -{ - unsigned int i; - - for (i=0; i<za->nsource; i++) { - if (za->source[i]->ud == ud) { - za->source[i] = za->source[za->nsource-1]; - za->nsource--; - break; - } - } -} - - -static int -_zip_register_source(struct zip *za, struct zip_source *src) -{ - struct zip_source **source; - - if (za->nsource+1 >= za->nsource_alloc) { - unsigned int n; - n = za->nsource_alloc + 10; - source = (struct zip_source **)realloc(za->source, n*sizeof(struct zip_source *)); - if (source == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return -1; - } - za->nsource_alloc = n; - za->source = source; - } - - za->source[za->nsource++] = src; - - return 0; }
diff --git a/lib/zip_source_free.c b/lib/zip_source_free.c index d1e8f3d..715efb5 100644 --- a/lib/zip_source_free.c +++ b/lib/zip_source_free.c
@@ -1,6 +1,6 @@ /* zip_source_free.c -- free zip data source - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -38,20 +38,40 @@ ZIP_EXTERN void -zip_source_free(struct zip_source *src) +zip_source_free(zip_source_t *src) +{ + _zip_source_free_or_pop(src, 1); +} + + +void +_zip_source_free_or_pop(zip_source_t *src, int recurse) { if (src == NULL) return; - if (src->is_open) - zip_source_close(src); - - if (src->src == NULL) - (void)src->cb.f(src->ud, NULL, 0, ZIP_SOURCE_FREE); - else { - (void)src->cb.l(src->src, src->ud, NULL, 0, ZIP_SOURCE_FREE); - zip_source_free(src->src); + if (src->refcount > 0) { + src->refcount--; } - + if (src->refcount > 0) { + return; + } + + if (ZIP_SOURCE_IS_OPEN_READING(src)) { + zip_source_close(src); + } + if (ZIP_SOURCE_IS_OPEN_WRITING(src)) { + zip_source_rollback_write(src); + } + + if (src->source_archive && !src->source_closed) { + _zip_deregister_source(src->source_archive, src); + } + + (void)_zip_source_call(src, NULL, 0, ZIP_SOURCE_FREE); + + if (recurse && src->src) { + zip_source_free(src->src); + } free(src); }
diff --git a/lib/zip_source_function.c b/lib/zip_source_function.c index 03f766e..884d5ad 100644 --- a/lib/zip_source_function.c +++ b/lib/zip_source_function.c
@@ -1,6 +1,6 @@ /* zip_source_function.c -- create zip data source from callback function - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -40,12 +40,20 @@ ZIP_EXTERN struct zip_source * zip_source_function(struct zip *za, zip_source_callback zcb, void *ud) { + if (za == NULL) { + return NULL; + } + + return zip_source_function_create(zcb, ud, &za->error); +} + + +ZIP_EXTERN zip_source_t * +zip_source_function_create(zip_source_callback zcb, void *ud, zip_error_t *error) +{ struct zip_source *zs; - if (za == NULL) - return NULL; - - if ((zs=_zip_source_new(za)) == NULL) + if ((zs=_zip_source_new(error)) == NULL) return NULL; zs->cb.f = zcb; @@ -55,21 +63,32 @@ } +ZIP_EXTERN void +zip_source_keep(zip_source_t *src) +{ + src->refcount++; +} + + struct zip_source * -_zip_source_new(struct zip *za) +_zip_source_new(zip_error_t *error) { struct zip_source *src; if ((src=(struct zip_source *)malloc(sizeof(*src))) == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + zip_error_set(error, ZIP_ER_MEMORY, 0); return NULL; } src->src = NULL; src->cb.f = NULL; src->ud = NULL; - src->error_source = ZIP_LES_NONE; - src->is_open = 0; + src->open_count = 0; + src->write_state = ZIP_SOURCE_WRITE_CLOSED; + src->source_closed = 0; + src->source_archive = NULL; + src->refcount = 1; + zip_error_init(&src->error); return src; }
diff --git a/lib/zip_source_is_deleted.c b/lib/zip_source_is_deleted.c new file mode 100644 index 0000000..e50cdd9 --- /dev/null +++ b/lib/zip_source_is_deleted.c
@@ -0,0 +1,42 @@ +/* + zip_source_is_deleted.c -- was archive was removed? + Copyright (C) 2014 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" + + +ZIP_EXTERN int +zip_source_is_deleted(zip_source_t *src) +{ + return src->write_state == ZIP_SOURCE_WRITE_REMOVED; +}
diff --git a/lib/zip_source_layered.c b/lib/zip_source_layered.c index 30450d0..3cf1f71 100644 --- a/lib/zip_source_layered.c +++ b/lib/zip_source_layered.c
@@ -1,6 +1,6 @@ /* zip_source_layered.c -- create layered source - Copyright (C) 2009 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -38,17 +38,24 @@ struct zip_source * -zip_source_layered(struct zip *za, struct zip_source *src, - zip_source_layered_callback cb, void *ud) +zip_source_layered(struct zip *za, struct zip_source *src, zip_source_layered_callback cb, void *ud) +{ + if (za == NULL) + return NULL; + + return zip_source_layered_create(src, cb, ud, &za->error); +} + + +zip_source_t * +zip_source_layered_create(struct zip_source *src, zip_source_layered_callback cb, void *ud, zip_error_t *error) { struct zip_source *zs; - - if (za == NULL) - return NULL; - - if ((zs=_zip_source_new(za)) == NULL) - return NULL; - + + if ((zs=_zip_source_new(error)) == NULL) + return NULL; + + zip_source_keep(src); zs->src = src; zs->cb.l = cb; zs->ud = ud;
diff --git a/lib/zip_source_open.c b/lib/zip_source_open.c index 82efadb..46bf491 100644 --- a/lib/zip_source_open.c +++ b/lib/zip_source_open.c
@@ -1,6 +1,6 @@ /* zip_source_open.c -- open zip_source (prepare for reading) - Copyright (C) 2009-2013 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -38,37 +38,38 @@ int zip_source_open(struct zip_source *src) { - zip_int64_t ret; - - if (src->is_open) { - src->error_source = ZIP_LES_INVAL; + if (src->source_closed) { + return -1; + } + if (src->write_state == ZIP_SOURCE_WRITE_REMOVED) { + zip_error_set(&src->error, ZIP_ER_DELETED, 0); return -1; } - - if (src->src == NULL) { - if (src->cb.f(src->ud, NULL, 0, ZIP_SOURCE_OPEN) < 0) - return -1; + if (ZIP_SOURCE_IS_OPEN_READING(src)) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; } - else { - if (zip_source_open(src->src) < 0) { - src->error_source = ZIP_LES_LOWER; - return -1; - } - - ret = src->cb.l(src->src, src->ud, NULL, 0, ZIP_SOURCE_OPEN); - - if (ret < 0) { - zip_source_close(src->src); - - if (ret == ZIP_SOURCE_ERR_LOWER) - src->error_source = ZIP_LES_LOWER; - else - src->error_source = ZIP_LES_UPPER; - return -1; - } + + if (ZIP_SOURCE_IS_LAYERED(src)) { + if (ZIP_SOURCE_IS_OPEN_READING(src->src)) { + src->src->open_count++; + } + else { + if (zip_source_open(src->src) < 0) { + zip_error_set_from_source(&src->error, src->src); + return -1; + } + } } - src->is_open = 1; + if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_OPEN) < 0) { + if (ZIP_SOURCE_IS_LAYERED(src)) { + zip_source_close(src->src); + } + return -1; + } + + src->open_count++; return 0; }
diff --git a/lib/zip_source_pkware.c b/lib/zip_source_pkware.c index 78504b0..5e550e3 100644 --- a/lib/zip_source_pkware.c +++ b/lib/zip_source_pkware.c
@@ -1,6 +1,6 @@ /* zip_source_pkware.c -- Traditional PKWARE de/encryption routines - Copyright (C) 2009 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -38,8 +38,7 @@ #include "zipint.h" struct trad_pkware { - int e[2]; - + zip_error_t error; zip_uint32_t key[3]; }; @@ -65,20 +64,20 @@ struct zip_source *s2; if (password == NULL || src == NULL || em != ZIP_EM_TRAD_PKWARE) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return NULL; } if (flags & ZIP_CODEC_ENCODE) { - _zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); + zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); return NULL; } if ((ctx=(struct trad_pkware *)malloc(sizeof(*ctx))) == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); return NULL; } - ctx->e[0] = ctx->e[1] = 0; + zip_error_init(&ctx->error); ctx->key[0] = KEY0; ctx->key[1] = KEY1; @@ -134,13 +133,12 @@ unsigned short dostime, dosdate; if ((n=zip_source_read(src, header, HEADERLEN)) < 0) { - zip_source_error(src, ctx->e, ctx->e+1); + zip_error_set_from_source(&ctx->error, src); return -1; } if (n != HEADERLEN) { - ctx->e[0] = ZIP_ER_EOF; - ctx->e[1] = 0; + zip_error_set(&ctx->error, ZIP_ER_EOF, 0); return -1; } @@ -153,10 +151,8 @@ _zip_u2d_time(st.mtime, &dostime, &dosdate); - if (header[HEADERLEN-1] != st.crc>>24 - && header[HEADERLEN-1] != dostime>>8) { - ctx->e[0] = ZIP_ER_WRONGPASSWD; - ctx->e[1] = 0; + if (header[HEADERLEN-1] != st.crc>>24 && header[HEADERLEN-1] != dostime>>8) { + zip_error_set(&ctx->error, ZIP_ER_WRONGPASSWD, 0); return -1; } @@ -174,24 +170,25 @@ ctx = (struct trad_pkware *)ud; switch (cmd) { - case ZIP_SOURCE_OPEN: - if (decrypt_header(src, ctx) < 0) - return -1; - return 0; + case ZIP_SOURCE_OPEN: + if (decrypt_header(src, ctx) < 0) + return -1; + return 0; - case ZIP_SOURCE_READ: - if ((n=zip_source_read(src, data, len)) < 0) - return ZIP_SOURCE_ERR_LOWER; + case ZIP_SOURCE_READ: + if ((n=zip_source_read(src, data, len)) < 0) { + zip_error_set_from_source(&ctx->error, src); + return -1; + } - decrypt((struct trad_pkware *)ud, (zip_uint8_t *)data, (zip_uint8_t *)data, (zip_uint64_t)n, - 0); - return n; + decrypt((struct trad_pkware *)ud, (zip_uint8_t *)data, (zip_uint8_t *)data, (zip_uint64_t)n, 0); + return n; - case ZIP_SOURCE_CLOSE: - return 0; + case ZIP_SOURCE_CLOSE: + return 0; - case ZIP_SOURCE_STAT: - { + case ZIP_SOURCE_STAT: + { struct zip_stat *st; st = (struct zip_stat *)data; @@ -201,21 +198,23 @@ /* TODO: deduce HEADERLEN from size for uncompressed */ if (st->valid & ZIP_STAT_COMP_SIZE) st->comp_size -= HEADERLEN; - } - return 0; + + return 0; + } + + case ZIP_SOURCE_SUPPORTS: + return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1); - case ZIP_SOURCE_ERROR: - memcpy(data, ctx->e, sizeof(int)*2); - return sizeof(int)*2; + case ZIP_SOURCE_ERROR: + return zip_error_to_data(&ctx->error, data, len); - case ZIP_SOURCE_FREE: - pkware_free(ctx); - return 0; + case ZIP_SOURCE_FREE: + pkware_free(ctx); + return 0; - default: - ctx->e[0] = ZIP_ER_INVAL; - ctx->e[1] = 0; - return -1; + default: + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; } }
diff --git a/lib/zip_source_pop.c b/lib/zip_source_pop.c index 49e3ae8..78c7ce1 100644 --- a/lib/zip_source_pop.c +++ b/lib/zip_source_pop.c
@@ -1,6 +1,6 @@ /* zip_source_pop.c -- pop top layer from zip data source - Copyright (C) 2009 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -47,15 +47,7 @@ lower = src->src; - if (lower == NULL) - zip_source_free(src); - else { - if (src->is_open) - (void)src->cb.l(src, src->ud, NULL, 0, ZIP_SOURCE_CLOSE); - (void)src->cb.l(src, src->ud, NULL, 0, ZIP_SOURCE_FREE); - - free(src); - } + _zip_source_free_or_pop(src, 0); return lower; }
diff --git a/lib/zip_source_read.c b/lib/zip_source_read.c index 910649d..8249b82 100644 --- a/lib/zip_source_read.c +++ b/lib/zip_source_read.c
@@ -1,6 +1,6 @@ /* zip_source_read.c -- read data from zip_source - Copyright (C) 2009 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -38,25 +38,13 @@ zip_int64_t zip_source_read(struct zip_source *src, void *data, zip_uint64_t len) { - zip_int64_t ret; - - if (!src->is_open || len > ZIP_INT64_MAX || (len > 0 && data == NULL)) { - src->error_source = ZIP_LES_INVAL; + if (src->source_closed) { + return -1; + } + if (!ZIP_SOURCE_IS_OPEN_READING(src) || len > ZIP_INT64_MAX || (len > 0 && data == NULL)) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); return -1; } - if (src->src == NULL) - return src->cb.f(src->ud, data, len, ZIP_SOURCE_READ); - - ret = src->cb.l(src->src, src->ud, data, len, ZIP_SOURCE_READ); - - if (ret < 0) { - if (ret == ZIP_SOURCE_ERR_LOWER) - src->error_source = ZIP_LES_LOWER; - else - src->error_source = ZIP_LES_UPPER; - return -1; - } - - return ret; + return _zip_source_call(src, data, len, ZIP_SOURCE_READ); }
diff --git a/lib/zip_source_remove.c b/lib/zip_source_remove.c new file mode 100644 index 0000000..470a5ed --- /dev/null +++ b/lib/zip_source_remove.c
@@ -0,0 +1,61 @@ +/* + zip_source_remove.c -- remove empty archive + Copyright (C) 2014 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" + + +int +zip_source_remove(zip_source_t *src) +{ + if (src->write_state == ZIP_SOURCE_WRITE_REMOVED) { + return 0; + } + + if (ZIP_SOURCE_IS_OPEN_READING(src)) { + if (zip_source_close(src) < 0) { + return -1; + } + } + if (src->write_state != ZIP_SOURCE_WRITE_CLOSED) { + zip_source_rollback_write(src); + } + + if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_REMOVE) < 0) { + return -1; + } + + src->write_state = ZIP_SOURCE_WRITE_REMOVED; + + return 0; +}
diff --git a/lib/zip_source_rollback_write.c b/lib/zip_source_rollback_write.c new file mode 100644 index 0000000..a93cd20 --- /dev/null +++ b/lib/zip_source_rollback_write.c
@@ -0,0 +1,47 @@ +/* + zip_source_rollback_write.c -- discard changes + Copyright (C) 2014 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" + + +void +zip_source_rollback_write(zip_source_t *src) +{ + if (src->write_state != ZIP_SOURCE_WRITE_OPEN && src->write_state != ZIP_SOURCE_WRITE_FAILED) { + return; + } + + _zip_source_call(src, NULL, 0, ZIP_SOURCE_ROLLBACK_WRITE); + src->write_state = ZIP_SOURCE_WRITE_CLOSED; +}
diff --git a/lib/zip_source_seek.c b/lib/zip_source_seek.c new file mode 100644 index 0000000..25886f7 --- /dev/null +++ b/lib/zip_source_seek.c
@@ -0,0 +1,55 @@ +/* + zip_source_seek.c -- seek to offset + Copyright (C) 2014 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" + + +int +zip_source_seek(struct zip_source *src, zip_int64_t offset, int whence) +{ + zip_source_args_seek_t args; + + if (src->source_closed) { + return -1; + } + if (!ZIP_SOURCE_IS_OPEN_READING(src) || (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END)) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + args.offset = offset; + args.whence = whence; + + return (_zip_source_call(src, &args, sizeof(args), ZIP_SOURCE_SEEK) < 0 ? -1 : 0); +}
diff --git a/lib/zip_source_seek_write.c b/lib/zip_source_seek_write.c new file mode 100644 index 0000000..6f4e351 --- /dev/null +++ b/lib/zip_source_seek_write.c
@@ -0,0 +1,52 @@ +/* + zip_source_seek_write.c -- seek to offset for writing + Copyright (C) 2014 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" + + +int +zip_source_seek_write(struct zip_source *src, zip_int64_t offset, int whence) +{ + zip_source_args_seek_t args; + + if (!ZIP_SOURCE_IS_OPEN_WRITING(src) || (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END)) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + args.offset = offset; + args.whence = whence; + + return (_zip_source_call(src, &args, sizeof(args), ZIP_SOURCE_SEEK_WRITE) < 0 ? -1 : 0); +}
diff --git a/lib/zip_source_stat.c b/lib/zip_source_stat.c index 3d5fc88..f70e8e9 100644 --- a/lib/zip_source_stat.c +++ b/lib/zip_source_stat.c
@@ -1,6 +1,6 @@ /* zip_source_stat.c -- get meta information from zip_source - Copyright (C) 2009 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -38,33 +38,30 @@ int zip_source_stat(struct zip_source *src, struct zip_stat *st) { - zip_int64_t ret; - + if (src->source_closed) { + return -1; + } if (st == NULL) { - src->error_source = ZIP_LES_INVAL; + zip_error_set(&src->error, ZIP_ER_INVAL, 0); return -1; } - if (src->src == NULL) { - if (src->cb.f(src->ud, st, sizeof(*st), ZIP_SOURCE_STAT) < 0) - return -1; - return 0; - } - - if (zip_source_stat(src->src, st) < 0) { - src->error_source = ZIP_LES_LOWER; - return -1; - } - - ret = src->cb.l(src->src, src->ud, st, sizeof(*st), ZIP_SOURCE_STAT); - - if (ret < 0) { - if (ret == ZIP_SOURCE_ERR_LOWER) - src->error_source = ZIP_LES_LOWER; - else - src->error_source = ZIP_LES_UPPER; - return -1; - } + zip_stat_init(st); + if (ZIP_SOURCE_IS_LAYERED(src)) { + if (zip_source_stat(src->src, st) < 0) { + zip_error_set_from_source(&src->error, src->src); + return -1; + } + } + + if (_zip_source_call(src, st, sizeof(*st), ZIP_SOURCE_STAT) < 0) { + return -1; + } + + if ((st->valid & ZIP_STAT_COMP_METHOD) && ZIP_CM_IS_DEFAULT(st->comp_method)) { + st->valid &= ~ZIP_STAT_COMP_METHOD; + } + return 0; }
diff --git a/lib/zip_source_supports.c b/lib/zip_source_supports.c new file mode 100644 index 0000000..6f8d26c --- /dev/null +++ b/lib/zip_source_supports.c
@@ -0,0 +1,76 @@ +/* + zip_source_supports.c -- check for supported functions + Copyright (C) 2014 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 <stdarg.h> + +#include "zipint.h" + + +zip_int64_t +zip_source_supports(struct zip_source *src) +{ + zip_int64_t ret; + + ret = _zip_source_call(src, NULL , 0, ZIP_SOURCE_SUPPORTS); + + if (ret < 0) { + ret = zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1); + } + + return ret; +} + + +zip_int64_t +zip_source_make_command_bitmap(enum zip_source_cmd cmd0, ...) +{ + zip_int64_t bitmap; + va_list ap; + + bitmap = 1<<cmd0; + + + + va_start(ap, cmd0); + for (;;) { + int cmd = va_arg(ap, int); + if (cmd < 0) { + break; + } + bitmap |= 1<<cmd; + } + va_end(ap); + + return bitmap; +}
diff --git a/lib/zip_source_tell.c b/lib/zip_source_tell.c new file mode 100644 index 0000000..fdf2e77 --- /dev/null +++ b/lib/zip_source_tell.c
@@ -0,0 +1,50 @@ +/* + zip_source_tell.c -- report current offset + Copyright (C) 2014 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" + + +zip_int64_t +zip_source_tell(struct zip_source *src) +{ + if (src->source_closed) { + return -1; + } + if (!ZIP_SOURCE_IS_OPEN_READING(src)) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + return _zip_source_call(src, NULL, 0, ZIP_SOURCE_TELL); +}
diff --git a/lib/zip_source_tell_write.c b/lib/zip_source_tell_write.c new file mode 100644 index 0000000..558fa0d --- /dev/null +++ b/lib/zip_source_tell_write.c
@@ -0,0 +1,47 @@ +/* + zip_source_tell_write.c -- report current offset for writing + Copyright (C) 2014 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" + + +zip_int64_t +zip_source_tell_write(struct zip_source *src) +{ + if (!ZIP_SOURCE_IS_OPEN_WRITING(src)) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + return _zip_source_call(src, NULL, 0, ZIP_SOURCE_TELL_WRITE); +}
diff --git a/lib/zip_source_window.c b/lib/zip_source_window.c index 9bc0f75..56dc256 100644 --- a/lib/zip_source_window.c +++ b/lib/zip_source_window.c
@@ -1,6 +1,6 @@ /* zip_source_window.c -- return part of lower source - Copyright (C) 2012-2013 Dieter Baron and Thomas Klausner + Copyright (C) 2012-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -38,42 +38,80 @@ #include "zipint.h" struct window { - zip_uint64_t skip; - zip_uint64_t len; - zip_uint64_t left; - int e[2]; + zip_uint64_t start; + zip_uint64_t end; + zip_uint64_t offset; + zip_stat_t stat; + zip_error_t error; + zip_int64_t supports; + int needs_seek; }; -static zip_int64_t window_read(struct zip_source *, void *, void *, - zip_uint64_t, enum zip_source_cmd); +static zip_int64_t window_read(struct zip_source *, void *, void *, zip_uint64_t, enum zip_source_cmd); struct zip_source * zip_source_window(struct zip *za, struct zip_source *src, zip_uint64_t start, zip_uint64_t len) { + return _zip_source_window_new(src, start, len, NULL, &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) +{ struct window *ctx; - - if (src == NULL) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return NULL; + + if (src == NULL || start + length < start) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; } - + if ((ctx=(struct window *)malloc(sizeof(*ctx))) == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return NULL; + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; } + + ctx->start = start; + ctx->end = start + length; + zip_stat_init(&ctx->stat); + zip_error_init(&ctx->error); + ctx->supports = (zip_source_supports(src) & zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_SEEK, ZIP_SOURCE_TELL, -1)) | (zip_source_make_command_bitmap(ZIP_SOURCE_TELL, -1)); + ctx->needs_seek = ctx->supports & zip_source_make_command_bitmap(ZIP_SOURCE_SEEK, -1); + + 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); +} - ctx->skip = start; - ctx->len = len; - ctx->left = len; - return zip_source_layered(za, src, window_read, ctx); +int +_zip_source_set_source_archive(struct zip_source *src, struct zip *za) +{ + src->source_archive = za; + return _zip_register_source(za, src); +} + + +/* called by zip_discard to avoid operating on file from closed archive */ +void +_zip_source_invalidate(struct zip_source *src) +{ + src->source_closed = 1; + + if (zip_error_code_zip(&src->error) == ZIP_ER_OK) { + zip_error_set(&src->error, ZIP_ER_ZIPCLOSED, 0); + } } static zip_int64_t -window_read(struct zip_source *src, void *_ctx, void *data, - zip_uint64_t len, enum zip_source_cmd cmd) +window_read(struct zip_source *src, void *_ctx, void *data, zip_uint64_t len, enum zip_source_cmd cmd) { struct window *ctx; zip_int64_t ret; @@ -83,65 +121,152 @@ ctx = (struct window *)_ctx; switch (cmd) { - case ZIP_SOURCE_OPEN: - for (n=0; n<ctx->skip; n+=(zip_uint64_t)ret) { - i = (ctx->skip-n > sizeof(b) ? sizeof(b) : ctx->skip-n); - if ((ret=zip_source_read(src, b, i)) < 0) - return ZIP_SOURCE_ERR_LOWER; - if (ret==0) { - ctx->e[0] = ZIP_ER_EOF; - ctx->e[1] = 0; + 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->needs_seek) { + for (n=0; n<ctx->start; n+=(zip_uint64_t)ret) { + i = (ctx->start-n > sizeof(b) ? sizeof(b) : ctx->start-n); + if ((ret=zip_source_read(src, b, i)) < 0) { + zip_error_set_from_source(&ctx->error, src); + return -1; + } + if (ret==0) { + zip_error_set(&ctx->error, ZIP_ER_EOF, 0); + 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; + } + + ctx->offset += (zip_uint64_t)ret; + + if (ret == 0) { + if (ctx->offset < ctx->end) { + zip_error_set(&ctx->error, ZIP_ER_EOF, 0); + return -1; + } + } + return ret; + + case ZIP_SOURCE_SEEK: + { + zip_int64_t new_offset; + zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error); + + if (args == NULL) return -1; - } - } - return 0; + + switch (args->whence) { + case SEEK_CUR: + new_offset = (zip_int64_t)ctx->offset + args->offset; + break; + + case SEEK_END: + new_offset = (zip_int64_t)ctx->end + args->offset; + break; + + case SEEK_SET: + new_offset = (zip_int64_t)ctx->start + args->offset; + break; + } + + if (new_offset < (zip_int64_t)ctx->start || (zip_uint64_t)new_offset > ctx->end) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } + + ctx->offset = (zip_uint64_t)new_offset; + return 0; + } - case ZIP_SOURCE_READ: - if (len > ctx->left) - len = ctx->left; - - if (len == 0) - return 0; - - if ((ret=zip_source_read(src, data, len)) < 0) - return ZIP_SOURCE_ERR_LOWER; - - ctx->left -= (zip_uint64_t)ret; - - if (ret == 0) { - if (ctx->left > 0) { - ctx->e[0] = ZIP_ER_EOF; - ctx->e[1] = 0; - return -1; - } - } - return ret; - - case ZIP_SOURCE_CLOSE: - return 0; - - case ZIP_SOURCE_STAT: - { - struct zip_stat *st; - + case ZIP_SOURCE_STAT: + { + struct zip_stat *st; + st = (struct zip_stat *)data; + + if (_zip_stat_merge(st, &ctx->stat, &ctx->error) < 0) { + return -1; + } + return 0; + } + + 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; + } +} - st->size = ctx->len; - st->valid |= ZIP_STAT_SIZE; - st->valid &= ~(ZIP_STAT_CRC|ZIP_STAT_COMP_SIZE); - } - return 0; - - case ZIP_SOURCE_ERROR: - memcpy(data, ctx->e, sizeof(ctx->e)); - return 0; - case ZIP_SOURCE_FREE: - free(ctx); - return 0; +void +_zip_deregister_source(struct zip *za, zip_source_t *src) +{ + unsigned int i; + + for (i=0; i<za->nopen_source; i++) { + if (za->open_source[i] == src) { + za->open_source[i] = za->open_source[za->nopen_source-1]; + za->nopen_source--; + break; + } + } +} - default: - return -1; + +int +_zip_register_source(zip_t *za, zip_source_t *src) +{ + zip_source_t **open_source; + + if (za->nopen_source+1 >= za->nopen_source_alloc) { + unsigned int n; + n = za->nopen_source_alloc + 10; + open_source = (struct zip_source **)realloc(za->open_source, n*sizeof(struct zip_source *)); + if (open_source == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + za->nopen_source_alloc = n; + za->open_source = open_source; } + za->open_source[za->nopen_source++] = src; + + return 0; }
diff --git a/lib/zip_source_write.c b/lib/zip_source_write.c new file mode 100644 index 0000000..bbf5d0b --- /dev/null +++ b/lib/zip_source_write.c
@@ -0,0 +1,47 @@ +/* + zip_source_write.c -- start a new file for writing + Copyright (C) 2014 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" + + +zip_int64_t +zip_source_write(struct zip_source *src, const void *data, zip_uint64_t length) +{ + if (!ZIP_SOURCE_IS_OPEN_WRITING(src) || length > ZIP_INT64_MAX) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + return _zip_source_call(src, (void *)data, length, ZIP_SOURCE_WRITE); +}
diff --git a/lib/zip_source_zip.c b/lib/zip_source_zip.c index 7ebfb81..8f85200 100644 --- a/lib/zip_source_zip.c +++ b/lib/zip_source_zip.c
@@ -1,6 +1,6 @@ /* zip_source_zip.c -- create data source from zip file - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -43,7 +43,7 @@ zip_flags_t flags, zip_uint64_t start, zip_int64_t len) { if (len < -1) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return NULL; }
diff --git a/lib/zip_source_zip_new.c b/lib/zip_source_zip_new.c index 3f4fbd2..f8af9ad 100644 --- a/lib/zip_source_zip_new.c +++ b/lib/zip_source_zip_new.c
@@ -51,18 +51,18 @@ return NULL; if (srcza == NULL || srcidx >= srcza->nentry) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return NULL; } if ((flags & ZIP_FL_UNCHANGED) == 0 && (ZIP_ENTRY_DATA_CHANGED(srcza->entry+srcidx) || srcza->entry[srcidx].deleted)) { - _zip_error_set(&za->error, ZIP_ER_CHANGED, 0); + zip_error_set(&za->error, ZIP_ER_CHANGED, 0); return NULL; } if (zip_stat_index(srcza, srcidx, flags|ZIP_FL_UNCHANGED, &st) < 0) { - _zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); return NULL; } @@ -70,24 +70,24 @@ flags |= ZIP_FL_COMPRESSED; if ((start > 0 || len > 0) && (flags & ZIP_FL_COMPRESSED)) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return NULL; } /* overflow or past end of file */ if ((start > 0 || len > 0) && (start+len < start || start+len > st.size)) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + 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 (password == NULL) { - _zip_error_set(&za->error, ZIP_ER_NOPASSWD, 0); + zip_error_set(&za->error, ZIP_ER_NOPASSWD, 0); return NULL; } if ((enc_impl=_zip_get_encryption_implementation(st.encryption_method)) == NULL) { - _zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); + zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); return NULL; } } @@ -96,7 +96,7 @@ if ((flags & ZIP_FL_COMPRESSED) == 0) { if (st.comp_method != ZIP_CM_STORE) { if ((comp_impl=_zip_get_compression_implementation(st.comp_method)) == NULL) { - _zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); + zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); return NULL; } } @@ -119,17 +119,17 @@ st2.mtime = st.mtime; st2.valid = ZIP_STAT_SIZE|ZIP_STAT_COMP_SIZE|ZIP_STAT_COMP_METHOD|ZIP_STAT_MTIME; - /* TODO: check for overflow of st2.size */ - if ((src=_zip_source_file_or_p(za, NULL, srcza->zp, offset+start, (zip_int64_t)st2.size, 0, &st2)) == NULL) - return NULL; + if ((src = _zip_source_window_new(za->src, offset+start, st2.size, &st2, &za->error)) == NULL) { + return NULL; + } } else { - /* TODO: check for overflow of st.comp_size */ - if ((src=_zip_source_file_or_p(za, NULL, srcza->zp, offset, (zip_int64_t)st.comp_size, 0, &st)) == NULL) - return NULL; + if ((src = _zip_source_window_new(srcza->src, offset, st.comp_size, &st, &za->error)) == NULL) { + return NULL; + } } - if (_zip_source_filep_set_source_archive(src, srcza) < 0) { + if (_zip_source_set_source_archive(src, srcza) < 0) { zip_source_free(src); return NULL; } @@ -137,7 +137,6 @@ if (enc_impl) { if ((s2=enc_impl(za, src, st.encryption_method, 0, password)) == NULL) { zip_source_free(src); - /* TODO: set error (how?) */ return NULL; } src = s2; @@ -145,7 +144,6 @@ if (comp_impl) { if ((s2=comp_impl(za, src, st.comp_method, 0)) == NULL) { zip_source_free(src); - /* TODO: set error (how?) */ return NULL; } src = s2; @@ -155,7 +153,6 @@ /* when reading the whole file, check for crc errors */ if ((s2=zip_source_crc(za, src, 1)) == NULL) { zip_source_free(src); - /* TODO: set error (how?) */ return NULL; } src = s2; @@ -164,7 +161,6 @@ if (start+len > 0 && (comp_impl || enc_impl)) { if ((s2=zip_source_window(za, src, start, len ? len : st.size-start)) == NULL) { zip_source_free(src); - /* TODO: set error (how?) (why?) */ return NULL; } src = s2;
diff --git a/lib/zip_stat.c b/lib/zip_stat.c index 9f52639..b87182b 100644 --- a/lib/zip_stat.c +++ b/lib/zip_stat.c
@@ -1,6 +1,6 @@ /* zip_stat.c -- get information about file by name - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/lib/zip_stat_index.c b/lib/zip_stat_index.c index 03eaad3..a58345b 100644 --- a/lib/zip_stat_index.c +++ b/lib/zip_stat_index.c
@@ -1,6 +1,6 @@ /* zip_stat_index.c -- get information about file by index - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -52,7 +52,7 @@ if ((flags & ZIP_FL_UNCHANGED) == 0 && ZIP_ENTRY_DATA_CHANGED(za->entry+index)) { if (zip_source_stat(za->entry[index].source, st) < 0) { - _zip_error_set(&za->error, ZIP_ER_CHANGED, 0); + zip_error_set(&za->error, ZIP_ER_CHANGED, 0); return -1; } }
diff --git a/lib/zip_stat_init.c b/lib/zip_stat_init.c index 204477b..0a8bf5a 100644 --- a/lib/zip_stat_init.c +++ b/lib/zip_stat_init.c
@@ -1,6 +1,6 @@ /* zip_stat_init.c -- initialize struct zip_stat. - Copyright (C) 2006-2009 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -31,6 +31,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <string.h> #include "zipint.h" @@ -48,3 +49,37 @@ st->comp_method = ZIP_CM_STORE; st->encryption_method = ZIP_EM_NONE; } + + +int +_zip_stat_merge(zip_stat_t *dst, const zip_stat_t *src, zip_error_t *error) +{ + /* name is not merged, since zip_stat_t doesn't own it, and src may not be valid as long as dst */ + if (src->valid & ZIP_STAT_INDEX) { + dst->index = src->index; + } + if (src->valid & ZIP_STAT_SIZE) { + dst->size = src->size; + } + if (src->valid & ZIP_STAT_COMP_SIZE) { + dst->comp_size = src->comp_size; + } + if (src->valid & ZIP_STAT_MTIME) { + dst->mtime = src->mtime; + } + if (src->valid & ZIP_STAT_CRC) { + dst->crc = src->crc; + } + if (src->valid & ZIP_STAT_COMP_METHOD) { + dst->comp_method = src->comp_method; + } + if (src->valid & ZIP_STAT_ENCRYPTION_METHOD) { + dst->encryption_method = src->encryption_method; + } + if (src->valid & ZIP_STAT_FLAGS) { + dst->flags = src->flags; + } + dst->valid |= src->valid; + + return 0; +}
diff --git a/lib/zip_strerror.c b/lib/zip_strerror.c index f08fdd2..548c021 100644 --- a/lib/zip_strerror.c +++ b/lib/zip_strerror.c
@@ -1,6 +1,6 @@ /* zip_sterror.c -- get string representation of zip error - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -38,5 +38,5 @@ ZIP_EXTERN const char * zip_strerror(struct zip *za) { - return _zip_error_strerror(&za->error); + return zip_error_strerror(&za->error); }
diff --git a/lib/zip_string.c b/lib/zip_string.c index 6c3f1c0..a731ebb 100644 --- a/lib/zip_string.c +++ b/lib/zip_string.c
@@ -1,6 +1,6 @@ /* zip_string.c -- string handling (with encoding) - Copyright (C) 2012 Dieter Baron and Thomas Klausner + Copyright (C) 2012-2014 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> @@ -145,12 +145,12 @@ expected_encoding = ZIP_ENCODING_CP437; break; default: - _zip_error_set(error, ZIP_ER_INVAL, 0); + zip_error_set(error, ZIP_ER_INVAL, 0); return NULL; } if ((s=(struct zip_string *)malloc(sizeof(*s))) == NULL) { - _zip_error_set(error, ZIP_ER_MEMORY, 0); + zip_error_set(error, ZIP_ER_MEMORY, 0); return NULL; } @@ -169,7 +169,7 @@ if (expected_encoding != ZIP_ENCODING_UNKNOWN) { if (_zip_guess_encoding(s, expected_encoding) == ZIP_ENCODING_ERROR) { _zip_string_free(s); - _zip_error_set(error, ZIP_ER_INVAL, 0); + zip_error_set(error, ZIP_ER_INVAL, 0); return NULL; } } @@ -178,11 +178,11 @@ } -void -_zip_string_write(const struct zip_string *s, FILE *f) +int +_zip_string_write(zip_t *za, const zip_string_t *s) { if (s == NULL) - return; + return 0; - fwrite(s->raw, s->length, 1, f); + return _zip_write(za, s->raw, s->length); }
diff --git a/lib/zip_unchange.c b/lib/zip_unchange.c index 6e6d042..aa840d0 100644 --- a/lib/zip_unchange.c +++ b/lib/zip_unchange.c
@@ -1,6 +1,6 @@ /* zip_unchange.c -- undo changes to file in zip archive - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -50,14 +50,14 @@ zip_int64_t i; if (idx >= za->nentry) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } if (!allow_duplicates && za->entry[idx].changes && (za->entry[idx].changes->changed & ZIP_DIRENT_FILENAME)) { i = _zip_name_locate(za, _zip_get_name(za, idx, ZIP_FL_UNCHANGED, NULL), 0, NULL); if (i >= 0 && (zip_uint64_t)i != idx) { - _zip_error_set(&za->error, ZIP_ER_EXISTS, 0); + zip_error_set(&za->error, ZIP_ER_EXISTS, 0); return -1; } }
diff --git a/lib/zip_unchange_all.c b/lib/zip_unchange_all.c index 83b4166..c57cdf8 100644 --- a/lib/zip_unchange_all.c +++ b/lib/zip_unchange_all.c
@@ -1,6 +1,6 @@ /* zip_unchange.c -- undo changes to all files in zip archive - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/lib/zip_unchange_archive.c b/lib/zip_unchange_archive.c index cf93375..291b826 100644 --- a/lib/zip_unchange_archive.c +++ b/lib/zip_unchange_archive.c
@@ -1,6 +1,6 @@ /* zip_unchange_archive.c -- undo global changes to ZIP archive - Copyright (C) 2006-2008 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/lib/zip_unchange_data.c b/lib/zip_unchange_data.c index 2793a70..a95a81c 100644 --- a/lib/zip_unchange_data.c +++ b/lib/zip_unchange_data.c
@@ -1,6 +1,6 @@ /* zip_unchange_data.c -- undo helper function - Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/lib/zip_utf-8.c b/lib/zip_utf-8.c index 8eb5fe3..58c4195 100644 --- a/lib/zip_utf-8.c +++ b/lib/zip_utf-8.c
@@ -1,6 +1,6 @@ /* zip_utf-8.c -- UTF-8 support functions for libzip - Copyright (C) 2011-2012 Dieter Baron and Thomas Klausner + Copyright (C) 2011-2014 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> @@ -233,7 +233,7 @@ buflen += _zip_unicode_to_utf8_len(_cp437_to_unicode[cp437buf[i]]); if ((utf8buf=(zip_uint8_t*)malloc(buflen)) == NULL) { - _zip_error_set(error, ZIP_ER_MEMORY, 0); + zip_error_set(error, ZIP_ER_MEMORY, 0); return NULL; }
diff --git a/lib/zipint.h b/lib/zipint.h index e4cb066..ace8a0b 100644 --- a/lib/zipint.h +++ b/lib/zipint.h
@@ -165,14 +165,17 @@ #define ZIP_EXT_ATTRIB_DEFAULT_DIR (0040777u<<16) +#define ZIP_MAX(a, b) ((a) > (b) ? (a) : (b)) +#define ZIP_MIN(a, b) ((a) < (b) ? (a) : (b)) + /* This section contains API that won't materialize like this. It's placed in the internal section, pending cleanup. */ -typedef struct zip_source *(*zip_compression_implementation)(struct zip *, - struct zip_source *, +typedef zip_source_t *(*zip_compression_implementation)(struct zip *, + zip_source_t *, zip_int32_t, int); -typedef struct zip_source *(*zip_encryption_implementation)(struct zip *, - struct zip_source *, +typedef zip_source_t *(*zip_encryption_implementation)(struct zip *, + zip_source_t *, zip_uint16_t, int, const char *); @@ -189,38 +192,30 @@ user-supplied compression/encryption implementation is finished. Thus we will keep it private for now. */ -typedef zip_int64_t (*zip_source_layered_callback)(struct zip_source *, void *, - void *, zip_uint64_t, - enum zip_source_cmd); - -void zip_source_close(struct zip_source *); -struct zip_source *zip_source_crc(struct zip *, struct zip_source *, - int); -struct zip_source *zip_source_deflate(struct zip *, - struct zip_source *, - zip_int32_t, int); -void zip_source_error(struct zip_source *, int *, int *); -struct zip_source *zip_source_layered(struct zip *, - struct zip_source *, - zip_source_layered_callback, - void *); -int zip_source_open(struct zip_source *); -struct zip_source *zip_source_pkware(struct zip *, - struct zip_source *, - zip_uint16_t, int, - const char *); -zip_int64_t zip_source_read(struct zip_source *, void *, - zip_uint64_t); -int zip_source_stat(struct zip_source *, struct zip_stat *); -struct zip_source *zip_source_window(struct zip *, struct zip_source *, - zip_uint64_t, zip_uint64_t); +typedef zip_int64_t (*zip_source_layered_callback)(zip_source_t *, void *, void *, zip_uint64_t, enum zip_source_cmd); +int zip_source_begin_write(zip_source_t *); +int zip_source_commit_write(zip_source_t *); +zip_source_t *zip_source_crc(struct zip *, zip_source_t *, int); +zip_source_t *zip_source_deflate(struct zip *, zip_source_t *, zip_int32_t, int); +zip_source_t *zip_source_layered(struct zip *, 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(struct zip *, zip_source_t *, zip_uint16_t, int, const char *); +int zip_source_remove(zip_source_t *); +void zip_source_rollback_write(zip_source_t *); +int zip_source_seek(zip_source_t *, zip_int64_t, int); +int zip_source_seek_write(zip_source_t *, zip_int64_t, int); +zip_int64_t zip_source_supports(zip_source_t *src); +zip_int64_t zip_source_tell(zip_source_t *); +zip_int64_t zip_source_tell_write(zip_source_t *); +zip_source_t *zip_source_window(struct zip *, zip_source_t *, zip_uint64_t, zip_uint64_t); +zip_int64_t zip_source_write(zip_source_t *, const void *, zip_uint64_t); /* This function will probably remain private. It is not needed to implement compression/encryption routines. (We should probably rename it to _zip_source_pop.) */ -struct zip_source *zip_source_pop(struct zip_source *); +zip_source_t *zip_source_pop(zip_source_t *); /* error source for layered sources */ @@ -255,38 +250,38 @@ ZIP_ENCODING_ERROR /* should be UTF-8 but isn't */ }; -/* error information */ +typedef enum zip_encoding_type zip_encoding_type_t; -struct zip_error { - int zip_err; /* libzip error code (ZIP_ER_*) */ - int sys_err; /* copy of errno (E*) or zlib error code */ - char *str; /* string representation or NULL */ -}; +typedef struct zip_cdir zip_cdir_t; +typedef struct zip_dirent zip_dirent_t; +typedef struct zip_entry zip_entry_t; +typedef struct zip_extra_field zip_extra_field_t; +typedef struct zip_string zip_string_t; + /* zip archive, part of API */ struct zip { - char *zn; /* file name */ - FILE *zp; /* file */ + zip_source_t *src; /* data source for archive */ unsigned int open_flags; /* flags passed to zip_open */ - struct zip_error error; /* error information */ + zip_error_t error; /* error information */ unsigned int flags; /* archive global flags */ unsigned int ch_flags; /* changed archive global flags */ char *default_password; /* password used when no other supplied */ - struct zip_string *comment_orig; /* archive comment */ - struct zip_string *comment_changes; /* changed archive comment */ + zip_string_t *comment_orig; /* archive comment */ + zip_string_t *comment_changes; /* changed archive comment */ int comment_changed; /* whether archive comment was changed */ zip_uint64_t nentry; /* number of entries */ zip_uint64_t nentry_alloc; /* number of entries allocated */ - struct zip_entry *entry; /* entries */ + zip_entry_t *entry; /* entries */ - unsigned int nsource; /* number of open sources using archive */ - unsigned int nsource_alloc; /* number of sources allocated */ - struct zip_source **source; /* open sources using archive */ + unsigned int nopen_source; /* number of open sources using archive */ + unsigned int nopen_source_alloc; /* number of sources allocated */ + zip_source_t **open_source; /* open sources using archive */ char *tempdir; /* custom temp dir (needed e.g. for OS X sandboxing) */ }; @@ -294,10 +289,10 @@ /* file in zip archive, part of API */ struct zip_file { - struct zip *za; /* zip archive containing this file */ - struct zip_error error; /* error information */ + zip_t *za; /* zip archive containing this file */ + zip_error_t error; /* error information */ int eof; - struct zip_source *src; /* data source */ + zip_source_t *src; /* data source */ }; /* zip archive directory entry (central or local) */ @@ -312,64 +307,79 @@ struct zip_dirent { zip_uint32_t changed; - int local_extra_fields_read; /* whether we already read in local header extra fields */ - int cloned; /* whether this instance is cloned, and thus shares non-changed strings */ + int local_extra_fields_read; /* whether we already read in local header extra fields */ + int cloned; /* whether this instance is cloned, and thus shares non-changed strings */ - zip_uint16_t version_madeby; /* (c) version of creator */ - zip_uint16_t version_needed; /* (cl) version needed to extract */ - zip_uint16_t bitflags; /* (cl) general purpose bit flag */ - zip_int32_t comp_method; /* (cl) compression method used (uint16 and ZIP_CM_DEFAULT (-1)) */ - time_t last_mod; /* (cl) time of last modification */ - zip_uint32_t crc; /* (cl) CRC-32 of uncompressed data */ - zip_uint64_t comp_size; /* (cl) size of compressed data */ - zip_uint64_t uncomp_size; /* (cl) size of uncompressed data */ - struct zip_string *filename; /* (cl) file name (NUL-terminated) */ - struct zip_extra_field *extra_fields; /* (cl) extra fields, parsed */ - struct zip_string *comment; /* (c) file comment */ - zip_uint32_t disk_number; /* (c) disk number start */ - zip_uint16_t int_attrib; /* (c) internal file attributes */ - zip_uint32_t ext_attrib; /* (c) external file attributes */ - zip_uint64_t offset; /* (c) offset of local header */ + zip_uint16_t version_madeby; /* (c) version of creator */ + zip_uint16_t version_needed; /* (cl) version needed to extract */ + zip_uint16_t bitflags; /* (cl) general purpose bit flag */ + zip_int32_t comp_method; /* (cl) compression method used (uint16 and ZIP_CM_DEFAULT (-1)) */ + time_t last_mod; /* (cl) time of last modification */ + zip_uint32_t crc; /* (cl) CRC-32 of uncompressed data */ + zip_uint64_t comp_size; /* (cl) size of compressed data */ + zip_uint64_t uncomp_size; /* (cl) size of uncompressed data */ + zip_string_t *filename; /* (cl) file name (NUL-terminated) */ + zip_extra_field_t *extra_fields; /* (cl) extra fields, parsed */ + zip_string_t *comment; /* (c) file comment */ + zip_uint32_t disk_number; /* (c) disk number start */ + zip_uint16_t int_attrib; /* (c) internal file attributes */ + zip_uint32_t ext_attrib; /* (c) external file attributes */ + zip_uint64_t offset; /* (c) offset of local header */ }; /* zip archive central directory */ struct zip_cdir { - struct zip_entry *entry; /* directory entries */ - zip_uint64_t nentry; /* number of entries */ - zip_uint64_t nentry_alloc; /* number of entries allocated */ + zip_entry_t *entry; /* directory entries */ + zip_uint64_t nentry; /* number of entries */ + zip_uint64_t nentry_alloc; /* number of entries allocated */ - off_t size; /* size of central directory */ - off_t offset; /* offset of central directory in file */ - struct zip_string *comment; /* zip archive comment */ + zip_uint64_t size; /* size of central directory */ + zip_uint64_t offset; /* offset of central directory in file */ + zip_string_t *comment; /* zip archive comment */ }; struct zip_extra_field { - struct zip_extra_field *next; - zip_flags_t flags; /* in local/central header */ - zip_uint16_t id; /* header id */ - zip_uint16_t size; /* data size */ + zip_extra_field_t *next; + zip_flags_t flags; /* in local/central header */ + zip_uint16_t id; /* header id */ + zip_uint16_t size; /* data size */ zip_uint8_t *data; }; +enum zip_source_write_state { + ZIP_SOURCE_WRITE_CLOSED, /* write is not in progress */ + ZIP_SOURCE_WRITE_OPEN, /* write is in progress */ + ZIP_SOURCE_WRITE_FAILED, /* commit failed, only rollback allowed */ + ZIP_SOURCE_WRITE_REMOVED /* file was removed */ +}; +typedef enum zip_source_write_state zip_source_write_state_t; struct zip_source { - struct zip_source *src; + zip_source_t *src; union { zip_source_callback f; zip_source_layered_callback l; } cb; void *ud; - enum zip_les error_source; - int is_open; + zip_error_t error; + unsigned int open_count; /* number of times source was opened (directly or as lower layer) */ + zip_source_write_state_t write_state; /* whether source is open for writing */ + int source_closed; /* set if source archive is closed */ + zip_t *source_archive; /* zip archive we're reading from, NULL if not from archive */ + unsigned int refcount; }; +#define ZIP_SOURCE_IS_OPEN_READING(src) ((src)->open_count > 0) +#define ZIP_SOURCE_IS_OPEN_WRITING(src) ((src)->write_state == ZIP_SOURCE_WRITE_OPEN) +#define ZIP_SOURCE_IS_LAYERED(src) ((src)->src != NULL) + /* entry in zip archive directory */ struct zip_entry { - struct zip_dirent *orig; - struct zip_dirent *changes; - struct zip_source *source; + zip_dirent_t *orig; + zip_dirent_t *changes; + zip_source_t *source; int deleted; }; @@ -392,6 +402,8 @@ const char *name; }; +typedef struct zip_filelist zip_filelist_t; + extern const char * const _zip_err_str[]; extern const int _zip_nerr_str; @@ -411,7 +423,8 @@ void _zip_cdir_free(struct zip_cdir *); int _zip_cdir_grow(struct zip_cdir *, zip_uint64_t, struct zip_error *); struct zip_cdir *_zip_cdir_new(zip_uint64_t, struct zip_error *); -zip_int64_t _zip_cdir_write(struct zip *, const struct zip_filelist *, zip_uint64_t, FILE *); +zip_int64_t _zip_cdir_write(struct zip *za, const struct zip_filelist *filelist, zip_uint64_t survivors); +void _zip_deregister_source(zip_t *za, zip_source_t *src); struct zip_dirent *_zip_dirent_clone(const struct zip_dirent *); void _zip_dirent_free(struct zip_dirent *); @@ -419,11 +432,12 @@ void _zip_dirent_init(struct zip_dirent *); int _zip_dirent_needs_zip64(const struct zip_dirent *, zip_flags_t); struct zip_dirent *_zip_dirent_new(void); -int _zip_dirent_read(struct zip_dirent *, FILE *, const unsigned char **, - zip_uint64_t *, int, struct zip_error *); -zip_int32_t _zip_dirent_size(FILE *, zip_uint16_t, struct zip_error *); +int _zip_dirent_read(struct zip_dirent *zde, zip_source_t *src, + const unsigned char **bufp, zip_uint64_t *leftp, int local, + zip_error_t *error); +zip_int32_t _zip_dirent_size(zip_source_t *src, zip_uint16_t, struct zip_error *); void _zip_dirent_torrent_normalize(struct zip_dirent *); -int _zip_dirent_write(struct zip_dirent *, FILE *, zip_flags_t, struct zip_error *); +int _zip_dirent_write(struct zip *za, struct zip_dirent *dirent, zip_flags_t flags); struct zip_extra_field *_zip_ef_clone(const struct zip_extra_field *, struct zip_error *); struct zip_extra_field *_zip_ef_delete_by_id(struct zip_extra_field *, zip_uint16_t, zip_uint16_t, zip_flags_t); @@ -434,19 +448,16 @@ struct zip_extra_field *_zip_ef_parse(const zip_uint8_t *, zip_uint16_t, zip_flags_t, struct zip_error *); struct zip_extra_field *_zip_ef_remove_internal(struct zip_extra_field *); zip_uint16_t _zip_ef_size(const struct zip_extra_field *, zip_flags_t); -void _zip_ef_write(const struct zip_extra_field *, zip_flags_t, FILE *); +int _zip_ef_write(struct zip *za, const struct zip_extra_field *ef, zip_flags_t flags); void _zip_entry_finalize(struct zip_entry *); void _zip_entry_init(struct zip_entry *); void _zip_error_clear(struct zip_error *); -void _zip_error_copy(struct zip_error *, const struct zip_error *); -void _zip_error_fini(struct zip_error *); void _zip_error_get(const struct zip_error *, int *, int *); -void _zip_error_init(struct zip_error *); -void _zip_error_set(struct zip_error *, int, int); -void _zip_error_set_from_source(struct zip_error *, struct zip_source *); -const char *_zip_error_strerror(struct zip_error *); + +void _zip_error_copy(zip_error_t *dst, const struct zip_error *src); +void _zip_error_set_from_source(zip_error_t *, zip_source_t *); const zip_uint8_t *_zip_extract_extra_field_by_id(struct zip_error *, zip_uint16_t, int, const zip_uint8_t *, zip_uint16_t, zip_uint16_t *); @@ -454,30 +465,45 @@ int _zip_file_fillbuf(void *, size_t, struct zip_file *); zip_uint64_t _zip_file_get_offset(const struct zip *, zip_uint64_t, struct zip_error *); -int _zip_filerange_crc(FILE *, off_t, off_t, uLong *, struct zip_error *); +int _zip_filerange_crc(zip_source_t *src, zip_uint64_t offset, zip_uint64_t length, uLong *crcp, struct zip_error *error); struct zip_dirent *_zip_get_dirent(struct zip *, zip_uint64_t, zip_flags_t, struct zip_error *); enum zip_encoding_type _zip_guess_encoding(struct zip_string *, enum zip_encoding_type); zip_uint8_t *_zip_cp437_to_utf8(const zip_uint8_t * const, zip_uint32_t, zip_uint32_t *, struct zip_error *); -struct zip *_zip_open(const char *, FILE *, unsigned int, int *); +struct zip *_zip_open(zip_source_t *, unsigned int, struct zip_error *); +void _zip_put_16(zip_uint8_t **p, zip_uint16_t i); +void _zip_put_32(zip_uint8_t **p, zip_uint32_t i); +void _zip_put_64(zip_uint8_t **p, zip_uint64_t i); +void _zip_put_data(zip_uint8_t **p, const char *s, size_t len); + +int _zip_read(zip_source_t *src, zip_uint8_t *data, zip_uint64_t length, struct zip_error *error); +int _zip_read_at_offset(zip_source_t *src, zip_uint64_t offset, unsigned char *b, size_t length, struct zip_error *error); int _zip_read_local_ef(struct zip *, zip_uint64_t); +struct zip_string *_zip_read_string(const zip_uint8_t **buf, zip_source_t *src, zip_uint16_t len, int nulp, struct zip_error *error); +int _zip_register_source(zip_t *za, zip_source_t *src); -struct zip_source *_zip_source_file_or_p(struct zip *, const char *, FILE *, zip_uint64_t, zip_int64_t, int, const struct zip_stat *); -void _zip_source_filep_invalidate(struct zip_source *); -int _zip_source_filep_set_source_archive(struct zip_source *, struct zip *); -struct zip_source *_zip_source_new(struct zip *); -struct zip_source *_zip_source_zip_new(struct zip *, struct zip *, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_uint64_t, const char *); +void _zip_set_open_error(int *zep, const struct zip_error *err, int ze); +zip_int64_t _zip_source_call(zip_source_t *src, void *data, zip_uint64_t length, enum zip_source_cmd command); +zip_source_t *_zip_source_file_or_p(const char *, FILE *, zip_uint64_t, zip_int64_t, int, const struct zip_stat *, zip_error_t *error); +void _zip_source_invalidate(zip_source_t *src); +void _zip_source_free_or_pop(zip_source_t *src, int recurse); +zip_source_t *_zip_source_new(zip_error_t *error); +int _zip_source_set_source_archive(zip_source_t *, struct zip *); +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_zip_new(struct zip *, struct zip *, 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); int _zip_string_equal(const struct zip_string *, const struct zip_string *); void _zip_string_free(struct zip_string *); zip_uint32_t _zip_string_crc32(const struct zip_string *); const zip_uint8_t *_zip_string_get(struct zip_string *, zip_uint32_t *, zip_flags_t, struct zip_error *); zip_uint16_t _zip_string_length(const struct zip_string *); struct zip_string *_zip_string_new(const zip_uint8_t *, zip_uint16_t, zip_flags_t, struct zip_error *); -void _zip_string_write(const struct zip_string *, FILE *); +int _zip_string_write(struct zip *za, const struct zip_string *string); int _zip_changed(const struct zip *, zip_uint64_t *); const char *_zip_get_name(struct zip *, zip_uint64_t, zip_flags_t, struct zip_error *); @@ -485,21 +511,15 @@ void *_zip_memdup(const void *, size_t, struct zip_error *); zip_int64_t _zip_name_locate(struct zip *, const char *, zip_flags_t, struct zip_error *); struct zip *_zip_new(struct zip_error *); -zip_uint16_t _zip_read2(const zip_uint8_t **); -zip_uint32_t _zip_read4(const zip_uint8_t **); -zip_uint64_t _zip_read8(const zip_uint8_t **); -zip_uint8_t *_zip_read_data(const zip_uint8_t **, FILE *, size_t, int, struct zip_error *); -zip_int64_t _zip_file_replace(struct zip *, zip_uint64_t, const char *, struct zip_source *, zip_flags_t); +zip_uint16_t _zip_get_16(const zip_uint8_t **); +zip_uint32_t _zip_get_32(const zip_uint8_t **); +zip_uint64_t _zip_get_64(const zip_uint8_t **); +zip_uint8_t *_zip_read_data(const zip_uint8_t **bufferp, zip_source_t *src, size_t length, int nulp, struct zip_error *error); +zip_int64_t _zip_file_replace(struct zip *, zip_uint64_t, const char *, zip_source_t *, zip_flags_t); int _zip_set_name(struct zip *, zip_uint64_t, const char *, zip_flags_t); void _zip_u2d_time(time_t, zip_uint16_t *, zip_uint16_t *); int _zip_unchange(struct zip *, zip_uint64_t, int); void _zip_unchange_data(struct zip_entry *); - -void _zip_poke4(zip_uint32_t, zip_uint8_t **); -void _zip_poke8(zip_uint64_t, zip_uint8_t **); -void _zip_write2(zip_uint16_t, FILE *); -void _zip_write4(zip_uint32_t, FILE *); -void _zip_write8(zip_uint64_t, FILE *); - +int _zip_write(struct zip *za, const void *data, zip_uint64_t length); #endif /* zipint.h */
diff --git a/man/zip_open.mdoc b/man/zip_open.mdoc index 41fbb7e..f805da0 100644 --- a/man/zip_open.mdoc +++ b/man/zip_open.mdoc
@@ -1,5 +1,5 @@ .\" zip_open.mdoc -- open zip archive -.\" Copyright (C) 2003-2012 Dieter Baron and Thomas Klausner +.\" Copyright (C) 2003-2014 Dieter Baron and Thomas Klausner .\" .\" This file is part of libzip, a library to manipulate ZIP archives. .\" The authors can be contacted at <libzip@nih.at> @@ -29,7 +29,7 @@ .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd February 13, 2012 +.Dd August 17, 2014 .Dt ZIP_OPEN 3 .Os .Sh NAME @@ -63,6 +63,8 @@ .It Dv ZIP_TRUNCATE If archive exists, ignore its current contents. In other words, handle it the same way as an empty archive. +.It Dv ZIP_RDONLY +Open archive in read-only mode. .El .Pp If an error occurs and
diff --git a/man/zip_source_function.mdoc b/man/zip_source_function.mdoc index ae00975..4c52e72 100644 --- a/man/zip_source_function.mdoc +++ b/man/zip_source_function.mdoc
@@ -29,7 +29,7 @@ .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd August 2, 2014 +.Dd August 11, 2014 .Dt ZIP_SOURCE_FUNCTION 3 .Os .Sh NAME @@ -52,6 +52,10 @@ void *data, zip_uint64_t len, enum zip_source_cmd cmd); .Ed .Pp +.Ar archive +is used for reporting errors and can be +.Dv NULL . +.Pp When called by the library, the first argument is the .Ar userdata argument supplied to @@ -142,7 +146,10 @@ .Dv NULL is returned and the error code in .Ar archive -is set to indicate the error. +is set to indicate the error (unless +.Ar archive +is +.Dv NULL ) . .Sh ERRORS .Fn zip_source_function fails if:
diff --git a/regress/CMakeLists.txt b/regress/CMakeLists.txt index 8508031..d426fce 100644 --- a/regress/CMakeLists.txt +++ b/regress/CMakeLists.txt
@@ -22,14 +22,12 @@ SET(HELPER_TEST_PROGRAMS # modify set_compression -# stat_index # tryopen ) SET(GETOPT_USERS fread modify - stat_index tryopen ) @@ -47,6 +45,7 @@ add_from_zip_partial_stored.test add_from_zip_stored.test add_stored.test + add_stored_in_memory.test delete_add_same.test delete_invalid.test delete_last.test
diff --git a/regress/Makefile.am b/regress/Makefile.am index 6905c9b..83a5bff 100644 --- a/regress/Makefile.am +++ b/regress/Makefile.am
@@ -14,7 +14,6 @@ set_comment_removeglobal \ set_comment_revert \ set_compression \ - stat_index \ tryopen EXTRA_DIST= \ @@ -126,6 +125,7 @@ add_from_zip_partial_stored.test \ add_from_zip_stored.test \ add_stored.test \ + add_stored_in_memory.test \ delete_add_same.test \ delete_invalid.test \ delete_last.test \
diff --git a/regress/add_from_buffer.c b/regress/add_from_buffer.c index c5442ff..e31fa7e 100644 --- a/regress/add_from_buffer.c +++ b/regress/add_from_buffer.c
@@ -1,6 +1,6 @@ /* add_from_buffer.c -- test case for adding file from buffer to archive - Copyright (C) 1999, 2003, 2005 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/regress/add_from_filep.c b/regress/add_from_filep.c index a501f4e..59b19d9 100644 --- a/regress/add_from_filep.c +++ b/regress/add_from_filep.c
@@ -1,6 +1,6 @@ /* add_from_filep.c -- test case for adding file to archive - Copyright (C) 1999, 2003, 2005 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/regress/add_stored_in_memory.test b/regress/add_stored_in_memory.test new file mode 100644 index 0000000..9b13849 --- /dev/null +++ b/regress/add_stored_in_memory.test
@@ -0,0 +1,5 @@ +# add file, set compression method to ZIP_CM_STORE +program modify +return 0 +args -mn test.zip add foo foo set_file_compression 0 store 0 +file-new test.zip foo-stored.zip
diff --git a/regress/encrypt.test b/regress/encrypt.test index f325f91..c571863 100644 --- a/regress/encrypt.test +++ b/regress/encrypt.test
@@ -1,8 +1,8 @@ # test encryption support # TODO: only checks recognition of encrypted entries for now. -program stat_index +program modify return 0 -args encrypt.zzip 0 1 +args encrypt.zzip stat 0 stat 1 file encrypt.zzip encrypt.zip encrypt.zip stdout name: 'encrypted' stdout index: '0'
diff --git a/regress/extra_add_multiple.test b/regress/extra_add_multiple.test index d4dde6f..c174e4d 100644 --- a/regress/extra_add_multiple.test +++ b/regress/extra_add_multiple.test
@@ -1,11 +1,9 @@ # add extra fields program modify -args testfile.zip set_extra 0 2345 65535 cl extra1 set_extra 0 2345 65535 cl extra2 set_extra 0 2345 0 c extra1c set_extra 0 2345 1 l extra2l get_extra_by_id 0 2345 0 c get_extra_by_id 0 2345 1 c get_extra_by_id 0 2345 2 c get_extra_by_id 0 2345 0 l get_extra_by_id 0 2345 1 l get_extra_by_id 0 2345 2 l -return 1 +args testfile.zip set_extra 0 2345 65535 cl extra1 set_extra 0 2345 65535 cl extra2 set_extra 0 2345 0 c extra1c set_extra 0 2345 1 l extra2l get_extra_by_id 0 2345 0 c get_extra_by_id 0 2345 1 c get_extra_by_id 0 2345 0 l get_extra_by_id 0 2345 1 l +return 0 file testfile.zip testfile.zip testfile-plus-extra.zip stdout Extra field 0x0929: len 7, data 0x65787472613163 stdout Extra field 0x0929: len 6, data 0x657874726132 -stderr can't get extra field data for file at index 0, extra field id 2345, ef index 2, flags 512: No such file stdout Extra field 0x0929: len 6, data 0x657874726131 stdout Extra field 0x0929: len 7, data 0x6578747261326c -stderr can't get extra field data for file at index 0, extra field id 2345, ef index 2, flags 256: No such file
diff --git a/regress/extra_delete.test b/regress/extra_delete.test index e2a2344..4ca5d49 100644 --- a/regress/extra_delete.test +++ b/regress/extra_delete.test
@@ -1,8 +1,8 @@ # delete extra field by index program modify -args encrypt.zip get_extra 0 0 c get_extra 0 1 c get_extra 0 2 c get_extra 0 0 l get_extra 0 1 l get_extra 0 2 l delete_extra 0 2 c delete_extra 0 0 l get_extra 0 0 c get_extra 0 1 c get_extra 0 2 c get_extra 0 0 l get_extra 0 1 l get_extra 0 2 l +args encrypt.zip get_extra 0 0 c get_extra 0 1 c get_extra 0 2 c get_extra 0 0 l get_extra 0 1 l get_extra 0 2 l delete_extra 0 2 c delete_extra 0 0 l get_extra 0 0 c get_extra 0 1 c get_extra 0 0 l get_extra 0 1 l file encrypt.zip encrypt_plus_extra.zip encrypt.zip -return 1 +return 0 stdout Extra field 0x5455: len 5, data 0x033dda4c44 stdout Extra field 0x7855: len 0 stdout Extra field 0x0929: len 17, data 0x65787472616669656c64636f6e74656e74 @@ -13,5 +13,3 @@ stdout Extra field 0x7855: len 0 stdout Extra field 0x5455: len 9, data 0x033dda4c444dda4c44 stdout Extra field 0x7855: len 4, data 0x64001400 -stderr can't get extra field data for file at index 0, extra field 2, flags 512: No such file -stderr can't get extra field data for file at index 0, extra field 2, flags 256: No such file
diff --git a/regress/extra_delete_by_id.test b/regress/extra_delete_by_id.test index dff30d2..8525739 100644 --- a/regress/extra_delete_by_id.test +++ b/regress/extra_delete_by_id.test
@@ -1,8 +1,7 @@ # delete extra field by id and index program modify #args encrypt.zip set_extra 0 2345 65535 cl extrafieldcontent -args encrypt.zip delete_extra_by_id 0 2345 0 c delete_extra_by_id 0 2345 0 l get_extra_by_id 0 2345 0 c get_extra_by_id 0 2345 0 l +args encrypt.zip delete_extra_by_id 0 2345 0 c delete_extra_by_id 0 2345 0 l get_extra_by_id 0 2345 0 c return 1 file encrypt.zip encrypt_plus_extra.zip encrypt.zip stderr can't get extra field data for file at index 0, extra field id 2345, ef index 0, flags 512: No such file -stderr can't get extra field data for file at index 0, extra field id 2345, ef index 0, flags 256: No such file
diff --git a/regress/extra_set.test b/regress/extra_set.test index 1bcce9e..92e8cf1 100644 --- a/regress/extra_set.test +++ b/regress/extra_set.test
@@ -1,8 +1,8 @@ # set extra field program modify -args encrypt get_extra 0 0 c get_extra 0 1 c get_extra 0 2 c get_extra 0 0 l get_extra 0 1 l get_extra 0 2 l set_extra 0 2345 -1 l extrafieldcontent set_extra 0 2345 -1 c extrafieldcontent get_extra 0 0 c get_extra 0 1 c get_extra 0 2 c get_extra 0 0 l get_extra 0 1 l get_extra 0 2 l +args encrypt get_extra 0 0 c get_extra 0 1 c get_extra 0 0 l get_extra 0 1 l set_extra 0 2345 -1 l extrafieldcontent set_extra 0 2345 -1 c extrafieldcontent get_extra 0 0 c get_extra 0 1 c get_extra 0 2 c get_extra 0 0 l get_extra 0 1 l get_extra 0 2 l file encrypt encrypt.zip encrypt_plus_extra.zip -return 1 +return 0 stdout Extra field 0x5455: len 5, data 0x033dda4c44 stdout Extra field 0x7855: len 0 stdout Extra field 0x5455: len 9, data 0x033dda4c444dda4c44 @@ -13,5 +13,3 @@ stdout Extra field 0x5455: len 9, data 0x033dda4c444dda4c44 stdout Extra field 0x7855: len 4, data 0x64001400 stdout Extra field 0x0929: len 17, data 0x65787472616669656c64636f6e74656e74 -stderr can't get extra field data for file at index 0, extra field 2, flags 512: No such file -stderr can't get extra field data for file at index 0, extra field 2, flags 256: No such file
diff --git a/regress/fopen_unchanged.c b/regress/fopen_unchanged.c index 7c025d8..d3c042d 100644 --- a/regress/fopen_unchanged.c +++ b/regress/fopen_unchanged.c
@@ -1,6 +1,6 @@ /* fopen_unchanged.c -- test case for adding file and reading from unchanged - Copyright (C) 2012 Dieter Baron and Thomas Klausner + Copyright (C) 2012-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/regress/fread.c b/regress/fread.c index b06e5b6..f3cda37 100644 --- a/regress/fread.c +++ b/regress/fread.c
@@ -1,6 +1,6 @@ /* fread.c -- test cases for reading from zip archives - Copyright (C) 2004-2009 Dieter Baron and Thomas Klausner + Copyright (C) 2004-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -54,7 +54,7 @@ "no", "zip_fopen", "zip_fread", "zip_fclose" }; -static int do_read(struct zip *, const char *, int, enum when, int, int); +static int do_read(struct zip *z, const char *name, zip_flags_t flags, enum when when_ex, int ze_ex, int se_ex); int verbose; @@ -70,6 +70,7 @@ struct zip_source *zs; char *archive; char errstr[1024]; + zip_int64_t idx; verbose = 0; fail = 0; @@ -98,8 +99,7 @@ if ((z=zip_open(archive, 0, &ze)) == NULL) { zip_error_to_str(errstr, sizeof(errstr), ze, errno); - printf("%s: can't open zip archive '%s': %s\n", - prg, archive, errstr); + printf("%s: can't open zip archive '%s': %s\n", prg, archive, errstr); return 1; } @@ -112,8 +112,7 @@ fail += do_read(z, "nosuchfile", 0, WHEN_OPEN, ZIP_ER_NOENT, 0); fail += do_read(z, "deflatezliberror", ZIP_FL_COMPRESSED, WHEN_NEVER, 0,0); fail += do_read(z, "deflatecrcerror", ZIP_FL_COMPRESSED, WHEN_NEVER, 0, 0); - fail += do_read(z, "storedcrcerror", ZIP_FL_COMPRESSED, - WHEN_READ, ZIP_ER_CRC, 0); + fail += do_read(z, "storedcrcerror", ZIP_FL_COMPRESSED, WHEN_READ, ZIP_ER_CRC, 0); fail += do_read(z, "storedok", ZIP_FL_COMPRESSED, WHEN_NEVER, 0, 0); fail += do_read(z, "cryptok", 0, WHEN_OPEN, ZIP_ER_NOPASSWD, 0); @@ -124,18 +123,44 @@ zip_set_default_password(z, NULL); zs = zip_source_buffer(z, "asdf", 4, 0); - zip_replace(z, zip_name_locate(z, "storedok", 0), zs); - fail += do_read(z, "storedok", 0, WHEN_OPEN, ZIP_ER_CHANGED, 0); - fail += do_read(z, "storedok", ZIP_FL_UNCHANGED, WHEN_NEVER, 0, 0); - zip_delete(z, zip_name_locate(z, "storedok", 0)); - fail += do_read(z, "storedok", 0, WHEN_OPEN, ZIP_ER_NOENT, 0); - fail += do_read(z, "storedok", ZIP_FL_UNCHANGED, WHEN_NEVER, 0, 0); + if ((idx = zip_name_locate(z, "storedok", 0)) < 0) { + fprintf(stderr, "%s: can't locate 'storedok' in zip archive '%s': %s\n", prg, archive, zip_strerror(z)); + fail++; + } + else { + if (zip_replace(z, (zip_uint64_t)idx, zs) < 0) { + fprintf(stderr, "%s: can't replace 'storedok' in zip archive '%s': %s\n", prg, archive, zip_strerror(z)); + fail++; + } + else { + fail += do_read(z, "storedok", 0, WHEN_OPEN, ZIP_ER_CHANGED, 0); + fail += do_read(z, "storedok", ZIP_FL_UNCHANGED, WHEN_NEVER, 0, 0); + } + } + if ((idx = zip_name_locate(z, "storedok", 0)) < 0) { + fprintf(stderr, "%s: can't locate 'storedok' in zip archive '%s': %s\n", prg, archive, zip_strerror(z)); + fail++; + } + else { + if (zip_delete(z, (zip_uint64_t)idx) < 0) { + fprintf(stderr, "%s: can't replace 'storedok' in zip archive '%s': %s\n", prg, archive, zip_strerror(z)); + fail++; + } + else { + fail += do_read(z, "storedok", 0, WHEN_OPEN, ZIP_ER_NOENT, 0); + fail += do_read(z, "storedok", ZIP_FL_UNCHANGED, WHEN_NEVER, 0, 0); + } + } zs = zip_source_buffer(z, "asdf", 4, 0); - if (zip_file_add(z, "new_file", zs, 0) < 0) + if (zip_file_add(z, "new_file", zs, 0) < 0) { fprintf(stderr, "%s: can't add file to zip archive '%s': %s\n", prg, archive, zip_strerror(z)); - fail += do_read(z, "new_file", 0, WHEN_OPEN, ZIP_ER_CHANGED, 0); + fail++; + } + else { + fail += do_read(z, "new_file", 0, WHEN_OPEN, ZIP_ER_CHANGED, 0); + } + zip_unchange_all(z); - if (zip_close(z) == -1) { fprintf(stderr, "%s: can't close zip archive '%s': %s\n", prg, archive, zip_strerror(z)); return 1; @@ -146,8 +171,7 @@ static int -do_read(struct zip *z, const char *name, int flags, - enum when when_ex, int ze_ex, int se_ex) +do_read(struct zip *z, const char *name, zip_flags_t flags, enum when when_ex, int ze_ex, int se_ex) { struct zip_file *zf; enum when when_got;
diff --git a/regress/modify.c b/regress/modify.c index 5d6e5ff..c5df6cf 100644 --- a/regress/modify.c +++ b/regress/modify.c
@@ -36,6 +36,7 @@ #include <errno.h> #include <stdlib.h> #include <string.h> +#include <sys/stat.h> #ifdef HAVE_UNISTD_H #include <unistd.h> #endif @@ -46,36 +47,388 @@ #include "zip.h" -const char *prg; +typedef struct dispatch_table_s { + const char *cmdline_name; + int argument_count; + const char *arg_names; + const char *description; + int (*function)(int argc, char *argv[]); +} dispatch_table_t; -const char * const usage = "usage: %s [-cent] archive command1 [args] [command2 [args] ...]\n\n" - "Supported options are:\n" - "\t-c\tcheck consistency\n" - "\t-e\terror if archive already exists (only useful with -n)\n" - "\t-n\tcreate archive if it doesn't exist (default)\n" - "\t-t\tdisregard current archive contents, if any\n" - "\nSupported commands and arguments are:\n" - "\tadd name content\n" - "\tadd_dir name\n" - "\tadd_file name file_to_add offset len\n" - "\tadd_from_zip name archivename index offset len\n" - "\tcount_extra index flags\n" - "\tcount_extra_by_id index extra_id flags\n" - "\tdelete index\n" - "\tdelete_extra index extra_idx flags\n" - "\tdelete_extra_by_id index extra_id extra_index flags\n" - "\tget_archive_comment\n" - "\tget_extra index extra_index flags\n" - "\tget_extra_by_id index extra_id extra_index flags\n" - "\tget_file_comment index\n" - "\trename index name\n" - "\treplace_file_contents idx data\n" - "\tset_extra index extra_id extra_index flags value\n" - "\tset_file_comment index comment\n" - "\tset_file_compression index method flags\n" - "\tset_file_mtime index timestamp\n" - "\tzin_close\n" - "\nThe index is zero-based.\n"; +const char *prg; +static zip_flags_t get_flags(const char *arg); +static zip_int32_t get_compression_method(const char *arg); +static void hexdump(const zip_uint8_t *data, zip_uint16_t len); +static struct zip *read_to_memory(const char *archive, int flags, int *err, zip_source_t **srcp); + +struct zip *za, *z_in; +zip_flags_t stat_flags; + +static int +add(int argc, char *argv[]) { + struct zip_source *zs; + + if ((zs=zip_source_buffer(za, argv[1], strlen(argv[1]), 0)) == NULL) { + fprintf(stderr, "can't create zip_source from buffer: %s\n", zip_strerror(za)); + return -1; + } + + if (zip_add(za, argv[0], zs) == -1) { + zip_source_free(zs); + fprintf(stderr, "can't add file '%s': %s\n", argv[0], zip_strerror(za)); + return -1; + } + return 0; +} + +static int +add_dir(int argc, char *argv[]) { + /* add directory */ + if (zip_add_dir(za, argv[0]) < 0) { + fprintf(stderr, "can't add directory '%s': %s\n", argv[0], zip_strerror(za)); + return -1; + } + return 0; +} + +static int +add_file(int argc, char *argv[]) { + struct zip_source *zs; + zip_uint64_t start = strtoull(argv[2], NULL, 10); + zip_int64_t len = strtoll(argv[3], NULL, 10); + + if (strcmp(argv[1], "/dev/stdin") == 0) { + if ((zs=zip_source_filep(za, stdin, start, len)) == NULL) { + fprintf(stderr, "can't create zip_source from stdin: %s\n", zip_strerror(za)); + return -1; + } + } else { + if ((zs=zip_source_file(za, argv[1], start, len)) == NULL) { + fprintf(stderr, "can't create zip_source from file: %s\n", zip_strerror(za)); + return -1; + } + } + + if (zip_add(za, argv[0], zs) == -1) { + zip_source_free(zs); + fprintf(stderr, "can't add file '%s': %s\n", argv[0], zip_strerror(za)); + return -1; + } + return 0; +} + +static int +add_from_zip(int argc, char *argv[]) { + zip_uint64_t idx; + int err; + char buf[100]; + struct zip_source *zs; + /* add from another zip file */ + idx = strtoull(argv[2], NULL, 10); + zip_uint64_t start = strtoull(argv[3], NULL, 10); + zip_int64_t len = strtoll(argv[4], NULL, 10); + if ((z_in=zip_open(argv[1], ZIP_CHECKCONS, &err)) == NULL) { + zip_error_to_str(buf, sizeof(buf), err, errno); + fprintf(stderr, "can't open source zip archive '%s': %s\n", argv[1], buf); + return -1; + } + if ((zs=zip_source_zip(za, z_in, idx, 0, start, len)) == NULL) { + fprintf(stderr, "error creating file source from '%s' index '%d': %s\n", argv[1], idx, zip_strerror(za)); + zip_close(z_in); + return -1; + } + if (zip_add(za, argv[0], zs) == -1) { + fprintf(stderr, "can't add file '%s': %s\n", argv[0], zip_strerror(za)); + zip_source_free(zs); + zip_close(z_in); + return -1; + } + return 0; +} + +static int +count_extra(int argc, char *argv[]) { + zip_int16_t count; + zip_uint64_t idx; + zip_flags_t ceflags = 0; + idx = strtoull(argv[0], NULL, 10); + ceflags = get_flags(argv[1]); + if ((count=zip_file_extra_fields_count(za, idx, ceflags)) < 0) { + fprintf(stderr, "can't get extra field count for file at index '%d': %s\n", idx, zip_strerror(za)); + return -1; + } else { + printf("Extra field count: %d\n", count); + } + return 0; +} + +static int +count_extra_by_id(int argc, char *argv[]) { + zip_int16_t count, eid; + zip_flags_t ceflags = 0; + zip_uint64_t idx; + idx = strtoull(argv[0], NULL, 10); + eid = strtoull(argv[1], NULL, 10); + ceflags = get_flags(argv[2]); + if ((count=zip_file_extra_fields_count_by_id(za, idx, eid, ceflags)) < 0) { + fprintf(stderr, "can't get extra field count for file at index '%d' and for id `%d': %s\n", idx, eid, zip_strerror(za)); + return -1; + } else { + printf("Extra field count: %d\n", count); + } + return 0; +} + +static int +delete(int argc, char *argv[]) { + zip_uint64_t idx; + idx = strtoull(argv[0], NULL, 10); + if (zip_delete(za, idx) < 0) { + fprintf(stderr, "can't delete file at index '%d': %s\n", idx, zip_strerror(za)); + return -1; + } + return 0; +} + +static int +delete_extra(int argc, char *argv[]) { + zip_flags_t geflags; + zip_uint16_t eid; + zip_uint64_t idx; + idx = strtoull(argv[0], NULL, 10); + eid = strtoull(argv[1], NULL, 10); + geflags = get_flags(argv[2]); + if ((zip_file_extra_field_delete(za, idx, eid, geflags)) < 0) { + fprintf(stderr, "can't delete extra field data for file at index '%d', extra field id `%d': %s\n", idx, eid, zip_strerror(za)); + return -1; + } + return 0; +} + +static int +delete_extra_by_id(int argc, char *argv[]) { + zip_flags_t geflags; + zip_uint16_t eid, eidx; + zip_uint64_t idx; + idx = strtoull(argv[0], NULL, 10); + eid = strtoull(argv[1], NULL, 10); + eidx = strtoull(argv[2], NULL, 10); + geflags = get_flags(argv[3]); + if ((zip_file_extra_field_delete_by_id(za, idx, eid, eidx, geflags)) < 0) { + fprintf(stderr, "can't delete extra field data for file at index '%d', extra field id `%d', extra field idx `%d': %s\n", idx, eid, eidx, zip_strerror(za)); + return -1; + } + return 0; +} + +static int +get_archive_comment(int argc, char *argv[]) { + const char *comment; + int len; + /* get archive comment */ + if ((comment=zip_get_archive_comment(za, &len, 0)) == NULL) + printf("No archive comment\n"); + else + printf("Archive comment: %.*s\n", len, comment); + return 0; +} + +static int +get_extra(int argc, char *argv[]) { + zip_flags_t geflags; + zip_uint16_t id, eidx, eflen; + const zip_uint8_t *efdata; + zip_uint64_t idx; + /* get extra field data */ + idx = strtoull(argv[0], NULL, 10); + eidx = strtoull(argv[1], NULL, 10); + geflags = get_flags(argv[2]); + if ((efdata=zip_file_extra_field_get(za, idx, eidx, &id, &eflen, geflags)) == NULL) { + fprintf(stderr, "can't get extra field data for file at index %d, extra field %d, flags %u: %s\n", idx, eidx, geflags, zip_strerror(za)); + return -1; + } + printf("Extra field 0x%04x: len %d", id, eflen); + if (eflen > 0) { + printf(", data "); + hexdump(efdata, eflen); + } + printf("\n"); + return 0; +} + +static int +get_extra_by_id(int argc, char *argv[]) { + zip_flags_t geflags; + zip_uint16_t eid, eidx, eflen; + const zip_uint8_t *efdata; + zip_uint64_t idx; + idx = strtoull(argv[0], NULL, 10); + eid = strtoull(argv[1], NULL, 10); + eidx = strtoull(argv[2], NULL, 10); + geflags = get_flags(argv[3]); + if ((efdata=zip_file_extra_field_get_by_id(za, idx, eid, eidx, &eflen, geflags)) == NULL) { + fprintf(stderr, "can't get extra field data for file at index %d, extra field id %d, ef index %d, flags %u: %s\n", idx, eid, eidx, geflags, zip_strerror(za)); + return -1; + } + printf("Extra field 0x%04x: len %d", eid, eflen); + if (eflen > 0) { + printf(", data "); + hexdump(efdata, eflen); + } + printf("\n"); + return 0; +} + +static int +get_file_comment(int argc, char *argv[]) { + const char *comment; + int len; + zip_uint64_t idx; + /* get file comment */ + idx = strtoull(argv[0], NULL, 10); + if ((comment=zip_get_file_comment(za, idx, &len, 0)) == NULL) { + fprintf(stderr, "can't get comment for '%s': %s\n", zip_get_name(za, idx, 0), zip_strerror(za)); + return -1; + } else if (len == 0) + printf("No comment for '%s'\n", zip_get_name(za, idx, 0)); + else + printf("File comment for '%s': %.*s\n", zip_get_name(za, idx, 0), len, comment); + return 0; +} + +static int +zrename(int argc, char *argv[]) { + zip_uint64_t idx; + idx = strtoull(argv[0], NULL, 10); + if (zip_rename(za, idx, argv[1]) < 0) { + fprintf(stderr, "can't rename file at index '%d' to `%s': %s\n", idx, argv[1], zip_strerror(za)); + return -1; + } + return 0; +} + +static int +replace_file_contents(int argc, char *argv[]) { + /* replace file contents with data from command line */ + const char *content; + struct zip_source *s; + zip_uint64_t idx; + idx = strtoull(argv[0], NULL, 10); + content = argv[1]; + if ((s=zip_source_buffer(za, content, strlen(content), 0)) == NULL || + zip_file_replace(za, idx, s, 0) < 0) { + zip_source_free(s); + fprintf(stderr, "error replacing file data: %s\n", zip_strerror(za)); + return -1; + } + return 0; +} + +static int +set_extra(int argc, char *argv[]) { + zip_flags_t geflags; + zip_uint16_t eid, eidx; + const zip_uint8_t *efdata; + zip_uint64_t idx; + idx = strtoull(argv[0], NULL, 10); + eid = strtoull(argv[1], NULL, 10); + eidx = strtoull(argv[2], NULL, 10); + geflags = get_flags(argv[3]); + efdata = (zip_uint8_t *)argv[4]; + if ((zip_file_extra_field_set(za, idx, eid, eidx, efdata, (zip_uint16_t)strlen((const char *)efdata), geflags)) < 0) { + fprintf(stderr, "can't set extra field data for file at index '%d', extra field id `%d', index `%d': %s\n", idx, eid, eidx, zip_strerror(za)); + return -1; + } + return 0; +} + +static int +set_file_comment(int argc, char *argv[]) { + zip_uint64_t idx; + idx = strtoull(argv[0], NULL, 10); + if (zip_file_set_comment(za, idx, argv[1], (zip_uint16_t)strlen(argv[1]), 0) < 0) { + fprintf(stderr, "can't set file comment at index '%d' to `%s': %s\n", idx, argv[1], zip_strerror(za)); + return -1; + } + return 0; +} + +static int +set_file_compression(int argc, char *argv[]) { + zip_int32_t method; + zip_uint32_t flags; + zip_uint64_t idx; + idx = strtoull(argv[0], NULL, 10); + method = get_compression_method(argv[1]); + flags = strtoull(argv[2], NULL, 10); + if (zip_set_file_compression(za, idx, method, flags) < 0) { + fprintf(stderr, "can't set file compression method at index '%d' to `%s', flags `%d': %s\n", idx, argv[1], flags, zip_strerror(za)); + return -1; + } + return 0; +} + +static int +set_file_mtime(int argc, char *argv[]) { + /* set file last modification time (mtime) */ + time_t mtime; + zip_uint64_t idx; + idx = strtoull(argv[0], NULL, 10); + mtime = strtoull(argv[1], NULL, 10); + if (zip_file_set_mtime(za, idx, mtime, 0) < 0) { + fprintf(stderr, "can't set file mtime at index '%d' to `%ld': %s\n", idx, mtime, zip_strerror(za)); + return -1; + } + return 0; +} + +static int +zstat(int argc, char *argv[]) { + int index; + char buf[100]; + struct zip_stat sb; + index = strtoull(argv[0], NULL, 10); + + if (zip_stat_index(za, index, stat_flags, &sb) < 0) { + fprintf(stderr, "zip_stat_index failed on '%" PRIu64 "' failed: %s\n", index, zip_strerror(za)); + return -1; + } + + if (sb.valid & ZIP_STAT_NAME) + printf("name: '%s'\n", sb.name); + if (sb.valid & ZIP_STAT_INDEX) + printf("index: '%"PRIu64"'\n", sb.index); + if (sb.valid & ZIP_STAT_SIZE) + printf("size: '%"PRIu64"'\n", sb.size); + if (sb.valid & ZIP_STAT_COMP_SIZE) + printf("compressed size: '%"PRIu64"'\n", sb.comp_size); + if (sb.valid & ZIP_STAT_MTIME) { + struct tm *tpm; + tpm = localtime(&sb.mtime); + strftime(buf, sizeof(buf), "%a %b %d %Y %H:%M:%S", tpm); + printf("mtime: '%s'\n", buf); + } + if (sb.valid & ZIP_STAT_CRC) + printf("crc: '%0x'\n", sb.crc); + if (sb.valid & ZIP_STAT_COMP_METHOD) + printf("compression method: '%d'\n", sb.comp_method); + if (sb.valid & ZIP_STAT_ENCRYPTION_METHOD) + printf("encryption method: '%d'\n", sb.encryption_method); + if (sb.valid & ZIP_STAT_FLAGS) + printf("flags: '%ld'\n", (long)sb.flags); + printf("\n"); + + return 0; +} + +static int +zin_close(int argc, char *argv[]) { + if (zip_close(z_in) < 0) { + fprintf(stderr, "can't close source archive: %s\n", zip_strerror(z_in)); + return -1; + } + return 0; +} static zip_flags_t get_flags(const char *arg) @@ -118,24 +471,201 @@ return; } +static struct zip * +read_to_memory(const char *archive, int flags, int *err, zip_source_t **srcp) +{ + struct stat st; + zip_source_t *src; + zip_t *za; + zip_error_t error; + + if (stat(archive, &st) < 0) { + if (errno == ENOENT) { + src = zip_source_buffer_create(NULL, 0, 0, &error); + } + else { + *err = ZIP_ER_OPEN; + return NULL; + } + } + else { + char *buf; + FILE *fp; + if ((buf=malloc(st.st_size)) == NULL) { + *err = ZIP_ER_MEMORY; + return NULL; + } + if ((fp=fopen(archive, "r")) == NULL) { + free(buf); + *err = ZIP_ER_READ; + return NULL; + } + if (fread(buf, st.st_size, 1, fp) < 1) { + free(buf); + *err = ZIP_ER_READ; + return NULL; + } + fclose(fp); + src = zip_source_buffer_create(buf, st.st_size, 1, &error); + if (src == NULL) { + free(buf); + } + } + if (src == NULL) { + *err = zip_error_code_zip(&error); + errno = zip_error_code_system(&error); + return NULL; + } + za = zip_open_from_source(src, flags, &error); + if (za == NULL) { + *err = zip_error_code_zip(&error); + errno = zip_error_code_system(&error); + zip_source_free(src); + return NULL; + } + zip_source_keep(src); + *srcp = src; + return za; +} + +static int +write_memory_src_to_file(const char *archive, zip_source_t *src) +{ + zip_stat_t zst; + char *buf; + FILE *fp; + + if (zip_source_stat(src, &zst) < 0) { + fprintf(stderr, "zip_source_stat on buffer failed: %s\n", zip_error_strerror(zip_source_error(src))); + return -1; + } + if (zip_source_open(src) < 0) { + if (zip_error_code_zip(zip_source_error(src)) == ZIP_ER_DELETED) { + if (remove(archive) < 0 && errno != ENOENT) { + fprintf(stderr, "remove failed: %s\n", strerror(errno)); + return -1; + } + return 0; + } + fprintf(stderr, "zip_source_open on buffer failed: %s\n", zip_error_strerror(zip_source_error(src))); + return -1; + } + if ((buf=malloc(zst.size)) == NULL) { + fprintf(stderr, "malloc failed: %s\n", strerror(errno)); + zip_source_close(src); + return -1; + } + if (zip_source_read(src, buf, zst.size) < zst.size) { + fprintf(stderr, "zip_source_read on buffer failed: %s\n", zip_error_strerror(zip_source_error(src))); + zip_source_close(src); + free(buf); + return -1; + } + zip_source_close(src); + if ((fp=fopen(archive, "wb")) == NULL) { + fprintf(stderr, "fopen failed: %s\n", strerror(errno)); + free(buf); + return -1; + } + if (fwrite(buf, zst.size, 1, fp) < 1) { + fprintf(stderr, "fwrite failed: %s\n", strerror(errno)); + free(buf); + return -1; + } + free(buf); + if (fclose(fp) != 0) { + fprintf(stderr, "fclose failed: %s\n", strerror(errno)); + return -1; + } + return 0; +} + +dispatch_table_t dispatch_table[] = { + { "add", 2, "name content", "add file called name using content", add }, + { "add_dir", 1, "name", "add directory", add_dir }, + { "add_file", 4, "name file_to_add offset len", "add file to archive, len bytes starting from offset", add_file }, + { "add_from_zip", 5, "name archivename index offset len", "add file from another archive, len bytes starting from offset", add_from_zip }, + { "count_extra", 2, "index flags", "show number of extra fields for archive entry", count_extra }, + { "count_extra_by_id", 3, "index extra_id flags", "show number of extra fields of type extra_id for archive entry", count_extra_by_id }, + { "delete", 1, "index", "remove entry", delete }, + { "delete_extra", 3, "index extra_idx flags", "remove extra field", delete_extra }, + { "delete_extra_by_id", 4, "index extra_id extra_index flags", "remove extra field of type extra_id", delete_extra_by_id }, + { "get_archive_comment", 0, "", "show archive comment", get_archive_comment }, + { "get_extra", 3, "index extra_index flags", "show extra field", get_extra }, + { "get_extra_by_id", 4, "index extra_id extra_index flags", "show extra field of type extra_id", get_extra_by_id }, + { "get_file_comment", 1, "index", "get file comment", get_file_comment }, + { "rename", 2, "index name", "rename entry", zrename }, + { "replace_file_contents", 2, "index data", "replace entry with data", replace_file_contents }, + { "set_extra", 5, "index extra_id extra_index flags value", "set extra field", set_extra }, + { "set_file_comment", 2, "index comment", "set file comment", set_file_comment }, + { "set_file_compression", 3, "index method flags", "set file compression method", set_file_compression }, + { "set_file_mtime", 2, "index timestamp", "set file modification time", set_file_mtime }, + { "stat", 1, "index", "print information about entry", zstat }, + { "zin_close", 0, "", "close input zip_source (for internal tests)", zin_close } +}; + +int +dispatch(int argc, char *argv[]) +{ + int i; + for (i=0; i<sizeof(dispatch_table)/sizeof(dispatch_table_t); i++) { + if (strcmp(dispatch_table[i].cmdline_name, argv[0]) == 0) { + argc--; + argv++; + /* 1 for the command, argument_count for the arguments */ + if (argc < dispatch_table[i].argument_count) { + fprintf(stderr, "not enough arguments for command '%s': %d available, %d needed\n", dispatch_table[i].cmdline_name, argc, dispatch_table[i].argument_count); + return -1; + } + if (dispatch_table[i].function(argc, argv) == 0) + return 1 + dispatch_table[i].argument_count; + return -1; + } + } + + fprintf(stderr, "unknown command '%s'\n", argv[0]); + return -1; +} + + +void +usage(const char *prg) +{ + int i; + fprintf(stderr, "usage: %s [-cemnt] archive command1 [args] [command2 [args] ...]\n\n" + "Supported options are:\n" + "\t-c\tcheck consistency\n" + "\t-e\terror if archive already exists (only useful with -n)\n" + "\t-g\tguess file name encoding (for stat)\n" + "\t-m\tread archive into memory, and modify there; write out at end\n" + "\t-n\tcreate archive if it doesn't exist (default)\n" + "\t-r\tprint raw file name encoding without translation (for stat)\n" + "\t-s\tfollow file name convention strictly (for stat)\n" + "\t-t\tdisregard current archive contents, if any\n", prg); + fprintf(stderr, "\nSupported commands and arguments are:\n"); + for (i=0; i<sizeof(dispatch_table)/sizeof(dispatch_table_t); i++) { + fprintf(stderr, "\t%s %s -- %s\n", dispatch_table[i].cmdline_name, dispatch_table[i].arg_names, dispatch_table[i].description); + } + fprintf(stderr, "\nThe index is zero-based.\n"); + exit(1); +} + int main(int argc, char *argv[]) { const char *archive; - struct zip *za, *z_in; - struct zip_source *zs; + struct zip_source *zs, *memory_src; char buf[100]; - int c, arg, err, flags, idx; + int c, arg, err, flags, idx, in_memory; flags = 0; + in_memory = 0; prg = argv[0]; - if (argc < 2) { - fprintf(stderr, usage, prg); - return 1; - } + if (argc < 2) + usage(prg); - while ((c=getopt(argc, argv, "cent")) != -1) { + while ((c=getopt(argc, argv, "cegmnrst")) != -1) { switch (c) { case 'c': flags |= ZIP_CHECKCONS; @@ -143,16 +673,27 @@ case 'e': flags |= ZIP_EXCL; break; + case 'g': + stat_flags = ZIP_FL_ENC_GUESS; + break; + case 'm': + in_memory = 1; + break; case 'n': flags |= ZIP_CREATE; break; + case 'r': + stat_flags = ZIP_FL_ENC_RAW; + break; + case 's': + stat_flags = ZIP_FL_ENC_STRICT; + break; case 't': flags |= ZIP_TRUNCATE; break; default: - fprintf(stderr, usage, argv[0]); - return 1; + usage(prg); } } @@ -163,7 +704,12 @@ if (flags == 0) flags = ZIP_CREATE; - if ((za=zip_open(archive, flags, &err)) == NULL) { + if (in_memory) { + za = read_to_memory(archive, flags, &err, &memory_src); + } else { + za = zip_open(archive, flags, &err); + } + if (za == NULL) { zip_error_to_str(buf, sizeof(buf), err, errno); fprintf(stderr, "can't open zip archive '%s': %s\n", archive, buf); return 1; @@ -171,280 +717,11 @@ err = 0; while (arg < argc) { - if (strcmp(argv[arg], "add") == 0 && arg+2 < argc) { - /* add */ - if ((zs=zip_source_buffer(za, argv[arg+2], strlen(argv[arg+2]), 0)) == NULL) { - fprintf(stderr, "can't create zip_source from buffer: %s\n", zip_strerror(za)); - err = 1; - break; - } - - if (zip_add(za, argv[arg+1], zs) == -1) { - zip_source_free(zs); - fprintf(stderr, "can't add file '%s': %s\n", argv[arg+1], zip_strerror(za)); - err = 1; - break; - } - arg += 3; - } else if (strcmp(argv[arg], "add_dir") == 0 && arg+1 < argc) { - /* add directory */ - if (zip_add_dir(za, argv[arg+1]) < 0) { - fprintf(stderr, "can't add directory '%s': %s\n", argv[arg+1], zip_strerror(za)); - err = 1; - break; - } - arg += 2; - } else if (strcmp(argv[arg], "add_file") == 0 && arg+4 < argc) { - /* add */ - if (strcmp(argv[arg+2], "/dev/stdin") == 0) { - if ((zs=zip_source_filep(za, stdin, atoi(argv[arg+3]), atoi(argv[arg+4]))) == NULL) { - fprintf(stderr, "can't create zip_source from stdin: %s\n", zip_strerror(za)); - err = 1; - break; - } - } else { - if ((zs=zip_source_file(za, argv[arg+2], atoi(argv[arg+3]), atoi(argv[arg+4]))) == NULL) { - fprintf(stderr, "can't create zip_source from file: %s\n", zip_strerror(za)); - err = 1; - break; - } - } - - if (zip_add(za, argv[arg+1], zs) == -1) { - zip_source_free(zs); - fprintf(stderr, "can't add file '%s': %s\n", argv[arg+1], zip_strerror(za)); - err = 1; - break; - } - arg += 5; - } else if (strcmp(argv[arg], "add_from_zip") == 0 && arg+5 < argc) { - /* add from another zip file */ - idx = atoi(argv[arg+3]); - if ((z_in=zip_open(argv[arg+2], ZIP_CHECKCONS, &err)) == NULL) { - zip_error_to_str(buf, sizeof(buf), err, errno); - fprintf(stderr, "can't open source zip archive '%s': %s\n", argv[arg+2], buf); - err = 1; - break; - } - if ((zs=zip_source_zip(za, z_in, idx, 0, atoi(argv[arg+4]), atoi(argv[arg+5]))) == NULL) { - fprintf(stderr, "error creating file source from '%s' index '%d': %s\n", argv[arg+2], idx, zip_strerror(za)); - zip_close(z_in); - err = 1; - break; - } - if (zip_add(za, argv[arg+1], zs) == -1) { - fprintf(stderr, "can't add file '%s': %s\n", argv[arg+1], zip_strerror(za)); - zip_source_free(zs); - zip_close(z_in); - err = 1; - break; - } - arg += 6; - } else if (strcmp(argv[arg], "count_extra") == 0 && arg+2 < argc) { - zip_int16_t count; - zip_flags_t ceflags = 0; - idx = atoi(argv[arg+1]); - ceflags = get_flags(argv[arg+2]); - if ((count=zip_file_extra_fields_count(za, idx, ceflags)) < 0) { - fprintf(stderr, "can't get extra field count for file at index '%d': %s\n", idx, zip_strerror(za)); - err = 1; - break; - } else { - printf("Extra field count: %d\n", count); - } - arg += 3; - } else if (strcmp(argv[arg], "count_extra_by_id") == 0 && arg+3 < argc) { - zip_int16_t count, eid; - zip_flags_t ceflags = 0; - idx = atoi(argv[arg+1]); - eid = atoi(argv[arg+2]); - ceflags = get_flags(argv[arg+3]); - if ((count=zip_file_extra_fields_count_by_id(za, idx, eid, ceflags)) < 0) { - fprintf(stderr, "can't get extra field count for file at index '%d' and for id `%d': %s\n", idx, eid, zip_strerror(za)); - err = 1; - break; - } else { - printf("Extra field count: %d\n", count); - } - arg += 4; - } else if (strcmp(argv[arg], "delete") == 0 && arg+1 < argc) { - /* delete */ - idx = atoi(argv[arg+1]); - if (zip_delete(za, idx) < 0) { - fprintf(stderr, "can't delete file at index '%d': %s\n", idx, zip_strerror(za)); - err = 1; - break; - } - arg += 2; - } else if (strcmp(argv[arg], "delete_extra") == 0 && arg+1 < argc) { - zip_flags_t geflags; - zip_uint16_t eid; - idx = atoi(argv[arg+1]); - eid = atoi(argv[arg+2]); - geflags = get_flags(argv[arg+3]); - if ((zip_file_extra_field_delete(za, idx, eid, geflags)) < 0) { - fprintf(stderr, "can't delete extra field data for file at index '%d', extra field id `%d': %s\n", idx, eid, zip_strerror(za)); - err = 1; - break; - } - arg += 4; - } else if (strcmp(argv[arg], "delete_extra_by_id") == 0 && arg+1 < argc) { - zip_flags_t geflags; - zip_uint16_t eid, eidx; - idx = atoi(argv[arg+1]); - eid = atoi(argv[arg+2]); - eidx = atoi(argv[arg+3]); - geflags = get_flags(argv[arg+4]); - if ((zip_file_extra_field_delete_by_id(za, idx, eid, eidx, geflags)) < 0) { - fprintf(stderr, "can't delete extra field data for file at index '%d', extra field id `%d', extra field idx `%d': %s\n", idx, eid, eidx, zip_strerror(za)); - err = 1; - break; - } - arg += 5; - } else if (strcmp(argv[arg], "get_archive_comment") == 0) { - const char *comment; - int len; - /* get archive comment */ - if ((comment=zip_get_archive_comment(za, &len, 0)) == NULL) - printf("No archive comment\n"); - else - printf("Archive comment: %.*s\n", len, comment); - arg += 1; - } else if (strcmp(argv[arg], "get_extra") == 0 && arg+3 < argc) { - zip_flags_t geflags; - zip_uint16_t id, eidx, eflen; - const zip_uint8_t *efdata; - /* get extra field data */ - idx = atoi(argv[arg+1]); - eidx = atoi(argv[arg+2]); - geflags = get_flags(argv[arg+3]); - if ((efdata=zip_file_extra_field_get(za, idx, eidx, &id, &eflen, geflags)) == NULL) { - fprintf(stderr, "can't get extra field data for file at index %d, extra field %d, flags %u: %s\n", idx, eidx, geflags, zip_strerror(za)); - err = 1; - } else { - printf("Extra field 0x%04x: len %d", id, eflen); - if (eflen > 0) { - printf(", data "); - hexdump(efdata, eflen); - } - printf("\n"); - } - arg += 4; - } else if (strcmp(argv[arg], "get_extra_by_id") == 0 && arg+4 < argc) { - zip_flags_t geflags; - zip_uint16_t eid, eidx, eflen; - const zip_uint8_t *efdata; - idx = atoi(argv[arg+1]); - eid = atoi(argv[arg+2]); - eidx = atoi(argv[arg+3]); - geflags = get_flags(argv[arg+4]); - if ((efdata=zip_file_extra_field_get_by_id(za, idx, eid, eidx, &eflen, geflags)) == NULL) { - fprintf(stderr, "can't get extra field data for file at index %d, extra field id %d, ef index %d, flags %u: %s\n", idx, eid, eidx, geflags, zip_strerror(za)); - err = 1; - } else { - printf("Extra field 0x%04x: len %d", eid, eflen); - if (eflen > 0) { - printf(", data "); - hexdump(efdata, eflen); - } - printf("\n"); - } - arg += 5; - } else if (strcmp(argv[arg], "get_file_comment") == 0 && arg+1 < argc) { - const char *comment; - int len; - /* get file comment */ - idx = atoi(argv[arg+1]); - if ((comment=zip_get_file_comment(za, idx, &len, 0)) == NULL) { - fprintf(stderr, "can't get comment for '%s': %s\n", zip_get_name(za, idx, 0), zip_strerror(za)); - err = 1; - break; - } else if (len == 0) - printf("No comment for '%s'\n", zip_get_name(za, idx, 0)); - else - printf("File comment for '%s': %.*s\n", zip_get_name(za, idx, 0), len, comment); - arg += 2; - } else if (strcmp(argv[arg], "rename") == 0 && arg+2 < argc) { - /* rename */ - idx = atoi(argv[arg+1]); - if (zip_rename(za, idx, argv[arg+2]) < 0) { - fprintf(stderr, "can't rename file at index '%d' to `%s': %s\n", idx, argv[arg+2], zip_strerror(za)); - err = 1; - break; - } - arg += 3; - } else if (strcmp(argv[arg], "replace_file_contents") == 0 && arg+2 < argc) { - /* replace file contents with data from command line */ - const char *content; - struct zip_source *s; - idx = atoi(argv[arg+1]); - content = argv[arg+2]; - if ((s=zip_source_buffer(za, content, strlen(content), 0)) == NULL || - zip_file_replace(za, idx, s, 0) < 0) { - zip_source_free(s); - fprintf(stderr, "error replacing file data: %s\n", zip_strerror(za)); - err = 1; - break; - } - arg += 3; - } else if (strcmp(argv[arg], "set_extra") == 0 && arg+5 < argc) { - zip_flags_t geflags; - zip_uint16_t eid, eidx; - const zip_uint8_t *efdata; - idx = atoi(argv[arg+1]); - eid = atoi(argv[arg+2]); - eidx = atoi(argv[arg+3]); - geflags = get_flags(argv[arg+4]); - efdata = (zip_uint8_t *)argv[arg+5]; - if ((zip_file_extra_field_set(za, idx, eid, eidx, efdata, (zip_uint16_t)strlen((const char *)efdata), geflags)) < 0) { - fprintf(stderr, "can't set extra field data for file at index '%d', extra field id `%d', index `%d': %s\n", idx, eid, eidx, zip_strerror(za)); - err = 1; - break; - } - arg += 6; - } else if (strcmp(argv[arg], "set_file_comment") == 0 && arg+2 < argc) { - /* set file comment */ - idx = atoi(argv[arg+1]); - if (zip_file_set_comment(za, idx, argv[arg+2], (zip_uint16_t)strlen(argv[arg+2]), 0) < 0) { - fprintf(stderr, "can't set file comment at index '%d' to `%s': %s\n", idx, argv[arg+2], zip_strerror(za)); - err = 1; - break; - } - arg += 3; - } else if (strcmp(argv[arg], "set_file_compression") == 0 && arg+3 < argc) { - /* set file compression */ - zip_int32_t method; - zip_uint32_t flags; - idx = atoi(argv[arg+1]); - method = get_compression_method(argv[arg+2]); - flags = atoi(argv[arg+3]); - if (zip_set_file_compression(za, idx, method, flags) < 0) { - fprintf(stderr, "can't set file compression method at index '%d' to `%s', flags `%d': %s\n", idx, argv[arg+2], flags, zip_strerror(za)); - err = 1; - break; - } - arg += 4; - } else if (strcmp(argv[arg], "set_mtime") == 0 && arg+2 < argc) { - /* set file last modification time (mtime) */ - time_t mtime; - idx = atoi(argv[arg+1]); - /* TODO: add configure check for strtoll or similar, and use it */ - mtime = atoi(argv[arg+2]); - if (zip_file_set_mtime(za, idx, mtime, 0) < 0) { - fprintf(stderr, "can't set file mtime at index '%d' to `%ld': %s\n", idx, mtime, zip_strerror(za)); - err = 1; - break; - } - arg += 3; - } else if (strcmp(argv[arg], "zin_close") == 0) { - if (zip_close(z_in) < 0) { - fprintf(stderr, "can't close source archive: %s\n", zip_strerror(z_in)); - err = 1; - break; - } - arg += 1; + int ret; + ret = dispatch(argc-arg, argv+arg); + if (ret > 0) { + arg += ret; } else { - fprintf(stderr, "unrecognized command '%s', or not enough arguments\n", argv[arg]); err = 1; break; } @@ -454,6 +731,12 @@ fprintf(stderr, "can't close zip archive '%s': %s\n", archive, zip_strerror(za)); return 1; } + if (in_memory) { + if (write_memory_src_to_file(archive, memory_src) < 0) { + err = 1; + } + zip_source_free(memory_src); + } return err; }
diff --git a/regress/name_locate.c b/regress/name_locate.c index 7dfc13f..265eb2f 100644 --- a/regress/name_locate.c +++ b/regress/name_locate.c
@@ -1,6 +1,6 @@ /* name_locate.c -- test cases for finding files in zip archives - Copyright (C) 2005-2006 Dieter Baron and Thomas Klausner + Copyright (C) 2005-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -40,8 +40,8 @@ #include "compat.h" -static int find_fail(struct zip *, const char *, int, int); -static int find_success(struct zip *, const char *, int); +static int find_fail(struct zip *z, const char *name, zip_flags_t flags, int zerr); +static int find_success(struct zip *z, const char *name, zip_flags_t flags); const char *prg; @@ -115,7 +115,7 @@ static int -find_fail(struct zip *z, const char *name, int flags, int zerr) +find_fail(struct zip *z, const char *name, zip_flags_t flags, int zerr) { int ze, se; char expected[80]; @@ -139,7 +139,7 @@ static int -find_success(struct zip *z, const char *name, int flags) +find_success(struct zip *z, const char *name, zip_flags_t flags) { if (zip_name_locate(z, name, flags) < 0) {
diff --git a/regress/runtest.in b/regress/runtest.in index bab2623..cd1b2fc 100755 --- a/regress/runtest.in +++ b/regress/runtest.in
@@ -38,6 +38,6 @@ use NiHTest; -my $test = NiHTest::new({ default_program => 'modify', srcdir => '@srcdir@' }); +my $test = NiHTest::new({ default_program => 'modify', srcdir => '@srcdir@', zipcmp => '../../src/zipcmp' }); $test->run(@ARGV);
diff --git a/regress/set_comment_all.c b/regress/set_comment_all.c index 1071f13..114cf5d 100644 --- a/regress/set_comment_all.c +++ b/regress/set_comment_all.c
@@ -1,6 +1,6 @@ /* set_comment_all.c -- set global and file comments - Copyright (C) 2006-2013 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -37,7 +37,8 @@ #include <stdlib.h> #include <string.h> -#include "zipint.h" +#include "zip.h" +#include "compat.h" const char *prg; const char *new_archive_comment="This is the new,\r\n" @@ -51,7 +52,7 @@ struct zip *za; char buf[100]; int err; - int i; + zip_int64_t i; prg = argv[0]; @@ -64,24 +65,20 @@ if ((za=zip_open(archive, 0, &err)) == NULL) { zip_error_to_str(buf, sizeof(buf), err, errno); - fprintf(stderr, "%s: can't open zip archive '%s': %s\n", prg, - archive, buf); + fprintf(stderr, "%s: can't open zip archive '%s': %s\n", prg, archive, buf); return 1; } - if (zip_set_archive_comment(za, new_archive_comment, - (zip_uint16_t)strlen(new_archive_comment)) < 0) { + if (zip_set_archive_comment(za, new_archive_comment, (zip_uint16_t)strlen(new_archive_comment)) < 0) { zip_error_to_str(buf, sizeof(buf), err, errno); - fprintf(stderr, "%s: zip_set_archive_comment failed: %s\n", - prg, buf); + fprintf(stderr, "%s: zip_set_archive_comment failed: %s\n", prg, buf); } for (i=0; i<zip_get_num_entries(za, 0); i++) { - snprintf(buf, sizeof(buf), "File comment no %d", i); - if (zip_file_set_comment(za, i, buf, (zip_uint16_t)strlen(buf), 0) < 0) { + snprintf(buf, sizeof(buf), "File comment no %" PRId64, i); + if (zip_file_set_comment(za, (zip_uint64_t)i, buf, (zip_uint16_t)strlen(buf), 0) < 0) { zip_error_to_str(buf, sizeof(buf), err, errno); - fprintf(stderr, "%s: zip_set_file_comment on file %d failed: %s\n", - prg, i, buf); + fprintf(stderr, "%s: zip_set_file_comment on file %" PRId64 " failed: %s\n", prg, i, buf); } }
diff --git a/regress/set_comment_localonly.c b/regress/set_comment_localonly.c index 12f3838..2deadab 100644 --- a/regress/set_comment_localonly.c +++ b/regress/set_comment_localonly.c
@@ -1,6 +1,6 @@ /* set_comment_localonly.c -- set file comments - Copyright (C) 2006-2013 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -37,7 +37,8 @@ #include <stdlib.h> #include <string.h> -#include "zipint.h" +#include "zip.h" +#include "compat.h" const char *prg; @@ -48,7 +49,7 @@ struct zip *za; char buf[100]; int err; - int i; + zip_int64_t i; prg = argv[0]; @@ -61,24 +62,21 @@ if ((za=zip_open(archive, 0, &err)) == NULL) { zip_error_to_str(buf, sizeof(buf), err, errno); - fprintf(stderr, "%s: can't open zip archive '%s': %s\n", prg, - archive, buf); + fprintf(stderr, "%s: can't open zip archive '%s': %s\n", prg, archive, buf); return 1; } for (i=0; i<zip_get_num_entries(za, 0); i++) { - snprintf(buf, sizeof(buf), "File comment no %d", i); - if (zip_file_set_comment(za, i, buf, (zip_uint16_t)strlen(buf), 0) < 0) { + snprintf(buf, sizeof(buf), "File comment no %" PRId64, i); + if (zip_file_set_comment(za, (zip_uint64_t)i, buf, (zip_uint16_t)strlen(buf), 0) < 0) { zip_error_to_str(buf, sizeof(buf), err, errno); - fprintf(stderr, "%s: zip_file_set_comment on file %d failed: %s\n", - prg, i, buf); + fprintf(stderr, "%s: zip_file_set_comment on file %" PRId64 " failed: %s\n", prg, i, buf); } } /* remove comment for third file */ if (zip_file_set_comment(za, 2, NULL, 0, 0) < 0) { zip_error_to_str(buf, sizeof(buf), err, errno); - fprintf(stderr, "%s: zip_file_set_comment on file %d failed: %s\n", - prg, i, buf); + fprintf(stderr, "%s: zip_file_set_comment on file 2 failed: %s\n", prg, buf); } if (zip_close(za) == -1) {
diff --git a/regress/set_comment_removeglobal.c b/regress/set_comment_removeglobal.c index 5a57dde..bfaee6e 100644 --- a/regress/set_comment_removeglobal.c +++ b/regress/set_comment_removeglobal.c
@@ -1,6 +1,6 @@ /* set_comment_removeglobal.c -- remove archive comment - Copyright (C) 2006-2012 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/regress/set_comment_revert.c b/regress/set_comment_revert.c index 724183b..eea1b7f 100644 --- a/regress/set_comment_revert.c +++ b/regress/set_comment_revert.c
@@ -1,6 +1,6 @@ /* set_comment_revert.c -- set global and file comments, but revert - Copyright (C) 2006-2013 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -37,7 +37,8 @@ #include <stdlib.h> #include <string.h> -#include "zipint.h" +#include "zip.h" +#include "compat.h" const char *prg; const char *new_archive_comment="This is the new,\r\n" @@ -51,7 +52,7 @@ struct zip *za; char buf[100]; int err; - int i; + zip_int64_t i; prg = argv[0]; @@ -64,30 +65,26 @@ if ((za=zip_open(archive, 0, &err)) == NULL) { zip_error_to_str(buf, sizeof(buf), err, errno); - fprintf(stderr, "%s: can't open zip archive '%s': %s\n", prg, - archive, buf); + fprintf(stderr, "%s: can't open zip archive '%s': %s\n", prg, archive, buf); return 1; } if (zip_set_archive_comment(za, new_archive_comment, (zip_uint16_t)strlen(new_archive_comment)) < 0) { zip_error_to_str(buf, sizeof(buf), err, errno); - fprintf(stderr, "%s: zip_set_archive_comment failed: %s\n", - prg, buf); + fprintf(stderr, "%s: zip_set_archive_comment failed: %s\n", prg, buf); } for (i=0; i<zip_get_num_entries(za, 0); i++) { - snprintf(buf, sizeof(buf), "File comment no %d", i); - if (zip_file_set_comment(za, i, buf, (zip_uint16_t)strlen(buf), 0) < 0) { + snprintf(buf, sizeof(buf), "File comment no %" PRId64, i); + if (zip_file_set_comment(za, (zip_uint64_t)i, buf, (zip_uint16_t)strlen(buf), 0) < 0) { zip_error_to_str(buf, sizeof(buf), err, errno); - fprintf(stderr, "%s: zip_set_file_comment on file %d failed: %s\n", - prg, i, buf); + fprintf(stderr, "%s: zip_set_file_comment on file %" PRId64 " failed: %s\n", prg, i, buf); } } if (zip_unchange_all(za) == -1) { - fprintf(stderr, "%s: can't revert changes to archive '%s'\n", - prg, archive); + fprintf(stderr, "%s: can't revert changes to archive '%s'\n", prg, archive); return 1; }
diff --git a/regress/set_compression.c b/regress/set_compression.c index 7e932b9..1e755f2 100644 --- a/regress/set_compression.c +++ b/regress/set_compression.c
@@ -1,6 +1,6 @@ /* set_compression.c -- set compression method for file in archive - Copyright (C) 2012 Dieter Baron and Thomas Klausner + Copyright (C) 2012-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -75,9 +75,8 @@ prg, name, zip_strerror(za)); return 1; } - if (zip_set_file_compression(za, idx, method, /* TODO: add flags * when supported */ 0) < 0) { - fprintf(stderr, "zip_set_file_compression with method '%d' on file %" PRId64 " failed: %s\n", - method, idx, zip_strerror(za)); + if (zip_set_file_compression(za, (zip_uint64_t)idx, method, /* TODO: add flags * when supported */ 0) < 0) { + fprintf(stderr, "zip_set_file_compression with method '%d' on file %" PRId64 " failed: %s\n", method, idx, zip_strerror(za)); return 1; } if (zip_close(za) == -1) {
diff --git a/regress/stat_index_cp437_guess.test b/regress/stat_index_cp437_guess.test index fa2ad90..34c4d0f 100644 --- a/regress/stat_index_cp437_guess.test +++ b/regress/stat_index_cp437_guess.test
@@ -1,6 +1,6 @@ # guess CP437 file names and autoconvert them -program stat_index -args test-cp437.zip 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 +program modify +args test-cp437.zip stat 0 stat 1 stat 2 stat 3 stat 4 stat 5 stat 6 stat 7 stat 8 stat 9 stat 10 stat 11 stat 12 stat 13 stat 14 stat 15 return 0 file test-cp437.zip test-cp437.zip test-cp437.zip stdout name: '☺☻♥♦♣♠•○◘◙♂♀♪♫☼►'
diff --git a/regress/stat_index_cp437_raw.test b/regress/stat_index_cp437_raw.test index e8c401f..8239b45 100644 --- a/regress/stat_index_cp437_raw.test +++ b/regress/stat_index_cp437_raw.test Binary files differ
diff --git a/regress/stat_index_cp437_strict.test b/regress/stat_index_cp437_strict.test index 5af49c4..ab5da3d 100644 --- a/regress/stat_index_cp437_strict.test +++ b/regress/stat_index_cp437_strict.test
@@ -1,6 +1,6 @@ # strictly follow ZIP spec and expect CP437 file names, and autoconvert them -program stat_index -args -s test-cp437.zip 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 +program modify +args -s test-cp437.zip stat 0 stat 1 stat 2 stat 3 stat 4 stat 5 stat 6 stat 7 stat 8 stat 9 stat 10 stat 11 stat 12 stat 13 stat 14 stat 15 return 0 file test-cp437.zip test-cp437.zip test-cp437.zip stdout name: '☺☻♥♦♣♠•○◘◙♂♀♪♫☼►'
diff --git a/regress/stat_index_fileorder.test b/regress/stat_index_fileorder.test index 4182c04..e9f065c 100644 --- a/regress/stat_index_fileorder.test +++ b/regress/stat_index_fileorder.test
@@ -1,6 +1,6 @@ # zip_open: entries ordered by central directory order -program stat_index -args fileorder.zzip 0 1 +program modify +args fileorder.zzip stat 0 stat 1 return 0 file fileorder.zzip fileorder.zip fileorder.zip stdout name: 'file1'
diff --git a/regress/stat_index_streamed.test b/regress/stat_index_streamed.test index 9c0c73b..bda69dc 100644 --- a/regress/stat_index_streamed.test +++ b/regress/stat_index_streamed.test
@@ -1,6 +1,6 @@ # stat file in streamed zip file -program stat_index -args streamed 0 +program modify +args streamed stat 0 file streamed streamed.zip streamed.zip return 0 stdout name: '-'
diff --git a/regress/stat_index_streamed_zip64.test b/regress/stat_index_streamed_zip64.test index d243987..c9dca38 100644 --- a/regress/stat_index_streamed_zip64.test +++ b/regress/stat_index_streamed_zip64.test
@@ -1,6 +1,6 @@ # stat file in streamed zip file -program stat_index -args streamed 0 +program modify +args streamed stat 0 file streamed streamed-zip64.zip streamed-zip64.zip return 0 stdout name: '-'
diff --git a/regress/stat_index_utf8_guess.test b/regress/stat_index_utf8_guess.test index 9964e6c..baabbce 100644 --- a/regress/stat_index_utf8_guess.test +++ b/regress/stat_index_utf8_guess.test
@@ -1,6 +1,6 @@ # guess UTF-8 file names -program stat_index -args test-utf8.zip 0 +program modify +args test-utf8.zip stat 0 return 0 file test-utf8.zip test-utf8.zip test-utf8.zip stdout name: 'ÄÖÜäöüßćçĉéèêëē'
diff --git a/regress/stat_index_utf8_raw.test b/regress/stat_index_utf8_raw.test index 2ded8fc..95fd85e 100644 --- a/regress/stat_index_utf8_raw.test +++ b/regress/stat_index_utf8_raw.test
@@ -1,6 +1,6 @@ # print UTF-8 file names -program stat_index -args -r test-utf8.zip 0 +program modify +args -r test-utf8.zip stat 0 return 0 file test-utf8.zip test-utf8.zip test-utf8.zip stdout name: 'ÄÖÜäöüßćçĉéèêëē'
diff --git a/regress/stat_index_utf8_strict.test b/regress/stat_index_utf8_strict.test index 87eb03e..f1c5558 100644 --- a/regress/stat_index_utf8_strict.test +++ b/regress/stat_index_utf8_strict.test
@@ -1,7 +1,7 @@ # follow strict rules and convert UTF-8 as if it was CP437, but not # if the files are marked as having UTF-8 names -program stat_index -args -s test-utf8.zip 0 +program modify +args -s test-utf8.zip stat 0 return 0 file test-utf8.zip test-utf8.zip test-utf8.zip stdout name: 'ÄÖÜäöüßćçĉéèêëē'
diff --git a/regress/stat_index_utf8_unmarked_strict.test b/regress/stat_index_utf8_unmarked_strict.test index be783d8..341e64e 100644 --- a/regress/stat_index_utf8_unmarked_strict.test +++ b/regress/stat_index_utf8_unmarked_strict.test
@@ -1,7 +1,7 @@ # follow strict rules and convert UTF-8 as if it was CP437, # if not marked otherwise (in this case: not marked) -program stat_index -args -s test-utf8-unmarked.zip 0 +program modify +args -s test-utf8-unmarked.zip stat 0 return 0 file test-utf8-unmarked.zip test-utf8-unmarked.zip test-utf8-unmarked.zip stdout name: 'ÄÖÜäöüßćçĉéèêëē'
diff --git a/regress/stat_index_zip64.test b/regress/stat_index_zip64.test index 68e07b1..14ff74b 100644 --- a/regress/stat_index_zip64.test +++ b/regress/stat_index_zip64.test
@@ -1,6 +1,6 @@ # stat file in zip64 zip file -program stat_index -args bigzero 0 +program modify +args bigzero stat 0 file bigzero bigzero.zip bigzero.zip return 0 stdout name: 'bigzero'
diff --git a/regress/tryopen.c b/regress/tryopen.c index ec10c37..7e0edae 100644 --- a/regress/tryopen.c +++ b/regress/tryopen.c
@@ -1,6 +1,6 @@ /* tryopen.c -- tool for tests that try opening zip archives - Copyright (C) 1999-2011 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at>
diff --git a/regress/utf-8-standardization.test b/regress/utf-8-standardization.test index 8a8a6a1..3f89dbb 100644 --- a/regress/utf-8-standardization.test +++ b/regress/utf-8-standardization.test
@@ -1,5 +1,5 @@ # replace file contents and make UTF-8 name program modify return 0 -args testfile replace_file_contents 0 "Some new content for the file." set_mtime 0 1406885162 +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
diff --git a/src/zipcmp.c b/src/zipcmp.c index 6b6278b..cba5f75 100644 --- a/src/zipcmp.c +++ b/src/zipcmp.c
@@ -65,7 +65,7 @@ zip_uint64_t nentry; struct entry *entry; const char *comment; - int comment_length; + size_t comment_length; }; struct ef { @@ -82,7 +82,7 @@ zip_uint32_t crc; zip_uint32_t comp_method; struct ef *extra_fields; - int n_extra_fields; + zip_uint16_t n_extra_fields; const char *comment; zip_uint32_t comment_length; }; @@ -109,7 +109,7 @@ Report bugs to <libzip@nih.at>.\n"; char version_string[] = PROGRAM " (" PACKAGE " " VERSION ")\n\ -Copyright (C) 2014 Dieter Baron and Thomas Klausner\n\ +Copyright (C) 2003-2014 Dieter Baron and Thomas Klausner\n\ " PACKAGE " comes with ABSOLUTELY NO WARRANTY, to the extent permitted by law.\n"; #define OPTIONS "hVipqtv" @@ -117,7 +117,7 @@ #define BOTH_ARE_ZIPS(a) (a[0].za && a[1].za) -static int comment_compare(const char *c1, int l1, const char *c2, int l2); +static int comment_compare(const char *c1, size_t l1, const char *c2, size_t l2); static int compare_list(char * const name[], const void *l[], const zip_uint64_t n[], int size, int (*cmp)(const void *, const void *), @@ -127,7 +127,7 @@ static int ef_compare(char *const name[2], const struct entry *e1, const struct entry *e2); static int ef_order(const void *a, const void *b); static void ef_print(const void *p); -static int ef_read(struct zip *za, int idx, struct entry *e); +static int ef_read(struct zip *za, zip_uint64_t idx, struct entry *e); static int entry_cmp(const void *p1, const void *p2); static int entry_paranoia_checks(char *const name[2], const void *p1, const void *p2); static void entry_print(const void *p); @@ -136,7 +136,7 @@ static int list_directory(const char *name, struct archive *a); #endif static int list_zip(const char *name, struct archive *a); -static int test_file(struct zip *za, int idx, zip_int64_t size, unsigned int crc); +static int test_file(struct zip *za, zip_uint64_t idx, zip_uint64_t size, zip_uint32_t crc); int ignore_case, test_files, paranoid, verbose; int header_done; @@ -241,8 +241,8 @@ if (paranoid) { if (comment_compare(a[0].comment, a[0].comment_length, a[1].comment, a[1].comment_length) != 0) { if (verbose) { - printf("--- archive comment (%d)\n", a[0].comment_length); - printf("+++ archive comment (%d)\n", a[1].comment_length); + printf("--- archive comment (%zd)\n", a[0].comment_length); + printf("+++ archive comment (%zd)\n", a[1].comment_length); } res = 1; } @@ -264,12 +264,12 @@ } } - +#ifdef HAVE_FTS_H static zip_int64_t compute_crc(const char *fname) { FILE *f; - zip_uint32_t crc = crc32(0L, Z_NULL, 0); + uLong crc = crc32(0L, Z_NULL, 0); size_t n; Bytef buffer[8192]; @@ -280,7 +280,7 @@ } while ((n=fread(buffer, 1, sizeof(buffer), f)) > 0) { - crc = crc32(crc, buffer, n); + crc = crc32(crc, buffer, (unsigned int)n); } if (ferror(f)) { @@ -291,8 +291,9 @@ fclose(f); - return crc; + return (zip_int64_t)crc; } +#endif static int @@ -396,7 +397,7 @@ } a->za = za; - a->nentry = zip_get_num_entries(za, 0); + a->nentry = (zip_uint64_t)zip_get_num_entries(za, 0); if (a->nentry == 0) a->entry = NULL; @@ -424,8 +425,11 @@ } } - if (paranoid) - a->comment = zip_get_archive_comment(za, &a->comment_length, 0); + if (paranoid) { + int length; + a->comment = zip_get_archive_comment(za, &length, 0); + a->comment_length = (size_t)length; + } else { a->comment = NULL; a->comment_length = 0; @@ -437,7 +441,7 @@ static int -comment_compare(const char *c1, int l1, const char *c2, int l2) { +comment_compare(const char *c1, size_t l1, const char *c2, size_t l2) { if (l1 != l2) return 1; @@ -447,7 +451,7 @@ if (c1 == NULL || c2 == NULL) return c1 == c2; - return memcmp(c1, c2, l2); + return memcmp(c1, c2, (size_t)l2); } @@ -508,14 +512,17 @@ static int -ef_read(struct zip *za, int idx, struct entry *e) +ef_read(struct zip *za, zip_uint64_t idx, struct entry *e) { - int n_local, n_central; + zip_int16_t n_local, n_central; int i; - n_local = zip_file_extra_fields_count(za, idx, ZIP_FL_LOCAL); - n_central = zip_file_extra_fields_count(za, idx, ZIP_FL_CENTRAL); - e->n_extra_fields = n_local + n_central; + if ((n_local = zip_file_extra_fields_count(za, idx, ZIP_FL_LOCAL)) < 0 + || (n_central = zip_file_extra_fields_count(za, idx, ZIP_FL_CENTRAL)) < 0) { + return -1; + } + + e->n_extra_fields = (zip_uint16_t)n_local + (zip_uint16_t)n_central; if ((e->extra_fields=(struct ef *)malloc(sizeof(e->extra_fields[0])*e->n_extra_fields)) == NULL) return -1; @@ -604,7 +611,7 @@ return -1; } if (e1->crc != e2->crc) - return e1->crc - e2->crc; + return (int)e1->crc - (int)e2->crc; return 0; } @@ -668,16 +675,16 @@ static int -test_file(struct zip *za, int idx, zip_int64_t size, unsigned int crc) +test_file(struct zip *za, zip_uint64_t idx, zip_uint64_t size, zip_uint32_t crc) { struct zip_file *zf; char buf[8192]; - zip_int64_t n, nsize; + zip_uint64_t nsize; + zip_int64_t n; zip_uint32_t ncrc; if ((zf=zip_fopen_index(za, idx, 0)) == NULL) { - fprintf(stderr, "%s: cannot open file %d in archive: %s\n", - prg, idx, zip_strerror(za)); + fprintf(stderr, "%s: cannot open file %" PRIu64 " in archive: %s\n", prg, idx, zip_strerror(za)); return -1; } @@ -685,13 +692,12 @@ nsize = 0; while ((n=zip_fread(zf, buf, sizeof(buf))) > 0) { - nsize += n; + nsize += (zip_uint64_t)n; ncrc = (zip_uint32_t)crc32(ncrc, (const Bytef *)buf, (unsigned int)n); } if (n < 0) { - fprintf(stderr, "%s: error reading file %d in archive: %s\n", - prg, idx, zip_file_strerror(zf)); + fprintf(stderr, "%s: error reading file %" PRIu64 " in archive: %s\n", prg, idx, zip_file_strerror(zf)); zip_fclose(zf); return -1; } @@ -699,13 +705,11 @@ zip_fclose(zf); if (nsize != size) { - fprintf(stderr, "%s: file %d: unexpected length %" PRId64 " (should be %" PRId64 ")\n", - prg, idx, nsize, size); + fprintf(stderr, "%s: file %" PRIu64 ": unexpected length %" PRId64 " (should be %" PRId64 ")\n", prg, idx, nsize, size); return -2; } if (ncrc != crc) { - fprintf(stderr, "%s: file %d: unexpected length %x (should be %x)\n", - prg, idx, ncrc, crc); + fprintf(stderr, "%s: file %" PRIu64 ": unexpected length %x (should be %x)\n", prg, idx, ncrc, crc); return -2; }
diff --git a/src/zipmerge.c b/src/zipmerge.c index 58aadf5..dc8b007 100644 --- a/src/zipmerge.c +++ b/src/zipmerge.c
@@ -1,6 +1,6 @@ /* zipmerge.c -- merge zip archives - Copyright (C) 2004-2012 Dieter Baron and Thomas Klausner + Copyright (C) 2004-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -72,7 +72,7 @@ Report bugs to <libzip@nih.at>.\n"; char version_string[] = PROGRAM " (" PACKAGE " " VERSION ")\n\ -Copyright (C) 2012 Dieter Baron and Thomas Klausner\n\ +Copyright (C) 2004-2014 Dieter Baron and Thomas Klausner\n\ " PACKAGE " comes with ABSOLUTELY NO WARRANTY, to the extent permitted by law.\n"; #define OPTIONS "hVDiIsS"
diff --git a/src/ziptorrent.c b/src/ziptorrent.c index 1d0eabc..a51e891 100644 --- a/src/ziptorrent.c +++ b/src/ziptorrent.c
@@ -1,6 +1,6 @@ /* ziptorrent.c -- convert zip to torrentzip - Copyright (C) 2008-2012 Dieter Baron and Thomas Klausner + Copyright (C) 2008-2014 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> @@ -71,7 +71,7 @@ Report bugs to <libzip@nih.at>.\n"; char version_string[] = PROGRAM " (" PACKAGE " " VERSION ")\n\ -Copyright (C) 2010 Dieter Baron and Thomas Klausner\n\ +Copyright (C) 2008-2014 Dieter Baron and Thomas Klausner\n\ " PACKAGE " comes with ABSOLUTELY NO WARRANTY, to the extent permitted by law.\n"; #define OPTIONS "hnVv"
diff --git a/xcode/Info.plist b/xcode/Info.plist index a389fa9..650add7 100644 --- a/xcode/Info.plist +++ b/xcode/Info.plist
@@ -41,6 +41,6 @@ <key>CFPlugInUnloadFunction</key> <string></string> <key>NSHumanReadableCopyright</key> - <string>Copyright © 2013 Dieter Baron and Thomas Klausner</string> + <string>Copyright © 2014 Dieter Baron and Thomas Klausner</string> </dict> </plist>
diff --git a/xcode/libzip.xcodeproj/project.pbxproj b/xcode/libzip.xcodeproj/project.pbxproj index b9d2fb5..e94d829 100644 --- a/xcode/libzip.xcodeproj/project.pbxproj +++ b/xcode/libzip.xcodeproj/project.pbxproj
@@ -209,6 +209,30 @@ 4BACD64B15BC301300920691 /* libzip.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B01D68B15B2F3F1002D5007 /* libzip.framework */; }; 4BACD65215BC301B00920691 /* stat_index.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BACD58315BC2AEF00920691 /* stat_index.c */; }; 4BACD65315BC302500920691 /* tryopen.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BACD58415BC2AEF00920691 /* tryopen.c */; }; + 4BCF3021199A2F820064207B /* zip_io_util.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF3019199A2F820064207B /* zip_io_util.c */; }; + 4BCF3022199A2F820064207B /* zip_io_util.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF3019199A2F820064207B /* zip_io_util.c */; }; + 4BCF3023199A2F820064207B /* zip_source_begin_write.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF301A199A2F820064207B /* zip_source_begin_write.c */; }; + 4BCF3024199A2F820064207B /* zip_source_begin_write.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF301A199A2F820064207B /* zip_source_begin_write.c */; }; + 4BCF3025199A2F820064207B /* zip_source_commit_write.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF301B199A2F820064207B /* zip_source_commit_write.c */; }; + 4BCF3026199A2F820064207B /* zip_source_commit_write.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF301B199A2F820064207B /* zip_source_commit_write.c */; }; + 4BCF3027199A2F820064207B /* zip_source_rollback_write.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF301C199A2F820064207B /* zip_source_rollback_write.c */; }; + 4BCF3028199A2F820064207B /* zip_source_rollback_write.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF301C199A2F820064207B /* zip_source_rollback_write.c */; }; + 4BCF3029199A2F820064207B /* zip_source_seek.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF301D199A2F820064207B /* zip_source_seek.c */; }; + 4BCF302A199A2F820064207B /* zip_source_seek.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF301D199A2F820064207B /* zip_source_seek.c */; }; + 4BCF302B199A2F820064207B /* zip_source_supports.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF301E199A2F820064207B /* zip_source_supports.c */; }; + 4BCF302C199A2F820064207B /* zip_source_supports.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF301E199A2F820064207B /* zip_source_supports.c */; }; + 4BCF302D199A2F820064207B /* zip_source_tell.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF301F199A2F820064207B /* zip_source_tell.c */; }; + 4BCF302E199A2F820064207B /* zip_source_tell.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF301F199A2F820064207B /* zip_source_tell.c */; }; + 4BCF302F199A2F820064207B /* zip_source_write.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF3020199A2F820064207B /* zip_source_write.c */; }; + 4BCF3030199A2F820064207B /* zip_source_write.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF3020199A2F820064207B /* zip_source_write.c */; }; + 4BCF3032199ABD3A0064207B /* zip_source_remove.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF3031199ABD3A0064207B /* zip_source_remove.c */; }; + 4BCF3033199ABD3A0064207B /* zip_source_remove.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF3031199ABD3A0064207B /* zip_source_remove.c */; }; + 4BCF3036199ABDDA0064207B /* zip_source_seek_write.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF3034199ABDDA0064207B /* zip_source_seek_write.c */; }; + 4BCF3037199ABDDA0064207B /* zip_source_seek_write.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF3034199ABDDA0064207B /* zip_source_seek_write.c */; }; + 4BCF3038199ABDDA0064207B /* zip_source_tell_write.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF3035199ABDDA0064207B /* zip_source_tell_write.c */; }; + 4BCF3039199ABDDA0064207B /* zip_source_tell_write.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF3035199ABDDA0064207B /* zip_source_tell_write.c */; }; + 4BD5053319A0116D007DD28A /* zip_source_call.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BD5053219A0116D007DD28A /* zip_source_call.c */; }; + 4BD5053419A01BB0007DD28A /* zip_source_call.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BD5053219A0116D007DD28A /* zip_source_call.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 */; }; @@ -785,8 +809,20 @@ 4BACD63115BC2FAE00920691 /* set_compression */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = set_compression; sourceTree = BUILT_PRODUCTS_DIR; }; 4BACD64215BC2FEF00920691 /* stat_index */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = stat_index; sourceTree = BUILT_PRODUCTS_DIR; }; 4BACD65015BC301300920691 /* tryopen */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tryopen; sourceTree = BUILT_PRODUCTS_DIR; }; + 4BCF3019199A2F820064207B /* zip_io_util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip_io_util.c; sourceTree = "<group>"; }; + 4BCF301A199A2F820064207B /* zip_source_begin_write.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip_source_begin_write.c; sourceTree = "<group>"; }; + 4BCF301B199A2F820064207B /* zip_source_commit_write.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip_source_commit_write.c; sourceTree = "<group>"; }; + 4BCF301C199A2F820064207B /* zip_source_rollback_write.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip_source_rollback_write.c; sourceTree = "<group>"; }; + 4BCF301D199A2F820064207B /* zip_source_seek.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip_source_seek.c; sourceTree = "<group>"; }; + 4BCF301E199A2F820064207B /* zip_source_supports.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip_source_supports.c; sourceTree = "<group>"; }; + 4BCF301F199A2F820064207B /* zip_source_tell.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip_source_tell.c; sourceTree = "<group>"; }; + 4BCF3020199A2F820064207B /* zip_source_write.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip_source_write.c; sourceTree = "<group>"; }; + 4BCF3031199ABD3A0064207B /* zip_source_remove.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip_source_remove.c; sourceTree = "<group>"; }; + 4BCF3034199ABDDA0064207B /* zip_source_seek_write.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip_source_seek_write.c; sourceTree = "<group>"; }; + 4BCF3035199ABDDA0064207B /* zip_source_tell_write.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip_source_tell_write.c; sourceTree = "<group>"; }; 4BD155CE191CD28D0046F012 /* NiHTest.pm */ = {isa = PBXFileReference; indentWidth = 8; lastKnownFileType = text.script.perl; path = NiHTest.pm; sourceTree = "<group>"; }; 4BD155CF191CD28D0046F012 /* runtest.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = runtest.in; sourceTree = "<group>"; }; + 4BD5053219A0116D007DD28A /* zip_source_call.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip_source_call.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>"; }; @@ -1203,17 +1239,15 @@ 4BDC729E15B1B4E900236D3C /* zipconf.h */, 4BDC729815B1B2A600236D3C /* zip.h */, 4BDC729915B1B2A600236D3C /* zipint.h */, - 4BDC71F315B1B25E00236D3C /* zip_add.c */, 4BDC71F115B1B25E00236D3C /* zip_add_dir.c */, 4BDC71F215B1B25E00236D3C /* zip_add_entry.c */, + 4BDC71F315B1B25E00236D3C /* zip_add.c */, 4BDC71F415B1B25E00236D3C /* zip_close.c */, 4BDC71F515B1B25E00236D3C /* zip_delete.c */, 4BDC71F615B1B25E00236D3C /* zip_dir_add.c */, 4BDC71F715B1B25E00236D3C /* zip_dirent.c */, 4BDC71F815B1B25E00236D3C /* zip_discard.c */, 4BDC71F915B1B25E00236D3C /* zip_entry.c */, - 4B97204D188EBE85002FAFAD /* zip_file_get_external_attributes.c */, - 4B97204E188EBE85002FAFAD /* zip_file_set_external_attributes.c */, 4BDC71FA15B1B25E00236D3C /* zip_err_str.c */, 4BDC71FB15B1B25E00236D3C /* zip_error_clear.c */, 4BDC71FC15B1B25E00236D3C /* zip_error_get_sys_type.c */, @@ -1229,10 +1263,12 @@ 4BDC720615B1B25E00236D3C /* zip_file_error_clear.c */, 4BDC720715B1B25E00236D3C /* zip_file_error_get.c */, 4BDC720815B1B25E00236D3C /* zip_file_get_comment.c */, + 4B97204D188EBE85002FAFAD /* zip_file_get_external_attributes.c */, 4BDC720915B1B25E00236D3C /* zip_file_get_offset.c */, 4BDC720A15B1B25E00236D3C /* zip_file_rename.c */, 4BDC720B15B1B25E00236D3C /* zip_file_replace.c */, 4BDC720C15B1B25E00236D3C /* zip_file_set_comment.c */, + 4B97204E188EBE85002FAFAD /* zip_file_set_external_attributes.c */, 4B82CED319915F360097BC18 /* zip_file_set_mtime.c */, 4BDC720D15B1B25E00236D3C /* zip_file_strerror.c */, 4BDC720E15B1B25E00236D3C /* zip_filerange_crc.c */, @@ -1249,6 +1285,7 @@ 4BDC721915B1B25E00236D3C /* zip_get_name.c */, 4BDC721A15B1B25E00236D3C /* zip_get_num_entries.c */, 4BDC721B15B1B25E00236D3C /* zip_get_num_files.c */, + 4BCF3019199A2F820064207B /* zip_io_util.c */, 4BDC721C15B1B25E00236D3C /* zip_memdup.c */, 4BDC721D15B1B25E00236D3C /* zip_name_locate.c */, 4BDC721E15B1B25E00236D3C /* zip_new.c */, @@ -1261,8 +1298,11 @@ 4BDC722515B1B25E00236D3C /* zip_set_file_comment.c */, 4BDC722615B1B25E00236D3C /* zip_set_file_compression.c */, 4BDC722715B1B25E00236D3C /* zip_set_name.c */, + 4BCF301A199A2F820064207B /* zip_source_begin_write.c */, 4BDC722815B1B25E00236D3C /* zip_source_buffer.c */, + 4BD5053219A0116D007DD28A /* zip_source_call.c */, 4BDC722915B1B25E00236D3C /* zip_source_close.c */, + 4BCF301B199A2F820064207B /* zip_source_commit_write.c */, 4BDC722A15B1B25E00236D3C /* zip_source_crc.c */, 4BDC722B15B1B25E00236D3C /* zip_source_deflate.c */, 4BDC722C15B1B25E00236D3C /* zip_source_error.c */, @@ -1275,8 +1315,16 @@ 4BDC723315B1B25E00236D3C /* zip_source_pkware.c */, 4BDC723415B1B25E00236D3C /* zip_source_pop.c */, 4BDC723515B1B25E00236D3C /* zip_source_read.c */, + 4BCF3031199ABD3A0064207B /* zip_source_remove.c */, + 4BCF301C199A2F820064207B /* zip_source_rollback_write.c */, + 4BCF301D199A2F820064207B /* zip_source_seek.c */, + 4BCF3034199ABDDA0064207B /* zip_source_seek_write.c */, 4BDC723615B1B25E00236D3C /* zip_source_stat.c */, + 4BCF301E199A2F820064207B /* zip_source_supports.c */, + 4BCF301F199A2F820064207B /* zip_source_tell.c */, + 4BCF3035199ABDDA0064207B /* zip_source_tell_write.c */, 4BDC723715B1B25E00236D3C /* zip_source_window.c */, + 4BCF3020199A2F820064207B /* zip_source_write.c */, 4BDC723815B1B25E00236D3C /* zip_source_zip_new.c */, 4BDC723915B1B25E00236D3C /* zip_source_zip.c */, 4BDC723A15B1B25E00236D3C /* zip_stat_index.c */, @@ -1767,8 +1815,10 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 4BCF3039199ABDDA0064207B /* zip_source_tell_write.c in Sources */, 4B01D6A615B2F46B002D5007 /* zip_add_dir.c in Sources */, 4B972052188EBE85002FAFAD /* zip_file_set_external_attributes.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 */, @@ -1790,15 +1840,18 @@ 4B01D6B915B2F46B002D5007 /* zip_fdopen.c in Sources */, 4B01D6BA15B2F46B002D5007 /* zip_file_add.c in Sources */, 4B01D6BB15B2F46B002D5007 /* zip_file_error_clear.c in Sources */, + 4BCF3026199A2F820064207B /* zip_source_commit_write.c in Sources */, 4B01D6BC15B2F46B002D5007 /* zip_file_error_get.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 */, 4B01D6C015B2F46B002D5007 /* zip_file_replace.c in Sources */, 4B01D6C115B2F46B002D5007 /* zip_file_set_comment.c in Sources */, + 4BCF3033199ABD3A0064207B /* zip_source_remove.c in Sources */, 4B01D6C215B2F46B002D5007 /* zip_file_strerror.c in Sources */, 4B01D6C315B2F46B002D5007 /* zip_filerange_crc.c in Sources */, 4B01D6C415B2F46B002D5007 /* zip_fopen_encrypted.c in Sources */, + 4BCF302A199A2F820064207B /* zip_source_seek.c in Sources */, 4B01D6C515B2F46B002D5007 /* zip_fopen_index_encrypted.c in Sources */, 4B01D6C615B2F46B002D5007 /* zip_fopen_index.c in Sources */, 4B01D6C715B2F46B002D5007 /* zip_fopen.c in Sources */, @@ -1806,6 +1859,8 @@ 4B01D6C915B2F46B002D5007 /* zip_get_archive_comment.c in Sources */, 4B01D6CA15B2F46B002D5007 /* zip_get_archive_flag.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 */, 4B01D6CD15B2F46B002D5007 /* zip_get_file_comment.c in Sources */, 4B01D6CE15B2F46B002D5007 /* zip_get_name.c in Sources */, @@ -1816,6 +1871,7 @@ 4B01D6D315B2F46B002D5007 /* zip_new.c in Sources */, 4B01D6D415B2F46B002D5007 /* zip_open.c in Sources */, 4B01D6D515B2F46B002D5007 /* zip_rename.c in Sources */, + 4BCF302E199A2F820064207B /* zip_source_tell.c in Sources */, 4B972050188EBE85002FAFAD /* zip_file_get_external_attributes.c in Sources */, 4B01D6D615B2F46B002D5007 /* zip_replace.c in Sources */, 4B01D6D715B2F46B002D5007 /* zip_set_archive_comment.c in Sources */, @@ -1833,12 +1889,14 @@ 4B01D6E315B2F46B002D5007 /* zip_source_filep.c in Sources */, 4B01D6E415B2F46B002D5007 /* zip_source_free.c in Sources */, 4B01D6E515B2F46B002D5007 /* zip_source_function.c in Sources */, + 4BCF3022199A2F820064207B /* zip_io_util.c in Sources */, 4B01D6E615B2F46B002D5007 /* zip_source_layered.c in Sources */, 4B01D6E715B2F46B002D5007 /* zip_source_open.c in Sources */, 4B01D6E815B2F46B002D5007 /* zip_source_pkware.c in Sources */, 4B01D6E915B2F46B002D5007 /* zip_source_pop.c in Sources */, 4B01D6EA15B2F46B002D5007 /* zip_source_read.c in Sources */, 4B01D6EB15B2F46B002D5007 /* zip_source_stat.c in Sources */, + 4BCF302C199A2F820064207B /* zip_source_supports.c in Sources */, 4B01D6EC15B2F46B002D5007 /* zip_source_window.c in Sources */, 4B01D6ED15B2F46B002D5007 /* zip_source_zip_new.c in Sources */, 4B01D6EE15B2F46B002D5007 /* zip_source_zip.c in Sources */, @@ -1850,6 +1908,8 @@ 4B01D6F315B2F46B002D5007 /* zip_string.c in Sources */, 4B01D6F415B2F46B002D5007 /* zip_unchange_all.c in Sources */, 4B01D6F515B2F46B002D5007 /* zip_unchange_archive.c in Sources */, + 4BCF3028199A2F820064207B /* zip_source_rollback_write.c in Sources */, + 4BCF3037199ABDDA0064207B /* zip_source_seek_write.c in Sources */, 4B01D6F615B2F46B002D5007 /* zip_unchange_data.c in Sources */, 4B01D6F715B2F46B002D5007 /* zip_unchange.c in Sources */, 4B01D6F815B2F46B002D5007 /* zip_utf-8.c in Sources */, @@ -1988,8 +2048,10 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 4BCF3038199ABDDA0064207B /* zip_source_tell_write.c in Sources */, 4BDC724415B1B25E00236D3C /* zip_add_dir.c in Sources */, 4B972051188EBE85002FAFAD /* zip_file_set_external_attributes.c in Sources */, + 4BCF3023199A2F820064207B /* zip_source_begin_write.c in Sources */, 4BDC724515B1B25E00236D3C /* zip_add_entry.c in Sources */, 4BDC724615B1B25E00236D3C /* zip_add.c in Sources */, 4BDC724715B1B25E00236D3C /* zip_close.c in Sources */, @@ -2011,15 +2073,18 @@ 4BDC725715B1B25E00236D3C /* zip_fdopen.c in Sources */, 4BDC725815B1B25E00236D3C /* zip_file_add.c in Sources */, 4BDC725915B1B25E00236D3C /* zip_file_error_clear.c in Sources */, + 4BCF3025199A2F820064207B /* zip_source_commit_write.c in Sources */, 4BDC725A15B1B25E00236D3C /* zip_file_error_get.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 */, 4BDC725E15B1B25E00236D3C /* zip_file_replace.c in Sources */, 4BDC725F15B1B25E00236D3C /* zip_file_set_comment.c in Sources */, + 4BCF3032199ABD3A0064207B /* zip_source_remove.c in Sources */, 4BDC726015B1B25E00236D3C /* zip_file_strerror.c in Sources */, 4BDC726115B1B25E00236D3C /* zip_filerange_crc.c in Sources */, 4BDC726215B1B25E00236D3C /* zip_fopen_encrypted.c in Sources */, + 4BCF3029199A2F820064207B /* zip_source_seek.c in Sources */, 4BDC726315B1B25E00236D3C /* zip_fopen_index_encrypted.c in Sources */, 4BDC726415B1B25E00236D3C /* zip_fopen_index.c in Sources */, 4BDC726515B1B25E00236D3C /* zip_fopen.c in Sources */, @@ -2027,6 +2092,8 @@ 4BDC726715B1B25E00236D3C /* zip_get_archive_comment.c in Sources */, 4BDC726815B1B25E00236D3C /* zip_get_archive_flag.c in Sources */, 4BDC726915B1B25E00236D3C /* zip_get_compression_implementation.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 */, 4BDC726B15B1B25E00236D3C /* zip_get_file_comment.c in Sources */, 4BDC726C15B1B25E00236D3C /* zip_get_name.c in Sources */, @@ -2037,6 +2104,7 @@ 4BDC727115B1B25E00236D3C /* zip_new.c in Sources */, 4BDC727215B1B25E00236D3C /* zip_open.c in Sources */, 4BDC727315B1B25E00236D3C /* zip_rename.c in Sources */, + 4BCF302D199A2F820064207B /* zip_source_tell.c in Sources */, 4B97204F188EBE85002FAFAD /* zip_file_get_external_attributes.c in Sources */, 4BDC727415B1B25E00236D3C /* zip_replace.c in Sources */, 4BDC727515B1B25E00236D3C /* zip_set_archive_comment.c in Sources */, @@ -2054,12 +2122,14 @@ 4BDC728115B1B25E00236D3C /* zip_source_filep.c in Sources */, 4BDC728215B1B25E00236D3C /* zip_source_free.c in Sources */, 4BDC728315B1B25E00236D3C /* zip_source_function.c in Sources */, + 4BCF3021199A2F820064207B /* zip_io_util.c in Sources */, 4BDC728415B1B25E00236D3C /* zip_source_layered.c in Sources */, 4BDC728515B1B25E00236D3C /* zip_source_open.c in Sources */, 4BDC728615B1B25E00236D3C /* zip_source_pkware.c in Sources */, 4BDC728715B1B25E00236D3C /* zip_source_pop.c in Sources */, 4BDC728815B1B25E00236D3C /* zip_source_read.c in Sources */, 4BDC728915B1B25E00236D3C /* zip_source_stat.c in Sources */, + 4BCF302B199A2F820064207B /* zip_source_supports.c in Sources */, 4BDC728A15B1B25E00236D3C /* zip_source_window.c in Sources */, 4BDC728B15B1B25E00236D3C /* zip_source_zip_new.c in Sources */, 4BDC728C15B1B25E00236D3C /* zip_source_zip.c in Sources */, @@ -2071,6 +2141,8 @@ 4BDC729115B1B25E00236D3C /* zip_string.c in Sources */, 4BDC729215B1B25E00236D3C /* zip_unchange_all.c in Sources */, 4BDC729315B1B25E00236D3C /* zip_unchange_archive.c in Sources */, + 4BCF3027199A2F820064207B /* zip_source_rollback_write.c in Sources */, + 4BCF3036199ABDDA0064207B /* zip_source_seek_write.c in Sources */, 4BDC729415B1B25E00236D3C /* zip_unchange_data.c in Sources */, 4BDC729515B1B25E00236D3C /* zip_unchange.c in Sources */, 4BDC729615B1B25E00236D3C /* zip_utf-8.c in Sources */,