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 */,