]> granicus.if.org Git - php/commitdiff
update libzip to version 1.0.1
authorRemi Collet <remi@fedoraproject.org>
Wed, 6 May 2015 12:36:18 +0000 (14:36 +0200)
committerRemi Collet <remi@php.net>
Wed, 6 May 2015 13:16:43 +0000 (15:16 +0200)
113 files changed:
ext/zip/LICENSE_libzip
ext/zip/config.m4
ext/zip/config.w32
ext/zip/lib/config.h
ext/zip/lib/mkstemp.c
ext/zip/lib/php_zip_config.w32.h
ext/zip/lib/zip.h
ext/zip/lib/zip_add.c
ext/zip/lib/zip_add_dir.c
ext/zip/lib/zip_add_entry.c
ext/zip/lib/zip_buffer.c [new file with mode: 0644]
ext/zip/lib/zip_close.c
ext/zip/lib/zip_delete.c
ext/zip/lib/zip_dir_add.c
ext/zip/lib/zip_dirent.c
ext/zip/lib/zip_discard.c
ext/zip/lib/zip_entry.c
ext/zip/lib/zip_err_str.c
ext/zip/lib/zip_error.c
ext/zip/lib/zip_error_clear.c
ext/zip/lib/zip_error_get.c
ext/zip/lib/zip_error_get_sys_type.c
ext/zip/lib/zip_error_strerror.c
ext/zip/lib/zip_error_to_str.c
ext/zip/lib/zip_extra_field.c
ext/zip/lib/zip_extra_field_api.c
ext/zip/lib/zip_fclose.c
ext/zip/lib/zip_fdopen.c
ext/zip/lib/zip_file_add.c
ext/zip/lib/zip_file_error_clear.c
ext/zip/lib/zip_file_error_get.c
ext/zip/lib/zip_file_get_comment.c
ext/zip/lib/zip_file_get_external_attributes.c
ext/zip/lib/zip_file_get_offset.c
ext/zip/lib/zip_file_rename.c
ext/zip/lib/zip_file_replace.c
ext/zip/lib/zip_file_set_comment.c
ext/zip/lib/zip_file_set_external_attributes.c
ext/zip/lib/zip_file_set_mtime.c [new file with mode: 0644]
ext/zip/lib/zip_file_strerror.c
ext/zip/lib/zip_filerange_crc.c
ext/zip/lib/zip_fopen.c
ext/zip/lib/zip_fopen_encrypted.c
ext/zip/lib/zip_fopen_index.c
ext/zip/lib/zip_fopen_index_encrypted.c
ext/zip/lib/zip_fread.c
ext/zip/lib/zip_get_archive_comment.c
ext/zip/lib/zip_get_archive_flag.c
ext/zip/lib/zip_get_compression_implementation.c
ext/zip/lib/zip_get_encryption_implementation.c
ext/zip/lib/zip_get_file_comment.c
ext/zip/lib/zip_get_name.c
ext/zip/lib/zip_get_num_entries.c
ext/zip/lib/zip_get_num_files.c
ext/zip/lib/zip_io_util.c [new file with mode: 0644]
ext/zip/lib/zip_memdup.c
ext/zip/lib/zip_name_locate.c
ext/zip/lib/zip_new.c
ext/zip/lib/zip_open.c
ext/zip/lib/zip_rename.c
ext/zip/lib/zip_replace.c
ext/zip/lib/zip_set_archive_comment.c
ext/zip/lib/zip_set_archive_flag.c
ext/zip/lib/zip_set_default_password.c
ext/zip/lib/zip_set_file_comment.c
ext/zip/lib/zip_set_file_compression.c
ext/zip/lib/zip_set_name.c
ext/zip/lib/zip_source_begin_write.c [moved from ext/zip/lib/zip_source_pop.c with 75% similarity]
ext/zip/lib/zip_source_buffer.c
ext/zip/lib/zip_source_call.c [new file with mode: 0644]
ext/zip/lib/zip_source_close.c
ext/zip/lib/zip_source_commit_write.c [new file with mode: 0644]
ext/zip/lib/zip_source_crc.c
ext/zip/lib/zip_source_deflate.c
ext/zip/lib/zip_source_error.c
ext/zip/lib/zip_source_file.c
ext/zip/lib/zip_source_filep.c
ext/zip/lib/zip_source_free.c
ext/zip/lib/zip_source_function.c
ext/zip/lib/zip_source_is_deleted.c [new file with mode: 0644]
ext/zip/lib/zip_source_layered.c
ext/zip/lib/zip_source_open.c
ext/zip/lib/zip_source_pkware.c
ext/zip/lib/zip_source_read.c
ext/zip/lib/zip_source_remove.c [new file with mode: 0644]
ext/zip/lib/zip_source_rollback_write.c [new file with mode: 0644]
ext/zip/lib/zip_source_seek.c [new file with mode: 0644]
ext/zip/lib/zip_source_seek_write.c [new file with mode: 0644]
ext/zip/lib/zip_source_stat.c
ext/zip/lib/zip_source_supports.c [new file with mode: 0644]
ext/zip/lib/zip_source_tell.c [new file with mode: 0644]
ext/zip/lib/zip_source_tell_write.c [new file with mode: 0644]
ext/zip/lib/zip_source_win32a.c [new file with mode: 0644]
ext/zip/lib/zip_source_win32handle.c [new file with mode: 0644]
ext/zip/lib/zip_source_win32utf8.c [new file with mode: 0644]
ext/zip/lib/zip_source_win32w.c [new file with mode: 0644]
ext/zip/lib/zip_source_window.c
ext/zip/lib/zip_source_write.c [new file with mode: 0644]
ext/zip/lib/zip_source_zip.c
ext/zip/lib/zip_source_zip_new.c
ext/zip/lib/zip_stat.c
ext/zip/lib/zip_stat_index.c
ext/zip/lib/zip_stat_init.c
ext/zip/lib/zip_strerror.c
ext/zip/lib/zip_string.c
ext/zip/lib/zip_unchange.c
ext/zip/lib/zip_unchange_all.c
ext/zip/lib/zip_unchange_archive.c
ext/zip/lib/zip_unchange_data.c
ext/zip/lib/zip_utf-8.c
ext/zip/lib/zipconf.h
ext/zip/lib/zipint.h
ext/zip/lib/zipwin32.h [new file with mode: 0644]

index 9b2fda07b10544150710719a50d81af45053bb15..bf308010781668b1af46a71f3baae2df09737022 100644 (file)
@@ -1,18 +1,22 @@
-Copyright (C) 1999-2008 Dieter Baron and Thomas Klausner
+Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+
 The authors can be contacted at <libzip@nih.at>
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions
 are met:
+
 1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
+  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.
+  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.
+  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
index a21ad2d3e12e63f455f52d6e417226e191c6fdce..6dbc1e292bbdc9f52327d6f74c1b80f50bbf4a17 100644 (file)
@@ -106,6 +106,11 @@ if test "$PHP_ZIP" != "no"; then
 
 
   PHP_ZIP_SOURCES="$PHP_ZIP_SOURCES lib/zip_add.c lib/zip_add_dir.c lib/zip_add_entry.c\
+                       lib/zip_buffer.c lib/zip_file_set_mtime.c lib/zip_io_util.c lib/zip_source_begin_write.c \
+                       lib/zip_source_call.c lib/zip_source_commit_write.c lib/zip_source_is_deleted.c \
+                       lib/zip_source_remove.c lib/zip_source_rollback_write.c lib/zip_source_seek.c \
+                       lib/zip_source_seek_write.c lib/zip_source_supports.c lib/zip_source_tell.c \
+                       lib/zip_source_tell_write.c lib/zip_source_write.c \
                        lib/zip_close.c lib/zip_delete.c lib/zip_dir_add.c lib/zip_dirent.c lib/zip_discard.c lib/zip_entry.c\
                        lib/zip_err_str.c lib/zip_error.c lib/zip_error_clear.c lib/zip_error_get.c lib/zip_error_get_sys_type.c\
                        lib/zip_error_strerror.c lib/zip_error_to_str.c lib/zip_extra_field.c lib/zip_extra_field_api.c\
@@ -120,7 +125,7 @@ if test "$PHP_ZIP" != "no"; then
                        lib/zip_set_archive_comment.c lib/zip_set_archive_flag.c lib/zip_set_default_password.c lib/zip_set_file_comment.c\
                        lib/zip_set_file_compression.c lib/zip_set_name.c lib/zip_source_buffer.c lib/zip_source_close.c lib/zip_source_crc.c\
                        lib/zip_source_deflate.c lib/zip_source_error.c lib/zip_source_file.c lib/zip_source_filep.c lib/zip_source_free.c\
-                       lib/zip_source_function.c lib/zip_source_layered.c lib/zip_source_open.c lib/zip_source_pkware.c lib/zip_source_pop.c\
+                       lib/zip_source_function.c lib/zip_source_layered.c lib/zip_source_open.c lib/zip_source_pkware.c \
                        lib/zip_source_read.c lib/zip_source_stat.c lib/zip_source_window.c lib/zip_source_zip.c lib/zip_source_zip_new.c\
                        lib/zip_stat.c lib/zip_stat_index.c lib/zip_stat_init.c lib/zip_strerror.c lib/zip_string.c lib/zip_unchange.c lib/zip_unchange_all.c\
                        lib/zip_unchange_archive.c lib/zip_unchange_data.c lib/zip_utf-8.c lib/mkstemp.c"
@@ -132,6 +137,8 @@ if test "$PHP_ZIP" != "no"; then
   PHP_SUBST(ZIP_SHARED_LIBADD)
 fi
 
+AC_CHECK_HEADERS(stdbool.h)
+AC_CHECK_HEADERS(fts.h)
 
 AC_CHECK_TYPES([int8_t])
 AC_CHECK_TYPES([int16_t])
index 28de34478560eef5c977aecc60b6e5c0fc165abe..a9a8088fb5c51efa896afbdbc43bca447b4591cc 100644 (file)
@@ -24,11 +24,14 @@ if (PHP_ZIP != "no") {
                        zip_set_archive_comment.c zip_set_archive_flag.c zip_set_default_password.c zip_set_file_comment.c\
                        zip_set_file_compression.c zip_set_name.c zip_source_buffer.c zip_source_close.c zip_source_crc.c\
                        zip_source_deflate.c zip_source_error.c zip_source_file.c zip_source_filep.c zip_source_free.c\
-                       zip_source_function.c zip_source_layered.c zip_source_open.c zip_source_pkware.c zip_source_pop.c\
+                       zip_source_function.c zip_source_layered.c zip_source_open.c zip_source_pkware.c \
                        zip_source_read.c zip_source_stat.c zip_source_window.c zip_source_zip.c zip_source_zip_new.c\
                        zip_stat.c zip_stat_index.c zip_stat_init.c zip_strerror.c zip_string.c zip_unchange.c zip_unchange_all.c\
                        zip_unchange_archive.c zip_unchange_data.c zip_utf-8.c mkstemp.c \
-                       zip_file_set_external_attributes.c zip_file_get_external_attributes.c", "zip");
+                       zip_file_set_external_attributes.c zip_file_get_external_attributes.c zip_source_write.c \
+                       zip_source_call.c zip_source_supports.c zip_buffer.c zip_source_seek.c zip_source_tell.c \
+                       zip_io_util.c zip_source_remove.c zip_source_rollback_write.c zip_source_commit_write.c \
+                       zip_source_tell_write.c zip_source_begin_write.c zip_source_seek_write.c", "zip");
 
                AC_DEFINE('HAVE_ZIP', 1);
                ADD_FLAG("CFLAGS_ZIP", "/D _WIN32");
index 8a4db4039de60615f0c5965387ede367cfb09ecb..ee77c66d43ce8dd780685d9728794378a57aaac0 100644 (file)
@@ -1,8 +1,8 @@
 /*
   +----------------------------------------------------------------------+
-  | PHP Version 7                                                        |
+  | PHP Version 5                                                        |
   +----------------------------------------------------------------------+
-  | Copyright (c) 1997-2015 The PHP Group                                |
+  | Copyright (c) 1997-2013 The PHP Group                                |
   +----------------------------------------------------------------------+
   | This source file is subject to version 3.01 of the PHP license,      |
   | that is bundled with this package in the file LICENSE, and is        |
index 3d03ee9acc62fa4299543f33de152f5328f41683..2ccd3a48789eb9b3f0f46e5291e30358e05c711e 100644 (file)
@@ -49,7 +49,6 @@
 #endif
 
 
-
 int
 _zip_mkstemp(char *path)
 {
@@ -62,7 +61,7 @@ _zip_mkstemp(char *path)
                return ret;
        }
 #else
-       int fd;
+       int fd;   
        char *start, *trv;
        struct stat sbuf;
        pid_t pid;
@@ -80,7 +79,7 @@ _zip_mkstemp(char *path)
                if (*trv == 'X')
                        xcnt++;
                else
-                       xcnt = 0;
+                       xcnt = 0;       
 
        /* Use at least one from xtra.  Use 2 if more than 6 X's. */
        if (*(trv - 1) == 'X')
index b3192cbdd4573b8e05251af4219d64adb037d029..31efa7aee46e00c2439efc6b073ada0acf2a3901 100644 (file)
@@ -57,4 +57,12 @@ typedef long long ssize_t;
 # undef strcasecmp
 # define strcasecmp _strcmpi
 
+#if !defined(EOPNOTSUPP) && defined(_WIN32)
+# define EOPNOTSUPP 130
+#endif
+
+#if !defined(EOVERFLOW) && defined(_WIN32)
+# define EOVERFLOW 132
+#endif
+
 #endif /* HAD_CONFIG_H */
index 2eef0548adc0571be6e4a50c228ac56338a95b4d..7b243bcd05b578df4101dc29dbdf54d738aeffe8 100644 (file)
@@ -3,7 +3,7 @@
 
 /*
   zip.h -- exported declarations.
-  Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -20,7 +20,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
-#include "main/php.h"
-
-#ifdef PHP_WIN32
-#ifdef PHP_ZIP_EXPORTS
-#  define ZIP_EXTERN __declspec(dllexport) _stdcall
+#ifndef ZIP_EXTERN
+# ifndef ZIP_STATIC
+#  if defined(_WIN32) && defined(PHP_ZIP_EXPORTS)
+#   define ZIP_EXTERN __declspec(dllimport)
+#  elif defined(__GNUC__) && __GNUC__ >= 4
+#   define ZIP_EXTERN __attribute__ ((visibility ("default")))
+#  else
+#   define ZIP_EXTERN
+#  endif
 # else
 #  define ZIP_EXTERN
 # endif
-#elif defined(__GNUC__) && __GNUC__ >= 4
-# define ZIP_EXTERN __attribute__ ((visibility("default")))
-#else
-# define ZIP_EXTERN
 #endif
 
-
-
 #ifdef __cplusplus
 extern "C" {
+#if 0
+} /* fix autoindent */
+#endif
 #endif
 
 #include <zipconf.h>
@@ -68,6 +68,7 @@ extern "C" {
 #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, ... */
@@ -90,7 +91,6 @@ extern "C" {
 
 /* archive global flags flags */
 
-#define ZIP_AFL_TORRENT                1u /* torrent zipped */
 #define ZIP_AFL_RDONLY         2u /* read only -- cannot be cleared */
 
 
@@ -99,11 +99,6 @@ extern "C" {
 #define ZIP_EXTRA_FIELD_ALL    ZIP_UINT16_MAX
 #define ZIP_EXTRA_FIELD_NEW    ZIP_UINT16_MAX
 
-/* flags for compression and encryption sources */
-
-#define ZIP_CODEC_DECODE       0 /* decompress/decrypt (encode flag not set) */
-#define ZIP_CODEC_ENCODE       1 /* compress/encrypt */
-
 
 /* libzip error codes */
 
@@ -124,7 +119,7 @@ extern "C" {
 #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,9 +127,12 @@ extern "C" {
 #define ZIP_ER_REMOVE        22  /* S Can't remove file */
 #define ZIP_ER_DELETED       23  /* N Entry has been deleted */
 #define ZIP_ER_ENCRNOTSUPP   24  /* N Encryption method not supported */
-#define ZIP_ER_RDONLY        25  /* N Read-only archive */
+#define ZIP_ER_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 */
 
@@ -207,17 +205,66 @@ extern "C" {
 #define ZIP_OPSYS_DEFAULT      ZIP_OPSYS_UNIX
 
 
-
 enum zip_source_cmd {
-    ZIP_SOURCE_OPEN,   /* prepare for reading */
-    ZIP_SOURCE_READ,   /* read data */
-    ZIP_SOURCE_CLOSE,  /* reading is done */
-    ZIP_SOURCE_STAT,   /* get meta information */
-    ZIP_SOURCE_ERROR,  /* get error information */
-    ZIP_SOURCE_FREE    /* cleanup and free resources */
+    ZIP_SOURCE_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_MAKE_COMMAND_BITMASK(cmd)    (1<<(cmd))
+
+#define ZIP_SOURCE_SUPPORTS_READABLE   (ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_OPEN) \
+                                         | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_READ) \
+                                         | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_CLOSE) \
+                                         | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_STAT) \
+                                         | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ERROR) \
+                                         | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_FREE))
+
+#define ZIP_SOURCE_SUPPORTS_SEEKABLE   (ZIP_SOURCE_SUPPORTS_READABLE \
+                                         | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK) \
+                                         | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_TELL) \
+                                         | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SUPPORTS))
+
+#define ZIP_SOURCE_SUPPORTS_WRITABLE    (ZIP_SOURCE_SUPPORTS_SEEKABLE \
+                                         | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE) \
+                                         | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_COMMIT_WRITE) \
+                                         | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ROLLBACK_WRITE) \
+                                         | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_WRITE) \
+                                         | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK_WRITE) \
+                                         | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_TELL_WRITE) \
+                                         | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_REMOVE))
+
+/* for use by sources */
+struct zip_source_args_seek {
+    zip_int64_t offset;
+    int whence;
 };
 
-#define ZIP_SOURCE_ERR_LOWER   -2
+typedef struct zip_source_args_seek zip_source_args_seek_t;
+#define ZIP_SOURCE_GET_ARGS(type, data, len, error) ((len) < sizeof(type) ? zip_error_set((error), ZIP_ER_INVAL, 0), (type *)NULL : (type *)(data))
+
+
+/* error information */
+/* use zip_error_*() to access */
+struct zip_error {
+    int zip_err;       /* libzip error code (ZIP_ER_*) */
+    int sys_err;       /* copy of errno (E*) or zlib error code */
+    char *str;         /* string representation or NULL */
+};
 
 #define ZIP_STAT_NAME                  0x0001u
 #define ZIP_STAT_INDEX                 0x0002u
@@ -246,79 +293,127 @@ struct zip;
 struct zip_file;
 struct zip_source;
 
-typedef zip_uint32_t zip_flags_t;
+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_int64_t (*zip_source_callback)(void *, void *, zip_uint64_t,
-                                          enum zip_source_cmd);
+typedef zip_uint32_t zip_flags_t;    
 
+typedef zip_int64_t (*zip_source_callback)(void *, void *, zip_uint64_t, zip_source_cmd_t);
 
 
 #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_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_set_file_comment(struct zip *, zip_uint64_t, const char *, int); /* use zip_file_set_comment */
+ZIP_EXTERN zip_int64_t zip_add(zip_t *, const char *, zip_source_t *); /* use zip_file_add */
+ZIP_EXTERN zip_int64_t zip_add_dir(zip_t *, const char *); /* use zip_dir_add */
+ZIP_EXTERN const char *zip_get_file_comment(zip_t *, zip_uint64_t, int *, int); /* use zip_file_get_comment */
+ZIP_EXTERN int zip_get_num_files(zip_t *);  /* use zip_get_num_entries instead */
+ZIP_EXTERN int zip_rename(zip_t *, zip_uint64_t, const char *); /* use zip_file_rename */
+ZIP_EXTERN int zip_replace(zip_t *, zip_uint64_t, zip_source_t *); /* use zip_file_replace */
+ZIP_EXTERN int zip_set_file_comment(zip_t *, 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(zip_t *, int *, int *); /* use zip_get_error, zip_error_code_zip / zip_error_code_system */
+ZIP_EXTERN int zip_error_to_str(char *, zip_uint64_t, int, int);
+ZIP_EXTERN void zip_file_error_get(zip_file_t *, 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 *);
-ZIP_EXTERN int zip_close(struct zip *);
-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 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_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 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);
-ZIP_EXTERN zip_int16_t zip_file_extra_fields_count(struct zip *, zip_uint64_t, zip_flags_t);
-ZIP_EXTERN zip_int16_t zip_file_extra_fields_count_by_id(struct zip *, zip_uint64_t, zip_uint16_t, zip_flags_t);
-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 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_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 const char *zip_file_strerror(struct zip_file *);
-ZIP_EXTERN struct zip_file *zip_fopen(struct zip *, const char *, zip_flags_t);
-ZIP_EXTERN struct zip_file *zip_fopen_encrypted(struct zip *, const char *, zip_flags_t, const char *);
-ZIP_EXTERN struct zip_file *zip_fopen_index(struct zip *, zip_uint64_t, zip_flags_t);
-ZIP_EXTERN struct zip_file *zip_fopen_index_encrypted(struct zip *, zip_uint64_t, zip_flags_t, const char *);
-ZIP_EXTERN zip_int64_t zip_fread(struct zip_file *, void *, zip_uint64_t);
-ZIP_EXTERN const char *zip_get_archive_comment(struct zip *, int *, zip_flags_t);
-ZIP_EXTERN int zip_get_archive_flag(struct zip *, zip_flags_t, zip_flags_t);
-ZIP_EXTERN const char *zip_get_name(struct zip *, zip_uint64_t, zip_flags_t);
-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 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 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 *);
-ZIP_EXTERN const char *zip_strerror(struct zip *);
-ZIP_EXTERN int zip_unchange(struct zip *, zip_uint64_t);
-ZIP_EXTERN int zip_unchange_all(struct zip *);
-ZIP_EXTERN int zip_unchange_archive(struct zip *);
+ZIP_EXTERN int zip_archive_set_tempdir(zip_t *, const char *);
+ZIP_EXTERN int zip_close(zip_t *);
+ZIP_EXTERN int zip_delete(zip_t *, zip_uint64_t);
+ZIP_EXTERN zip_int64_t zip_dir_add(zip_t *, const char *, zip_flags_t);
+ZIP_EXTERN void zip_discard(zip_t *);
+
+ZIP_EXTERN zip_error_t *zip_get_error(zip_t *);
+ZIP_EXTERN void zip_error_clear(zip_t *);
+ZIP_EXTERN int zip_error_code_zip(const zip_error_t *);
+ZIP_EXTERN int zip_error_code_system(const zip_error_t *);
+ZIP_EXTERN void zip_error_fini(zip_error_t *);
+ZIP_EXTERN void zip_error_init(zip_error_t *);
+ZIP_EXTERN void zip_error_init_with_code(zip_error_t *, int);
+ZIP_EXTERN void zip_error_set(zip_error_t *, int, int);
+ZIP_EXTERN const char *zip_error_strerror(zip_error_t *);
+ZIP_EXTERN int zip_error_system_type(const zip_error_t *);
+ZIP_EXTERN zip_int64_t zip_error_to_data(const zip_error_t *, void *, zip_uint64_t);
+
+ZIP_EXTERN int zip_fclose(zip_file_t *);
+ZIP_EXTERN zip_t *zip_fdopen(int, int, int *);
+ZIP_EXTERN zip_int64_t zip_file_add(zip_t *, const char *, zip_source_t *, zip_flags_t);
+ZIP_EXTERN void zip_file_error_clear(zip_file_t *);
+ZIP_EXTERN int zip_file_extra_field_delete(zip_t *, zip_uint64_t, zip_uint16_t, zip_flags_t);
+ZIP_EXTERN int zip_file_extra_field_delete_by_id(zip_t *, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_flags_t);
+ZIP_EXTERN int zip_file_extra_field_set(zip_t *, zip_uint64_t, zip_uint16_t, zip_uint16_t, const zip_uint8_t *, zip_uint16_t, zip_flags_t);
+ZIP_EXTERN zip_int16_t zip_file_extra_fields_count(zip_t *, zip_uint64_t, zip_flags_t);
+ZIP_EXTERN zip_int16_t zip_file_extra_fields_count_by_id(zip_t *, zip_uint64_t, zip_uint16_t, zip_flags_t);
+ZIP_EXTERN const zip_uint8_t *zip_file_extra_field_get(zip_t *, 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(zip_t *, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_uint16_t *, zip_flags_t);
+ZIP_EXTERN const char *zip_file_get_comment(zip_t *, zip_uint64_t, zip_uint32_t *, zip_flags_t);
+ZIP_EXTERN zip_error_t *zip_file_get_error(zip_file_t *);
+ZIP_EXTERN int zip_file_get_external_attributes(zip_t *, zip_uint64_t, zip_flags_t, zip_uint8_t *, zip_uint32_t *);
+ZIP_EXTERN int zip_file_rename(zip_t *, zip_uint64_t, const char *, zip_flags_t);
+ZIP_EXTERN int zip_file_replace(zip_t *, zip_uint64_t, zip_source_t *, zip_flags_t);
+ZIP_EXTERN int zip_file_set_comment(zip_t *, zip_uint64_t, const char *, zip_uint16_t, zip_flags_t);
+ZIP_EXTERN int zip_file_set_external_attributes(zip_t *, zip_uint64_t, zip_flags_t, zip_uint8_t, zip_uint32_t);
+ZIP_EXTERN int zip_file_set_mtime(zip_t *, zip_uint64_t, time_t, zip_flags_t);
+ZIP_EXTERN const char *zip_file_strerror(zip_file_t *);
+ZIP_EXTERN zip_file_t *zip_fopen(zip_t *, const char *, zip_flags_t);
+ZIP_EXTERN zip_file_t *zip_fopen_encrypted(zip_t *, const char *, zip_flags_t, const char *);
+ZIP_EXTERN zip_file_t *zip_fopen_index(zip_t *, zip_uint64_t, zip_flags_t);
+ZIP_EXTERN zip_file_t *zip_fopen_index_encrypted(zip_t *, zip_uint64_t, zip_flags_t, const char *);
+ZIP_EXTERN zip_int64_t zip_fread(zip_file_t *, void *, zip_uint64_t);
+ZIP_EXTERN const char *zip_get_archive_comment(zip_t *, int *, zip_flags_t);
+ZIP_EXTERN int zip_get_archive_flag(zip_t *, zip_flags_t, zip_flags_t);
+ZIP_EXTERN const char *zip_get_name(zip_t *, zip_uint64_t, zip_flags_t);
+ZIP_EXTERN zip_int64_t zip_get_num_entries(zip_t *, zip_flags_t);
+ZIP_EXTERN zip_int64_t zip_name_locate(zip_t *, const char *, zip_flags_t);
+ZIP_EXTERN zip_t *zip_open(const char *, int, int *);
+ZIP_EXTERN zip_t *zip_open_from_source(zip_source_t *, int, zip_error_t *);
+ZIP_EXTERN int zip_set_archive_comment(zip_t *, const char *, zip_uint16_t);
+ZIP_EXTERN int zip_set_archive_flag(zip_t *, zip_flags_t, int);
+ZIP_EXTERN int zip_set_default_password(zip_t *, const char *);
+ZIP_EXTERN int zip_set_file_compression(zip_t *, zip_uint64_t, zip_int32_t, zip_uint32_t);
+ZIP_EXTERN int zip_source_begin_write(zip_source_t *);
+ZIP_EXTERN zip_source_t *zip_source_buffer(zip_t *, 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 int zip_source_commit_write(zip_source_t *);
+ZIP_EXTERN zip_error_t *zip_source_error(zip_source_t *src);
+ZIP_EXTERN zip_source_t *zip_source_file(zip_t *, 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, zip_error_t *);
+ZIP_EXTERN zip_source_t *zip_source_filep(zip_t *, FILE *, zip_uint64_t, zip_int64_t);
+ZIP_EXTERN zip_source_t *zip_source_filep_create(FILE *, zip_uint64_t, zip_int64_t, zip_error_t *);
+ZIP_EXTERN void zip_source_free(zip_source_t *);
+ZIP_EXTERN zip_source_t *zip_source_function(zip_t *, 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(zip_source_cmd_t, ...);
+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 void zip_source_rollback_write(zip_source_t *);
+ZIP_EXTERN int zip_source_seek(zip_source_t *, zip_int64_t, int);
+ZIP_EXTERN zip_int64_t zip_source_seek_compute_offset(zip_uint64_t, zip_uint64_t, void *, zip_uint64_t, zip_error_t *);
+ZIP_EXTERN int zip_source_seek_write(zip_source_t *, zip_int64_t, int);
+ZIP_EXTERN int zip_source_stat(zip_source_t *, zip_stat_t *);
+ZIP_EXTERN zip_int64_t zip_source_tell(zip_source_t *);
+ZIP_EXTERN zip_int64_t zip_source_tell_write(zip_source_t *);
+#ifdef _WIN32
+ZIP_EXTERN zip_source_t *zip_source_win32a(zip_t *, const char *, zip_uint64_t, zip_int64_t);
+ZIP_EXTERN zip_source_t *zip_source_win32a_create(const char *, zip_uint64_t, zip_int64_t, zip_error_t *);
+ZIP_EXTERN zip_source_t *zip_source_win32handle(zip_t *, void *, zip_uint64_t, zip_int64_t);
+ZIP_EXTERN zip_source_t *zip_source_win32handle_create(void *, zip_uint64_t, zip_int64_t, zip_error_t *);
+ZIP_EXTERN zip_source_t *zip_source_win32w(zip_t *, const wchar_t *, zip_uint64_t, zip_int64_t);
+ZIP_EXTERN zip_source_t *zip_source_win32w_create(const wchar_t *, zip_uint64_t, zip_int64_t, zip_error_t *);
+#endif
+ZIP_EXTERN zip_int64_t zip_source_write(zip_source_t *, const void *, zip_uint64_t);
+ZIP_EXTERN zip_source_t *zip_source_zip(zip_t *, zip_t *, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t);
+ZIP_EXTERN int zip_stat(zip_t *, const char *, zip_flags_t, zip_stat_t *);
+ZIP_EXTERN int zip_stat_index(zip_t *, zip_uint64_t, zip_flags_t, zip_stat_t *);
+ZIP_EXTERN void zip_stat_init(zip_stat_t *);
+ZIP_EXTERN const char *zip_strerror(zip_t *);
+ZIP_EXTERN int zip_unchange(zip_t *, zip_uint64_t);
+ZIP_EXTERN int zip_unchange_all(zip_t *);
+ZIP_EXTERN int zip_unchange_archive(zip_t *);
 
 #ifdef __cplusplus
 }
index 6de3cd2cf238349510eab4963e451c0c71dd8be3..d1be133b6d189f0704269b2efadabd1d2ac64c6d 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   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
 */
 
 
-
 #define _ZIP_COMPILING_DEPRECATED
 #include "zipint.h"
 
 
-
 /*
   NOTE: Return type is signed so we can return -1 on error.
         The index can not be larger than ZIP_INT64_MAX since the size
@@ -46,7 +44,7 @@
 */
 
 ZIP_EXTERN zip_int64_t
-zip_add(struct zip *za, const char *name, struct zip_source *source)
+zip_add(zip_t *za, const char *name, zip_source_t *source)
 {
     return zip_file_add(za, name, source, 0);
 }
index f84a4edffb9c102ded4eb40867f0cba684c1c578..14bdeda112238933df40362158d35f003a7e78c0 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_add_dir.c -- add directory
-  Copyright (C) 1999-2015 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>
@@ -17,7 +17,7 @@
   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
 */
 
 
-
 #define _ZIP_COMPILING_DEPRECATED
 #include "zipint.h"
 
 
-
 /* NOTE: Signed due to -1 on error.  See zip_add.c for more details. */
 
 ZIP_EXTERN zip_int64_t
-zip_add_dir(struct zip *za, const char *name)
+zip_add_dir(zip_t *za, const char *name)
 {
     return zip_dir_add(za, name, 0);
 }
index 583efc45619a9abd4f24b78ec1f080b813828371..24dbdaf47c32117f45434a1da161f9f4f39ddbc0 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <stdlib.h>
 
 #include "zipint.h"
 
 
-
 /* NOTE: Signed due to -1 on error.  See zip_add.c for more details. */
 
 zip_int64_t
-_zip_add_entry(struct zip *za)
+_zip_add_entry(zip_t *za)
 {
     zip_uint64_t idx;
 
     if (za->nentry+1 >= za->nentry_alloc) {
-       struct zip_entry *rentries;
+       zip_entry_t *rentries;
        zip_uint64_t nalloc = za->nentry_alloc + 16;
-        /* TODO check for overflow */
-       rentries = (struct zip_entry *)realloc(za->entry, sizeof(struct zip_entry) * (size_t)nalloc);
+       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 = (zip_entry_t *)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/ext/zip/lib/zip_buffer.c b/ext/zip/lib/zip_buffer.c
new file mode 100644 (file)
index 0000000..3d79b09
--- /dev/null
@@ -0,0 +1,310 @@
+/*
+ zip_buffer.c -- bounds checked access to memory buffer
+ 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 <stdlib.h>
+#include <string.h>
+
+#include "zipint.h"
+
+zip_uint8_t *
+_zip_buffer_data(zip_buffer_t *buffer)
+{
+    return buffer->data;
+}
+
+
+void
+_zip_buffer_free(zip_buffer_t *buffer)
+{
+    if (buffer == NULL) {
+        return;
+    }
+    
+    if (buffer->free_data) {
+        free(buffer->data);
+    }
+    
+    free(buffer);
+}
+
+
+bool
+_zip_buffer_eof(zip_buffer_t *buffer)
+{
+    return buffer->ok && buffer->offset == buffer->size;
+}
+
+
+zip_uint8_t *
+_zip_buffer_get(zip_buffer_t *buffer, zip_uint64_t length)
+{
+    zip_uint8_t *data;
+    
+    if (!buffer->ok || buffer->offset + length < length || buffer->offset + length > buffer->size) {
+        buffer->ok = false;
+        return NULL;
+    }
+    
+    data = buffer->data + buffer->offset;
+    buffer->offset += length;
+    return data;
+}
+
+
+zip_uint16_t
+_zip_buffer_get_16(zip_buffer_t *buffer)
+{
+    zip_uint8_t *data = _zip_buffer_get(buffer, 2);
+    
+    if (data == NULL) {
+        return 0;
+    }
+    
+    return (zip_uint16_t)(data[0] + (data[1] << 8));
+}
+
+
+zip_uint32_t
+_zip_buffer_get_32(zip_buffer_t *buffer)
+{
+    zip_uint8_t *data = _zip_buffer_get(buffer, 4);
+    
+    if (data == NULL) {
+        return 0;
+    }
+    
+    return ((((((zip_uint32_t)data[3] << 8) + data[2]) << 8) + data[1]) << 8) + data[0];
+}
+
+
+zip_uint64_t
+_zip_buffer_get_64(zip_buffer_t *buffer)
+{
+    zip_uint8_t *data = _zip_buffer_get(buffer, 8);
+    
+    if (data == NULL) {
+        return 0;
+    }
+
+    return ((zip_uint64_t)data[7] << 56) + ((zip_uint64_t)data[6] << 48) + ((zip_uint64_t)data[5] << 40) + ((zip_uint64_t)data[4] << 32) + ((zip_uint64_t)data[3] << 24) + ((zip_uint64_t)data[2] << 16) + ((zip_uint64_t)data[1] << 8) + (zip_uint64_t)data[0];
+}
+
+
+
+zip_uint8_t
+_zip_buffer_get_8(zip_buffer_t *buffer)
+{
+    zip_uint8_t *data = _zip_buffer_get(buffer, 1);
+    
+    if (data == NULL) {
+        return 0;
+    }
+    
+    return data[0];
+}
+
+
+zip_uint64_t
+_zip_buffer_left(zip_buffer_t *buffer)
+{
+    return buffer->ok ? buffer->size - buffer->offset : 0;
+}
+
+
+zip_buffer_t *
+_zip_buffer_new(zip_uint8_t *data, zip_uint64_t size)
+{
+    bool free_data = (data == NULL);
+    zip_buffer_t *buffer;
+    
+    if (data == NULL) {
+        if ((data = (zip_uint8_t *)malloc(size)) == NULL) {
+            return NULL;
+        }
+    }
+
+    if ((buffer = (zip_buffer_t *)malloc(sizeof(*buffer))) == NULL) {
+        if (free_data) {
+            free(data);
+        }
+        return NULL;
+    }
+    
+    buffer->ok = true;
+    buffer->data = data;
+    buffer->size = size;
+    buffer->offset = 0;
+    buffer->free_data = free_data;
+    
+    return buffer;
+}
+
+
+zip_buffer_t *
+_zip_buffer_new_from_source(zip_source_t *src, zip_uint64_t size, zip_uint8_t *buf, zip_error_t *error)
+{
+    zip_buffer_t *buffer;
+    
+    if ((buffer = _zip_buffer_new(buf, size)) == NULL) {
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
+    }
+    
+    if (_zip_read(src, buffer->data, size, error) < 0) {
+        _zip_buffer_free(buffer);
+        return NULL;
+    }
+    
+    return buffer;
+}
+
+
+zip_uint64_t
+_zip_buffer_offset(zip_buffer_t *buffer)
+{
+    return buffer->ok ? buffer->offset : 0;
+}
+
+
+bool
+_zip_buffer_ok(zip_buffer_t *buffer)
+{
+    return buffer->ok;
+}
+
+
+int
+_zip_buffer_put(zip_buffer_t *buffer, const void *src, size_t length)
+{
+    zip_uint8_t *dst = _zip_buffer_get(buffer, length);
+    
+    if (dst == NULL) {
+        return -1;
+    }
+    
+    memcpy(dst, src, length);
+    return 0;
+}
+
+
+int
+_zip_buffer_put_16(zip_buffer_t *buffer, zip_uint16_t i)
+{
+    zip_uint8_t *data = _zip_buffer_get(buffer, 2);
+    
+    if (data == NULL) {
+        return -1;
+    }
+
+    data[0] = (zip_uint8_t)(i & 0xff);
+    data[1] = (zip_uint8_t)((i >> 8) & 0xff);
+    
+    return 0;
+}
+
+
+int
+_zip_buffer_put_32(zip_buffer_t *buffer, zip_uint32_t i)
+{
+    zip_uint8_t *data = _zip_buffer_get(buffer, 4);
+    
+    if (data == NULL) {
+        return -1;
+    }
+    
+    data[0] = (zip_uint8_t)(i & 0xff);
+    data[1] = (zip_uint8_t)((i >> 8) & 0xff);
+    data[2] = (zip_uint8_t)((i >> 16) & 0xff);
+    data[3] = (zip_uint8_t)((i >> 24) & 0xff);
+    
+    return 0;
+}
+
+
+int
+_zip_buffer_put_64(zip_buffer_t *buffer, zip_uint64_t i)
+{
+    zip_uint8_t *data = _zip_buffer_get(buffer, 8);
+    
+    if (data == NULL) {
+        return -1;
+    }
+    
+    data[0] = (zip_uint8_t)(i & 0xff);
+    data[1] = (zip_uint8_t)((i >> 8) & 0xff);
+    data[2] = (zip_uint8_t)((i >> 16) & 0xff);
+    data[3] = (zip_uint8_t)((i >> 24) & 0xff);
+    data[4] = (zip_uint8_t)((i >> 32) & 0xff);
+    data[5] = (zip_uint8_t)((i >> 40) & 0xff);
+    data[6] = (zip_uint8_t)((i >> 48) & 0xff);
+    data[7] = (zip_uint8_t)((i >> 56) & 0xff);
+    
+    return 0;
+}
+
+
+int
+_zip_buffer_put_8(zip_buffer_t *buffer, zip_uint8_t i)
+{
+    zip_uint8_t *data = _zip_buffer_get(buffer, 1);
+    
+    if (data == NULL) {
+        return -1;
+    }
+    
+    data[0] = i;
+    
+    return 0;
+}
+
+
+int
+_zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset)
+{
+    if (offset > buffer->size) {
+        buffer->ok = false;
+        return -1;
+    }
+    
+    buffer->ok = true;
+    buffer->offset = offset;
+    
+    return 0;
+}
+
+
+zip_uint64_t
+_zip_buffer_size(zip_buffer_t *buffer)
+{
+    return buffer->size;
+}
index 79f9dab256f7ef11860e8c115f290de7f3f4f139..a13e4466b3e9298e538d2e91600dfd46b9063178 100644 (file)
@@ -17,7 +17,7 @@
   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
@@ -32,7 +32,6 @@
 */
 
 
-
 #include "zipint.h"
 
 #include <stdio.h>
 #endif
 
 
-
 /* 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 _zip_torrentzip_cmp(const void *, const void *);
-
+static int add_data(zip_t *, zip_source_t *, zip_dirent_t *);
+static int copy_data(zip_t *, zip_uint64_t);
+static int copy_source(zip_t *, zip_source_t *);
+static int write_cdir(zip_t *, const zip_filelist_t *, zip_uint64_t);
 
 
 ZIP_EXTERN int
-zip_close(struct zip *za)
+zip_close(zip_t *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;
+    zip_filelist_t *filelist;
     int changed;
 
-    reopen_on_error = 0;
-
     if (za == NULL)
        return -1;
 
@@ -90,15 +77,15 @@ zip_close(struct zip *za)
 
     /* don't create zip files with no entries */
     if (survivors == 0) {
-       if (za->zn && ((za->open_flags & ZIP_TRUNCATE) || (changed && za->zp))) {
-           if (remove(za->zn) != 0) {
-               _zip_error_set(&za->error, ZIP_ER_REMOVE, errno);
+       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;
            }
        }
        zip_discard(za);
        return 0;
-    }
+    }         
 
     if (!changed) {
        zip_discard(za);
@@ -106,24 +93,13 @@ zip_close(struct zip *za)
     }
 
     if (survivors > za->nentry) {
-        _zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+        zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
         return -1;
     }
-
-    if ((filelist=(struct zip_filelist *)malloc(sizeof(filelist[0])*(size_t)survivors)) == NULL)
+    
+    if ((filelist=(zip_filelist_t *)malloc(sizeof(filelist[0])*(size_t)survivors)) == NULL)
        return -1;
 
-    /* archive comment is special for torrentzip */
-    if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0)) {
-       /* TODO: use internal function when zip_set_archive_comment clears TORRENT flag */
-       if (zip_set_archive_comment(za, TORRENT_SIG "XXXXXXXX", TORRENT_SIG_LEN + TORRENT_CRC_LEN) < 0) {
-           free(filelist);
-           return -1;
-       }
-    }
-    /* TODO: if no longer torrentzip and archive comment not changed by user, delete it */
-
-
     /* create list of files with index into original archive  */
     for (i=j=0; i<za->nentry; i++) {
        if (za->entry[i].deleted)
@@ -131,49 +107,40 @@ zip_close(struct zip *za)
 
         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;
         }
-
+        
        filelist[j].idx = i;
-       filelist[j].name = zip_get_name(za, i, 0);
        j++;
     }
     if (j < survivors) {
         free(filelist);
-        _zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+        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);
-
-    new_torrentzip = (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0) == 1
-                     && zip_get_archive_flag(za, ZIP_AFL_TORRENT,
-                                             ZIP_FL_UNCHANGED) == 0);
+    
     error = 0;
     for (j=0; j<survivors; j++) {
        int new_data;
-       struct zip_entry *entry;
-       struct zip_dirent *de;
+       zip_entry_t *entry;
+       zip_dirent_t *de;
 
        i = filelist[j].idx;
        entry = za->entry+i;
 
-       new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || new_torrentzip || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD));
+       new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD));
 
        /* create new local directory entry */
        if (entry->changes == NULL) {
            if ((entry->changes=_zip_dirent_clone(entry->orig)) == NULL) {
-                _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+                zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
                 error = 1;
                 break;
            }
@@ -185,14 +152,14 @@ zip_close(struct zip *za)
            break;
        }
 
-       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;
+           zip_source_t *zs;
 
            zs = NULL;
            if (!ZIP_ENTRY_DATA_CHANGED(entry)) {
@@ -203,7 +170,7 @@ zip_close(struct zip *za)
            }
 
            /* 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);
@@ -216,8 +183,8 @@ zip_close(struct zip *za)
            zip_uint64_t offset;
 
            /* 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) {
+           de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
+           if (_zip_dirent_write(za, de, ZIP_FL_LOCAL) < 0) {
                error = 1;
                break;
            }
@@ -225,12 +192,12 @@ zip_close(struct zip *za)
                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;
            }
@@ -238,65 +205,40 @@ zip_close(struct zip *za)
     }
 
     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 (fclose(out) != 0) {
-       _zip_error_set(&za->error, ZIP_ER_CLOSE, errno);
-       (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 (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");
-       }
+    if (error) {
+       zip_source_rollback_write(za->src);
        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(zip_t *za, zip_source_t *src, zip_dirent_t *de)
 {
-    off_t offstart, offdata, offend;
+    zip_int64_t offstart, offdata, offend;
     struct zip_stat st;
-    struct zip_source *s2;
+    zip_source_t *s2;
     int ret;
     int is_zip64;
     zip_flags_t flags;
-
+    
     if (zip_source_stat(src, &st) < 0) {
        _zip_error_set_from_source(&za->error, src);
        return -1;
@@ -325,32 +267,33 @@ add_data(struct zip *za, struct zip_source *src, struct zip_dirent *de, FILE *ft
        flags |= ZIP_FL_FORCE_ZIP64;
     else {
        de->uncomp_size = st.size;
-
+       
        if ((st.valid & ZIP_STAT_COMP_SIZE) == 0) {
            if (( ((de->comp_method == ZIP_CM_DEFLATE || ZIP_CM_IS_DEFAULT(de->comp_method)) && st.size > MAX_DEFLATE_SIZE_32)
-                || (de->comp_method != ZIP_CM_STORE && de->comp_method != ZIP_CM_DEFLATE && !ZIP_CM_IS_DEFAULT(de->comp_method))))
+                 || (de->comp_method != ZIP_CM_STORE && de->comp_method != ZIP_CM_DEFLATE && !ZIP_CM_IS_DEFAULT(de->comp_method))))
                flags |= ZIP_FL_FORCE_ZIP64;
        }
        else
            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)
+    de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
+    if ((is_zip64=_zip_dirent_write(za, de, flags)) < 0)
        return -1;
 
 
     if (st.comp_method == ZIP_CM_STORE || (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != de->comp_method)) {
-       struct zip_source *s_store, *s_crc;
+       zip_source_t *s_store, *s_crc;
        zip_compression_implementation comp_impl;
-
+       
        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) {
@@ -358,91 +301,90 @@ add_data(struct zip *za, struct zip_source *src, struct zip_dirent *de, FILE *ft
                return -1;
            }
        }
-       else
+       else {
+           /* to have the same reference count to src as in the case where it's not stored */
+           zip_source_keep(src);
            s_store = src;
+       }
 
-       if ((s_crc=zip_source_crc(za, s_store, 0)) == NULL) {
-           if (s_store != src)
-               zip_source_pop(s_store);
+       s_crc = zip_source_crc(za, s_store, 0);
+       zip_source_free(s_store);
+       if (s_crc == NULL) {
            return -1;
        }
 
-       /* 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_source_pop(s_crc);
-               if (s_store != src)
-                   zip_source_pop(s_store);
+               zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
+               zip_source_free(s_crc);
                return -1;
            }
-           if ((s2=comp_impl(za, s_crc, de->comp_method, ZIP_CODEC_ENCODE)) == NULL) {
-               zip_source_pop(s_crc);
-               if (s_store != src)
-                   zip_source_pop(s_store);
+           s2 = comp_impl(za, s_crc, de->comp_method, ZIP_CODEC_ENCODE);
+           zip_source_free(s_crc);
+           if (s2 == NULL) {
                return -1;
            }
        }
-       else
+       else {
            s2 = s_crc;
+       }
     }
-    else
+    else {
+       zip_source_keep(src);
        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 */
-           ret = -1;
-           break;
-       }
-    }
+    zip_source_free(s2);
 
     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;
     }
 
-    if (st.valid & ZIP_STAT_MTIME)
-       de->last_mod = st.mtime;
-    else
-       time(&de->last_mod);
+    if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0) {
+        if (st.valid & ZIP_STAT_MTIME)
+            de->last_mod = st.mtime;
+        else
+            time(&de->last_mod);
+    }
     de->comp_method = st.comp_method;
     de->crc = st.crc;
     de->uncomp_size = st.size;
     de->comp_size = (zip_uint64_t)(offend - offdata);
 
-    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;
     }
 
@@ -450,34 +392,22 @@ add_data(struct zip *za, struct zip_source *src, struct zip_dirent *de, FILE *ft
 }
 
 
-
 static int
-copy_data(FILE *fs, zip_uint64_t len, FILE *ft, struct zip_error *error)
+copy_data(zip_t *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;
-            }
-        }
-
-       if (fwrite(buf, 1, n, ft) != (size_t)n) {
-           _zip_error_set(error, ZIP_ER_WRITE, errno);
+       n = len > sizeof(buf) ? sizeof(buf) : len;
+       if (_zip_read(za->src, buf, n, &za->error) < 0) {
            return -1;
        }
 
+       if (_zip_write(za, buf, n) < 0) {
+           return -1;
+       }
+       
        len -= n;
     }
 
@@ -485,11 +415,10 @@ copy_data(FILE *fs, zip_uint64_t len, FILE *ft, struct zip_error *error)
 }
 
 
-
 static int
-copy_source(struct zip *za, struct zip_source *src, FILE *ft)
+copy_source(zip_t *za, zip_source_t *src)
 {
-    char buf[BUFSIZE];
+    zip_uint8_t buf[BUFSIZE];
     zip_int64_t n;
     int ret;
 
@@ -500,69 +429,46 @@ copy_source(struct zip *za, struct zip_source *src, FILE *ft)
 
     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);
-
+    
     return ret;
 }
 
 
-
 static int
-write_cdir(struct zip *za, const struct zip_filelist *filelist, zip_uint64_t survivors, FILE *out)
+write_cdir(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors)
 {
-    off_t cd_start, end;
-    zip_int64_t size;
-    uLong crc;
-    char buf[TORRENT_CRC_LEN+1];
-
-    cd_start = ftello(out);
-
-    if ((size=_zip_cdir_write(za, filelist, survivors, out)) < 0)
-       return -1;
-
-    end = ftello(out);
-
-    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)
-       return -1;
-
-    snprintf(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);
-       return -1;
+    zip_int64_t cd_start, end, size;
+    
+    if ((cd_start = zip_source_tell_write(za->src)) < 0) {
+        return -1;
     }
 
-    if (fwrite(buf, TORRENT_CRC_LEN, 1, out) != 1) {
-       _zip_error_set(&za->error, ZIP_ER_WRITE, errno);
+    if ((size=_zip_cdir_write(za, filelist, survivors)) < 0) {
        return -1;
     }
+    
+    if ((end = zip_source_tell_write(za->src)) < 0) {
+        return -1;
+    }
 
     return 0;
 }
 
 
-
 int
-_zip_changed(const struct zip *za, zip_uint64_t *survivorsp)
+_zip_changed(const zip_t *za, zip_uint64_t *survivorsp)
 {
     int changed;
     zip_uint64_t i, survivors;
@@ -585,69 +491,3 @@ _zip_changed(const struct zip *za, zip_uint64_t *survivorsp)
 
     return changed;
 }
-
-
-
-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)
-{
-    const char *aname = ((const struct zip_filelist *)a)->name;
-    const char *bname = ((const struct zip_filelist *)b)->name;
-
-    if (aname == NULL)
-       return (bname != NULL) * -1;
-    else if (bname == NULL)
-       return 1;
-
-    return strcasecmp(aname, bname);
-}
index 799a81249b3f67623bb5ae60144ef00134fd3166..b3e7abb848a210e908201107a12e90f669c0cc2b 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
 
-
 ZIP_EXTERN int
-zip_delete(struct zip *za, zip_uint64_t idx)
+zip_delete(zip_t *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;
     }
 
@@ -60,4 +58,3 @@ zip_delete(struct zip *za, zip_uint64_t idx)
     return 0;
 }
 
-
index 408f19174f04e7e1eb4314fc836e15b478099d30..f535b21f2163838c792e465918d60d74c5350ac4 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_dir_add.c -- add directory
-  Copyright (C) 1999-2015 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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <stdlib.h>
 #include <string.h>
 
 #include "zipint.h"
 
 
-
 /* NOTE: Signed due to -1 on error.  See zip_add.c for more details. */
 
 ZIP_EXTERN zip_int64_t
-zip_dir_add(struct zip *za, const char *name, zip_flags_t flags)
+zip_dir_add(zip_t *za, const char *name, zip_flags_t flags)
 {
     size_t len;
     zip_int64_t idx;
     char *s;
-    struct zip_source *source;
+    zip_source_t *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;
     }
 
@@ -65,7 +63,7 @@ zip_dir_add(struct zip *za, const char *name, zip_flags_t flags)
 
     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);
@@ -77,7 +75,7 @@ zip_dir_add(struct zip *za, const char *name, zip_flags_t flags)
        free(s);
        return -1;
     }
-
+       
     idx = _zip_file_replace(za, ZIP_UINT64_MAX, s ? s : name, source, flags);
 
     free(s);
index 4009d93248c035baadcb5ecfb9956ad32aee1669..e3a78b31465eb4764abbd0bc21501aa64b0f64fa 100644 (file)
@@ -17,7 +17,7 @@
   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
@@ -32,7 +32,6 @@
 */
 
 
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #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 *);
-
+static zip_string_t *_zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string_t *str);
+static zip_extra_field_t *_zip_ef_utf8(zip_uint16_t, zip_string_t *, zip_error_t *);
 
 
 void
-_zip_cdir_free(struct zip_cdir *cd)
+_zip_cdir_free(zip_cdir_t *cd)
 {
     zip_uint64_t i;
 
@@ -65,53 +62,21 @@ _zip_cdir_free(struct zip_cdir *cd)
 }
 
 
-
-int
-_zip_cdir_grow(struct zip_cdir *cd, zip_uint64_t nentry, struct zip_error *error)
-{
-    struct zip_entry *entry;
-    zip_uint64_t i;
-
-    if (nentry < cd->nentry_alloc) {
-       _zip_error_set(error, ZIP_ER_INTERNAL, 0);
-       return -1;
-    }
-
-    if (nentry == cd->nentry_alloc)
-       return 0;
-
-    if ((entry=((struct zip_entry *)
-               realloc(cd->entry, sizeof(*(cd->entry))*(size_t)nentry))) == NULL) {
-       _zip_error_set(error, ZIP_ER_MEMORY, 0);
-       return -1;
-    }
-
-    for (i=cd->nentry_alloc; i<nentry; i++)
-       _zip_entry_init(entry+i);
-
-    cd->nentry_alloc = nentry;
-    cd->entry = entry;
-
-    return 0;
-}
-
-
-
-struct zip_cdir *
-_zip_cdir_new(zip_uint64_t nentry, struct zip_error *error)
+zip_cdir_t *
+_zip_cdir_new(zip_uint64_t nentry, zip_error_t *error)
 {
-    struct zip_cdir *cd;
+    zip_cdir_t *cd;
     zip_uint64_t i;
-
-    if ((cd=(struct zip_cdir *)malloc(sizeof(*cd))) == NULL) {
-       _zip_error_set(error, ZIP_ER_MEMORY, 0);
+    
+    if ((cd=(zip_cdir_t *)malloc(sizeof(*cd))) == NULL) {
+       zip_error_set(error, ZIP_ER_MEMORY, 0);
        return NULL;
     }
 
     if (nentry == 0)
        cd->entry = NULL;
-    else if (nentry > ((size_t)-1)/sizeof(*(cd->entry)) || (cd->entry=(struct zip_entry *)malloc(sizeof(*(cd->entry))*(size_t)nentry)) == NULL) {
-       _zip_error_set(error, ZIP_ER_MEMORY, 0);
+    else if ((nentry > SIZE_MAX/sizeof(*(cd->entry))) || (cd->entry=(zip_entry_t *)malloc(sizeof(*(cd->entry))*(size_t)nentry)) == NULL) {
+       zip_error_set(error, ZIP_ER_MEMORY, 0);
        free(cd);
        return NULL;
     }
@@ -127,19 +92,20 @@ _zip_cdir_new(zip_uint64_t nentry, struct zip_error *error)
 }
 
 
-
 zip_int64_t
-_zip_cdir_write(struct zip *za, const struct zip_filelist *filelist, zip_uint64_t survivors, FILE *fp)
+_zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors)
 {
-    off_t off;
     zip_uint64_t offset, size;
-    struct zip_string *comment;
+    zip_string_t *comment;
+    zip_uint8_t buf[EOCDLEN + EOCD64LEN + EOCD64LOCLEN];
+    zip_buffer_t *buffer;
+    zip_int64_t off;
     zip_uint64_t i;
-    int is_zip64;
+    bool 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;
@@ -147,79 +113,93 @@ _zip_cdir_write(struct zip *za, const struct zip_filelist *filelist, zip_uint64_
     is_zip64 = 0;
 
     for (i=0; i<survivors; i++) {
-       struct zip_entry *entry = za->entry+filelist[i].idx;
+       zip_entry_t *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;
+           is_zip64 = true;
     }
 
-    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;
 
     if (offset > ZIP_UINT32_MAX || survivors > ZIP_UINT16_MAX)
-       is_zip64 = 1;
+       is_zip64 = true;
 
-    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);
 
+    if ((buffer = _zip_buffer_new(buf, sizeof(buf))) == NULL) {
+        zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+        return -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);
+    
+    if (is_zip64) {
+       _zip_buffer_put(buffer, EOCD64_MAGIC, 4);
+        _zip_buffer_put_64(buffer, EOCD64LEN-12);
+       _zip_buffer_put_16(buffer, 45);
+       _zip_buffer_put_16(buffer, 45);
+       _zip_buffer_put_32(buffer, 0);
+       _zip_buffer_put_32(buffer, 0);
+       _zip_buffer_put_64(buffer, survivors);
+       _zip_buffer_put_64(buffer, survivors);
+       _zip_buffer_put_64(buffer, size);
+       _zip_buffer_put_64(buffer, offset);
+       _zip_buffer_put(buffer, EOCD64LOC_MAGIC, 4);
+       _zip_buffer_put_32(buffer, 0);
+       _zip_buffer_put_64(buffer, offset+size);
+       _zip_buffer_put_32(buffer, 1);
+    }
+    
+    _zip_buffer_put(buffer, EOCD_MAGIC, 4);
+    _zip_buffer_put_32(buffer, 0);
+    _zip_buffer_put_16(buffer, (zip_uint16_t)(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : survivors));
+    _zip_buffer_put_16(buffer, (zip_uint16_t)(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : survivors));
+    _zip_buffer_put_32(buffer, size >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : (zip_uint32_t)size);
+    _zip_buffer_put_32(buffer, 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_buffer_put_16(buffer, (zip_uint16_t)(comment ? comment->length : 0));
+    
+    if (!_zip_buffer_ok(buffer)) {
+        zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+        _zip_buffer_free(buffer);
+        return -1;
+    }
 
-    if (ferror(fp)) {
-       _zip_error_set(&za->error, ZIP_ER_WRITE, errno);
+    if (_zip_write(za, _zip_buffer_data(buffer), _zip_buffer_offset(buffer)) < 0) {
+        _zip_buffer_free(buffer);
        return -1;
     }
 
+    _zip_buffer_free(buffer);
+
+    if (comment) {
+       if (_zip_write(za, comment->raw, comment->length) < 0) {
+           return -1;
+       }
+    }
+
     return (zip_int64_t)size;
 }
 
 
-
-struct zip_dirent *
-_zip_dirent_clone(const struct zip_dirent *sde)
+zip_dirent_t *
+_zip_dirent_clone(const zip_dirent_t *sde)
 {
-    struct zip_dirent *tde;
+    zip_dirent_t *tde;
 
-    if ((tde=(struct zip_dirent *)malloc(sizeof(*tde))) == NULL)
+    if ((tde=(zip_dirent_t *)malloc(sizeof(*tde))) == NULL)
        return NULL;
 
     if (sde)
        memcpy(tde, sde, sizeof(*sde));
     else
        _zip_dirent_init(tde);
-
+    
     tde->changed = 0;
     tde->cloned = 1;
 
@@ -227,22 +207,26 @@ _zip_dirent_clone(const struct zip_dirent *sde)
 }
 
 
-
 void
-_zip_dirent_finalize(struct zip_dirent *zde)
+_zip_dirent_finalize(zip_dirent_t *zde)
 {
-    if (!zde->cloned || zde->changed & ZIP_DIRENT_FILENAME)
+    if (!zde->cloned || zde->changed & ZIP_DIRENT_FILENAME) {
        _zip_string_free(zde->filename);
-    if (!zde->cloned || zde->changed & ZIP_DIRENT_EXTRA_FIELD)
+       zde->filename = NULL;
+    }
+    if (!zde->cloned || zde->changed & ZIP_DIRENT_EXTRA_FIELD) {
        _zip_ef_free(zde->extra_fields);
-    if (!zde->cloned || zde->changed & ZIP_DIRENT_COMMENT)
+       zde->extra_fields = NULL;
+    }
+    if (!zde->cloned || zde->changed & ZIP_DIRENT_COMMENT) {
        _zip_string_free(zde->comment);
+       zde->comment = NULL;
+    }
 }
 
 
-
 void
-_zip_dirent_free(struct zip_dirent *zde)
+_zip_dirent_free(zip_dirent_t *zde)
 {
     if (zde == NULL)
        return;
@@ -252,9 +236,8 @@ _zip_dirent_free(struct zip_dirent *zde)
 }
 
 
-
 void
-_zip_dirent_init(struct zip_dirent *de)
+_zip_dirent_init(zip_dirent_t *de)
 {
     de->changed = 0;
     de->local_extra_fields_read = 0;
@@ -278,25 +261,23 @@ _zip_dirent_init(struct zip_dirent *de)
 }
 
 
-
-int
-_zip_dirent_needs_zip64(const struct zip_dirent *de, zip_flags_t flags)
+bool
+_zip_dirent_needs_zip64(const zip_dirent_t *de, zip_flags_t flags)
 {
     if (de->uncomp_size >= ZIP_UINT32_MAX || de->comp_size >= ZIP_UINT32_MAX
        || ((flags & ZIP_FL_CENTRAL) && de->offset >= ZIP_UINT32_MAX))
-       return 1;
+       return true;
 
-    return 0;
+    return false;
 }
 
 
-
-struct zip_dirent *
+zip_dirent_t *
 _zip_dirent_new(void)
 {
-    struct zip_dirent *de;
+    zip_dirent_t *de;
 
-    if ((de=(struct zip_dirent *)malloc(sizeof(*de))) == NULL)
+    if ((de=(zip_dirent_t *)malloc(sizeof(*de))) == NULL)
        return NULL;
 
     _zip_dirent_init(de);
@@ -304,89 +285,71 @@ _zip_dirent_new(void)
 }
 
 
-
 /* _zip_dirent_read(zde, fp, bufp, left, localp, error):
    Fills the zip directory entry zde.
 
-   If bufp is non-NULL, data is taken from there and bufp is advanced
-   by the amount of data used; otherwise data is read from fp as needed.
-
-   if leftp is non-NULL, no more bytes than specified by it are used,
-   and *leftp is reduced by the number of bytes used.
+   If buffer is non-NULL, data is taken from there; otherwise data is read from fp as needed.
+   
+   If local is true, it reads a local header instead of a central directory entry.
 
-   If local != 0, it reads a local header instead of a central
-   directory entry.
-
-   Returns 0 if successful. On error, error is filled in and -1 is
-   returned.
-
-   TODO: leftp and file position undefined on error.
+   Returns size of dirent read if successful. On error, error is filled in and -1 is returned.
 */
 
-int
-_zip_dirent_read(struct zip_dirent *zde, FILE *fp,
-                const unsigned char **bufp, zip_uint64_t *leftp, int local,
-                struct zip_error *error)
+zip_int64_t
+_zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, bool local, zip_error_t *error)
 {
-    unsigned char buf[CDENTRYSIZE];
-    const unsigned char *cur;
+    zip_uint8_t buf[CDENTRYSIZE];
     zip_uint16_t dostime, dosdate;
-    zip_uint32_t size;
+    zip_uint32_t size, variable_size;
     zip_uint16_t filename_len, comment_len, ef_len;
 
-    if (local)
-       size = LENTRYSIZE;
-    else
-       size = CDENTRYSIZE;
-
-    if (leftp && (*leftp < size)) {
-       _zip_error_set(error, ZIP_ER_NOZIP, 0);
-       return -1;
-    }
+    bool from_buffer = (buffer != NULL);
+    
+    size = local ? LENTRYSIZE : CDENTRYSIZE;
 
-    if (bufp) {
-       /* use data from buffer */
-       cur = *bufp;
+    if (buffer) {
+        if (_zip_buffer_left(buffer) < size) {
+            zip_error_set(error, ZIP_ER_NOZIP, 0);
+            return -1;
+        }
     }
     else {
-       /* read entry from disk */
-       if ((fread(buf, 1, size, fp)<size)) {
-           _zip_error_set(error, ZIP_ER_READ, errno);
-           return -1;
-       }
-       cur = buf;
+        if ((buffer = _zip_buffer_new_from_source(src, size, buf, error)) == NULL) {
+            return -1;
+        }
     }
 
-    if (memcmp(cur, (local ? LOCAL_MAGIC : CENTRAL_MAGIC), 4) != 0) {
-       _zip_error_set(error, ZIP_ER_NOZIP, 0);
+    if (memcmp(_zip_buffer_get(buffer, 4), (local ? LOCAL_MAGIC : CENTRAL_MAGIC), 4) != 0) {
+       zip_error_set(error, ZIP_ER_NOZIP, 0);
+        if (!from_buffer) {
+            _zip_buffer_free(buffer);
+        }
        return -1;
     }
-    cur += 4;
-
 
     /* convert buffercontents to zip_dirent */
 
     _zip_dirent_init(zde);
     if (!local)
-       zde->version_madeby = _zip_read2(&cur);
+       zde->version_madeby = _zip_buffer_get_16(buffer);
     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_buffer_get_16(buffer);
+    zde->bitflags = _zip_buffer_get_16(buffer);
+    zde->comp_method = _zip_buffer_get_16(buffer);
+    
     /* convert to time_t */
-    dostime = _zip_read2(&cur);
-    dosdate = _zip_read2(&cur);
+    dostime = _zip_buffer_get_16(buffer);
+    dosdate = _zip_buffer_get_16(buffer);
     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);
-
-    filename_len = _zip_read2(&cur);
-    ef_len = _zip_read2(&cur);
-
+    
+    zde->crc = _zip_buffer_get_32(buffer);
+    zde->comp_size = _zip_buffer_get_32(buffer);
+    zde->uncomp_size = _zip_buffer_get_32(buffer);
+    
+    filename_len = _zip_buffer_get_16(buffer);
+    ef_len = _zip_buffer_get_16(buffer);
+    
     if (local) {
        comment_len = 0;
        zde->disk_number = 0;
@@ -394,44 +357,78 @@ _zip_dirent_read(struct zip_dirent *zde, FILE *fp,
        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_buffer_get_16(buffer);
+       zde->disk_number = _zip_buffer_get_16(buffer);
+       zde->int_attrib = _zip_buffer_get_16(buffer);
+       zde->ext_attrib = _zip_buffer_get_32(buffer);
+       zde->offset = _zip_buffer_get_32(buffer);
+    }
+    
+    if (!_zip_buffer_ok(buffer)) {
+        zip_error_set(error, ZIP_ER_INTERNAL, 0);
+        if (!from_buffer) {
+            _zip_buffer_free(buffer);
+        }
+        return -1;
     }
 
     zde->filename = NULL;
     zde->extra_fields = NULL;
     zde->comment = NULL;
 
-    size += filename_len+ef_len+comment_len;
+    variable_size = (zip_uint32_t)filename_len+(zip_uint32_t)ef_len+(zip_uint32_t)comment_len;
 
-    if (leftp && (*leftp < size)) {
-       _zip_error_set(error, ZIP_ER_INCONS, 0);
-       return -1;
+    if (from_buffer) {
+        if (_zip_buffer_left(buffer) < variable_size) {
+            zip_error_set(error, ZIP_ER_INCONS, 0);
+            return -1;
+        }
+    }
+    else {
+        _zip_buffer_free(buffer);
+        
+        if ((buffer = _zip_buffer_new_from_source(src, variable_size, NULL, error)) == NULL) {
+            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(buffer, src, filename_len, 1, error);
+        if (!zde->filename) {
+            if (zip_error_code_zip(error) == ZIP_ER_EOF) {
+                zip_error_set(error, ZIP_ER_INCONS, 0);
+            }
+            if (!from_buffer) {
+                _zip_buffer_free(buffer);
+            }
            return -1;
+        }
 
        if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) {
            if (_zip_guess_encoding(zde->filename, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) {
-               _zip_error_set(error, ZIP_ER_INCONS, 0);
+               zip_error_set(error, ZIP_ER_INCONS, 0);
+                if (!from_buffer) {
+                    _zip_buffer_free(buffer);
+                }
                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(buffer, src, ef_len, 0, error);
 
-       if (ef == NULL)
+        if (ef == NULL) {
+            if (!from_buffer) {
+                _zip_buffer_free(buffer);
+            }
            return -1;
-       if ((zde->extra_fields=_zip_ef_parse(ef, ef_len, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, error)) == NULL) {
+        }
+        if ((zde->extra_fields=_zip_ef_parse(ef, ef_len, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, error)) == NULL) {
            free(ef);
+            if (!from_buffer) {
+                _zip_buffer_free(buffer);
+            }
            return -1;
        }
        free(ef);
@@ -440,13 +437,19 @@ _zip_dirent_read(struct zip_dirent *zde, FILE *fp,
     }
 
     if (comment_len) {
-       zde->comment = _zip_read_string(bufp ? &cur : NULL, fp, comment_len, 0, error);
-       if (!zde->comment)
+       zde->comment = _zip_read_string(buffer, src, comment_len, 0, error);
+        if (!zde->comment) {
+            if (!from_buffer) {
+                _zip_buffer_free(buffer);
+            }
            return -1;
-
+        }
        if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) {
            if (_zip_guess_encoding(zde->comment, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) {
-               _zip_error_set(error, ZIP_ER_INCONS, 0);
+               zip_error_set(error, ZIP_ER_INCONS, 0);
+                if (!from_buffer) {
+                    _zip_buffer_free(buffer);
+                }
                return -1;
            }
        }
@@ -458,172 +461,145 @@ _zip_dirent_read(struct zip_dirent *zde, FILE *fp,
     /* Zip64 */
 
     if (zde->uncomp_size == ZIP_UINT32_MAX || zde->comp_size == ZIP_UINT32_MAX || zde->offset == ZIP_UINT32_MAX) {
-       zip_uint16_t got_len, needed_len;
+       zip_uint16_t got_len;
+        zip_buffer_t *ef_buffer;
        const zip_uint8_t *ef = _zip_ef_get_by_id(zde->extra_fields, &got_len, ZIP_EF_ZIP64, 0, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, error);
        /* TODO: if got_len == 0 && !ZIP64_EOCD: no error, 0xffffffff is valid value */
-       if (ef == NULL)
-           return -1;
-
-
-       if (local)
-           needed_len = 16;
-       else
-           needed_len = ((zde->uncomp_size == ZIP_UINT32_MAX) + (zde->comp_size == ZIP_UINT32_MAX) + (zde->offset == ZIP_UINT32_MAX)) * 8
-               + (zde->disk_number == ZIP_UINT16_MAX) * 4;
-
-       if (got_len != needed_len) {
-           _zip_error_set(error, ZIP_ER_INCONS, 0);
+        if (ef == NULL) {
+            if (!from_buffer) {
+                _zip_buffer_free(buffer);
+            }
            return -1;
-       }
-
+        }
+        
+        if ((ef_buffer = _zip_buffer_new((zip_uint8_t *)ef, got_len)) == NULL) {
+            zip_error_set(error, ZIP_ER_MEMORY, 0);
+            if (!from_buffer) {
+                _zip_buffer_free(buffer);
+            }
+            return -1;
+        }
+       
        if (zde->uncomp_size == ZIP_UINT32_MAX)
-           zde->uncomp_size = _zip_read8(&ef);
+           zde->uncomp_size = _zip_buffer_get_64(ef_buffer);
        else if (local)
            ef += 8;
        if (zde->comp_size == ZIP_UINT32_MAX)
-           zde->comp_size = _zip_read8(&ef);
+           zde->comp_size = _zip_buffer_get_64(ef_buffer);
        if (!local) {
            if (zde->offset == ZIP_UINT32_MAX)
-               zde->offset = _zip_read8(&ef);
+               zde->offset = _zip_buffer_get_64(ef_buffer);
            if (zde->disk_number == ZIP_UINT16_MAX)
-               zde->disk_number = _zip_read4(&ef);
+               zde->disk_number = _zip_buffer_get_32(buffer);
        }
-    }
-
-    if (!local) {
-        if (zde->offset > ZIP_OFF_MAX) {
-            _zip_error_set(error, ZIP_ER_SEEK, EFBIG);
+        
+        if (!_zip_buffer_eof(ef_buffer)) {
+            zip_error_set(error, ZIP_ER_INCONS, 0);
+            _zip_buffer_free(ef_buffer);
+            if (!from_buffer) {
+                _zip_buffer_free(buffer);
+            }
             return -1;
         }
+        _zip_buffer_free(ef_buffer);
+    }
+    
+    if (!_zip_buffer_ok(buffer)) {
+        zip_error_set(error, ZIP_ER_INTERNAL, 0);
+        if (!from_buffer) {
+            _zip_buffer_free(buffer);
+        }
+        return -1;
+    }
+    if (!from_buffer) {
+        _zip_buffer_free(buffer);
     }
 
+    /* zip_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);
 
-    if (bufp)
-      *bufp = cur;
-    if (leftp)
-       *leftp -= size;
-
-    return 0;
+    return (zip_int64_t)(size + variable_size);
 }
 
 
-
-static struct zip_string *
-_zip_dirent_process_ef_utf_8(const struct zip_dirent *de, zip_uint16_t id, struct zip_string *str)
+static zip_string_t *
+_zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string_t *str)
 {
     zip_uint16_t ef_len;
     zip_uint32_t ef_crc;
+    zip_buffer_t *buffer;
 
     const zip_uint8_t *ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, id, 0, ZIP_EF_BOTH, NULL);
-
-    if (ef == NULL || ef_len < 5 || ef[0] != 1)
+    
+    if (ef == NULL || ef_len < 5 || ef[0] != 1) {
        return str;
-
-    ef++;
-    ef_crc = _zip_read4(&ef);
+    }
+    
+    if ((buffer = _zip_buffer_new((zip_uint8_t *)ef, ef_len)) == NULL) {
+        return str;
+    }
+    
+    _zip_buffer_get_8(buffer);
+    ef_crc = _zip_buffer_get_32(buffer);
 
     if (_zip_string_crc32(str) == ef_crc) {
-       struct zip_string *ef_str = _zip_string_new(ef, ef_len-5, ZIP_ENCODING_UTF8_KNOWN, NULL);
+        zip_uint16_t len = (zip_uint16_t)_zip_buffer_left(buffer);
+        zip_string_t *ef_str = _zip_string_new(_zip_buffer_get(buffer, len), len, ZIP_FL_ENC_UTF_8, NULL);
 
        if (ef_str != NULL) {
            _zip_string_free(str);
            str = ef_str;
        }
     }
-
+    
+    _zip_buffer_free(buffer);
+    
     return str;
 }
 
 
-
 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);
+    bool local = (flags & ZIP_EF_LOCAL) != 0;
     int i;
-    unsigned char b[6];
-    const unsigned char *p;
+    zip_uint8_t b[6];
+    zip_buffer_t *buffer;
 
     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 ((buffer = _zip_buffer_new_from_source(src, local ? 4 : 6, b, error)) == NULL) {
        return -1;
     }
 
-    p = b;
     for (i=0; i<(local ? 2 : 3); i++) {
-       size += _zip_read2(&p);
+       size += _zip_buffer_get_16(buffer);
     }
-
-    return size;
-}
-
-
-
-/* _zip_dirent_torrent_normalize(de);
-   Set values suitable for torrentzip.
-*/
-
-void
-_zip_dirent_torrent_normalize(struct zip_dirent *de)
-{
-    static struct tm torrenttime;
-    static time_t last_mod = 0;
-
-    if (last_mod == 0) {
-#ifdef HAVE_STRUCT_TM_TM_ZONE
-       time_t now;
-       struct tm *l;
-#endif
-
-       torrenttime.tm_sec = 0;
-       torrenttime.tm_min = 32;
-       torrenttime.tm_hour = 23;
-       torrenttime.tm_mday = 24;
-       torrenttime.tm_mon = 11;
-       torrenttime.tm_year = 96;
-       torrenttime.tm_wday = 0;
-       torrenttime.tm_yday = 0;
-       torrenttime.tm_isdst = 0;
-
-#ifdef HAVE_STRUCT_TM_TM_ZONE
-       time(&now);
-       l = localtime(&now);
-       torrenttime.tm_gmtoff = l->tm_gmtoff;
-       torrenttime.tm_zone = l->tm_zone;
-#endif
-
-       last_mod = mktime(&torrenttime);
+    
+    if (!_zip_buffer_eof(buffer)) {
+        zip_error_set(error, ZIP_ER_INTERNAL, 0);
+       _zip_buffer_free(buffer);
+        return -1;
     }
 
-    de->version_madeby = 0;
-    de->version_needed = 20; /* 2.0 */
-    de->bitflags = 2; /* maximum compression */
-    de->comp_method = ZIP_CM_DEFLATE;
-    de->last_mod = last_mod;
-
-    de->disk_number = 0;
-    de->int_attrib = 0;
-    de->ext_attrib = 0;
-
-    _zip_ef_free(de->extra_fields);
-    de->extra_fields = NULL;
-    _zip_string_free(de->comment);
-    de->comment = NULL;
+    _zip_buffer_free(buffer);
+    return size;
 }
 
 
-
-/* _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.
@@ -633,20 +609,20 @@ _zip_dirent_torrent_normalize(struct zip_dirent *de)
 */
 
 int
-_zip_dirent_write(struct zip_dirent *de, FILE *fp, zip_flags_t flags, struct zip_error *error)
+_zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags)
 {
-    unsigned short 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_uint16_t dostime, dosdate;
+    zip_encoding_type_t com_enc, name_enc;
+    zip_extra_field_t *ef;
+    bool is_zip64;
+    bool is_really_zip64;
+    zip_uint8_t buf[CDENTRYSIZE];
+    zip_buffer_t *buffer;
+    zip_uint32_t ef_total_size;
 
     ef = NULL;
 
-    is_zip64 = 0;
-
-    fwrite((flags & ZIP_FL_LOCAL) ? LOCAL_MAGIC : CENTRAL_MAGIC, 1, 4, fp);
+    is_zip64 = false;
 
     name_enc = _zip_guess_encoding(de->filename, ZIP_ENCODING_UNKNOWN);
     com_enc = _zip_guess_encoding(de->comment, ZIP_ENCODING_UNKNOWN);
@@ -656,14 +632,14 @@ _zip_dirent_write(struct zip_dirent *de, FILE *fp, zip_flags_t flags, struct zip
        (name_enc == ZIP_ENCODING_UTF8_KNOWN  && com_enc == ZIP_ENCODING_UTF8_KNOWN))
        de->bitflags |= ZIP_GPBF_ENCODING_UTF_8;
     else {
-       de->bitflags &= ~ZIP_GPBF_ENCODING_UTF_8;
+       de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCODING_UTF_8;
        if (name_enc == ZIP_ENCODING_UTF8_KNOWN) {
-           ef = _zip_ef_utf8(ZIP_EF_UTF_8_NAME, de->filename, 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);
+           zip_extra_field_t *ef2 = _zip_ef_utf8(ZIP_EF_UTF_8_COMMENT, de->comment, &za->error);
            if (ef2 == NULL) {
                _zip_ef_free(ef);
                return -1;
@@ -672,106 +648,172 @@ _zip_dirent_write(struct zip_dirent *de, FILE *fp, zip_flags_t flags, struct zip
            ef = ef2;
        }
     }
+    
+    is_really_zip64 = _zip_dirent_needs_zip64(de, flags);
+    is_zip64 = (flags & (ZIP_FL_LOCAL|ZIP_FL_FORCE_ZIP64)) == (ZIP_FL_LOCAL|ZIP_FL_FORCE_ZIP64) || is_really_zip64;
+    
+    if (is_zip64) {
+        zip_uint8_t ef_zip64[EFZIP64SIZE];
+        zip_buffer_t *ef_buffer = _zip_buffer_new(ef_zip64, sizeof(ef_zip64));
+        zip_extra_field_t *ef64;
+        if (ef_buffer == NULL) {
+            zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+           _zip_ef_free(ef);
+            return -1;
+        }
+        
+        if (flags & ZIP_FL_LOCAL) {
+            if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX) {
+                _zip_buffer_put_64(ef_buffer, de->uncomp_size);
+                _zip_buffer_put_64(ef_buffer, de->comp_size);
+            }
+        }
+        else {
+            if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX || de->offset > ZIP_UINT32_MAX) {
+                if (de->uncomp_size >= ZIP_UINT32_MAX) {
+                    _zip_buffer_put_64(ef_buffer, de->uncomp_size);
+                }
+                if (de->comp_size >= ZIP_UINT32_MAX) {
+                    _zip_buffer_put_64(ef_buffer, de->comp_size);
+                }
+                if (de->offset >= ZIP_UINT32_MAX) {
+                    _zip_buffer_put_64(ef_buffer, de->offset);
+                }
+            }
+        }
+        
+        if (!_zip_buffer_ok(ef_buffer)) {
+            zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+            _zip_buffer_free(ef_buffer);
+           _zip_ef_free(ef);
+            return -1;
+        }
 
-    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);
-       }
-    }
-    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->comp_size >= ZIP_UINT32_MAX)
-               _zip_poke8(de->comp_size, &ef_zip64_p);
-           if (de->uncomp_size >= ZIP_UINT32_MAX)
-               _zip_poke8(de->uncomp_size, &ef_zip64_p);
-           if (de->offset >= ZIP_UINT32_MAX)
-               _zip_poke8(de->offset, &ef_zip64_p);
-       }
+        ef64 = _zip_ef_new(ZIP_EF_ZIP64, (zip_uint16_t)(_zip_buffer_offset(ef_buffer)), ef_zip64, ZIP_EF_BOTH);
+        _zip_buffer_free(ef_buffer);
+        ef64->next = ef;
+        ef = ef64;
     }
 
-    if (ef_zip64_p != ef_zip64) {
-       struct zip_extra_field *ef64 = _zip_ef_new(ZIP_EF_ZIP64, (zip_uint16_t)(ef_zip64_p-ef_zip64), ef_zip64, ZIP_EF_BOTH);
-       ef64->next = ef;
-       ef = ef64;
-       is_zip64 = 1;
+    if ((buffer = _zip_buffer_new(buf, sizeof(buf))) == NULL) {
+        zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+        _zip_ef_free(ef);
+        return -1;
     }
-
-    if ((flags & (ZIP_FL_LOCAL|ZIP_FL_FORCE_ZIP64)) == (ZIP_FL_LOCAL|ZIP_FL_FORCE_ZIP64))
-       is_really_zip64 = _zip_dirent_needs_zip64(de, flags);
-    else
-       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_buffer_put(buffer, (flags & ZIP_FL_LOCAL) ? LOCAL_MAGIC : CENTRAL_MAGIC, 4);
+    
+    if ((flags & ZIP_FL_LOCAL) == 0) {
+        _zip_buffer_put_16(buffer, (zip_uint16_t)(is_really_zip64 ? 45 : de->version_madeby));
+    }
+    _zip_buffer_put_16(buffer, (zip_uint16_t)(is_really_zip64 ? 45 : de->version_needed));
+    _zip_buffer_put_16(buffer, de->bitflags&0xfff9); /* clear compression method specific flags */
+    _zip_buffer_put_16(buffer, (zip_uint16_t)de->comp_method);
 
     _zip_u2d_time(de->last_mod, &dostime, &dosdate);
-    _zip_write2(dostime, fp);
-    _zip_write2(dosdate, fp);
-
-    _zip_write4(de->crc, fp);
-    if (de->comp_size < ZIP_UINT32_MAX)
-       _zip_write4((zip_uint32_t)de->comp_size, fp);
-    else
-       _zip_write4(ZIP_UINT32_MAX, fp);
-    if (de->uncomp_size < ZIP_UINT32_MAX)
-       _zip_write4((zip_uint32_t)de->uncomp_size, fp);
-    else
-       _zip_write4(ZIP_UINT32_MAX, fp);
-
-    _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_buffer_put_16(buffer, dostime);
+    _zip_buffer_put_16(buffer, dosdate);
+
+    _zip_buffer_put_32(buffer, de->crc);
+    
+    if (((flags & ZIP_FL_LOCAL) == ZIP_FL_LOCAL) && ((de->comp_size >= ZIP_UINT32_MAX) || (de->uncomp_size >= ZIP_UINT32_MAX))) {
+       /* In local headers, if a ZIP64 EF is written, it MUST contain
+        * both compressed and uncompressed sizes (even if one of the
+        * two is smaller than 0xFFFFFFFF); on the other hand, those
+        * may only appear when the corresponding standard entry is
+        * 0xFFFFFFFF.  (appnote.txt 4.5.3) */
+       _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
+       _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
+    }
+    else {
+        if (de->comp_size < ZIP_UINT32_MAX) {
+           _zip_buffer_put_32(buffer, (zip_uint32_t)de->comp_size);
+        }
+        else {
+           _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
+        }
+        if (de->uncomp_size < ZIP_UINT32_MAX) {
+           _zip_buffer_put_32(buffer, (zip_uint32_t)de->uncomp_size);
+        }
+        else {
+           _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
+        }
+    }
 
+    _zip_buffer_put_16(buffer, _zip_string_length(de->filename));
+    /* TODO: check for overflow */
+    ef_total_size = (zip_uint32_t)_zip_ef_size(de->extra_fields, flags) + (zip_uint32_t)_zip_ef_size(ef, ZIP_EF_BOTH);
+    _zip_buffer_put_16(buffer, (zip_uint16_t)ef_total_size);
+    
     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_buffer_put_16(buffer, _zip_string_length(de->comment));
+       _zip_buffer_put_16(buffer, (zip_uint16_t)de->disk_number);
+       _zip_buffer_put_16(buffer, de->int_attrib);
+       _zip_buffer_put_32(buffer, de->ext_attrib);
        if (de->offset < ZIP_UINT32_MAX)
-           _zip_write4((zip_uint32_t)de->offset, fp);
+           _zip_buffer_put_32(buffer, (zip_uint32_t)de->offset);
        else
-           _zip_write4(ZIP_UINT32_MAX, fp);
+           _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
+    }
+    
+    if (!_zip_buffer_ok(buffer)) {
+        zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+        _zip_buffer_free(buffer);
+        _zip_ef_free(ef);
+        return -1;
     }
 
-    if (de->filename)
-       _zip_string_write(de->filename, fp);
-
-    if (ef)
-       _zip_ef_write(ef, ZIP_EF_BOTH, fp);
-    if (de->extra_fields)
-       _zip_ef_write(de->extra_fields, flags, fp);
+    if (_zip_write(za, buf, _zip_buffer_offset(buffer)) < 0) {
+        _zip_buffer_free(buffer);
+        _zip_ef_free(ef);
+        return -1;
+    }
+    
+    _zip_buffer_free(buffer);
 
-    if ((flags & ZIP_FL_LOCAL) == 0) {
-       if (de->comment)
-           _zip_string_write(de->comment, fp);
+    if (de->filename) {
+       if (_zip_string_write(za, de->filename) < 0) {
+            _zip_ef_free(ef);
+           return -1;
+       }
     }
 
+    if (ef) {
+       if (_zip_ef_write(za, ef, ZIP_EF_BOTH) < 0) {
+            _zip_ef_free(ef);
+           return -1;
+       }
+    }
     _zip_ef_free(ef);
+    if (de->extra_fields) {
+       if (_zip_ef_write(za, de->extra_fields, flags) < 0) {
+           return -1;
+       }
+    }
 
-    if (ferror(fp)) {
-       _zip_error_set(error, ZIP_ER_WRITE, errno);
-       return -1;
+    if ((flags & ZIP_FL_LOCAL) == 0) {
+       if (de->comment) {
+           if (_zip_string_write(za, de->comment) < 0) {
+               return -1;
+           }
+       }
     }
 
+
     return is_zip64;
 }
 
 
-
 static time_t
 _zip_d2u_time(zip_uint16_t dtime, zip_uint16_t ddate)
 {
     struct tm tm;
 
     memset(&tm, 0, sizeof(tm));
-
+    
     /* let mktime decide if DST is in effect */
     tm.tm_isdst = -1;
-
+    
     tm.tm_year = ((ddate>>9)&127) + 1980 - 1900;
     tm.tm_mon = ((ddate>>5)&15) - 1;
     tm.tm_mday = ddate&31;
@@ -784,57 +826,61 @@ _zip_d2u_time(zip_uint16_t dtime, zip_uint16_t ddate)
 }
 
 
-
-static struct zip_extra_field *
-_zip_ef_utf8(zip_uint16_t id, struct zip_string *str, struct zip_error *error)
+static zip_extra_field_t *
+_zip_ef_utf8(zip_uint16_t id, zip_string_t *str, zip_error_t *error)
 {
     const zip_uint8_t *raw;
-    zip_uint8_t *data, *p;
     zip_uint32_t len;
-    struct zip_extra_field *ef;
+    zip_buffer_t *buffer;
+    zip_extra_field_t *ef;
 
     raw = _zip_string_get(str, &len, ZIP_FL_ENC_RAW, NULL);
 
     if (len+5 > ZIP_UINT16_MAX) {
-        /* TODO: error */
+        zip_error_set(error, ZIP_ER_INVAL, 0); /* TODO: better error code? */
+        return NULL;
     }
-
-    if ((data=(zip_uint8_t *)malloc(len+5)) == NULL) {
-       _zip_error_set(error, ZIP_ER_MEMORY, 0);
+    
+    if ((buffer = _zip_buffer_new(NULL, len+5)) == NULL) {
+       zip_error_set(error, ZIP_ER_MEMORY, 0);
        return NULL;
     }
 
-    p = data;
-    *(p++) = 1;
-    _zip_poke4(_zip_string_crc32(str), &p);
-    memcpy(p, raw, len);
-    p += len;
+    _zip_buffer_put_8(buffer, 1);
+    _zip_buffer_put_32(buffer, _zip_string_crc32(str));
+    _zip_buffer_put(buffer, raw, len);
+
+    if (!_zip_buffer_ok(buffer)) {
+        zip_error_set(error, ZIP_ER_INTERNAL, 0);
+        _zip_buffer_free(buffer);
+        return NULL;
+    }
+    
+    ef = _zip_ef_new(id, (zip_uint16_t)(_zip_buffer_offset(buffer)), _zip_buffer_data(buffer), ZIP_EF_BOTH);
+    _zip_buffer_free(buffer);
 
-    ef = _zip_ef_new(id, (zip_uint16_t)(p-data), data, ZIP_EF_BOTH);
-    free(data);
     return ef;
 }
 
 
-
-struct zip_dirent *
-_zip_get_dirent(struct zip *za, zip_uint64_t idx, zip_flags_t flags, struct zip_error *error)
+zip_dirent_t *
+_zip_get_dirent(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *error)
 {
     if (error == NULL)
        error = &za->error;
 
     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;
@@ -845,179 +891,13 @@ _zip_get_dirent(struct zip *za, zip_uint64_t idx, zip_flags_t flags, struct zip_
 
 
 
-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
-_zip_u2d_time(time_t time, zip_uint16_t *dtime, zip_uint16_t *ddate)
+_zip_u2d_time(time_t intime, zip_uint16_t *dtime, zip_uint16_t *ddate)
 {
     struct tm *tm;
 
-    tm = localtime(&time);
+    tm = localtime(&intime);
     *ddate = (zip_uint16_t)(((tm->tm_year+1900-1980)<<9) + ((tm->tm_mon+1)<<5) + tm->tm_mday);
     *dtime = (zip_uint16_t)(((tm->tm_hour)<<11) + ((tm->tm_min)<<5) + ((tm->tm_sec)>>1));
 
index 5b36df8b0ba76dc9720a6b431eb2d0cebc47e7d5..db22370842c59ad12e6b67450fc4e8bbd738c81c 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_discard.c -- discard and free struct zip
-  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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <stdlib.h>
 
 #include "zipint.h"
 
 
-
 /* zip_discard:
    frees the space allocated to a zipfile struct, and closes the
    corresponding file. */
 
 void
-zip_discard(struct zip *za)
+zip_discard(zip_t *za)
 {
     zip_uint64_t i;
 
     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);
@@ -67,16 +64,13 @@ zip_discard(struct zip *za)
        free(za->entry);
     }
 
-    for (i=0; i<za->nfile; i++) {
-       if (za->file[i]->error.zip_err == ZIP_ER_OK) {
-           _zip_error_set(&za->file[i]->error, ZIP_ER_ZIPCLOSED, 0);
-           za->file[i]->za = NULL;
-       }
+    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->file);
-
+    zip_error_fini(&za->error);
+    
     free(za);
 
     return;
index 2f41b2a470be73ec6f2dc89f5d0f07de571f2031..6f890068618d9e02e04045c6404d26a36c074bcc 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
 void
-_zip_entry_finalize(struct zip_entry *e)
+_zip_entry_finalize(zip_entry_t *e)
 {
     _zip_unchange_data(e);
     _zip_dirent_free(e->orig);
@@ -44,9 +43,8 @@ _zip_entry_finalize(struct zip_entry *e)
 }
 
 
-
 void
-_zip_entry_init(struct zip_entry *e)
+_zip_entry_init(zip_entry_t *e)
 {
     e->orig = NULL;
     e->changes = NULL;
index deac7004ba17b10445f9d0bcedba2aa9e50521cf..65698be00e46422a828ae99c1ba1b84556ed3d08 100644 (file)
@@ -5,8 +5,6 @@
 
 #include "zipint.h"
 
-
-
 const char * const _zip_err_str[] = {
     "No error",
     "Multi-disk zip archives not supported",
@@ -25,7 +23,7 @@ const char * const _zip_err_str[] = {
     "Malloc failure",
     "Entry has been changed",
     "Compression method not supported",
-    "Premature EOF",
+    "Premature end of file",
     "Invalid argument",
     "Not a zip archive",
     "Internal error",
@@ -33,9 +31,12 @@ const char * const _zip_err_str[] = {
     "Can't remove file",
     "Entry has been deleted",
     "Encryption method not supported",
-    "Read-only archive",
+    "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]);
@@ -70,7 +71,10 @@ const int _zip_err_type[] = {
     S,
     N,
     N,
+    N, 
     N,
     N,
     N,
+    N,
+    S,
 };
index 9287b968a942d363389199ff3e0b169ab1889744..a21a00bc2992c6d06ac3215475698204631ea912 100644 (file)
@@ -1,6 +1,6 @@
 /*
-  zip_error.c -- struct zip_error helper functions
-  Copyright (C) 1999-2015 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>
@@ -17,7 +17,7 @@
   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
   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-
-
+#include <errno.h>
 #include <stdlib.h>
 
 #include "zipint.h"
 
 
+ZIP_EXTERN int
+zip_error_code_system(const zip_error_t *error) {
+    return error->sys_err;
+}
 
-void
-_zip_error_clear(struct zip_error *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)
 {
-    if (err == NULL)
-       return;
+    free(err->str);
+    err->str = NULL;
+}
+
 
+ZIP_EXTERN void
+zip_error_init(zip_error_t *err)
+{
     err->zip_err = ZIP_ER_OK;
     err->sys_err = 0;
+    err->str = NULL;
+}
+
+ZIP_EXTERN void
+zip_error_init_with_code(zip_error_t *error, int ze)
+{
+    zip_error_init(error);
+    error->zip_err = ze;
+    switch (zip_error_system_type(error)) {
+    case ZIP_ET_SYS:
+       error->sys_err = errno;
+       break;
+
+    default:
+       error->sys_err = 0;
+       break;
+    }  
 }
 
 
+ZIP_EXTERN int
+zip_error_system_type(const zip_error_t *error) {
+    if (error->zip_err < 0 || error->zip_err >= _zip_nerr_str)
+        return ZIP_ET_NONE;
+    
+    return _zip_err_type[error->zip_err];
+}
+
 
 void
-_zip_error_copy(struct zip_error *dst, const struct zip_error *src)
+_zip_error_clear(zip_error_t *err)
 {
-    dst->zip_err = src->zip_err;
-    dst->sys_err = src->sys_err;
-}
+    if (err == NULL)
+       return;
 
+    err->zip_err = ZIP_ER_OK;
+    err->sys_err = 0;
+}
 
 
 void
-_zip_error_fini(struct zip_error *err)
+_zip_error_copy(zip_error_t *dst, const zip_error_t *src)
 {
-    free(err->str);
-    err->str = NULL;
+    dst->zip_err = src->zip_err;
+    dst->sys_err = src->sys_err;
 }
 
 
-
 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;
@@ -83,19 +124,8 @@ _zip_error_get(const struct zip_error *err, int *zep, int *sep)
 }
 
 
-
 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;
@@ -104,12 +134,23 @@ _zip_error_set(struct zip_error *err, int ze, int se)
 }
 
 
-
 void
-_zip_error_set_from_source(struct zip_error *err, struct zip_source *src)
+_zip_error_set_from_source(zip_error_t *err, zip_source_t *src)
 {
-    int ze, se;
+    _zip_error_copy(err, zip_source_error(src));
+}
 
-    zip_source_error(src, &ze, &se);
-    _zip_error_set(err, ze, se);
+
+zip_int64_t
+zip_error_to_data(const zip_error_t *error, void *data, zip_uint64_t length)
+{
+    int *e = (int *)data;
+    
+    if (length < sizeof(int)*2) {
+        return -1;
+    }
+    
+    e[0] = zip_error_code_zip(error);
+    e[1] = zip_error_code_system(error);
+    return sizeof(int)*2;
 }
index d7b32f963198bdb4bc9a2b8569ebdc8a48088df0..ec45e688e57afdcf0c1905be768b73090605607f 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
 
-
 ZIP_EXTERN void
-zip_error_clear(struct zip *za)
+zip_error_clear(zip_t *za)
 {
     if (za == NULL)
        return;
index 930610df322f620c4ef63f936e121f77b1ad8cd7..c222018993afb389832496c7632f33dc5432ef56 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   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
 */
 
 
-
+#define _ZIP_COMPILING_DEPRECATED
 #include "zipint.h"
 
 
-
 ZIP_EXTERN void
-zip_error_get(struct zip *za, int *zep, int *sep)
+zip_error_get(zip_t *za, int *zep, int *sep)
 {
     _zip_error_get(&za->error, zep, sep);
 }
+
+
+ZIP_EXTERN zip_error_t *
+zip_get_error(zip_t *za)
+{
+    return &za->error;
+}
+
+
+ZIP_EXTERN zip_error_t *
+zip_file_get_error(zip_file_t *f)
+{
+    return &f->error;
+}
index 22087199b6f93172046e0b4c159d390c1039761d..7e27bbf332f7428e6a62720a94a2e4a1cf97035f 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   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
   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-
-
+#define _ZIP_COMPILING_DEPRECATED
 #include "zipint.h"
 
 
-
 ZIP_EXTERN int
 zip_error_get_sys_type(int ze)
 {
index 74e49258dd8b08960b8328c3e049a5dbc822f8de..2f124ccd46675816e822d09e2bfa25c1cbb0c8f0 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   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
@@ -32,7 +32,6 @@
 */
 
 
-
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include "zipint.h"
 
 
-
-const char *
-_zip_error_strerror(struct zip_error *err)
+ZIP_EXTERN const char *
+zip_error_strerror(zip_error_t *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);
@@ -57,7 +55,7 @@ _zip_error_strerror(struct zip_error *err)
     }
     else {
        zs = _zip_err_str[err->zip_err];
-
+       
        switch (_zip_err_type[err->zip_err]) {
        case ZIP_ET_SYS:
            ss = strerror(err->sys_err);
@@ -78,7 +76,7 @@ _zip_error_strerror(struct zip_error *err)
        if ((s=(char *)malloc(strlen(ss)
                              + (zs ? strlen(zs)+2 : 0) + 1)) == NULL)
            return _zip_err_str[ZIP_ER_MEMORY];
-
+       
        sprintf(s, "%s%s%s",
                (zs ? zs : ""),
                (zs ? ": " : ""),
index c61e2d0c9e0f7603d1ba9a4bff729f108261328d..d4119253f766ec9282ed64690b66a5c42c2c5749 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
+#define _ZIP_COMPILING_DEPRECATED
 #include "zipint.h"
 
 
-
 ZIP_EXTERN int
 zip_error_to_str(char *buf, zip_uint64_t len, int ze, int se)
 {
@@ -51,16 +50,16 @@ zip_error_to_str(char *buf, zip_uint64_t len, int ze, int se)
        return snprintf(buf, len, "Unknown error %d", ze);
 
     zs = _zip_err_str[ze];
-
+       
     switch (_zip_err_type[ze]) {
     case ZIP_ET_SYS:
        ss = strerror(se);
        break;
-
+       
     case ZIP_ET_ZLIB:
        ss = zError(se);
        break;
-
+       
     default:
        ss = NULL;
     }
index c2d4f30a40245140915388118ab2441f9cf75d3b..b2566c68875ba42a6dd324a504d976edc1efe410 100644 (file)
@@ -17,7 +17,7 @@
   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
@@ -32,7 +32,6 @@
 */
 
 
-
 #include "zipint.h"
 
 #include <errno.h>
 #include <string.h>
 
 
-
-struct zip_extra_field *
-_zip_ef_clone(const struct zip_extra_field *ef, struct zip_error *error)
+zip_extra_field_t *
+_zip_ef_clone(const zip_extra_field_t *ef, zip_error_t *error)
 {
-    struct zip_extra_field *head, *prev, *def;
-
+    zip_extra_field_t *head, *prev, *def;
+    
     head = prev = NULL;
-
+    
     while (ef) {
         if ((def=_zip_ef_new(ef->id, ef->size, ef->data, ef->flags)) == NULL) {
-            _zip_error_set(error, ZIP_ER_MEMORY, 0);
+            zip_error_set(error, ZIP_ER_MEMORY, 0);
             _zip_ef_free(head);
             return NULL;
         }
-
+        
         if (head == NULL)
             head = def;
         if (prev)
@@ -63,15 +61,15 @@ _zip_ef_clone(const struct zip_extra_field *ef, struct zip_error *error)
 
        ef = ef->next;
     }
-
+    
     return head;
 }
 
 
-struct zip_extra_field *
-_zip_ef_delete_by_id(struct zip_extra_field *ef, zip_uint16_t id, zip_uint16_t id_idx, zip_flags_t flags)
+zip_extra_field_t *
+_zip_ef_delete_by_id(zip_extra_field_t *ef, zip_uint16_t id, zip_uint16_t id_idx, zip_flags_t flags)
 {
-    struct zip_extra_field *head, *prev;
+    zip_extra_field_t *head, *prev;
     int i;
 
     i = 0;
@@ -93,7 +91,7 @@ _zip_ef_delete_by_id(struct zip_extra_field *ef, zip_uint16_t id, zip_uint16_t i
                        continue;
                }
            }
-
+           
            i++;
            if (i > id_idx)
                break;
@@ -106,11 +104,10 @@ _zip_ef_delete_by_id(struct zip_extra_field *ef, zip_uint16_t id, zip_uint16_t i
 
 
 
-
 void
-_zip_ef_free(struct zip_extra_field *ef)
+_zip_ef_free(zip_extra_field_t *ef)
 {
-    struct zip_extra_field *ef2;
+    zip_extra_field_t *ef2;
 
     while (ef) {
        ef2 = ef->next;
@@ -121,12 +118,11 @@ _zip_ef_free(struct zip_extra_field *ef)
 }
 
 
-
 const zip_uint8_t *
-_zip_ef_get_by_id(const struct zip_extra_field *ef, zip_uint16_t *lenp, zip_uint16_t id, zip_uint16_t id_idx, zip_flags_t flags, struct zip_error *error)
+_zip_ef_get_by_id(const zip_extra_field_t *ef, zip_uint16_t *lenp, zip_uint16_t id, zip_uint16_t id_idx, zip_flags_t flags, zip_error_t *error)
 {
     static const zip_uint8_t empty[1] = { '\0' };
-
+    
     int i;
 
     i = 0;
@@ -146,16 +142,15 @@ _zip_ef_get_by_id(const struct zip_extra_field *ef, zip_uint16_t *lenp, zip_uint
        }
     }
 
-    _zip_error_set(error, ZIP_ER_NOENT, 0);
+    zip_error_set(error, ZIP_ER_NOENT, 0);
     return NULL;
 }
 
 
-
-struct zip_extra_field *
-_zip_ef_merge(struct zip_extra_field *to, struct zip_extra_field *from)
+zip_extra_field_t *
+_zip_ef_merge(zip_extra_field_t *to, zip_extra_field_t *from)
 {
-    struct zip_extra_field *ef2, *tt, *tail;
+    zip_extra_field_t *ef2, *tt, *tail;
     int duplicate;
 
     if (to == NULL)
@@ -187,13 +182,12 @@ _zip_ef_merge(struct zip_extra_field *to, struct zip_extra_field *from)
 }
 
 
-
-struct zip_extra_field *
+zip_extra_field_t *
 _zip_ef_new(zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, zip_flags_t flags)
 {
-    struct zip_extra_field *ef;
+    zip_extra_field_t *ef;
 
-    if ((ef=(struct zip_extra_field *)malloc(sizeof(*ef))) == NULL)
+    if ((ef=(zip_extra_field_t *)malloc(sizeof(*ef))) == NULL)
        return NULL;
 
     ef->next = NULL;
@@ -213,33 +207,34 @@ _zip_ef_new(zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, zip_fla
 }
 
 
-
-struct zip_extra_field *
-_zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, struct zip_error *error)
+zip_extra_field_t *
+_zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_error_t *error)
 {
-    struct zip_extra_field *ef, *ef2, *ef_head;
-    const zip_uint8_t *p;
-    zip_uint16_t fid, flen;
-
-    ef_head = NULL;
-    for (p=data; p<data+len; p+=flen) {
-       if (p+4 > data+len) {
-           _zip_error_set(error, ZIP_ER_INCONS, 0);
-           _zip_ef_free(ef_head);
-           return NULL;
-       }
+    zip_buffer_t *buffer;
+    zip_extra_field_t *ef, *ef2, *ef_head;
 
-       fid = _zip_read2(&p);
-       flen = _zip_read2(&p);
-
-       if (p+flen > data+len) {
-           _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);
+    if ((buffer = _zip_buffer_new((zip_uint8_t *)data, len)) == NULL) {
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
+    }
+    
+    ef_head = ef = NULL;
+    
+    while (_zip_buffer_ok(buffer) && !_zip_buffer_eof(buffer)) {
+        zip_uint16_t fid, flen;
+        zip_uint8_t *ef_data;
+        
+        fid = _zip_buffer_get_16(buffer);
+       flen = _zip_buffer_get_16(buffer);
+        ef_data = _zip_buffer_get(buffer, flen);
+
+        if (ef_data == NULL) {
+            break;
+        }
+        
+       if ((ef2=_zip_ef_new(fid, flen, ef_data, flags)) == NULL) {
+           zip_error_set(error, ZIP_ER_MEMORY, 0);
+            _zip_buffer_free(buffer);
            _zip_ef_free(ef_head);
            return NULL;
        }
@@ -252,20 +247,28 @@ _zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, stru
            ef_head = ef = ef2;
     }
 
+    if (!_zip_buffer_eof(buffer)) {
+        zip_error_set(error, ZIP_ER_INCONS, 0);
+        _zip_buffer_free(buffer);
+        _zip_ef_free(ef_head);
+        return NULL;
+    }
+
+    _zip_buffer_free(buffer);
+    
     return ef_head;
 }
 
 
-
-struct zip_extra_field *
-_zip_ef_remove_internal(struct zip_extra_field *ef)
+zip_extra_field_t *
+_zip_ef_remove_internal(zip_extra_field_t *ef)
 {
-    struct zip_extra_field *ef_head;
-    struct zip_extra_field *prev, *next;
-
+    zip_extra_field_t *ef_head;
+    zip_extra_field_t *prev, *next;
+    
     ef_head = ef;
     prev = NULL;
-
+    
     while (ef) {
         if (ZIP_EF_IS_INTERNAL(ef->id)) {
             next = ef->next;
@@ -282,52 +285,74 @@ _zip_ef_remove_internal(struct zip_extra_field *ef)
             ef = ef->next;
         }
     }
-
+    
     return ef_head;
 }
 
 
 zip_uint16_t
-_zip_ef_size(const struct zip_extra_field *ef, zip_flags_t flags)
+_zip_ef_size(const zip_extra_field_t *ef, zip_flags_t flags)
 {
     zip_uint16_t size;
 
     size = 0;
     for (; ef; ef=ef->next) {
        if (ef->flags & flags & ZIP_EF_BOTH)
-           size += 4+ef->size;
+           size = (zip_uint16_t)(size+4+ef->size);
     }
 
     return size;
 }
 
 
-
-void
-_zip_ef_write(const struct zip_extra_field *ef, zip_flags_t flags, FILE *f)
+int
+_zip_ef_write(zip_t *za, const zip_extra_field_t *ef, zip_flags_t flags)
 {
+    zip_uint8_t b[4];
+    zip_buffer_t *buffer = _zip_buffer_new(b, sizeof(b));
+
+    if (buffer == NULL) {
+       return -1;
+    }
+
     for (; ef; ef=ef->next) {
        if (ef->flags & flags & ZIP_EF_BOTH) {
-           _zip_write2(ef->id, f);
-           _zip_write2(ef->size, f);
-           if (ef->size > 0)
-               fwrite(ef->data, ef->size, 1, f);
+            _zip_buffer_set_offset(buffer, 0);
+            _zip_buffer_put_16(buffer, ef->id);
+           _zip_buffer_put_16(buffer, ef->size);
+            if (!_zip_buffer_ok(buffer)) {
+                zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+                _zip_buffer_free(buffer);
+                return -1;
+            }
+           if (_zip_write(za, b, 4) < 0) {
+                _zip_buffer_free(buffer);
+                return -1;
+           }
+           if (ef->size > 0) {
+               if (_zip_write(za, ef->data, ef->size) < 0) {
+                    _zip_buffer_free(buffer);
+                    return -1;
+               }
+           }
        }
     }
+    
+    _zip_buffer_free(buffer);
+    return 0;
 }
 
 
-
 int
-_zip_read_local_ef(struct zip *za, zip_uint64_t idx)
+_zip_read_local_ef(zip_t *za, zip_uint64_t idx)
 {
-    struct zip_entry *e;
+    zip_entry_t *e;
     unsigned char b[4];
-    const unsigned char *p;
+    zip_buffer_t *buffer;
     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;
     }
 
@@ -336,31 +361,41 @@ _zip_read_local_ef(struct zip *za, zip_uint64_t idx)
     if (e->orig == NULL || e->orig->local_extra_fields_read)
        return 0;
 
-
-    if (fseeko(za->zp, (off_t)(e->orig->offset + 26), SEEK_SET) < 0) {
-       _zip_error_set(&za->error, ZIP_ER_SEEK, errno);
+    if (e->orig->offset + 26 > ZIP_INT64_MAX) {
+       zip_error_set(&za->error, ZIP_ER_SEEK, EFBIG);
        return -1;
-    }
+    }  
 
-    if (fread(b, sizeof(b), 1, za->zp) != 1) {
-       _zip_error_set(&za->error, ZIP_ER_READ, 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;
     }
-
-    p = b;
-    fname_len = _zip_read2(&p);
-    ef_len = _zip_read2(&p);
-
+    
+    if ((buffer = _zip_buffer_new_from_source(za->src, sizeof(b), b, &za->error)) == NULL) {
+        return -1;
+    }
+    
+    fname_len = _zip_buffer_get_16(buffer);
+    ef_len = _zip_buffer_get_16(buffer);
+    
+    if (!_zip_buffer_eof(buffer)) {
+        _zip_buffer_free(buffer);
+        zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+        return -1;
+    }
+    
+    _zip_buffer_free(buffer);
+    
     if (ef_len > 0) {
-       struct zip_extra_field *ef;
+       zip_extra_field_t *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;
@@ -370,13 +405,13 @@ _zip_read_local_ef(struct zip *za, zip_uint64_t idx)
            return -1;
        }
        free(ef_raw);
-
+       
         ef = _zip_ef_remove_internal(ef);
        e->orig->extra_fields = _zip_ef_merge(e->orig->extra_fields, ef);
     }
 
     e->orig->local_extra_fields_read = 1;
-
+    
     if (e->changes && e->changes->local_extra_fields_read == 0) {
        e->changes->extra_fields = e->orig->extra_fields;
        e->changes->local_extra_fields_read = 1;
index d0bba96e04f6d83ae80b041bd255e4ce7c1d8a2b..ed93944ac8773475cdd6284ddae7f80dae7089d1 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_extra_field_api.c -- public extra fields API functions
-  Copyright (C) 2012-2015 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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
 
-
 ZIP_EXTERN int
-zip_file_extra_field_delete(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_flags_t flags)
+zip_file_extra_field_delete(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_flags_t flags)
 {
-    struct zip_dirent *de;
+    zip_dirent_t *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;
     }
-
+    
     if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
        return -1;
-
+    
     if (ZIP_IS_RDONLY(za)) {
-       _zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+       zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
        return -1;
     }
 
     if (_zip_file_extra_field_prepare_for_change(za, idx) < 0)
         return -1;
-
+    
     de = za->entry[idx].changes;
-
+    
     de->extra_fields = _zip_ef_delete_by_id(de->extra_fields, ZIP_EXTRA_FIELD_ALL, ef_idx, flags);
     return 0;
 }
 
 
-
 ZIP_EXTERN int
-zip_file_extra_field_delete_by_id(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, zip_flags_t flags)
+zip_file_extra_field_delete_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, zip_flags_t flags)
 {
-    struct zip_dirent *de;
+    zip_dirent_t *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;
     }
-
+    
     if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
        return -1;
 
     if (ZIP_IS_RDONLY(za)) {
-       _zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+       zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
        return -1;
     }
-
+    
     if (_zip_file_extra_field_prepare_for_change(za, idx) < 0)
         return -1;
-
+    
     de = za->entry[idx].changes;
 
     de->extra_fields = _zip_ef_delete_by_id(de->extra_fields, ef_id, ef_idx, flags);
@@ -104,18 +101,17 @@ zip_file_extra_field_delete_by_id(struct zip *za, zip_uint64_t idx, zip_uint16_t
 }
 
 
-
 ZIP_EXTERN const zip_uint8_t *
-zip_file_extra_field_get(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_uint16_t *idp, zip_uint16_t *lenp, zip_flags_t flags)
+zip_file_extra_field_get(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_uint16_t *idp, zip_uint16_t *lenp, zip_flags_t flags)
 {
     static const zip_uint8_t empty[1] = { '\0' };
 
-    struct zip_dirent *de;
-    struct zip_extra_field *ef;
+    zip_dirent_t *de;
+    zip_extra_field_t *ef;
     int i;
 
     if ((flags & ZIP_EF_BOTH) == 0) {
-       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
        return NULL;
     }
 
@@ -145,20 +141,19 @@ zip_file_extra_field_get(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_idx,
        }
     }
 
-    _zip_error_set(&za->error, ZIP_ER_NOENT, 0);
+    zip_error_set(&za->error, ZIP_ER_NOENT, 0);
     return NULL;
 
 }
 
 
-
 ZIP_EXTERN const zip_uint8_t *
-zip_file_extra_field_get_by_id(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, zip_uint16_t *lenp, zip_flags_t flags)
+zip_file_extra_field_get_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, zip_uint16_t *lenp, zip_flags_t flags)
 {
-    struct zip_dirent *de;
+    zip_dirent_t *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;
     }
 
@@ -173,16 +168,15 @@ zip_file_extra_field_get_by_id(struct zip *za, zip_uint64_t idx, zip_uint16_t ef
 }
 
 
-
 ZIP_EXTERN zip_int16_t
-zip_file_extra_fields_count(struct zip *za, zip_uint64_t idx, zip_flags_t flags)
+zip_file_extra_fields_count(zip_t *za, zip_uint64_t idx, zip_flags_t flags)
 {
-    struct zip_dirent *de;
-    struct zip_extra_field *ef;
+    zip_dirent_t *de;
+    zip_extra_field_t *ef;
     zip_uint16_t n;
 
     if ((flags & ZIP_EF_BOTH) == 0) {
-       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
        return -1;
     }
 
@@ -202,16 +196,15 @@ zip_file_extra_fields_count(struct zip *za, zip_uint64_t idx, zip_flags_t flags)
 }
 
 
-
 ZIP_EXTERN zip_int16_t
-zip_file_extra_fields_count_by_id(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_flags_t flags)
+zip_file_extra_fields_count_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_flags_t flags)
 {
-    struct zip_dirent *de;
-    struct zip_extra_field *ef;
+    zip_dirent_t *de;
+    zip_extra_field_t *ef;
     zip_uint16_t n;
 
     if ((flags & ZIP_EF_BOTH) == 0) {
-       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
        return -1;
     }
 
@@ -231,36 +224,35 @@ zip_file_extra_fields_count_by_id(struct zip *za, zip_uint64_t idx, zip_uint16_t
 }
 
 
-
 ZIP_EXTERN int
-zip_file_extra_field_set(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags)
+zip_file_extra_field_set(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags)
 {
-    struct zip_dirent *de;
+    zip_dirent_t *de;
     zip_uint16_t ls, cs;
-    struct zip_extra_field *ef, *ef_prev, *ef_new;
+    zip_extra_field_t *ef, *ef_prev, *ef_new;
     int i, found, new_len;
 
     if ((flags & ZIP_EF_BOTH) == 0) {
-       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
        return -1;
     }
 
     if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
        return -1;
-
+    
     if (ZIP_IS_RDONLY(za)) {
-       _zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+       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;
     }
 
     if (_zip_file_extra_field_prepare_for_change(za, idx) < 0)
         return -1;
-
+    
     de = za->entry[idx].changes;
 
     ef = de->extra_fields;
@@ -280,7 +272,7 @@ zip_file_extra_field_set(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_id, z
     }
 
     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;
     }
 
@@ -299,12 +291,12 @@ zip_file_extra_field_set(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_id, z
     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;
     }
 
@@ -322,7 +314,7 @@ zip_file_extra_field_set(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_id, z
            ef->flags &= ~(flags & ZIP_EF_BOTH);
            ef_new->next = ef->next;
            ef->next = ef_new;
-       }
+       }           
     }
     else if (ef_prev) {
        ef_new->next = ef_prev->next;
@@ -330,24 +322,24 @@ zip_file_extra_field_set(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_id, z
     }
     else
        de->extra_fields = ef_new;
-
+    
     return 0;
 }
 
 
 
 int
-_zip_file_extra_field_prepare_for_change(struct zip *za, zip_uint64_t idx)
+_zip_file_extra_field_prepare_for_change(zip_t *za, zip_uint64_t idx)
 {
-    struct zip_entry *e;
-
+    zip_entry_t *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;
     }
-
+    
     e = za->entry+idx;
-
+    
     if (e->changes && (e->changes->changed & ZIP_DIRENT_EXTRA_FIELD))
         return 0;
 
@@ -355,20 +347,20 @@ _zip_file_extra_field_prepare_for_change(struct zip *za, zip_uint64_t idx)
        if (_zip_read_local_ef(za, idx) < 0)
            return -1;
     }
-
+    
     if (e->changes == NULL) {
         if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) {
-            _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+            zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
             return -1;
         }
     }
-
+    
     if (e->orig && e->orig->extra_fields) {
        if ((e->changes->extra_fields=_zip_ef_clone(e->orig->extra_fields, &za->error)) == NULL)
            return -1;
     }
     e->changes->changed |= ZIP_DIRENT_EXTRA_FIELD;
-
+    
     return 0;
 }
 
index f24f109cb25710e01be2823eabec1c65dab952c2..25a201b18734f535eeb7b4debbe39f45d53820d1 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_fclose.c -- close 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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <stdlib.h>
 
 #include "zipint.h"
 
 
-
 ZIP_EXTERN int
-zip_fclose(struct zip_file *zf)
+zip_fclose(zip_file_t *zf)
 {
     int ret;
-    unsigned int i;
-
+    
     if (zf->src)
        zip_source_free(zf->src);
 
-    if (zf->za) {
-        for (i=0; i<zf->za->nfile; i++) {
-            if (zf->za->file[i] == zf) {
-                zf->za->file[i] = zf->za->file[zf->za->nfile-1];
-                zf->za->nfile--;
-                break;
-            }
-        }
-    }
-
     ret = 0;
     if (zf->error.zip_err)
        ret = zf->error.zip_err;
 
-    _zip_error_fini(&zf->error);
+    zip_error_fini(&zf->error);
     free(zf);
     return ret;
 }
index edeaa56488ee8c05eafe9e4a22d3e389b2fcde60..c5b55311d2f4705c454a1d30e5cc177ea9ce88e9 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
 
-
-ZIP_EXTERN struct zip *
+ZIP_EXTERN zip_t *
 zip_fdopen(int fd_orig, int _flags, int *zep)
 {
     int fd;
     FILE *fp;
-    unsigned int flags;
+    zip_t *za;
+    zip_source_t *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;
 }
index a30fd0b0f3b9d4da1f69ddcccc64954f58bf7d53..9944c0f122bb4b545bf9d47ba3914547a8d52204 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
-
 /*
   NOTE: Return type is signed so we can return -1 on error.
         The index can not be larger than ZIP_INT64_MAX since the size
 */
 
 ZIP_EXTERN zip_int64_t
-zip_file_add(struct zip *za, const char *name, struct zip_source *source, zip_flags_t flags)
+zip_file_add(zip_t *za, const char *name, zip_source_t *source, zip_flags_t flags)
 {
     if (name == NULL || source == NULL) {
-       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
        return -1;
     }
-
+       
     return _zip_file_replace(za, ZIP_UINT64_MAX, name, source, flags);
 }
index c433fbcb844161f0260c10cf7535c198d54fecd0..be454982a153d770479a075f0da2667e00a35b16 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
 
-
 ZIP_EXTERN void
-zip_file_error_clear(struct zip_file *zf)
+zip_file_error_clear(zip_file_t *zf)
 {
     if (zf == NULL)
        return;
index 65b08e3b13436f62bf70de9e31e245aa4446c38c..be764fd52d1af894367cbd029ea6f92a9a633961 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   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
   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-
-
+#define _ZIP_COMPILING_DEPRECATED
 #include "zipint.h"
 
 
-
 ZIP_EXTERN void
-zip_file_error_get(struct zip_file *zf, int *zep, int *sep)
+zip_file_error_get(zip_file_t *zf, int *zep, int *sep)
 {
     _zip_error_get(&zf->error, zep, sep);
 }
index 9a7a7b5cb5b2e78251ecf699019c96d001035b25..55e7dc28902c098f4dccb49f827de184ebbbd197 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
-
 /* lenp is 32 bit because converted comment can be longer than ZIP_UINT16_MAX */
 
 ZIP_EXTERN const char *
-zip_file_get_comment(struct zip *za, zip_uint64_t idx, zip_uint32_t *lenp, zip_flags_t flags)
+zip_file_get_comment(zip_t *za, zip_uint64_t idx, zip_uint32_t *lenp, zip_flags_t flags)
 {
-    struct zip_dirent *de;
+    zip_dirent_t *de;
     zip_uint32_t len;
     const zip_uint8_t *str;
 
index 461303f40e54cbf9bf25474dd29fddedee2673ce..b6526cf23a2de24fb60c0eec8b40f66a3c93140c 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 #include "zipint.h"
 
 int
-zip_file_get_external_attributes(struct zip *za, zip_uint64_t idx, zip_flags_t flags, zip_uint8_t *opsys, zip_uint32_t *attributes)
+zip_file_get_external_attributes(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_uint8_t *opsys, zip_uint32_t *attributes)
 {
-    struct zip_dirent *de;
+    zip_dirent_t *de;
 
     if ((de=_zip_get_dirent(za, idx, flags, NULL)) == NULL)
        return -1;
 
     if (opsys)
-       *opsys = (de->version_madeby >> 8) & 0xff;
+       *opsys = (zip_uint8_t)((de->version_madeby >> 8) & 0xff);
 
     if (attributes)
        *attributes = de->ext_attrib;
index 40b1f703c79cc74512ea009feafc522efefde4c5..1aaca712d743b3ace7ca484cb22b4f28693ede9b 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   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
@@ -32,7 +32,6 @@
 */
 
 
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -43,7 +42,6 @@
 #include "zipint.h"
 
 
-
 /* _zip_file_get_offset(za, ze):
    Returns the offset of the file data for entry ze.
 
 */
 
 zip_uint64_t
-_zip_file_get_offset(const struct zip *za, zip_uint64_t idx, struct zip_error *error)
+_zip_file_get_offset(const zip_t *za, zip_uint64_t idx, zip_error_t *error)
 {
     zip_uint64_t offset;
     zip_int32_t size;
 
     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;
     }
-
+    
     return offset + (zip_uint32_t)size;
 }
index dd4f2534570a2cb30c25769bc8a9469559208bf1..4400938ab5a99ce3a98e7638149908d6a15786a8 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <string.h>
 
 #include "zipint.h"
 
 
-
 ZIP_EXTERN int
-zip_file_rename(struct zip *za, zip_uint64_t idx, const char *name, zip_flags_t flags)
+zip_file_rename(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags)
 {
     const char *old_name;
     int old_is_dir, new_is_dir;
-
+    
     if (idx >= za->nentry || (name != NULL && strlen(name) > ZIP_UINT16_MAX)) {
-       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+       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 ((old_name=zip_get_name(za, idx, 0)) == NULL)
        return -1;
-
+                                                                   
     new_is_dir = (name != NULL && name[strlen(name)-1] == '/');
     old_is_dir = (old_name[strlen(old_name)-1] == '/');
 
     if (new_is_dir != old_is_dir) {
-       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
        return -1;
     }
 
index 622ef3c992db86a6e9655ea78df7e4ae2100c017..e430efae9e8c5cf2bd9ffb56ad6c4ccca23e3bcb 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
 
-
 ZIP_EXTERN int
-zip_file_replace(struct zip *za, zip_uint64_t idx, struct zip_source *source, zip_flags_t flags)
+zip_file_replace(zip_t *za, zip_uint64_t idx, zip_source_t *source, zip_flags_t flags)
 {
     if (idx >= za->nentry || source == NULL) {
-       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+       zip_error_set(&za->error, ZIP_ER_INVAL, 0);
        return -1;
     }
 
@@ -53,23 +51,22 @@ zip_file_replace(struct zip *za, zip_uint64_t idx, struct zip_source *source, zi
 
 
 
-
 /* NOTE: Signed due to -1 on error.  See zip_add.c for more details. */
 
 zip_int64_t
-_zip_file_replace(struct zip *za, zip_uint64_t idx, const char *name, struct zip_source *source, zip_flags_t flags)
+_zip_file_replace(zip_t *za, zip_uint64_t idx, const char *name, zip_source_t *source, zip_flags_t flags)
 {
     zip_uint64_t za_nentry_prev;
-
+    
     if (ZIP_IS_RDONLY(za)) {
-       _zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+       zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
        return -1;
     }
 
     za_nentry_prev = za->nentry;
     if (idx == ZIP_UINT64_MAX) {
        zip_int64_t i = -1;
-
+       
        if (flags & ZIP_FL_OVERWRITE)
            i = _zip_name_locate(za, name, flags, NULL);
 
@@ -80,7 +77,7 @@ _zip_file_replace(struct zip *za, zip_uint64_t idx, const char *name, struct zip
        }
        idx = (zip_uint64_t)i;
     }
-
+    
     if (name && _zip_set_name(za, idx, name, flags) != 0) {
        if (za->nentry != za_nentry_prev) {
            _zip_entry_finalize(za->entry+idx);
@@ -96,7 +93,7 @@ _zip_file_replace(struct zip *za, zip_uint64_t idx, const char *name, struct zip
     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;
             }
         }
@@ -104,7 +101,7 @@ _zip_file_replace(struct zip *za, zip_uint64_t idx, const char *name, struct zip
         za->entry[idx].changes->comp_method = ZIP_CM_REPLACED_DEFAULT;
         za->entry[idx].changes->changed |= ZIP_DIRENT_COMP_METHOD;
     }
-
+       
     za->entry[idx].source = source;
 
     return (zip_int64_t)idx;
index 541d3475a897f94687fc3efebd6b8efb35baa352..e455fbd28fc79facecac546ab10e35bb81489570 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <stdlib.h>
 
 #include "zipint.h"
 
 
-
 ZIP_EXTERN int
-zip_file_set_comment(struct zip *za, zip_uint64_t idx,
+zip_file_set_comment(zip_t *za, zip_uint64_t idx,
                     const char *comment, zip_uint16_t len, zip_flags_t flags)
 {
-    struct zip_entry *e;
-    struct zip_string *cstr;
+    zip_entry_t *e;
+    zip_string_t *cstr;
     int changed;
 
     if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
        return -1;
 
     if (ZIP_IS_RDONLY(za)) {
-       _zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+       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;
     }
 
@@ -81,11 +79,11 @@ zip_file_set_comment(struct zip *za, zip_uint64_t idx,
        changed = !_zip_string_equal(e->orig->comment, cstr);
     else
        changed = (cstr != NULL);
-
+       
     if (changed) {
         if (e->changes == NULL) {
             if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) {
-                _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+                zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
                _zip_string_free(cstr);
                 return -1;
             }
index 3f2817807fb44c246a83ffe54fb32423a450357f..b772c31e07511b8477e3f14124d2e38fd0e3bc45 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
 #include "zipint.h"
 
-int
-zip_file_set_external_attributes(struct zip *za, zip_uint64_t idx, zip_flags_t flags, zip_uint8_t opsys, zip_uint32_t attributes)
+ZIP_EXTERN int
+zip_file_set_external_attributes(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_uint8_t opsys, zip_uint32_t attributes)
 {
-    struct zip_entry *e;
+    zip_entry_t *e;
     int changed;
     zip_uint8_t unchanged_opsys;
     zip_uint32_t unchanged_attributes;
@@ -45,13 +45,13 @@ zip_file_set_external_attributes(struct zip *za, zip_uint64_t idx, zip_flags_t f
        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;
     }
 
     e = za->entry+idx;
 
-    unchanged_opsys = e->orig ? e->orig->version_madeby>>8 : ZIP_OPSYS_DEFAULT;
+    unchanged_opsys = (e->orig ? (zip_uint8_t)(e->orig->version_madeby>>8) : (zip_uint8_t)ZIP_OPSYS_DEFAULT);
     unchanged_attributes = e->orig ? e->orig->ext_attrib : ZIP_EXT_ATTRIB_DEFAULT;
 
     changed = (opsys != unchanged_opsys || attributes != unchanged_attributes);
@@ -59,11 +59,11 @@ zip_file_set_external_attributes(struct zip *za, zip_uint64_t idx, zip_flags_t f
     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;
             }
         }
-        e->changes->version_madeby = (opsys << 8) | (e->changes->version_madeby & 0xff);
+        e->changes->version_madeby = (zip_uint16_t)((opsys << 8) | (e->changes->version_madeby & 0xff));
        e->changes->ext_attrib = attributes;
         e->changes->changed |= ZIP_DIRENT_ATTRIBUTES;
     }
@@ -74,7 +74,7 @@ zip_file_set_external_attributes(struct zip *za, zip_uint64_t idx, zip_flags_t f
            e->changes = NULL;
        }
        else {
-           e->changes->version_madeby = (unchanged_opsys << 8) | (e->changes->version_madeby & 0xff);
+           e->changes->version_madeby = (zip_uint16_t)((unchanged_opsys << 8) | (e->changes->version_madeby & 0xff));
            e->changes->ext_attrib = unchanged_attributes;
        }
     }
diff --git a/ext/zip/lib/zip_file_set_mtime.c b/ext/zip/lib/zip_file_set_mtime.c
new file mode 100644 (file)
index 0000000..0cdd31a
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ zip_file_set_mtime.c -- set modification time of entry.
+ 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_file_set_mtime(zip_t *za, zip_uint64_t idx, time_t mtime, zip_flags_t flags)
+{
+    zip_entry_t *e;
+    int changed;
+    
+    if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
+        return -1;
+    
+    if (ZIP_IS_RDONLY(za)) {
+        zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+        return -1;
+    }
+    
+    e = za->entry+idx;
+
+    changed = e->orig == NULL || mtime != e->orig->last_mod;
+    
+    if (changed) {
+        if (e->changes == NULL) {
+            if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) {
+                zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+                return -1;
+            }
+        }
+        e->changes->last_mod = mtime;
+        e->changes->changed |= ZIP_DIRENT_LAST_MOD;
+    }
+    else {
+        if (e->changes) {
+            e->changes->changed &= ~ZIP_DIRENT_LAST_MOD;
+            if (e->changes->changed == 0) {
+               _zip_dirent_free(e->changes);
+                e->changes = NULL;
+            }
+        }
+    }
+    
+    return 0;
+}
index f06f698c64d6ccaad639fb3cec6445ab16512920..8366f1ea92a7913f10448bcee44e06ab49f21556 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
 
-
 ZIP_EXTERN const char *
-zip_file_strerror(struct zip_file *zf)
+zip_file_strerror(zip_file_t *zf)
 {
-    return _zip_error_strerror(&zf->error);
+    return zip_error_strerror(&zf->error);
 }
index 789cdd62b9c6fc4059686d13750825e8107e60f9..8e06e8fa8bed6611f3719318ab8d76aebe1dbff9 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_filerange_crc.c -- compute CRC32 for a range of a file
-  Copyright (C) 2008-2015 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>
@@ -17,7 +17,7 @@
   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
@@ -32,7 +32,6 @@
 */
 
 
-
 #include <stdio.h>
 #include <errno.h>
 
 
 
 
-
 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;
index 4bee7e500b1b3d752b8607d734f51de95273f75b..3adb5de65163a102f5cef437afaf85a70a4c7ec5 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
 
-
-ZIP_EXTERN struct zip_file *
-zip_fopen(struct zip *za, const char *fname, zip_flags_t flags)
+ZIP_EXTERN zip_file_t *
+zip_fopen(zip_t *za, const char *fname, zip_flags_t flags)
 {
     zip_int64_t idx;
 
index 18e198d4a94bb41bdd46fe5c97611cdcb54d83e2..5eaf2b04b716e909a6310608dfdc46585cc37e23 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
 
-
-ZIP_EXTERN struct zip_file *
-zip_fopen_encrypted(struct zip *za, const char *fname, zip_flags_t flags, const char *password)
+ZIP_EXTERN zip_file_t *
+zip_fopen_encrypted(zip_t *za, const char *fname, zip_flags_t flags, const char *password)
 {
     zip_int64_t idx;
 
index a84e97fa2682dc8a22a72384e5afa74708aa4214..e9a169a2e1aaee0b658ca04c407dbae13aa379e8 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_fopen_index.c -- open file in zip archive for reading by index
-  Copyright (C) 1999-2015 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>
@@ -17,7 +17,7 @@
   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
@@ -32,7 +32,6 @@
 */
 
 
-
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -40,9 +39,8 @@
 #include "zipint.h"
 
 
-
-ZIP_EXTERN struct zip_file *
-zip_fopen_index(struct zip *za, zip_uint64_t index, zip_flags_t flags)
+ZIP_EXTERN zip_file_t *
+zip_fopen_index(zip_t *za, zip_uint64_t index, zip_flags_t flags)
 {
     return zip_fopen_index_encrypted(za, index, flags, za->default_password);
 }
index 756e1e2e6baf8470f3ebc1c2618ed2ac307cbdde..21cc43333c8f7bb8db79c0942b9c79556b4e926a 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_fopen_index_encrypted.c -- open file for reading by index w/ password
-  Copyright (C) 1999-2015 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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 
 #include "zipint.h"
 
-static struct zip_file *_zip_file_new(struct zip *za);
+static zip_file_t *_zip_file_new(zip_t *za);
 
 
-
-ZIP_EXTERN struct zip_file *
-zip_fopen_index_encrypted(struct zip *za, zip_uint64_t index, zip_flags_t flags,
+ZIP_EXTERN zip_file_t *
+zip_fopen_index_encrypted(zip_t *za, zip_uint64_t index, zip_flags_t flags,
                          const char *password)
 {
-    struct zip_file *zf;
-    struct zip_source *src;
+    zip_file_t *zf;
+    zip_source_t *src;
 
     if ((src=_zip_source_zip_new(za, za, index, flags, 0, 0, password)) == NULL)
        return NULL;
@@ -70,35 +68,18 @@ zip_fopen_index_encrypted(struct zip *za, zip_uint64_t index, zip_flags_t flags,
 }
 
 
-
-static struct zip_file *
-_zip_file_new(struct zip *za)
+static zip_file_t *
+_zip_file_new(zip_t *za)
 {
-    struct zip_file *zf, **file;
+    zip_file_t *zf;
 
-    if ((zf=(struct zip_file *)malloc(sizeof(struct zip_file))) == NULL) {
-       _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+    if ((zf=(zip_file_t *)malloc(sizeof(struct zip_file))) == NULL) {
+       zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
        return NULL;
     }
 
-    if (za->nfile+1 >= za->nfile_alloc) {
-       unsigned int n;
-       n = za->nfile_alloc + 10;
-       file = (struct zip_file **)realloc(za->file,
-                                          n*sizeof(struct zip_file *));
-       if (file == NULL) {
-           _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-           free(zf);
-           return NULL;
-       }
-       za->nfile_alloc = n;
-       za->file = file;
-    }
-
-    za->file[za->nfile++] = zf;
-
     zf->za = za;
-    _zip_error_init(&zf->error);
+    zip_error_init(&zf->error);
     zf->eof = 0;
     zf->src = NULL;
 
index 67717e30d854a4e1db23d46ffcc6184eefb41db7..9c1cbe0c4ed533ecc0d793a3cf4f30766b90b997 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
 
-
 ZIP_EXTERN zip_int64_t
-zip_fread(struct zip_file *zf, void *outbuf, zip_uint64_t toread)
+zip_fread(zip_file_t *zf, void *outbuf, zip_uint64_t toread)
 {
     zip_int64_t n;
 
@@ -49,7 +47,7 @@ zip_fread(struct zip_file *zf, void *outbuf, zip_uint64_t toread)
        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;
     }
 
index 5d6b578b2689ad2080276da3bcab6d4e6d58292c..78f8ca09d28969ab1c9a4b438f86ac014d8ab0f3 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <string.h>
 
 #include "zipint.h"
 
 
-
 ZIP_EXTERN const char *
-zip_get_archive_comment(struct zip *za, int *lenp, zip_flags_t flags)
+zip_get_archive_comment(zip_t *za, int *lenp, zip_flags_t flags)
 {
-    struct zip_string *comment;
+    zip_string_t *comment;
     zip_uint32_t len;
     const zip_uint8_t *str;
 
index 46a2f566944602de03e2454147ae57ab3c1cb720..bffe10c1192b8cfc3406fe5857c1b3c2f6ac90a0 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
 
-
 ZIP_EXTERN int
-zip_get_archive_flag(struct zip *za, zip_flags_t flag, zip_flags_t flags)
+zip_get_archive_flag(zip_t *za, zip_flags_t flag, zip_flags_t flags)
 {
     unsigned int fl;
 
index a2e76e555dbb83959b91852664b5a842be157a86..c1120d3ea9b825763b05f92da95db5e1aaa0d8b2 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
 
-
 zip_compression_implementation
 _zip_get_compression_implementation(zip_int32_t cm)
 {
index 1cd12deff644af0ef2a2ff164321bec9b3b3ea35..e2f833b41663b1ee3faa5da610e2bade2fcbc355 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
 
-
 zip_encryption_implementation
 _zip_get_encryption_implementation(zip_uint16_t em)
 {
index 347b1386a647298c986b5fc57134f23829c968cc..d5f50bf2ab9b22cb536b743671b1fdbe9021bb7e 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   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
 */
 
 
-
 #define _ZIP_COMPILING_DEPRECATED
 #include "zipint.h"
 
 
-
 ZIP_EXTERN const char *
-zip_get_file_comment(struct zip *za, zip_uint64_t idx, int *lenp, int flags)
+zip_get_file_comment(zip_t *za, zip_uint64_t idx, int *lenp, int flags)
 {
     zip_uint32_t len;
     const char *s;
index f000db1815666681640f4e6b54cf18cc42dc90b7..d29e63658e3dea0eefff6b27870eaddb297187e8 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <string.h>
 
 #include "zipint.h"
 
 
-
 ZIP_EXTERN const char *
-zip_get_name(struct zip *za, zip_uint64_t idx, zip_flags_t flags)
+zip_get_name(zip_t *za, zip_uint64_t idx, zip_flags_t flags)
 {
     return _zip_get_name(za, idx, flags, &za->error);
 }
 
 
-
 const char *
-_zip_get_name(struct zip *za, zip_uint64_t idx, zip_flags_t flags, struct zip_error *error)
+_zip_get_name(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *error)
 {
-    struct zip_dirent *de;
+    zip_dirent_t *de;
     const zip_uint8_t *str;
 
     if ((de=_zip_get_dirent(za, idx, flags, error)) == NULL)
index e57921b9fdc5861c4bcd9c239ff87dc49ebb2fa5..c8644a4c5995728d7402df27b6cdf7425a753f29 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
 
-
 ZIP_EXTERN zip_int64_t
-zip_get_num_entries(struct zip *za, zip_flags_t flags)
+zip_get_num_entries(zip_t *za, zip_flags_t flags)
 {
     zip_uint64_t n;
 
index cc96ee43331d2542683e86caa300312e8d05f854..cf96353fcdef7e6bbef351587290a63f68c8ac14 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   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
 */
 
 
-
 #define _ZIP_COMPILING_DEPRECATED
 #include "zipint.h"
-
+#include <limits.h>
 
 
 ZIP_EXTERN int
-zip_get_num_files(struct zip *za)
+zip_get_num_files(zip_t *za)
 {
     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/ext/zip/lib/zip_io_util.c b/ext/zip/lib/zip_io_util.c
new file mode 100644 (file)
index 0000000..4a6bc1d
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ 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"
+
+int
+_zip_read(zip_source_t *src, zip_uint8_t *b, zip_uint64_t length, zip_error_t *error)
+{
+    zip_int64_t n;
+
+    if (length > ZIP_INT64_MAX) {
+       zip_error_set(error, ZIP_ER_INTERNAL, 0);
+       return -1;
+    }
+
+    if ((n = zip_source_read(src, b, length)) < 0) {
+       _zip_error_set_from_source(error, src);
+       return -1;
+    }
+
+    if (n < (zip_int64_t)length) {
+       zip_error_set(error, ZIP_ER_EOF, 0);
+       return -1;
+    }
+
+    return 0;
+}
+
+
+zip_uint8_t *
+_zip_read_data(zip_buffer_t *buffer, zip_source_t *src, size_t length, bool nulp, zip_error_t *error)
+{
+    zip_uint8_t *r;
+    
+    if (length == 0 && !nulp) {
+       return NULL;
+    }
+
+    r = (zip_uint8_t *)malloc(length + (nulp ? 1 : 0));
+    if (!r) {
+       zip_error_set(error, ZIP_ER_MEMORY, 0);
+       return NULL;
+    }
+
+    if (buffer) {
+        zip_uint8_t *data = _zip_buffer_get(buffer, length);
+        
+        if (data == NULL) {
+            zip_error_set(error, ZIP_ER_MEMORY, 0);
+            free(r);
+            return NULL;
+        }
+       memcpy(r, data, length);
+    }
+    else {
+       if (_zip_read(src, r, length, error) < 0) {
+           free(r);
+           return NULL;
+       }
+    }
+
+    if (nulp) {
+       zip_uint8_t *o;
+       /* replace any in-string NUL characters with spaces */
+       r[length] = 0;
+       for (o=r; o<r+length; o++)
+           if (*o == '\0')
+               *o = ' ';
+    }
+
+    return r;
+}
+
+
+zip_string_t *
+_zip_read_string(zip_buffer_t *buffer, zip_source_t *src, zip_uint16_t len, bool nulp, zip_error_t *error)
+{
+    zip_uint8_t *raw;
+    zip_string_t *s;
+
+    if ((raw=_zip_read_data(buffer, src, len, nulp, error)) == NULL)
+       return NULL;
+
+    s = _zip_string_new(raw, len, ZIP_FL_ENC_GUESS, error);
+    free(raw);
+    return s;
+}
+
+
+int
+_zip_write(zip_t *za, const void *data, zip_uint64_t length)
+{
+    zip_int64_t n;
+    
+    if ((n = zip_source_write(za->src, data, length)) < 0) {
+        _zip_error_set_from_source(&za->error, za->src);
+        return -1;
+    }
+    if ((zip_uint64_t)n != length) {
+        zip_error_set(&za->error, ZIP_ER_WRITE, EINTR);
+        return -1;
+    }
+    
+    return 0;
+}
index 4faa8982cb3c60cc5f0975054ff8293c0896a8bb..cc6d767d9174e398f18bf4120fe6e8e0fbc42abc 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   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
@@ -37,9 +37,8 @@
 #include "zipint.h"
 
 
-
 void *
-_zip_memdup(const void *mem, size_t len, struct zip_error *error)
+_zip_memdup(const void *mem, size_t len, zip_error_t *error)
 {
     void *ret;
 
@@ -48,7 +47,7 @@ _zip_memdup(const void *mem, size_t len, struct zip_error *error)
 
     ret = malloc(len);
     if (!ret) {
-       _zip_error_set(error, ZIP_ER_MEMORY, 0);
+       zip_error_set(error, ZIP_ER_MEMORY, 0);
        return NULL;
     }
 
index e527a5cda578681aa3ca78eed61cdb8fdb8af98b..820ea0ca7fad629c05947abc8214b2bc9a140c64 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   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
@@ -32,7 +32,6 @@
 */
 
 
-
 #include <string.h>
 #ifdef HAVE_STRINGS_H
 #include <strings.h>
 #include "zipint.h"
 
 
-
 ZIP_EXTERN zip_int64_t
-zip_name_locate(struct zip *za, const char *fname, zip_flags_t flags)
+zip_name_locate(zip_t *za, const char *fname, zip_flags_t flags)
 {
     return _zip_name_locate(za, fname, flags, &za->error);
 }
 
 
-
 zip_int64_t
-_zip_name_locate(struct zip *za, const char *fname, zip_flags_t flags, struct zip_error *error)
+_zip_name_locate(zip_t *za, const char *fname, zip_flags_t flags, zip_error_t *error)
 {
     int (*cmp)(const char *, const char *);
     const char *fn, *p;
@@ -61,7 +58,7 @@ _zip_name_locate(struct zip *za, const char *fname, zip_flags_t flags, struct zi
        return -1;
 
     if (fname == NULL) {
-       _zip_error_set(error, ZIP_ER_INVAL, 0);
+       zip_error_set(error, ZIP_ER_INVAL, 0);
        return -1;
     }
 
@@ -73,7 +70,7 @@ _zip_name_locate(struct zip *za, const char *fname, zip_flags_t flags, struct zi
        /* newly added (partially filled) entry or error */
        if (fn == NULL)
            continue;
-
+       
        if (flags & ZIP_FL_NODIR) {
            p = strrchr(fn, '/');
            if (p)
@@ -86,6 +83,6 @@ _zip_name_locate(struct zip *za, const char *fname, zip_flags_t flags, struct zi
        }
     }
 
-    _zip_error_set(error, ZIP_ER_NOENT, 0);
+    zip_error_set(error, ZIP_ER_NOENT, 0);
     return -1;
 }
index e91282b567a5158a4c95e4332cbae9a2a0c227a1..d54a247c29e622da0d51011c6d9626ed345ea273 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_new.c -- create and init struct zip
-  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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <stdlib.h>
 
 #include "zipint.h"
 
 
-
 /* _zip_new:
    creates a new zipfile struct, and sets the contents to zero; returns
    the new struct. */
 
-struct zip *
-_zip_new(struct zip_error *error)
+zip_t *
+_zip_new(zip_error_t *error)
 {
-    struct zip *za;
+    zip_t *za;
 
-    za = (struct zip *)malloc(sizeof(struct zip));
+    za = (zip_t *)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->nfile = za->nfile_alloc = 0;
-    za->file = NULL;
+    za->nopen_source = za->nopen_source_alloc = 0;
+    za->open_source = NULL;
     za->tempdir = NULL;
-
+    
     return za;
 }
index 1acaefa30ed1c25e84b91a32507ec0efb4aa8cd6..fb9c566cb1e7bb18e96ca98ff6e9cca70c01ca60 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_open.c -- open zip archive by name
-  Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -17,7 +17,7 @@
   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
@@ -32,7 +32,6 @@
 */
 
 
-
 #include <sys/stat.h>
 #include <errno.h>
 #include <limits.h>
 
 #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 *);
-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,
-                                      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 *);
-
-
-
-ZIP_EXTERN struct zip *
+typedef enum {
+    EXISTS_ERROR = -1,
+    EXISTS_NOT = 0,
+    EXISTS_EMPTY,
+    EXISTS_NONEMPTY,
+} exists_t;
+static zip_t *_zip_allocate_new(zip_source_t *src, unsigned int flags, zip_error_t *error);
+static zip_int64_t _zip_checkcons(zip_t *za, zip_cdir_t *cdir, zip_error_t *error);
+static zip_cdir_t *_zip_find_central_dir(zip_t *za, zip_uint64_t len);
+static exists_t _zip_file_exists(zip_source_t *src, zip_error_t *error);
+static int _zip_headercomp(const zip_dirent_t *, const zip_dirent_t *);
+static unsigned char *_zip_memmem(const unsigned char *, size_t, const unsigned char *, size_t);
+static zip_cdir_t *_zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_error_t *error);
+static zip_cdir_t *_zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error);
+static zip_cdir_t *_zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error);
+
+
+ZIP_EXTERN zip_t *
 zip_open(const char *fn, int _flags, int *zep)
 {
-    FILE *fp;
-    unsigned int flags;
+    zip_t *za;
+    zip_source_t *src;
+    struct zip_error error;
+
+    zip_error_init(&error);
+    if ((src = zip_source_file_create(fn, 0, -1, &error)) == NULL) {
+       _zip_set_open_error(zep, &error, 0);
+       zip_error_fini(&error);
+       return NULL;
+    }
+
+    if ((za = zip_open_from_source(src, _flags, &error)) == NULL) {
+       zip_source_free(src);
+       _zip_set_open_error(zep, &error, 0);
+       zip_error_fini(&error);
+       return NULL;
+    }
 
-    if (_flags < 0) {
-        if (zep)
-            *zep = ZIP_ER_INVAL;
+    zip_error_fini(&error);
+    return za;
+}
+
+
+ZIP_EXTERN zip_t *
+zip_open_from_source(zip_source_t *src, int _flags, zip_error_t *error)
+{
+    static zip_int64_t needed_support_read = -1;
+    static zip_int64_t needed_support_write = -1;
+    
+    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;
-    case 0:
-       return _zip_allocate_new(fn, flags, zep);
-    default:
-       if (flags & ZIP_TRUNCATE) {
-           FILE *f;
-
-           if ((f = fopen(fn, "rb")) == NULL) {
-               set_error(zep, NULL, ZIP_ER_OPEN);
-               return NULL;
-           }
-           fclose(f);
-           return _zip_allocate_new(fn, flags, zep);
-       }
-       break;
     }
 
-    if ((fp=fopen(fn, "rb")) == NULL) {
-       set_error(zep, NULL, ZIP_ER_OPEN);
+    exists = _zip_file_exists(src, error);
+    switch (exists) { 
+    case EXISTS_ERROR:
        return NULL;
-    }
 
-    return _zip_open(fn, fp, flags, zep);
-}
+    case EXISTS_NOT:
+       if ((flags & ZIP_CREATE) == 0) {
+           zip_error_set(error, ZIP_ER_NOENT, 0);
+           return NULL;
+       }
+       return _zip_allocate_new(src, flags, error);
+
+    default: {
+       zip_t *za;
+       if (flags & ZIP_EXCL) {
+           zip_error_set(error, ZIP_ER_EXISTS, 0);
+           return NULL;
+       }
+       if (zip_source_open(src) < 0) {
+           _zip_error_set_from_source(error, src);
+           return NULL;
+       }
+
+       if (flags & ZIP_TRUNCATE) {
+           za = _zip_allocate_new(src, flags, error);
+       }
+       else {
+           /* ZIP_CREATE gets ignored if file exists and not ZIP_EXCL, just like open() */
+           za = _zip_open(src, flags, error);
+       }
 
+       if (za == NULL) {
+           zip_source_close(src);
+           return NULL;
+       }
+       return za;
+    }
+    }
+}
 
 ZIP_EXTERN int
-zip_archive_set_tempdir(struct zip *za, const char *tempdir)
+zip_archive_set_tempdir(zip_t *za, const char *tempdir)
 {
     char *new_tempdir;
-
+    
     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;
         }
     }
     else
         new_tempdir = NULL;
-
+    
     free(za->tempdir);
     za->tempdir = new_tempdir;
-
+    
     return 0;
 }
 
-
-struct zip *
-_zip_open(const char *fn, FILE *fp, unsigned int flags, int *zep)
+zip_t *
+_zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error)
 {
-    struct zip *za;
-    struct zip_cdir *cdir;
-    off_t len;
-
-    if (fseeko(fp, 0, SEEK_END) < 0) {
-       *zep = ZIP_ER_SEEK;
+    zip_t *za;
+    zip_cdir_t *cdir;
+    struct zip_stat st;
+    zip_uint64_t len;
+
+    zip_stat_init(&st);
+    if (zip_source_stat(src, &st) < 0) {
+       _zip_error_set_from_source(error, src);
+       return NULL;
+    }
+    if ((st.valid & ZIP_STAT_SIZE) == 0) {
+       zip_error_set(error, ZIP_ER_SEEK, EOPNOTSUPP);
        return NULL;
     }
-    len = ftello(fp);
+    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);
+       /* keep src so discard does not get rid of it */
+       zip_source_keep(src);
+       zip_discard(za);
        return NULL;
     }
 
@@ -160,11 +223,7 @@ _zip_open(const char *fn, FILE *fp, unsigned int flags, int *zep)
     za->nentry = cdir->nentry;
     za->nentry_alloc = cdir->nentry_alloc;
     za->comment_orig = cdir->comment;
-
-    za->zp = fp;
-
-    _zip_check_torrentzip(za, cdir);
-
+    
     za->ch_flags = za->flags;
 
     free(cdir);
@@ -173,16 +232,14 @@ _zip_open(const char *fn, FILE *fp, unsigned int flags, int *zep)
 }
 
 
-
-static void
-set_error(int *zep, const struct zip_error *err, int ze)
+void
+_zip_set_open_error(int *zep, const zip_error_t *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)
@@ -190,90 +247,108 @@ set_error(int *zep, const struct zip_error *err, int ze)
 }
 
 
-
 /* _zip_readcdir:
    tries to find a valid end-of-central-directory at the beginning of
    buf, and then the corresponding central directory entries.
-   Returns a struct zip_cdir which contains the central directory
+   Returns a struct zip_cdir which contains the central directory 
    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)
+static zip_cdir_t *
+_zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_error_t *error)
 {
-    struct zip_cdir *cd;
-    const unsigned char *cdp;
-    const unsigned char **bufp;
-    zip_int64_t tail_len, comment_len;
+    zip_cdir_t *cd;
+    zip_uint16_t comment_len;
     zip_uint64_t i, left;
+    zip_uint64_t eocd_offset = _zip_buffer_offset(buffer);
+    zip_buffer_t *cd_buffer;
 
-    tail_len = buf + buflen - eocd - EOCDLEN;
-    if (tail_len < 0) {
+    if (_zip_buffer_left(buffer) < EOCDLEN) {
        /* 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);
+    if (memcmp(_zip_buffer_get(buffer, 4), EOCD_MAGIC, 4) != 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);
+    if (_zip_buffer_get_32(buffer) != 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);
-    else
-       cd = _zip_read_eocd(eocd, buf, buf_offset, buflen, flags, error);
+    if (eocd_offset >= EOCD64LOCLEN && memcmp(_zip_buffer_data(buffer) + eocd_offset - EOCD64LOCLEN, EOCD64LOC_MAGIC, 4) == 0) {
+        _zip_buffer_set_offset(buffer, eocd_offset - EOCD64LOCLEN);
+        cd = _zip_read_eocd64(za->src, buffer, buf_offset, za->flags, error);
+    }
+    else {
+        _zip_buffer_set_offset(buffer, eocd_offset);
+        cd = _zip_read_eocd(buffer, buf_offset, za->flags, error);
+    }
 
     if (cd == NULL)
        return NULL;
 
-    cdp = eocd + 20;
-    comment_len = _zip_read2(&cdp);
+    _zip_buffer_set_offset(buffer, eocd_offset + 20);
+    comment_len = _zip_buffer_get_16(buffer);
 
-    if ((zip_uint64_t)cd->offset+(zip_uint64_t)cd->size > (zip_uint64_t)buf_offset + (zip_uint64_t)(eocd-buf)) {
+    if (cd->offset + cd->size > buf_offset + eocd_offset) {
        /* 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);
-       _zip_cdir_free(cd);
-       return NULL;
-    }
+    if (comment_len || (za->open_flags & ZIP_CHECKCONS)) {
+        zip_uint64_t tail_len;
+        
+        _zip_buffer_set_offset(buffer, eocd_offset + EOCDLEN);
+        tail_len = _zip_buffer_left(buffer);
+        
+        if (tail_len < comment_len || ((za->open_flags & ZIP_CHECKCONS) && tail_len != comment_len)) {
+            zip_error_set(error, ZIP_ER_INCONS, 0);
+            _zip_cdir_free(cd);
+            return NULL;
+        }
 
-    if (comment_len) {
-       if ((cd->comment=_zip_string_new(eocd+EOCDLEN, (zip_uint16_t)comment_len, ZIP_FL_ENC_GUESS, error)) == NULL) {
-           _zip_cdir_free(cd);
-           return NULL;
-       }
+        if (comment_len) {
+            if ((cd->comment=_zip_string_new(_zip_buffer_get(buffer, comment_len), comment_len, ZIP_FL_ENC_GUESS, error)) == NULL) {
+                _zip_cdir_free(cd);
+                return NULL;
+            }
+        }
     }
 
     if (cd->offset >= buf_offset) {
+        zip_uint8_t *data;
        /* if buffer already read in, use it */
-       cdp = buf + (cd->offset - buf_offset);
-       bufp = &cdp;
+        _zip_buffer_set_offset(buffer, cd->offset - buf_offset);
+        
+        if ((data = _zip_buffer_get(buffer, cd->size)) == NULL) {
+            zip_error_set(error, ZIP_ER_INCONS, 0);
+            _zip_cdir_free(cd);
+            return NULL;
+        }
+        if ((cd_buffer = _zip_buffer_new(data, cd->size)) == NULL) {
+            zip_error_set(error, ZIP_ER_MEMORY, 0);
+            _zip_cdir_free(cd);
+            return NULL;
+        }
     }
     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);
+        cd_buffer = NULL;
+        
+        if (zip_source_seek(za->src, (zip_int64_t)cd->offset, SEEK_SET) < 0) {
+            _zip_error_set_from_source(error, za->src);
+            _zip_cdir_free(cd);
+            return NULL;
+        }
+
+       /* possible consistency check: cd->offset = len-(cd->size+cd->comment_len+EOCDLEN) ? */
+       if (zip_source_tell(za->src) != (zip_int64_t)cd->offset) {
+            zip_error_set(error, ZIP_ER_NOZIP, 0);
            _zip_cdir_free(cd);
            return NULL;
        }
@@ -282,24 +357,54 @@ _zip_readcdir(FILE *fp, off_t buf_offset, unsigned char *buf, const unsigned cha
     left = (zip_uint64_t)cd->size;
     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_int64_t entry_size;
+       if ((cd->entry[i].orig=_zip_dirent_new()) == NULL || (entry_size = _zip_dirent_read(cd->entry[i].orig, za->src, cd_buffer, false, error)) < 0) {
            _zip_cdir_free(cd);
+            _zip_buffer_free(cd_buffer);
            return NULL;
        }
        i++;
+        left -= (zip_uint64_t)entry_size;
     }
-    if (i != cd->nentry || ((flags & ZIP_CHECKCONS) && left != 0)) {
-        _zip_error_set(error, ZIP_ER_INCONS, 0);
+    
+    if (i != cd->nentry) {
+        zip_error_set(error, ZIP_ER_INCONS, 0);
+        _zip_buffer_free(cd_buffer);
         _zip_cdir_free(cd);
         return NULL;
     }
+    
+    if (za->open_flags & ZIP_CHECKCONS) {
+        bool ok;
+        
+        if (cd_buffer) {
+            ok = _zip_buffer_eof(cd_buffer);
+        }
+        else {
+            zip_int64_t offset = zip_source_tell(za->src);
+            
+            if (offset < 0) {
+                _zip_error_set_from_source(error, za->src);
+                _zip_buffer_free(cd_buffer);
+                _zip_cdir_free(cd);
+                return NULL;
+            }
+            ok = ((zip_uint64_t)offset == cd->offset + cd->size);
+        }
+        
+        if (!ok) {
+            zip_error_set(error, ZIP_ER_INCONS, 0);
+            _zip_buffer_free(cd_buffer);
+            _zip_cdir_free(cd);
+            return NULL;
+        }
+    }
 
+    _zip_buffer_free(cd_buffer);
     return cd;
 }
 
 
-
 /* _zip_checkcons:
    Checks the consistency of the central directory by comparing central
    directory entries with local headers and checking for plausible
@@ -307,12 +412,13 @@ _zip_readcdir(FILE *fp, off_t buf_offset, unsigned char *buf, const unsigned cha
    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(zip_t *za, zip_cdir_t *cd, zip_error_t *error)
 {
     zip_uint64_t i;
     zip_uint64_t min, max, j;
     struct zip_dirent temp;
 
+    _zip_dirent_init(&temp);
     if (cd->nentry) {
        max = cd->entry[0].orig->offset;
        min = cd->entry[0].orig->offset;
@@ -324,37 +430,39 @@ _zip_checkcons(FILE *fp, struct zip_cdir *cd, struct zip_error *error)
        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;
        }
-
+       
        j = cd->entry[i].orig->offset + cd->entry[i].orig->comp_size
            + _zip_string_length(cd->entry[i].orig->filename) + LENTRYSIZE;
        if (j > max)
            max = j;
        if (max > (zip_uint64_t)cd->offset) {
-           _zip_error_set(error, ZIP_ER_NOZIP, 0);
+           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, true, error) == -1) {
+           _zip_dirent_finalize(&temp);
            return -1;
-
+       }
+       
        if (_zip_headercomp(cd->entry[i].orig, &temp) != 0) {
-           _zip_error_set(error, ZIP_ER_INCONS, 0);
+           zip_error_set(error, ZIP_ER_INCONS, 0);
            _zip_dirent_finalize(&temp);
            return -1;
        }
-
+       
        cd->entry[i].orig->extra_fields = _zip_ef_merge(cd->entry[i].orig->extra_fields, temp.extra_fields);
        cd->entry[i].orig->local_extra_fields_read = 1;
        temp.extra_fields = NULL;
-
+       
        _zip_dirent_finalize(&temp);
     }
 
@@ -362,47 +470,12 @@ _zip_checkcons(FILE *fp, struct zip_cdir *cd, struct zip_error *error)
 }
 
 
-
-/* _zip_check_torrentzip:
-   check whether ZA has a valid TORRENTZIP comment, i.e. is torrentzipped */
-
-static void
-_zip_check_torrentzip(struct zip *za, const struct zip_cdir *cdir)
-{
-    uLong crc_got, crc_should;
-    char buf[8+1];
-    char *end;
-
-    if (za->zp == NULL || cdir == NULL)
-       return;
-
-    if (_zip_string_length(cdir->comment) != TORRENT_SIG_LEN+8
-       || strncmp((const char *)cdir->comment->raw, TORRENT_SIG, TORRENT_SIG_LEN) != 0)
-       return;
-
-    memcpy(buf, cdir->comment->raw+TORRENT_SIG_LEN, 8);
-    buf[8] = '\0';
-    errno = 0;
-    crc_should = strtoul(buf, &end, 16);
-    if ((crc_should == UINT_MAX && errno != 0) || (end && *end))
-       return;
-
-    if (_zip_filerange_crc(za->zp, cdir->offset, cdir->size, &crc_got, NULL) < 0)
-       return;
-
-    if (crc_got == crc_should)
-       za->flags |= ZIP_AFL_TORRENT;
-}
-
-
-
-
 /* _zip_headercomp:
    compares a central directory entry and a local file header
    Return 0 if they are consistent, -1 if not. */
 
 static int
-_zip_headercomp(const struct zip_dirent *central, const struct zip_dirent *local)
+_zip_headercomp(const zip_dirent_t *central, const zip_dirent_t *local)
 {
     if ((central->version_needed != local->version_needed)
 #if 0
@@ -415,7 +488,6 @@ _zip_headercomp(const struct zip_dirent *central, const struct zip_dirent *local
        || !_zip_string_equal(central->filename, local->filename))
        return -1;
 
-
     if ((central->crc != local->crc) || (central->comp_size != local->comp_size)
        || (central->uncomp_size != local->uncomp_size)) {
        /* InfoZip stores valid values in local header even when data descriptor is used.
@@ -429,157 +501,141 @@ _zip_headercomp(const struct zip_dirent *central, const struct zip_dirent *local
 }
 
 
-
-static struct zip *
-_zip_allocate_new(const char *fn, unsigned int flags, int *zep)
+static zip_t *
+_zip_allocate_new(zip_source_t *src, unsigned int flags, zip_error_t *error)
 {
-    struct zip *za;
-    struct zip_error error;
+    zip_t *za;
 
-    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;
 }
 
 
-
-static int
-_zip_file_exists(const char *fn, unsigned int flags, int *zep)
+/*
+ * tests for file existence
+ */
+static exists_t
+_zip_file_exists(zip_source_t *src, zip_error_t *error)
 {
-    struct stat st;
-
-    if (fn == NULL) {
-       set_error(zep, NULL, ZIP_ER_INVAL);
-       return -1;
-    }
+    struct zip_stat st;
 
-    if (stat(fn, &st) != 0) {
-       if (flags & ZIP_CREATE)
-           return 0;
-       else {
-           set_error(zep, NULL, ZIP_ER_OPEN);
-           return -1;
+    zip_stat_init(&st);
+    if (zip_source_stat(src, &st) != 0) {
+        zip_error_t *src_error = zip_source_error(src);
+        if (zip_error_code_zip(src_error) == ZIP_ER_READ && zip_error_code_system(src_error) == ENOENT) {
+           return EXISTS_NOT;
        }
+       _zip_error_copy(error, src_error);
+       return EXISTS_ERROR;
     }
-    else if ((flags & ZIP_EXCL)) {
-       set_error(zep, NULL, ZIP_ER_EXISTS);
-       return -1;
-    }
-    /* ZIP_CREATE gets ignored if file exists and not ZIP_EXCL,
-       just like open() */
 
-    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)
+static zip_cdir_t *
+_zip_find_central_dir(zip_t *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_cdir_t *cdir, *cdirnew;
+    zip_uint8_t *match;
+    zip_int64_t buf_offset;
+    zip_uint64_t buflen;
+    zip_int64_t a;
     zip_int64_t best;
-    struct zip_error zerr;
+    zip_error_t error;
+    zip_buffer_t *buffer;
 
-    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;
     }
 
-    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;
+    buflen = (len < CDBUFSIZE ? len : CDBUFSIZE);
+    if (zip_source_seek(za->src, -(zip_int64_t)buflen, SEEK_END) < 0) {
+       zip_error_t *src_error = zip_source_error(za->src);
+       if (zip_error_code_zip(src_error) != ZIP_ER_SEEK || zip_error_code_system(src_error) != EFBIG) {
+           /* seek before start of file on my machine */
+           _zip_error_copy(&za->error, src_error);
+           return NULL;
+       }
     }
-    buf_offset = ftello(fp);
-
-    /* 64k is too much for stack */
-    if ((buf=(unsigned char *)malloc(CDBUFSIZE)) == NULL) {
-       set_error(zep, NULL, ZIP_ER_MEMORY);
-       return NULL;
+    if ((buf_offset = zip_source_tell(za->src)) < 0) {
+        _zip_error_set_from_source(&za->error, za->src);
+        return NULL;
     }
-
-    clearerr(fp);
-    buflen = fread(buf, 1, CDBUFSIZE, fp);
-
-    if (ferror(fp)) {
-       set_error(zep, NULL, ZIP_ER_READ);
-       free(buf);
-       return NULL;
+    
+    if ((buffer = _zip_buffer_new_from_source(za->src, buflen, NULL, &za->error)) == NULL) {
+        return NULL;
     }
 
     best = -1;
     cdir = NULL;
-    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)
-           continue;
-
-       if (cdir) {
-           if (best <= 0)
-               best = _zip_checkcons(fp, cdir, &zerr);
-           a = _zip_checkcons(fp, cdirnew, &zerr);
-           if (best < a) {
-               _zip_cdir_free(cdir);
-               cdir = cdirnew;
-               best = a;
-           }
-           else
-               _zip_cdir_free(cdirnew);
-       }
-       else {
-           cdir = cdirnew;
-           if (flags & ZIP_CHECKCONS)
-               best = _zip_checkcons(fp, cdir, &zerr);
-           else
-               best = 0;
-       }
-       cdirnew = NULL;
+    if (buflen >= CDBUFSIZE) {
+        /* EOCD64 locator is before EOCD, so leave place for it */
+        _zip_buffer_set_offset(buffer, EOCD64LOCLEN);
+    }
+    zip_error_set(&error, ZIP_ER_NOZIP, 0);
+
+    match = _zip_buffer_get(buffer, 0);
+    while ((match=_zip_memmem(match, _zip_buffer_left(buffer)-(EOCDLEN-4), (const unsigned char *)EOCD_MAGIC, 4)) != NULL) {
+        _zip_buffer_set_offset(buffer, (zip_uint64_t)(match - _zip_buffer_data(buffer)));
+        if ((cdirnew = _zip_read_cdir(za, buffer, (zip_uint64_t)buf_offset, &error)) != NULL) {
+            if (cdir) {
+                if (best <= 0) {
+                    best = _zip_checkcons(za, cdir, &error);
+                }
+                
+                a = _zip_checkcons(za, cdirnew, &error);
+                if (best < a) {
+                    _zip_cdir_free(cdir);
+                    cdir = cdirnew;
+                    best = a;
+                }
+                else {
+                    _zip_cdir_free(cdirnew);
+                }
+            }
+            else {
+                cdir = cdirnew;
+                if (za->open_flags & ZIP_CHECKCONS)
+                    best = _zip_checkcons(za, cdir, &error);
+                else {
+                    best = 0;
+                }
+            }
+            cdirnew = NULL;
+        }
+        
+        match++;
+        _zip_buffer_set_offset(buffer, (zip_uint64_t)(match - _zip_buffer_data(buffer)));
     }
 
-    free(buf);
-
+    _zip_buffer_free(buffer);
+    
     if (best < 0) {
-       set_error(zep, &zerr, 0);
-       _zip_cdir_free(cdir);
-       return NULL;
+        _zip_error_copy(&za->error, &error);
+        _zip_cdir_free(cdir);
+        return NULL;
     }
 
     return cdir;
 }
 
 
-
 static unsigned char *
 _zip_memmem(const unsigned char *big, size_t biglen, const unsigned char *little, size_t littlelen)
 {
     const unsigned char *p;
-
+    
     if ((biglen < littlelen) || (littlelen == 0))
        return NULL;
     p = big-1;
@@ -593,150 +649,160 @@ _zip_memmem(const unsigned char *big, size_t biglen, const unsigned char *little
 }
 
 
-
-static struct zip_cdir *
-_zip_read_eocd(const unsigned char *eocd, const unsigned char *buf, off_t buf_offset, size_t buflen,
-              unsigned int flags, struct zip_error *error)
+static zip_cdir_t *_zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error)
 {
-    struct zip_cdir *cd;
-    const unsigned char *cdp;
-    zip_uint64_t i, nentry, size, offset;
+    zip_cdir_t *cd;
+    zip_uint64_t i, nentry, size, offset, eocd_offset;
 
-    if (eocd+EOCDLEN > buf+buflen) {
-       _zip_error_set(error, ZIP_ER_INCONS, 0);
+    if (_zip_buffer_left(buffer) < EOCDLEN) {
+       zip_error_set(error, ZIP_ER_INCONS, 0);
        return NULL;
     }
+    
+    eocd_offset = _zip_buffer_offset(buffer);
 
-    cdp = eocd + 8;
+    _zip_buffer_get(buffer, 8); /* magic and number of disks already verified */
 
     /* number of cdir-entries on this disk */
-    i = _zip_read2(&cdp);
+    i = _zip_buffer_get_16(buffer);
     /* number of cdir-entries */
-    nentry = _zip_read2(&cdp);
+    nentry = _zip_buffer_get_16(buffer);
 
     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_buffer_get_32(buffer);
+    offset = _zip_buffer_get_32(buffer);
 
-    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 + eocd_offset) {
        /* 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 + eocd_offset) {
+       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)
+static zip_cdir_t *
+_zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error)
 {
-    struct zip_cdir *cd;
+    zip_cdir_t *cd;
     zip_uint64_t offset;
-    const zip_uint8_t *cdp;
     zip_uint8_t eocd[EOCD64LEN];
     zip_uint64_t eocd_offset;
-    zip_uint64_t size, nentry, i;
-
-    cdp = eocd64loc+8;
-    eocd_offset = _zip_read8(&cdp);
-
-    if (eocd_offset > ZIP_OFF_MAX || eocd_offset + EOCD64LEN > ZIP_OFF_MAX) {
-        _zip_error_set(error, ZIP_ER_SEEK, EFBIG);
+    zip_uint64_t size, nentry, i, eocdloc_offset;
+    bool free_buffer;
+
+    eocdloc_offset = _zip_buffer_offset(buffer);
+    
+    _zip_buffer_get(buffer, 8); /* magic and single disk already verified */
+    eocd_offset = _zip_buffer_get_64(buffer);
+    
+    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 (eocd_offset + EOCD64LEN > eocdloc_offset + buf_offset) {
+       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 + _zip_buffer_size(buffer)) {
+        _zip_buffer_set_offset(buffer, eocd_offset - buf_offset);
+        free_buffer = false;
+    }
     else {
-       if (fseeko(f, (off_t)eocd_offset, SEEK_SET) != 0) {
-           _zip_error_set(error, ZIP_ER_SEEK, errno);
-           return NULL;
-       }
-
-       clearerr(f);
-       if (fread(eocd, 1, EOCD64LEN, f) < EOCD64LEN) {
-            _zip_error_set(error, ZIP_ER_READ, errno);
+        if (zip_source_seek(src, (zip_int64_t)eocd_offset, SEEK_SET) < 0) {
+            _zip_error_set_from_source(error, src);
             return NULL;
         }
-
-       if (ferror(f)) {
-           _zip_error_set(error, ZIP_ER_READ, errno);
-           return NULL;
-       }
-
-       cdp = eocd;
+        if ((buffer = _zip_buffer_new_from_source(src, EOCD64LEN, eocd, error)) == NULL) {
+            return NULL;
+        }
+        free_buffer = true;
     }
 
-    if (memcmp(cdp, EOCD64_MAGIC, 4) != 0) {
-       _zip_error_set(error, ZIP_ER_INCONS, 0);
+    if (memcmp(_zip_buffer_get(buffer, 4), EOCD64_MAGIC, 4) != 0) {
+       zip_error_set(error, ZIP_ER_INCONS, 0);
+        if (free_buffer) {
+            _zip_buffer_free(buffer);
+        }
        return NULL;
     }
-    cdp += 4;
-
-    size = _zip_read8(&cdp);
+    
+    size = _zip_buffer_get_64(buffer);
 
-    if ((flags & ZIP_CHECKCONS) && size+eocd_offset+12 != (zip_uint64_t)(buf_offset+(eocd64loc-buf))) {
-       _zip_error_set(error, ZIP_ER_INCONS, 0);
-       return NULL;
+    if ((flags & ZIP_CHECKCONS) && size + eocd_offset + 12 != buf_offset + eocdloc_offset) {
+       zip_error_set(error, ZIP_ER_INCONS, 0);
+        if (free_buffer) {
+            _zip_buffer_free(buffer);
+        }
+        return NULL;
     }
 
-    cdp += 4; /* skip version made by/needed */
-    cdp += 8; /* skip num disks */
-
-    nentry = _zip_read8(&cdp);
-    i = _zip_read8(&cdp);
+    _zip_buffer_get(buffer, 12); /* skip version made by/needed and num disks */
+    
+    nentry = _zip_buffer_get_64(buffer);
+    i = _zip_buffer_get_64(buffer);
 
     if (nentry != i) {
-       _zip_error_set(error, ZIP_ER_MULTIDISK, 0);
+       zip_error_set(error, ZIP_ER_MULTIDISK, 0);
+        if (free_buffer) {
+            _zip_buffer_free(buffer);
+        }
        return NULL;
     }
 
-    size = _zip_read8(&cdp);
-    offset = _zip_read8(&cdp);
+    size = _zip_buffer_get_64(buffer);
+    offset = _zip_buffer_get_64(buffer);
+    
+    if (!_zip_buffer_ok(buffer)) {
+        zip_error_set(error, ZIP_ER_INTERNAL, 0);
+        if (free_buffer) {
+            _zip_buffer_free(buffer);
+        }
+        return NULL;
+    }
 
-    if (size > ZIP_OFF_MAX || offset > ZIP_OFF_MAX || offset+size > ZIP_OFF_MAX) {
-        _zip_error_set(error, ZIP_ER_SEEK, EFBIG);
+    if (free_buffer) {
+        _zip_buffer_free(buffer);
+    }
+
+    if (offset > ZIP_INT64_MAX || offset+size < offset) {
+        zip_error_set(error, ZIP_ER_SEEK, EFBIG);
         return NULL;
     }
     if ((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;
     }
 
     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;
 }
index b1b0be7115f25ea7939a7aa6014c5c26dbf56d89..14e101d79bc9d85e46be452bd6f507c807df34a0 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <string.h>
 
 #define _ZIP_COMPILING_DEPRECATED
 #include "zipint.h"
 
 
-
 ZIP_EXTERN int
-zip_rename(struct zip *za, zip_uint64_t idx, const char *name)
+zip_rename(zip_t *za, zip_uint64_t idx, const char *name)
 {
     return zip_file_rename(za, idx, name, 0);
 }
index ad643f4948a2f4f1220bd4abb998a447c2184e14..eed019a097909eede9d60f3aa23b2b6786d28ae1 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   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
 */
 
 
-
 #define _ZIP_COMPILING_DEPRECATED
 #include "zipint.h"
 
 
-
 ZIP_EXTERN int
-zip_replace(struct zip *za, zip_uint64_t idx, struct zip_source *source)
+zip_replace(zip_t *za, zip_uint64_t idx, zip_source_t *source)
 {
     return zip_file_replace(za, idx, source, 0);
 }
index 52563473dafbf03972579501642cb261c9a6927c..9090eec956e265f7853b96c2d68f8bd30c4cf451 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_set_archive_comment.c -- set archive comment
-  Copyright (C) 2006-2015 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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <stdlib.h>
 
 #include "zipint.h"
 
 
-
 ZIP_EXTERN int
-zip_set_archive_comment(struct zip *za, const char *comment, zip_uint16_t len)
+zip_set_archive_comment(zip_t *za, const char *comment, zip_uint16_t len)
 {
-    struct zip_string *cstr;
+    zip_string_t *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;
     }
 
@@ -60,7 +58,7 @@ zip_set_archive_comment(struct zip *za, const char *comment, zip_uint16_t len)
 
        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;
        }
     }
@@ -79,6 +77,6 @@ zip_set_archive_comment(struct zip *za, const char *comment, zip_uint16_t len)
        za->comment_changes = cstr;
        za->comment_changed = 1;
     }
-
+    
     return 0;
 }
index 7e1463b0005629556d03897dbd652fcfd8ad35d6..2625b2e65373e23c43c7c60de7f72588a7c62a97 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
 
-
 ZIP_EXTERN int
-zip_set_archive_flag(struct zip *za, zip_flags_t flag, int value)
+zip_set_archive_flag(zip_t *za, zip_flags_t flag, int value)
 {
     unsigned int new_flags;
-
+    
     if (value)
        new_flags = za->ch_flags | flag;
     else
@@ -51,14 +49,14 @@ zip_set_archive_flag(struct zip *za, zip_flags_t flag, int value)
        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;
        }
     }
index d16a1b91124be63b175d52bf805e0d5476a7972a..ac098dc5fc123ee92254abc5cb5ee014ac847e8c 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <stdlib.h>
 #include <string.h>
 
 #include "zipint.h"
 
 
-
 ZIP_EXTERN int
-zip_set_default_password(struct zip *za, const char *passwd)
+zip_set_default_password(zip_t *za, const char *passwd)
 {
     if (za == NULL)
        return -1;
 
     if (za->default_password)
        free(za->default_password);
-
+    
     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;
        }
     }
index 93ea924f18a694e5df599f39a1f58bc5d8d1cecd..d3566937414217a670cc8b51a577b68e3413760d 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <stdlib.h>
 
 #define _ZIP_COMPILING_DEPRECATED
 #include "zipint.h"
 
 
-
 ZIP_EXTERN int
-zip_set_file_comment(struct zip *za, zip_uint64_t idx, const char *comment, int len)
+zip_set_file_comment(zip_t *za, zip_uint64_t idx, const char *comment, int len)
 {
     if (len < 0 || len > ZIP_UINT16_MAX) {
-        _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
         return -1;
     }
     return zip_file_set_comment(za, idx, comment, (zip_uint16_t)len, 0);
index a4abca8aff33f6bea8f7b069b31d730d6d2577a6..7bb0bf9450d39d27892ca900b18e3738c8cd5ed9 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
 
-
 ZIP_EXTERN int
-zip_set_file_compression(struct zip *za, zip_uint64_t idx,
-                        zip_int32_t method, zip_uint32_t flags)
+zip_set_file_compression(zip_t *za, zip_uint64_t idx, zip_int32_t method, zip_uint32_t flags)
 {
-    struct zip_entry *e;
+    zip_entry_t *e;
     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;
     }
 
     e = za->entry+idx;
-
+    
     old_method = (e->orig == NULL ? ZIP_CM_DEFAULT : e->orig->comp_method);
-
+    
     /* TODO: revisit this when flags are supported, since they may require a recompression */
-
+    
     if (method == old_method) {
        if (e->changes) {
            e->changes->changed &= ~ZIP_DIRENT_COMP_METHOD;
@@ -77,7 +74,7 @@ zip_set_file_compression(struct zip *za, zip_uint64_t idx,
     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;
             }
         }
@@ -85,6 +82,6 @@ zip_set_file_compression(struct zip *za, zip_uint64_t idx,
         e->changes->comp_method = method;
         e->changes->changed |= ZIP_DIRENT_COMP_METHOD;
     }
-
+    
     return 0;
 }
index 191e9ff44970bf369b9be0e6a792bc6c2c084ae5..5a103817530a32e7e1642689b4acc28c28752474 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <stdlib.h>
 #include <string.h>
 
 #include "zipint.h"
 
 
-
 int
-_zip_set_name(struct zip *za, zip_uint64_t idx, const char *name, zip_flags_t flags)
+_zip_set_name(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags)
 {
-    struct zip_entry *e;
-    struct zip_string *str;
+    zip_entry_t *e;
+    zip_string_t *str;
     int changed;
     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;
     }
 
-    if (name && name[0] != '\0') {
+    if (name && strlen(name) > 0) {
         /* TODO: check for string too long */
        if ((str=_zip_string_new((const zip_uint8_t *)name, (zip_uint16_t)strlen(name), flags, &za->error)) == NULL)
            return -1;
@@ -71,7 +69,7 @@ _zip_set_name(struct zip *za, zip_uint64_t idx, const char *name, zip_flags_t fl
     /* 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;
     }
 
@@ -93,11 +91,11 @@ _zip_set_name(struct zip *za, zip_uint64_t idx, const char *name, zip_flags_t fl
        changed = !_zip_string_equal(e->orig->filename, str);
     else
        changed = 1;
-
+       
     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;
             }
similarity index 75%
rename from ext/zip/lib/zip_source_pop.c
rename to ext/zip/lib/zip_source_begin_write.c
index 166ded832360fa71e7217a602a0ab0abf95dca7d..045933771fe5ace6e324feb802743a68be72b7b7 100644 (file)
@@ -1,6 +1,6 @@
 /*
-  zip_source_pop.c -- pop top layer from zip data source
-  Copyright (C) 2009 Dieter Baron and Thomas Klausner
+  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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
-#include <stdlib.h>
-
 #include "zipint.h"
 
 
-
-struct zip_source *
-zip_source_pop(struct zip_source *src)
+ZIP_EXTERN int
+zip_source_begin_write(zip_source_t *src)
 {
-    struct zip_source *lower;
-
-    if (src == NULL)
-       return NULL;
-
-    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);
+    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;
     }
 
-    return lower;
+    src->write_state = ZIP_SOURCE_WRITE_OPEN;
+    
+    return 0;
 }
index c81590ddcc1510afbf860416763efdec748f8858..aadf6e40b058a2243276a8a3a3c18057960b82e8 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   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
   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-
-
+#include <errno.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include "zipint.h"
 
+#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 {
-    const char *buf, *data, *end;
+    zip_error_t error;
     time_t mtime;
-    int freep;
+    buffer_t *in;
+    buffer_t *out;
 };
 
-static zip_int64_t read_data(void *, void *, zip_uint64_t, enum zip_source_cmd);
+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, zip_uint8_t *data, zip_uint64_t length);
+static int buffer_seek(buffer_t *buffer, void *data, zip_uint64_t len, zip_error_t *error);
+static zip_int64_t buffer_write(buffer_t *buffer, const zip_uint8_t *data, zip_uint64_t length, zip_error_t *);
 
+static zip_int64_t read_data(void *, void *, zip_uint64_t, zip_source_cmd_t);
 
 
-ZIP_EXTERN struct zip_source *
-zip_source_buffer(struct zip *za, const void *data, zip_uint64_t len, int freep)
+ZIP_EXTERN zip_source_t *
+zip_source_buffer(zip_t *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 zip_source_t *
+zip_source_buffer_create(const void *data, zip_uint64_t len, int freep, zip_error_t *error)
+{
+    struct read_data *ctx;
+    zip_source_t *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;
+    }
 
-    if ((zs=zip_source_function(za, read_data, f)) == NULL) {
-       free(f);
+    ctx->out = NULL;
+    ctx->mtime = time(NULL);
+    zip_error_init(&ctx->error);
+    
+    if ((zs=zip_source_function_create(read_data, ctx, error)) == NULL) {
+       buffer_free(ctx->in);
+       free(ctx);
        return NULL;
     }
 
@@ -81,81 +118,319 @@ zip_source_buffer(struct zip *za, const void *data, zip_uint64_t len, int freep)
 }
 
 
-
 static zip_int64_t
-read_data(void *state, void *data, zip_uint64_t len, enum zip_source_cmd cmd)
+read_data(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
 {
-    struct read_data *z;
-    char *buf;
-    zip_uint64_t n;
-
-    z = (struct read_data *)state;
-    buf = (char *)data;
+    struct read_data *ctx = (struct read_data *)state;
 
     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;
-
-       if (n) {
-           memcpy(buf, z->buf, n);
-           z->buf += n;
+        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;
+
+        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:
+           if (len > ZIP_INT64_MAX) {
+               zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
+               return -1;
+           }
+            return buffer_read(ctx->in, data, len);
+       
+        case ZIP_SOURCE_REMOVE:
+       {
+           buffer_t *empty = buffer_new_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_ROLLBACK_WRITE:
+           buffer_free(ctx->out);
+           ctx->out = NULL;
+           return 0;
 
-    case ZIP_SOURCE_CLOSE:
-       return 0;
+        case ZIP_SOURCE_SEEK:
+           return buffer_seek(ctx->in, data, len, &ctx->error);
 
-    case ZIP_SOURCE_STAT:
+        case ZIP_SOURCE_SEEK_WRITE:
+           return buffer_seek(ctx->out, data, len, &ctx->error);
+       
+        case ZIP_SOURCE_STAT:
         {
-           struct zip_stat *st;
-
-           if (len < sizeof(*st))
+            zip_stat_t *st;
+           
+           if (len < sizeof(*st)) {
+                zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
                return -1;
+           }
 
-           st = (struct zip_stat *)data;
+           st = (zip_stat_t *)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:
+            if (ctx->in->offset > ZIP_INT64_MAX) {
+               zip_error_set(&ctx->error, ZIP_ER_TELL, EOVERFLOW);
+               return -1;
+           }
+           return (zip_int64_t)ctx->in->offset;
+               
+            
+        case ZIP_SOURCE_TELL_WRITE:
+            if (ctx->out->offset > ZIP_INT64_MAX) {
+               zip_error_set(&ctx->error, ZIP_ER_TELL, EOVERFLOW);
+               return -1;
+           }
+           return (zip_int64_t)ctx->out->offset;
 
-           if (len < sizeof(int)*2)
+        case ZIP_SOURCE_WRITE:
+           if (len > ZIP_INT64_MAX) {
+               zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
                return -1;
+           }
+           return buffer_write(ctx->out, data, len, &ctx->error);
+
+        default:
+           zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
+            return -1;
+    }
+}
 
-           e = (int *)data;
-           e[0] = e[1] = 0;
+
+static void
+buffer_free(buffer_t *buffer)
+{
+    if (buffer == NULL) {
+       return; 
+    }
+
+    if (buffer->free_data) {
+       zip_uint64_t i;
+
+       for (i=0; i < buffer->nfragments; i++) {
+           free(buffer->fragments[i]);
        }
-       return sizeof(int)*2;
+    }
+    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;
+    }
 
-    case ZIP_SOURCE_FREE:
-       if (z->freep) {
-           free((void *)z->data);
-           z->data = NULL;
+    buffer->size = length;
+
+    if (length > 0) {
+       if ((buffer->fragments = malloc(sizeof(*(buffer->fragments)))) == NULL) {
+           buffer_free(buffer);
+           return NULL;
        }
-       free(z);
+       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, zip_uint8_t *data, zip_uint64_t length)
+{
+    zip_uint64_t n, i, fragment_offset;
+
+    length = ZIP_MIN(length, buffer->size - buffer->offset);
+
+    if (length == 0) {
        return 0;
+    }
+    if (length > ZIP_INT64_MAX) {
+       return -1;
+    }
+
+    i = buffer->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 (zip_int64_t)n;
+}
+
+
+static int
+buffer_seek(buffer_t *buffer, void *data, zip_uint64_t len, zip_error_t *error)
+{
+    zip_int64_t new_offset = zip_source_seek_compute_offset(buffer->offset, buffer->size, data, len, error);
+    
+    if (new_offset < 0) {
+        return -1;
+    }
+    
+    buffer->offset = (zip_uint64_t)new_offset;
+    return 0;
+}
+
+
+static zip_int64_t
+buffer_write(buffer_t *buffer, const zip_uint8_t *data, zip_uint64_t length, zip_error_t *error)
+{
+    zip_uint64_t 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;
+           zip_uint8_t **fragments;
+
+           while (new_capacity < needed_fragments) {
+               new_capacity *= 2;
+           }
+
+           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;
+    }
 
-    default:
-       ;
+    buffer->offset += n;
+    if (buffer->offset > buffer->size) {
+       buffer->size = buffer->offset;
     }
 
-    return -1;
+    return (zip_int64_t)n;
 }
diff --git a/ext/zip/lib/zip_source_call.c b/ext/zip/lib/zip_source_call.c
new file mode 100644 (file)
index 0000000..21f28bc
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ 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, zip_source_cmd_t command)
+{
+    zip_int64_t ret;
+    
+    if ((src->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(command)) == 0) {
+        zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0);
+        return -1;
+    }
+
+    if (src->src == NULL) {
+        ret = src->cb.f(src->ud, data, length, command);
+    }
+    else {
+        ret = src->cb.l(src->src, src->ud, data, length, command);
+    }
+    
+    if (ret < 0) {
+        if (command != ZIP_SOURCE_ERROR && command != ZIP_SOURCE_SUPPORTS) {
+            int e[2];
+            
+            if (_zip_source_call(src, e, sizeof(e), ZIP_SOURCE_ERROR) < 0) {
+                zip_error_set(&src->error, ZIP_ER_INTERNAL, 0);
+            }
+            else {
+                zip_error_set(&src->error, e[0], e[1]);
+            }
+        }
+    }
+
+    return ret;
+}
index a8e91daf5c870b4a539645bc19055839e11876be..36bc84235ea268587e2564f02d3a4cb50443b3dc 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
 
-
-void
-zip_source_close(struct zip_source *src)
+int
+zip_source_close(zip_source_t *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->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);
+           }
+       }
     }
 
-    src->is_open = 0;
+    return 0;
 }
diff --git a/ext/zip/lib/zip_source_commit_write.c b/ext/zip/lib/zip_source_commit_write.c
new file mode 100644 (file)
index 0000000..ba77abc
--- /dev/null
@@ -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"
+
+
+ZIP_EXTERN int
+zip_source_commit_write(zip_source_t *src)
+{
+    if (!ZIP_SOURCE_IS_OPEN_WRITING(src)) {
+        zip_error_set(&src->error, ZIP_ER_INVAL, 0);
+        return -1;
+    }
+    
+    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;
+}
index 739be2802133a51692c2441f56a957c76e4f3646..eed726616aba97385c34a75707241fb7b66a8209 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <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(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t);
 
 
-struct zip_source *
-zip_source_crc(struct zip *za, struct zip_source *src, int validate)
+zip_source_t *
+zip_source_crc(zip_t *za, zip_source_t *src, int validate)
 {
     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;
-
+    
     return zip_source_layered(za, src, crc_read, ctx);
 }
 
 
-
 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(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
 {
     struct crc_context *ctx;
     zip_int64_t n;
@@ -87,56 +83,62 @@ crc_read(struct zip_source *src, void *_ctx, void *data,
     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;
-
-       return 0;
-
-    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;
+        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;
+
+               for (i=0; i < (zip_uint64_t)n; i += nn) {
+                   nn = ZIP_MIN(UINT_MAX, (zip_uint64_t)n-i);
+
+                   ctx->crc = (zip_uint32_t)crc32(ctx->crc, (const Bytef *)data+i, (uInt)nn);
                }
-               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:
+        {
+            zip_stat_t *st;
 
-           st = (struct zip_stat *)data;
+           st = (zip_stat_t *)data;
 
            if (ctx->eof) {
                /* TODO: Set comp_size, comp_method, encryption_method?
@@ -148,19 +150,21 @@ crc_read(struct zip_source *src, void *_ctx, void *data,
                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;
-
-    case ZIP_SOURCE_FREE:
-       free(ctx);
-       return 0;
-
-    default:
-       return -1;
+            return 0;
+        }
+            
+        case ZIP_SOURCE_ERROR:
+            return zip_error_to_data(&ctx->error, data, len);
+
+        case ZIP_SOURCE_FREE:
+            free(ctx);
+            return 0;
+            
+        case ZIP_SOURCE_SUPPORTS:
+            return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1);
+            
+        default:
+            zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
+            return -1;
     }
-
 }
index dbb2f2791b03bd39c0bf4c63c448f642a9ef0fe2..2574ad017e4f6cf095247a41b8b954a4a142ea12 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_deflate.c -- deflate (de)compressoin routines
-  Copyright (C) 2009 Dieter Baron and Thomas Klausner
+  Copyright (C) 2009-2015 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -17,7 +17,7 @@
   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
   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-
-
 #include <stdlib.h>
 #include <string.h>
+#include <limits.h>
 
 #include "zipint.h"
 
 struct deflate {
-    int e[2];
-
-    int eof;
+    zip_error_t error;
+    
+    bool eof;
+    bool can_store;
+    bool is_stored;
     int mem_level;
     zip_uint64_t size;
-    char buffer[BUFSIZE];
+    zip_uint8_t buffer[BUFSIZE];
     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(zip_source_t *, struct deflate *, void *, zip_uint64_t);
+static zip_int64_t decompress_read(zip_source_t *, struct deflate *, void *, zip_uint64_t);
+static zip_int64_t deflate_compress(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t);
+static zip_int64_t deflate_decompress(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t);
 static void deflate_free(struct deflate *);
 
 
-
-struct zip_source *
-zip_source_deflate(struct zip *za, struct zip_source *src,
-                  zip_int32_t cm, int flags)
+zip_source_t *
+zip_source_deflate(zip_t *za, zip_source_t *src, zip_int32_t cm, int flags)
 {
     struct deflate *ctx;
-    struct zip_source *s2;
+    zip_source_t *s2;
 
     if (src == NULL || (cm != ZIP_CM_DEFLATE && !ZIP_CM_IS_DEFAULT(cm))) {
-       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+       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;
-    ctx->eof = 0;
+    zip_error_init(&ctx->error);
+    ctx->eof = false;
+    ctx->is_stored = false;
+    ctx->can_store = ZIP_CM_IS_DEFAULT(cm);
     if (flags & ZIP_CODEC_ENCODE) {
-       if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0))
-           ctx->mem_level = TORRENT_MEM_LEVEL;
-       else
-           ctx->mem_level = MAX_MEM_LEVEL;
+       ctx->mem_level = MAX_MEM_LEVEL;
     }
 
     if ((s2=zip_source_layered(za, src,
@@ -98,34 +92,55 @@ zip_source_deflate(struct zip *za, struct zip_source *src,
 }
 
 
-
 static zip_int64_t
-compress_read(struct zip_source *src, struct deflate *ctx,
-             void *data, zip_uint64_t len)
+compress_read(zip_source_t *src, struct deflate *ctx, void *data, zip_uint64_t len)
 {
     int end, ret;
     zip_int64_t n;
+    zip_uint64_t out_offset;
+    uInt out_len;
 
-    if (ctx->e[0] != 0)
+    if (zip_error_code_zip(&ctx->error) != ZIP_ER_OK)
        return -1;
-
-    if (len == 0)
+    
+    if (len == 0 || ctx->is_stored) {
        return 0;
-
+    }
+       
+    out_offset = 0;
+    out_len = (uInt)ZIP_MIN(UINT_MAX, len);
     ctx->zstr.next_out = (Bytef *)data;
-    ctx->zstr.avail_out = (uInt)len; /* TODO: check for overflow */
+    ctx->zstr.avail_out = out_len;
 
     end = 0;
     while (!end) {
        ret = deflate(&ctx->zstr, ctx->eof ? Z_FINISH : 0);
 
        switch (ret) {
+        case Z_STREAM_END:
+            if (ctx->can_store && ctx->zstr.total_in <= ctx->zstr.total_out) {
+                ctx->is_stored = true;
+                ctx->size = ctx->zstr.total_in;
+                memcpy(data, ctx->buffer, ctx->size);
+                return (zip_int64_t)ctx->size;
+            }
+            /* fallthrough */
        case Z_OK:
-       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 {
+                    ctx->can_store = false;
+                   end = 1;
+               }
+           }
+           else if (ctx->eof && ctx->zstr.avail_in == 0)
                end = 1;
            break;
 
@@ -137,16 +152,20 @@ compress_read(struct zip_source *src, struct deflate *ctx,
                }
 
                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;
                }
                else if (n == 0) {
-                   ctx->eof = 1;
-                   ctx->size = ctx->zstr.total_in;
+                   ctx->eof = true;
                    /* TODO: check against stat of src? */
+                   ctx->size = ctx->zstr.total_in;
                }
                else {
+                    if (ctx->zstr.total_in > 0) {
+                        /* we overwrote a previously filled ctx->buffer */
+                        ctx->can_store = false;
+                    }
                    ctx->zstr.next_in = (Bytef *)ctx->buffer;
                    ctx->zstr.avail_in = (uInt)n;
                }
@@ -157,46 +176,60 @@ compress_read(struct zip_source *src, struct deflate *ctx,
        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;
        }
     }
 
-    if (ctx->zstr.avail_out < len)
+    if (ctx->zstr.avail_out < len) {
+       ctx->can_store = false;
        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(zip_source_t *src, struct deflate *ctx, void *data, zip_uint64_t len)
 {
     int end, ret;
     zip_int64_t n;
+    zip_uint64_t out_offset;
+    uInt out_len;
 
-    if (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 && 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:
            ctx->eof = 1;
            end = 1;
@@ -210,12 +243,13 @@ decompress_read(struct zip_source *src, struct deflate *ctx,
                }
 
                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;
                }
-               else if (n == 0)
+               else if (n == 0) {
                    ctx->eof = 1;
+               }
                else {
                    ctx->zstr.next_in = (Bytef *)ctx->buffer;
                    ctx->zstr.avail_in = (uInt)n;
@@ -227,8 +261,7 @@ decompress_read(struct zip_source *src, struct deflate *ctx,
        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;
        }
@@ -237,14 +270,12 @@ decompress_read(struct zip_source *src, struct deflate *ctx,
     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(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
 {
     struct deflate *ctx;
     int ret;
@@ -262,11 +293,8 @@ deflate_compress(struct zip_source *src, void *ud, void *data,
        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;
        }
 
@@ -281,11 +309,11 @@ deflate_compress(struct zip_source *src, void *ud, void *data,
 
     case ZIP_SOURCE_STAT:
        {
-           struct zip_stat *st;
+           zip_stat_t *st;
 
-           st = (struct zip_stat *)data;
+           st = (zip_stat_t *)data;
 
-           st->comp_method = ZIP_CM_DEFLATE;
+           st->comp_method = ctx->is_stored ? ZIP_CM_STORE : ZIP_CM_DEFLATE;
            st->valid |= ZIP_STAT_COMP_METHOD;
            if (ctx->eof) {
                st->comp_size = ctx->size;
@@ -297,25 +325,25 @@ deflate_compress(struct zip_source *src, void *ud, void *data,
        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;
 
+    case ZIP_SOURCE_SUPPORTS:
+        return ZIP_SOURCE_SUPPORTS_READABLE;
+            
     default:
-       ctx->e[0] = ZIP_ER_INVAL;
-       ctx->e[1] = 0;
+        zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
        return -1;
     }
 }
 
 
-
 static zip_int64_t
-deflate_decompress(struct zip_source *src, void *ud, void *data,
-                  zip_uint64_t len, enum zip_source_cmd cmd)
+deflate_decompress(zip_source_t *src, void *ud, void *data,
+                  zip_uint64_t len, zip_source_cmd_t cmd)
 {
     struct deflate *ctx;
     zip_int64_t n;
@@ -324,69 +352,64 @@ deflate_decompress(struct zip_source *src, void *ud, void *data,
     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;
-
-       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 */;
-
-       /* 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;
-
-           return -1;
-       }
-       return 0;
-
-    case ZIP_SOURCE_READ:
-       return decompress_read(src, ctx, data, len);
-
-    case ZIP_SOURCE_CLOSE:
-       inflateEnd(&ctx->zstr);
-       return 0;
-
-    case ZIP_SOURCE_STAT:
-       {
-           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_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;
+        case ZIP_SOURCE_OPEN:
+            if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
+                _zip_error_set_from_source(&ctx->error, src);
+                return -1;
+            }
+
+            ctx->zstr.zalloc = Z_NULL;
+            ctx->zstr.zfree = Z_NULL;
+            ctx->zstr.opaque = NULL;
+            ctx->zstr.next_in = (Bytef *)ctx->buffer;
+            ctx->zstr.avail_in = (uInt)n;
+
+            /* negative value to tell zlib that there is no header */
+            if ((ret=inflateInit2(&ctx->zstr, -MAX_WBITS)) != Z_OK) {
+                zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret);
+                return -1;
+            }
+            return 0;
+
+        case ZIP_SOURCE_READ:
+            return decompress_read(src, ctx, data, len);
+
+        case ZIP_SOURCE_CLOSE:
+            inflateEnd(&ctx->zstr);
+            return 0;
+
+        case ZIP_SOURCE_STAT:
+        {
+            zip_stat_t *st;
+            
+            st = (zip_stat_t *)data;
+            
+            st->comp_method = ZIP_CM_STORE;
+            if (st->comp_size > 0 && st->size > 0)
+                st->comp_size = st->size;
+            
+            return 0;
+        }
+
+        case ZIP_SOURCE_ERROR:
+            return zip_error_to_data(&ctx->error, data, len);
+
+        case ZIP_SOURCE_FREE:
+            free(ctx);
+            return 0;
+            
+        case ZIP_SOURCE_SUPPORTS:
+            return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1);
+
+        default:
+            zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
+            return -1;
     }
-
 }
 
 
-
 static void
 deflate_free(struct deflate *ctx)
 {
-    /* TODO: deflateEnd if close was not called */
     free(ctx);
 }
index 87ac7fa14195d12b3fc8f02a5293d2efad3d687b..e09199bbefb82ffd1eb147e672f2b272e61203cf 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_error.c -- get last error from zip_source
-  Copyright (C) 2009-2015 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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
 
-
-void
-zip_source_error(struct zip_source *src, int *ze, int *se)
+zip_error_t *
+zip_source_error(zip_source_t *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;
 }
index 1f7f7b23666c03f45d4fd89705773f685c2ac63f..1465e1700ea3ecc150a37bf41693d8a64db196e1 100644 (file)
@@ -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-2015 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <errno.h>
 #include <stdio.h>
 
 #include "zipint.h"
 
 
-
-ZIP_EXTERN struct zip_source *
-zip_source_file(struct zip *za, const char *fname, zip_uint64_t start,
-               zip_int64_t len)
+ZIP_EXTERN zip_source_t *
+zip_source_file(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t len)
 {
     if (za == NULL)
        return NULL;
+    
+    return 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, NULL, error);
 }
index 9b1af4da0548a6c5eb75884031e95de8134c9a1e..e541305d7f555246ba2c603c71a33837e90aff53 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_filep.c -- create data source from FILE *
-  Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -17,7 +17,7 @@
   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
@@ -32,6 +32,7 @@
 */
 
 
+#include "zipint.h"
 
 #include <sys/stat.h>
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "zipint.h"
+#ifdef _WIN32
+/* WIN32 needs <fcntl.h> for _O_BINARY */
+#include <fcntl.h>
+#endif
+
+/* Windows sys/types.h does not provide these */
+#ifndef S_ISREG
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#endif
+#ifndef S_IRWXG
+#define S_IRWXG (S_IRWXU >> 3)
+#endif
+#ifndef S_IRWXO
+#define S_IRWXO (S_IRWXG >> 3)
+#endif
+
+#ifdef _MSC_VER
+/* MSVC doesn't have mode_t */
+typedef int mode_t;
+#endif
 
 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_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 */
+    zip_error_t error;      /* last error information */
+    zip_int64_t supports;
+
+    /* reading */
+    char *fname;            /* name of file to read from */
+    FILE *f;                /* file to read from */
+    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 zip_int64_t read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd);
+static int create_temp_output(struct read_file *ctx);
+static int _zip_fseek_u(FILE *f, zip_uint64_t offset, int whence, zip_error_t *error);
+static int _zip_fseek(FILE *f, zip_int64_t offset, int whence, zip_error_t *error);
 
 
-
-ZIP_EXTERN struct zip_source *
-zip_source_filep(struct zip *za, FILE *file, zip_uint64_t start,
-                zip_int64_t len)
+ZIP_EXTERN zip_source_t *
+zip_source_filep(zip_t *za, FILE *file, zip_uint64_t start, zip_int64_t len)
 {
     if (za == NULL)
        return NULL;
+    
+    return 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, 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_t *
+_zip_source_file_or_p(const char *fname, FILE *file, zip_uint64_t start, zip_int64_t len, const zip_stat_t *st, zip_error_t *error)
 {
-    struct read_file *f;
-    struct zip_source *zs;
-
+    struct read_file *ctx;
+    zip_source_t *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 ((f=(struct read_file *)malloc(sizeof(struct read_file))) == NULL) {
-       _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+    
+    if ((ctx=(struct read_file *)malloc(sizeof(struct read_file))) == NULL) {
+       zip_error_set(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;
-    if (st)
-       memcpy(&f->st, st, sizeof(f->st));
-    else
-       zip_stat_init(&f->st);
-
-    if ((zs=zip_source_function(za, read_file, f)) == NULL) {
-       free(f);
+    ctx->f = file;
+    ctx->start = start;
+    ctx->end = (len < 0 ? 0 : start+(zip_uint64_t)len);
+    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);
+
+    ctx->supports = ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1);
+    if (ctx->fname) {
+       struct stat sb;
+
+       if (stat(ctx->fname, &sb) < 0 || S_ISREG(sb.st_mode)) {
+            ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE;
+       }
+    }
+    else if (fseeko(ctx->f, 0, SEEK_CUR) == 0) {
+        ctx->supports = ZIP_SOURCE_SUPPORTS_SEEKABLE;
+    }
+
+    if ((zs=zip_source_function_create(read_file, ctx, error)) == NULL) {
+       free(ctx->fname);
+       free(ctx);
        return NULL;
     }
 
@@ -119,106 +169,269 @@ _zip_source_file_or_p(struct zip *za, const char *fname, FILE *file,
 }
 
 
+static int
+create_temp_output(struct read_file *ctx)
+{
+    char *temp;
+    int tfd;
+    mode_t mask;
+    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);
+
+#ifdef _WIN32
+    /* This might work under VS2015, however there's no good documentation
+       about it. So let it be for now. */
+    mask = 0;
+#else
+    mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
+#endif
+    if ((tfd=mkstemp(temp)) == -1) {
+        zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
+       umask(mask);
+        free(temp);
+        return -1;
+    }
+    umask(mask);
+
+    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->fname) {
-           if ((z->f=fopen(z->fname, "rb")) == NULL) {
-               z->e[0] = ZIP_ER_OPEN;
-               z->e[1] = errno;
-               return -1;
-           }
+        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);
+           /* not much we can do if chmod fails except make the whole commit fail */
+           (void)chmod(ctx->fname, 0666&~mask);
+           free(ctx->tmpname);
+           ctx->tmpname = NULL;
+            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);
+           free(ctx->tmpname);
+            if (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->start > 0) {
+                if (_zip_fseek_u(ctx->f, ctx->start, SEEK_SET, &ctx->error) < 0) {
+                    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 ((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;
 
-       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->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 (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;
+            }
+            (void)remove(ctx->tmpname);
+           free(ctx->tmpname);
+            ctx->tmpname = NULL;
+            return 0;
+       
+        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 (args == NULL)
                return -1;
-           }
-       }
+            
+            need_seek = 1;
+            
+            switch (args->whence) {
+                case SEEK_SET:
+                    new_current = args->offset;
+                    break;
+                    
+                case SEEK_END:
+                    if (ctx->end == 0) {
+                        if (_zip_fseek(ctx->f, args->offset, SEEK_END, &ctx->error) < 0) {
+                            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;
+
+                default:
+                    zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
+                    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;
+            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;
             }
-       }
-
-       if (z->remain != -1)
-           z->remain -= i;
-
-       return (zip_int64_t)i;
+            
+            ctx->current = (zip_uint64_t)new_current;
 
-    case ZIP_SOURCE_CLOSE:
-       if (z->fname) {
-           fclose(z->f);
-           z->f = NULL;
-       }
-       return 0;
+            if (need_seek) {
+                if (_zip_fseek_u(ctx->f, ctx->current, SEEK_SET, &ctx->error) < 0) {
+                    return -1;
+                }
+            }
+            return 0;
+        }
+            
+        case ZIP_SOURCE_SEEK_WRITE: {
+            zip_source_args_seek_t *args;
+            
+            args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);
+            if (args == NULL) {
+                return -1;
+            }
+            
+            if (_zip_fseek(ctx->fout, args->offset, args->whence, &ctx->error) < 0) {
+                return -1;
+            }
+            return 0;
+        }
 
-    case ZIP_SOURCE_STAT:
-        {
-           if (len < sizeof(z->st))
+        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;
+               zip_stat_t *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;
                }
 
-               st = (struct zip_stat *)data;
-
+               st = (zip_stat_t *)data;
+               
                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) {
@@ -226,26 +439,68 @@ read_file(void *state, void *data, zip_uint64_t len, enum zip_source_cmd cmd)
                    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;
+        default:
+            zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
+            return -1;
+    }
+}
 
-    case ZIP_SOURCE_FREE:
-       free(z->fname);
-       if (z->closep && z->f)
-           fclose(z->f);
-       free(z);
-       return 0;
 
-    default:
-       ;
+static int
+_zip_fseek_u(FILE *f, zip_uint64_t offset, int whence, zip_error_t *error)
+{
+    if (offset > ZIP_INT64_MAX) {
+       zip_error_set(error, ZIP_ER_SEEK, EOVERFLOW);
+       return -1;
     }
+    return _zip_fseek(f, (zip_int64_t)offset, whence, error);
+}
 
-    return -1;
+
+static int
+_zip_fseek(FILE *f, zip_int64_t offset, int whence, zip_error_t *error)
+{
+    if (offset > ZIP_FSEEK_MAX || offset < ZIP_FSEEK_MIN) {
+       zip_error_set(error, ZIP_ER_SEEK, EOVERFLOW);
+       return -1;
+    }
+    if (fseeko(f, (off_t)offset, whence) < 0) {
+       zip_error_set(error, ZIP_ER_SEEK, errno);
+       return -1;
+    }
+    return 0;
 }
index ae24ce9299351b2b0d4781e125f93d078d461838..9070469946f850160fe2f8d3d89415eea6333397 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_free.c -- free zip data source
-  Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <stdlib.h>
 
 #include "zipint.h"
 
 
-
 ZIP_EXTERN void
-zip_source_free(struct zip_source *src)
+zip_source_free(zip_source_t *src)
 {
     if (src == NULL)
        return;
 
-    if (src->is_open)
+    if (src->refcount > 0) {
+        src->refcount--;
+    }
+    if (src->refcount > 0) {
+        return;
+    }
+    
+    if (ZIP_SOURCE_IS_OPEN_READING(src)) {
+       src->open_count = 1; /* force close */
        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 (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 (src->src) {
+        zip_source_free(src->src);
     }
 
     free(src);
index 4e9d71e6743eb8f05c8d8010fbc97b7a9e372821..1d4be93c699d801ce6da7123ea92d0e1ddb3a5eb 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <stdlib.h>
 
 #include "zipint.h"
 
 
-
-ZIP_EXTERN struct zip_source *
-zip_source_function(struct zip *za, zip_source_callback zcb, void *ud)
+ZIP_EXTERN zip_source_t *
+zip_source_function(zip_t *za, zip_source_callback zcb, void *ud)
 {
-    struct zip_source *zs;
+    if (za == NULL) {
+        return NULL;
+    }
+    
+    return zip_source_function_create(zcb, ud, &za->error);
+}
 
-    if (za == NULL)
-       return NULL;
 
-    if ((zs=_zip_source_new(za)) == NULL)
+ZIP_EXTERN zip_source_t *
+zip_source_function_create(zip_source_callback zcb, void *ud, zip_error_t *error)
+{
+    zip_source_t *zs;
+
+    if ((zs=_zip_source_new(error)) == NULL)
        return NULL;
 
     zs->cb.f = zcb;
     zs->ud = ud;
-
+    
+    zs->supports = zcb(ud, NULL, 0, ZIP_SOURCE_SUPPORTS);
+    if (zs->supports < 0) {
+        zs->supports = ZIP_SOURCE_SUPPORTS_READABLE;
+    }
+    
     return zs;
 }
 
 
+ZIP_EXTERN void
+zip_source_keep(zip_source_t *src)
+{
+    src->refcount++;
+}
+
 
-struct zip_source *
-_zip_source_new(struct zip *za)
+zip_source_t *
+_zip_source_new(zip_error_t *error)
 {
-    struct zip_source *src;
+    zip_source_t *src;
 
-    if ((src=(struct zip_source *)malloc(sizeof(*src))) == NULL) {
-       _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+    if ((src=(zip_source_t *)malloc(sizeof(*src))) == NULL) {
+        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 = false;
+    src->source_archive = NULL;
+    src->refcount = 1;
+    zip_error_init(&src->error);
 
     return src;
 }
diff --git a/ext/zip/lib/zip_source_is_deleted.c b/ext/zip/lib/zip_source_is_deleted.c
new file mode 100644 (file)
index 0000000..e50cdd9
--- /dev/null
@@ -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;
+}
index c53d4fa3dac07fa0eb34c478f66e28414e13e938..94b33101093546b6cd2e69edce07509001f0da84 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <stdlib.h>
 
 #include "zipint.h"
 
 
-
-struct zip_source *
-zip_source_layered(struct zip *za, struct zip_source *src,
-                  zip_source_layered_callback cb, void *ud)
+zip_source_t *
+zip_source_layered(zip_t *za, zip_source_t *src, zip_source_layered_callback cb, void *ud)
 {
-    struct zip_source *zs;
-
     if (za == NULL)
-       return NULL;
+        return NULL;
+
+    return zip_source_layered_create(src, cb, ud, &za->error);
+}
 
-    if ((zs=_zip_source_new(za)) == NULL)
-       return NULL;
 
+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 *zs;
+    
+    if ((zs=_zip_source_new(error)) == NULL)
+        return NULL;
+    
+    zip_source_keep(src);
     zs->src = src;
     zs->cb.l = cb;
     zs->ud = ud;
 
+    zs->supports = cb(src, ud, NULL, 0, ZIP_SOURCE_SUPPORTS);
+    if (zs->supports < 0) {
+        zs->supports = ZIP_SOURCE_SUPPORTS_READABLE;
+    }
+
     return zs;
 }
index 3c2c29e5be6bd365bbe9502eb7db242168d26f22..ec5e39d542c6e43e0a508148583e49bb93c8da32 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_open.c -- open zip_source (prepare for reading)
-  Copyright (C) 2009-2015 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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
-
-
-int
-zip_source_open(struct zip_source *src)
+ZIP_EXTERN int
+zip_source_open(zip_source_t *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)
+    if (ZIP_SOURCE_IS_OPEN_READING(src)) {
+       if ((zip_source_supports(src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK)) == 0) {
+           zip_error_set(&src->error, ZIP_ER_INUSE, 0);
            return -1;
+       }
     }
     else {
-       if (zip_source_open(src->src) < 0) {
-           src->error_source = ZIP_LES_LOWER;
-           return -1;
+       if (ZIP_SOURCE_IS_LAYERED(src)) {
+           if (zip_source_open(src->src) < 0) {
+               _zip_error_set_from_source(&src->error, src->src);
+               return -1;
+           }
        }
-
-       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;
+       
+       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->is_open = 1;
-
+    src->open_count++;
+    
     return 0;
 }
index 905dbc1d26bed09d216389e5037589fd9a7b1eb9..ce281ac1483548099b8b9e4cced79cf83d2963ce 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <stdlib.h>
 #include <string.h>
 
 #include "zipint.h"
 
 struct trad_pkware {
-    int e[2];
-
+    zip_error_t error;
     zip_uint32_t key[3];
 };
 
@@ -50,38 +48,36 @@ struct trad_pkware {
 #define KEY2           878082192
 
 
-
 static void decrypt(struct trad_pkware *, zip_uint8_t *,
                    const zip_uint8_t *, zip_uint64_t, int);
-static int decrypt_header(struct zip_source *, struct trad_pkware *);
-static zip_int64_t pkware_decrypt(struct zip_source *, void *, void *,
-                                 zip_uint64_t, enum zip_source_cmd);
+static int decrypt_header(zip_source_t *, struct trad_pkware *);
+static zip_int64_t pkware_decrypt(zip_source_t *, void *, void *,
+                                 zip_uint64_t, zip_source_cmd_t);
 static void pkware_free(struct trad_pkware *);
 
 
-
-struct zip_source *
-zip_source_pkware(struct zip *za, struct zip_source *src,
+zip_source_t *
+zip_source_pkware(zip_t *za, zip_source_t *src,
                  zip_uint16_t em, int flags, const char *password)
 {
     struct trad_pkware *ctx;
-    struct zip_source *s2;
+    zip_source_t *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;
@@ -97,7 +93,6 @@ zip_source_pkware(struct zip *za, struct zip_source *src,
 }
 
 
-
 static void
 decrypt(struct trad_pkware *ctx, zip_uint8_t *out, const zip_uint8_t *in,
        zip_uint64_t len, int update_only)
@@ -112,8 +107,8 @@ decrypt(struct trad_pkware *ctx, zip_uint8_t *out, const zip_uint8_t *in,
        if (!update_only) {
            /* decrypt next byte */
            tmp = (zip_uint16_t)(ctx->key[2] | 2);
-           tmp = (tmp * (tmp ^ 1)) >> 8;
-           b ^= tmp;
+           tmp = (zip_uint16_t)((tmp * (tmp ^ 1)) >> 8);
+           b ^= (Bytef)tmp;
        }
 
        /* store cleartext */
@@ -123,15 +118,14 @@ decrypt(struct trad_pkware *ctx, zip_uint8_t *out, const zip_uint8_t *in,
        /* update keys */
        ctx->key[0] = (zip_uint32_t)crc32(ctx->key[0] ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL;
        ctx->key[1] = (ctx->key[1] + (ctx->key[0] & 0xff)) * 134775813 + 1;
-       b = ctx->key[1] >> 24;
+       b = (Bytef)(ctx->key[1] >> 24);
        ctx->key[2] = (zip_uint32_t)crc32(ctx->key[2] ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL;
     }
 }
 
 
-
 static int
-decrypt_header(struct zip_source *src, struct trad_pkware *ctx)
+decrypt_header(zip_source_t *src, struct trad_pkware *ctx)
 {
     zip_uint8_t header[HEADERLEN];
     struct zip_stat st;
@@ -139,13 +133,12 @@ decrypt_header(struct zip_source *src, struct trad_pkware *ctx)
     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;
     }
 
@@ -158,10 +151,8 @@ decrypt_header(struct zip_source *src, struct trad_pkware *ctx)
 
     _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;
     }
 
@@ -169,10 +160,9 @@ decrypt_header(struct zip_source *src, struct trad_pkware *ctx)
 }
 
 
-
 static zip_int64_t
-pkware_decrypt(struct zip_source *src, void *ud, void *data,
-              zip_uint64_t len, enum zip_source_cmd cmd)
+pkware_decrypt(zip_source_t *src, void *ud, void *data,
+              zip_uint64_t len, zip_source_cmd_t cmd)
 {
     struct trad_pkware *ctx;
     zip_int64_t n;
@@ -180,53 +170,55 @@ pkware_decrypt(struct zip_source *src, void *ud, void *data,
     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:
-       {
-           struct zip_stat *st;
+        case ZIP_SOURCE_STAT:
+        {
+           zip_stat_t *st;
 
-           st = (struct zip_stat *)data;
+           st = (zip_stat_t *)data;
 
            st->encryption_method = ZIP_EM_NONE;
            st->valid |= ZIP_STAT_ENCRYPTION_METHOD;
            /* TODO: deduce HEADERLEN from size for uncompressed */
            if (st->valid & ZIP_STAT_COMP_SIZE)
                st->comp_size -= HEADERLEN;
-       }
-       return 0;
-
-    case ZIP_SOURCE_ERROR:
-       memcpy(data, ctx->e, sizeof(int)*2);
-       return sizeof(int)*2;
-
-    case ZIP_SOURCE_FREE:
-       pkware_free(ctx);
-       return 0;
-
-    default:
-       ctx->e[0] = ZIP_ER_INVAL;
-       ctx->e[1] = 0;
-       return -1;
+       
+            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:
+            return zip_error_to_data(&ctx->error, data, len);
+
+        case ZIP_SOURCE_FREE:
+            pkware_free(ctx);
+            return 0;
+
+        default:
+            zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
+            return -1;
     }
 }
 
 
-
 static void
 pkware_free(struct trad_pkware *ctx)
 {
index 927280e913936a3df2dced5077f1b37d587f7f03..061a6f910ebb30b466c63c4a76ba44ae0cfbbb83 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
 
-
 zip_int64_t
-zip_source_read(struct zip_source *src, void *data, zip_uint64_t len)
+zip_source_read(zip_source_t *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;
-       return -1;
+    if (src->source_closed) {
+        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;
+    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;
     }
 
-    return ret;
+    return _zip_source_call(src, data, len, ZIP_SOURCE_READ);
 }
diff --git a/ext/zip/lib/zip_source_remove.c b/ext/zip/lib/zip_source_remove.c
new file mode 100644 (file)
index 0000000..470a5ed
--- /dev/null
@@ -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/ext/zip/lib/zip_source_rollback_write.c b/ext/zip/lib/zip_source_rollback_write.c
new file mode 100644 (file)
index 0000000..c35f30f
--- /dev/null
@@ -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"
+
+
+ZIP_EXTERN void
+zip_source_rollback_write(zip_source_t *src)
+{
+    if (src->write_state != ZIP_SOURCE_WRITE_OPEN && src->write_state != ZIP_SOURCE_WRITE_FAILED) {
+       return;
+    }
+    
+    _zip_source_call(src, NULL, 0, ZIP_SOURCE_ROLLBACK_WRITE);
+    src->write_state = ZIP_SOURCE_WRITE_CLOSED;
+}
diff --git a/ext/zip/lib/zip_source_seek.c b/ext/zip/lib/zip_source_seek.c
new file mode 100644 (file)
index 0000000..c3f4703
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+  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"
+
+
+ZIP_EXTERN int
+zip_source_seek(zip_source_t *src, zip_int64_t offset, int whence)
+{
+    zip_source_args_seek_t args;
+    
+    if (src->source_closed) {
+        return -1;
+    }
+    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);
+}
+
+
+zip_int64_t
+zip_source_seek_compute_offset(zip_uint64_t offset, zip_uint64_t length, void *data, zip_uint64_t data_length, zip_error_t *error)
+{
+    zip_int64_t new_offset;
+    zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, data_length, error);
+    
+    if (args == NULL) {
+        return -1;
+    }
+    
+    switch (args->whence) {
+        case SEEK_CUR:
+            new_offset = (zip_int64_t)offset + args->offset;
+            break;
+            
+        case SEEK_END:
+            new_offset = (zip_int64_t)length + args->offset;
+            break;
+            
+        case SEEK_SET:
+            new_offset = args->offset;
+            break;
+            
+        default:
+            zip_error_set(error, ZIP_ER_INVAL, 0);
+            return -1;
+    }
+    
+    if (new_offset < 0 || (zip_uint64_t)new_offset > length) {
+        zip_error_set(error, ZIP_ER_INVAL, 0);
+        return -1;
+    }
+    
+    return new_offset;
+}
diff --git a/ext/zip/lib/zip_source_seek_write.c b/ext/zip/lib/zip_source_seek_write.c
new file mode 100644 (file)
index 0000000..6660766
--- /dev/null
@@ -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"
+
+
+ZIP_EXTERN int
+zip_source_seek_write(zip_source_t *src, zip_int64_t offset, int whence)
+{
+    zip_source_args_seek_t args;
+        
+    if (!ZIP_SOURCE_IS_OPEN_WRITING(src) || (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END)) {
+        zip_error_set(&src->error, ZIP_ER_INVAL, 0);
+        return -1;
+    }
+    
+    args.offset = offset;
+    args.whence = whence;
+    
+    return (_zip_source_call(src, &args, sizeof(args), ZIP_SOURCE_SEEK_WRITE) < 0 ? -1 : 0);
+}
index 732db4f55f963d58783812c50d186ed6373ef11d..34cb05f4523bd658248762c3692e7cc02e92d6ec 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
 
-
 int
-zip_source_stat(struct zip_source *src, struct zip_stat *st)
+zip_source_stat(zip_source_t *src, zip_stat_t *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;
+    zip_stat_init(st);
+    
+    if (ZIP_SOURCE_IS_LAYERED(src)) {
+        if (zip_source_stat(src->src, st) < 0) {
+            _zip_error_set_from_source(&src->error, src->src);
+            return -1;
+        }
     }
 
-    if (zip_source_stat(src->src, st) < 0) {
-       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;
+    if (_zip_source_call(src, st, sizeof(*st), ZIP_SOURCE_STAT) < 0) {
        return -1;
     }
 
diff --git a/ext/zip/lib/zip_source_supports.c b/ext/zip/lib/zip_source_supports.c
new file mode 100644 (file)
index 0000000..3c100fb
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+  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(zip_source_t *src)
+{
+    return src->supports;
+}
+
+
+zip_int64_t
+zip_source_make_command_bitmap(zip_source_cmd_t cmd0, ...)
+{
+    zip_int64_t bitmap;
+    va_list ap;
+    
+    bitmap = ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd0);
+    
+    
+    
+    va_start(ap, cmd0);
+    for (;;) {
+        int cmd = va_arg(ap, int);
+        if (cmd < 0) {
+            break;
+        }
+        bitmap |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd);
+    }
+    va_end(ap);
+    
+    return bitmap;
+}
diff --git a/ext/zip/lib/zip_source_tell.c b/ext/zip/lib/zip_source_tell.c
new file mode 100644 (file)
index 0000000..f1c10b5
--- /dev/null
@@ -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_EXTERN zip_int64_t
+zip_source_tell(zip_source_t *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/ext/zip/lib/zip_source_tell_write.c b/ext/zip/lib/zip_source_tell_write.c
new file mode 100644 (file)
index 0000000..2fa1507
--- /dev/null
@@ -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_EXTERN zip_int64_t
+zip_source_tell_write(zip_source_t *src)
+{
+    if (!ZIP_SOURCE_IS_OPEN_WRITING(src)) {
+        zip_error_set(&src->error, ZIP_ER_INVAL, 0);
+        return -1;
+    }
+    
+    return _zip_source_call(src, NULL, 0, ZIP_SOURCE_TELL_WRITE);
+}
diff --git a/ext/zip/lib/zip_source_win32a.c b/ext/zip/lib/zip_source_win32a.c
new file mode 100644 (file)
index 0000000..c20e891
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+zip_source_win32a.c -- create data source from Windows file (ANSI)
+Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
+
+This file is part of libzip, a library to manipulate ZIP archives.
+The authors can be contacted at <libzip@nih.at>
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+3. The names of the authors may not be used to endorse or promote
+products derived from this software without specific prior
+written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include <errno.h>
+#include <stdio.h>
+
+#include "zipint.h"
+#include "zipwin32.h"
+
+static void * _win32_strdup_a(const void *str);
+static HANDLE _win32_open_a(_zip_source_win32_read_file_t *ctx);
+static HANDLE _win32_create_temp_a(_zip_source_win32_read_file_t *ctx, void **temp, zip_uint32_t value, PSECURITY_ATTRIBUTES sa);
+static int _win32_rename_temp_a(_zip_source_win32_read_file_t *ctx);
+static int _win32_remove_a(const void *fname);
+
+static _zip_source_win32_file_ops_t win32_ops_a = {
+    .op_strdup         = _win32_strdup_a,
+    .op_open           = _win32_open_a,
+    .op_create_temp    = _win32_create_temp_a,
+    .op_rename_temp    = _win32_rename_temp_a,
+    .op_remove         = _win32_remove_a
+};
+
+ZIP_EXTERN zip_source_t *
+zip_source_win32a(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t len)
+{
+    if (za == NULL)
+       return NULL;
+
+    return zip_source_win32a_create(fname, start, len, &za->error);
+}
+
+
+ZIP_EXTERN zip_source_t *
+zip_source_win32a_create(const char *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error)
+{
+    if (fname == NULL || length < -1) {
+       zip_error_set(error, ZIP_ER_INVAL, 0);
+       return NULL;
+    }
+
+    return _zip_source_win32_handle_or_name(fname, INVALID_HANDLE_VALUE, start, length, 1, NULL, &win32_ops_a, error);
+}
+
+
+static void *
+_win32_strdup_a(const void *str)
+{
+    return strdup((const char *)str);
+}
+
+
+static HANDLE
+_win32_open_a(_zip_source_win32_read_file_t *ctx)
+{
+    return CreateFileA(ctx->fname, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+}
+
+
+static HANDLE
+_win32_create_temp_a(_zip_source_win32_read_file_t *ctx, void **temp, zip_uint32_t value, PSECURITY_ATTRIBUTES sa)
+{
+    int len;
+
+    len = strlen((const char *)ctx->fname) + 10;
+    if (*temp == NULL) {
+       if ((*temp = malloc(sizeof(char) * len)) == NULL) {
+           zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
+           return INVALID_HANDLE_VALUE;
+       }
+    }
+    if (sprintf((char *)*temp, "%s.%08x", (const char *)ctx->fname, value) != len - 1) {
+       return INVALID_HANDLE_VALUE;
+    }
+
+    return CreateFileA((const char *)*temp, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, sa, CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_TEMPORARY, NULL);
+}
+
+
+static int
+_win32_rename_temp_a(_zip_source_win32_read_file_t *ctx)
+{
+    if (!MoveFileExA(ctx->tmpname, ctx->fname, MOVEFILE_REPLACE_EXISTING))
+       return -1;
+    return 0;
+}
+
+
+static int
+_win32_remove_a(const void *fname)
+{
+    DeleteFileA((const char *)fname);
+    return 0;
+}
diff --git a/ext/zip/lib/zip_source_win32handle.c b/ext/zip/lib/zip_source_win32handle.c
new file mode 100644 (file)
index 0000000..dd17c02
--- /dev/null
@@ -0,0 +1,607 @@
+/*
+zip_source_win32file.c -- create data source from HANDLE (Win32)
+Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
+
+This file is part of libzip, a library to manipulate ZIP archives.
+The authors can be contacted at <libzip@nih.at>
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+3. The names of the authors may not be used to endorse or promote
+products derived from this software without specific prior
+written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include <wchar.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "zipint.h"
+#include "zipwin32.h"
+
+static zip_int64_t _win32_read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd);
+static int _win32_create_temp_file(_zip_source_win32_read_file_t *ctx);
+static int _zip_filetime_to_time_t(FILETIME ft, time_t *t);
+static int _zip_seek_win32_u(void *h, zip_uint64_t offset, int whence, zip_error_t *error);
+static int _zip_seek_win32(void *h, zip_int64_t offset, int whence, zip_error_t *error);
+static int _zip_win32_error_to_errno(unsigned long win32err);
+static int _zip_stat_win32(void *h, zip_stat_t *st, _zip_source_win32_read_file_t *ctx);
+
+ZIP_EXTERN zip_source_t *
+zip_source_win32handle(zip_t *za, HANDLE h, zip_uint64_t start, zip_int64_t len)
+{
+    if (za == NULL)
+       return NULL;
+
+    return zip_source_win32handle_create(h, start, len, &za->error);
+}
+
+
+ZIP_EXTERN zip_source_t *
+zip_source_win32handle_create(HANDLE h, zip_uint64_t start, zip_int64_t length, zip_error_t *error)
+{
+    if (h == INVALID_HANDLE_VALUE || length < -1) {
+       zip_error_set(error, ZIP_ER_INVAL, 0);
+       return NULL;
+    }
+
+    return _zip_source_win32_handle_or_name(NULL, h, start, length, 1, NULL, NULL, error);
+}
+
+
+zip_source_t *
+_zip_source_win32_handle_or_name(const void *fname, HANDLE h, zip_uint64_t start, zip_int64_t len, int closep, const zip_stat_t *st, _zip_source_win32_file_ops_t *ops, zip_error_t *error)
+{
+    _zip_source_win32_read_file_t *ctx;
+    zip_source_t *zs;
+
+    if (h == INVALID_HANDLE_VALUE && fname == NULL) {
+       zip_error_set(error, ZIP_ER_INVAL, 0);
+       return NULL;
+    }
+
+    if ((ctx = (_zip_source_win32_read_file_t *)malloc(sizeof(_zip_source_win32_read_file_t))) == NULL) {
+       zip_error_set(error, ZIP_ER_MEMORY, 0);
+       return NULL;
+    }
+
+    ctx->fname = NULL;
+    if (fname) {
+       if ((ctx->fname = ops->op_strdup(fname)) == NULL) {
+           zip_error_set(error, ZIP_ER_MEMORY, 0);
+           free(ctx);
+           return NULL;
+       }
+    }
+
+    ctx->ops = ops;
+    ctx->h = h;
+    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->hout = INVALID_HANDLE_VALUE;
+
+    zip_error_init(&ctx->error);
+
+    ctx->supports = ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1);
+    if (ctx->fname) {
+       HANDLE th;
+
+       th = ops->op_open(ctx);
+       if (th == INVALID_HANDLE_VALUE || GetFileType(th) == FILE_TYPE_DISK) {
+           ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE;
+       }
+       if (th != INVALID_HANDLE_VALUE) {
+           CloseHandle(th);
+       }
+    }
+    else if (GetFileType(ctx->h) == FILE_TYPE_DISK) {
+       ctx->supports = ZIP_SOURCE_SUPPORTS_SEEKABLE;
+    }
+
+    if ((zs = zip_source_function_create(_win32_read_file, ctx, error)) == NULL) {
+       free(ctx->fname);
+       free(ctx);
+       return NULL;
+    }
+
+    return zs;
+}
+
+
+static zip_int64_t
+_win32_read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
+{
+    _zip_source_win32_read_file_t *ctx;
+    char *buf;
+    zip_uint64_t n;
+    DWORD i;
+
+    ctx = (_zip_source_win32_read_file_t *)state;
+    buf = (char *)data;
+
+    switch (cmd) {
+    case ZIP_SOURCE_BEGIN_WRITE:
+       if (ctx->fname == NULL) {
+           zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
+           return -1;
+       }
+       return _win32_create_temp_file(ctx);
+
+    case ZIP_SOURCE_COMMIT_WRITE: {
+       if (!CloseHandle(ctx->hout)) {
+           ctx->hout = INVALID_HANDLE_VALUE;
+           zip_error_set(&ctx->error, ZIP_ER_WRITE, _zip_win32_error_to_errno(GetLastError()));
+       }
+       ctx->hout = INVALID_HANDLE_VALUE;
+       if (ctx->ops->op_rename_temp(ctx) < 0) {
+           zip_error_set(&ctx->error, ZIP_ER_RENAME, _zip_win32_error_to_errno(GetLastError()));
+           return -1;
+       }
+       free(ctx->tmpname);
+       ctx->tmpname = NULL;
+       return 0;
+    }
+
+    case ZIP_SOURCE_CLOSE:
+       if (ctx->fname) {
+           CloseHandle(ctx->h);
+           ctx->h = INVALID_HANDLE_VALUE;
+       }
+       return 0;
+
+    case ZIP_SOURCE_ERROR:
+       return zip_error_to_data(&ctx->error, data, len);
+
+    case ZIP_SOURCE_FREE:
+       free(ctx->fname);
+       free(ctx->tmpname);
+       if (ctx->closep && ctx->h != INVALID_HANDLE_VALUE)
+           CloseHandle(ctx->h);
+       free(ctx);
+       return 0;
+
+    case ZIP_SOURCE_OPEN:
+       if (ctx->fname) {
+           if ((ctx->h = ctx->ops->op_open(ctx)) == INVALID_HANDLE_VALUE) {
+               zip_error_set(&ctx->error, ZIP_ER_OPEN, _zip_win32_error_to_errno(GetLastError()));
+               return -1;
+           }
+       }
+
+       if (ctx->closep && ctx->start > 0) {
+           if (_zip_seek_win32_u(ctx->h, ctx->start, SEEK_SET, &ctx->error) < 0) {
+               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 (!ctx->closep) {
+           if (_zip_seek_win32_u(ctx->h, ctx->current, SEEK_SET, &ctx->error) < 0) {
+               return -1;
+           }
+       }
+
+       if (!ReadFile(ctx->h, buf, (DWORD)n, &i, NULL)) {
+           zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError()));
+           return -1;
+       }
+       ctx->current += i;
+
+       return (zip_int64_t)i;
+
+    case ZIP_SOURCE_REMOVE:
+       if (ctx->ops->op_remove(ctx->fname) < 0) {
+           zip_error_set(&ctx->error, ZIP_ER_REMOVE, _zip_win32_error_to_errno(GetLastError()));
+           return -1;
+       }
+       return 0;
+
+    case ZIP_SOURCE_ROLLBACK_WRITE:
+       if (ctx->hout) {
+           CloseHandle(ctx->hout);
+           ctx->hout = INVALID_HANDLE_VALUE;
+       }
+       ctx->ops->op_remove(ctx->tmpname);
+       free(ctx->tmpname);
+       ctx->tmpname = NULL;
+       return 0;
+
+    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 (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) {
+               LARGE_INTEGER zero;
+               LARGE_INTEGER new_offset;
+
+               if (_zip_seek_win32(ctx->h, args->offset, SEEK_END, &ctx->error) < 0) {
+                   return -1;
+               }
+               zero.QuadPart = 0;
+               if (!SetFilePointerEx(ctx->h, zero, &new_offset, FILE_CURRENT)) {
+                   zip_error_set(&ctx->error, ZIP_ER_SEEK, _zip_win32_error_to_errno(GetLastError()));
+                   return -1;
+               }
+               new_current = new_offset.QuadPart;
+               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;
+
+       default:
+           zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
+           return -1;
+       }
+
+       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 (_zip_seek_win32_u(ctx->h, ctx->current, SEEK_SET, &ctx->error) < 0) {
+               return -1;
+           }
+       }
+       return 0;
+    }
+
+    case ZIP_SOURCE_SEEK_WRITE: {
+       zip_source_args_seek_t *args;
+
+       args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);
+       if (args == NULL) {
+           return -1;
+       }
+
+       if (_zip_seek_win32(ctx->hout, args->offset, args->whence, &ctx->error) < 0) {
+           return -1;
+       }
+       return 0;
+    }
+
+    case ZIP_SOURCE_STAT: {
+       if (len < sizeof(ctx->st))
+           return -1;
+
+       if (ctx->st.valid != 0)
+           memcpy(data, &ctx->st, sizeof(ctx->st));
+       else {
+           DWORD win32err;
+           zip_stat_t *st;
+           HANDLE h;
+           int success;
+
+           st = (zip_stat_t *)data;
+
+           if (ctx->h != INVALID_HANDLE_VALUE) {
+               h = ctx->h;
+           }
+           else {
+               h = ctx->ops->op_open(ctx);
+               if (h == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND) {
+                   zip_error_set(&ctx->error, ZIP_ER_READ, ENOENT);
+                   return -1;
+               }
+           }
+
+           success = _zip_stat_win32(h, st, ctx);
+           win32err = GetLastError();
+
+           /* We're done with the handle, so close it if we just opened it. */
+           if (h != ctx->h) {
+               CloseHandle(h);
+           }
+
+           if (success < 0) {
+               /* TODO: Is this the correct error to return in all cases? */
+               zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(win32err));
+               return -1;
+           }
+       }
+       return sizeof(ctx->st);
+    }
+
+    case ZIP_SOURCE_SUPPORTS:
+       return ctx->supports;
+
+    case ZIP_SOURCE_TELL:
+       return (zip_int64_t)ctx->current;
+
+    case ZIP_SOURCE_TELL_WRITE:
+    {
+       LARGE_INTEGER zero;
+       LARGE_INTEGER offset;
+
+       zero.QuadPart = 0;
+       if (!SetFilePointerEx(ctx->hout, zero, &offset, FILE_CURRENT)) {
+           zip_error_set(&ctx->error, ZIP_ER_TELL, _zip_win32_error_to_errno(GetLastError()));
+           return -1;
+       }
+
+       return offset.QuadPart;
+    }
+
+    case ZIP_SOURCE_WRITE:
+    {
+       DWORD ret;
+       if (!WriteFile(ctx->hout, data, (DWORD)len, &ret, NULL) || ret != len) {
+           zip_error_set(&ctx->error, ZIP_ER_WRITE, _zip_win32_error_to_errno(GetLastError()));
+           return -1;
+       }
+
+       return (zip_int64_t)ret;
+    }
+
+    default:
+       zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
+       return -1;
+    }
+}
+
+
+static int
+_win32_create_temp_file(_zip_source_win32_read_file_t *ctx)
+{
+    /*
+    Windows has GetTempFileName(), but it closes the file after
+    creation, leaving it open to a horrible race condition. So
+    we reinvent the wheel.
+    */
+    int i;
+    HANDLE th = INVALID_HANDLE_VALUE;
+    void *temp = NULL;
+    SECURITY_INFORMATION si;
+    SECURITY_ATTRIBUTES sa;
+    PSECURITY_DESCRIPTOR psd = NULL;
+    PSECURITY_ATTRIBUTES psa = NULL;
+    DWORD len;
+    BOOL success;
+
+    /*
+    Read the DACL from the original file, so we can copy it to the temp file.
+    If there is no original file, or if we can't read the DACL, we'll use the
+    default security descriptor.
+    */
+    if (ctx->h != INVALID_HANDLE_VALUE && GetFileType(ctx->h) == FILE_TYPE_DISK) {
+       si = DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION;
+       len = 0;
+       success = GetUserObjectSecurity(ctx->h, &si, NULL, len, &len);
+       if (!success && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+           if ((psd = (PSECURITY_DESCRIPTOR)malloc(len)) == NULL) {
+               zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
+               return -1;
+           }
+           success = GetUserObjectSecurity(ctx->h, &si, psd, len, &len);
+       }
+       if (success) {
+           sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+           sa.bInheritHandle = FALSE;
+           sa.lpSecurityDescriptor = psd;
+           psa = &sa;
+       }
+    }
+
+    zip_uint32_t value = GetTickCount();
+    for (i = 0; i < 1024 && th == INVALID_HANDLE_VALUE; i++) {
+       th = ctx->ops->op_create_temp(ctx, &temp, value + i, psa);
+       if (th == INVALID_HANDLE_VALUE && GetLastError() != ERROR_FILE_EXISTS)
+           break;
+    }
+
+    if (th == INVALID_HANDLE_VALUE) {
+       free(temp);
+       free(psd);
+       zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, _zip_win32_error_to_errno(GetLastError()));
+       return -1;
+    }
+
+    free(psd);
+    ctx->hout = th;
+    ctx->tmpname = temp;
+
+    return 0;
+}
+
+
+static int
+_zip_seek_win32_u(HANDLE h, zip_uint64_t offset, int whence, zip_error_t *error)
+{
+    if (offset > ZIP_INT64_MAX) {
+       zip_error_set(error, ZIP_ER_SEEK, EOVERFLOW);
+       return -1;
+    }
+    return _zip_seek_win32(h, (zip_int64_t)offset, whence, error);
+}
+
+
+static int
+_zip_seek_win32(HANDLE h, zip_int64_t offset, int whence, zip_error_t *error)
+{
+    LARGE_INTEGER li;
+    DWORD method;
+
+    switch (whence) {
+    case SEEK_SET:
+       method = FILE_BEGIN;
+       break;
+    case SEEK_END:
+       method = FILE_END;
+       break;
+    case SEEK_CUR:
+       method = FILE_CURRENT;
+       break;
+    default:
+       zip_error_set(error, ZIP_ER_SEEK, EINVAL);
+       return -1;
+    }
+
+    li.QuadPart = (LONGLONG)offset;
+    if (!SetFilePointerEx(h, li, NULL, method)) {
+       zip_error_set(error, ZIP_ER_SEEK, _zip_win32_error_to_errno(GetLastError()));
+       return -1;
+    }
+
+    return 0;
+}
+
+
+static int
+_zip_win32_error_to_errno(DWORD win32err)
+{
+    /*
+    Note: This list isn't exhaustive, but should cover common cases.
+    */
+    switch (win32err) {
+    case ERROR_INVALID_PARAMETER:
+       return EINVAL;
+    case ERROR_FILE_NOT_FOUND:
+       return ENOENT;
+    case ERROR_INVALID_HANDLE:
+       return EBADF;
+    case ERROR_ACCESS_DENIED:
+       return EACCES;
+    case ERROR_FILE_EXISTS:
+       return EEXIST;
+    case ERROR_TOO_MANY_OPEN_FILES:
+       return EMFILE;
+    case ERROR_DISK_FULL:
+       return ENOSPC;
+    default:
+       return 0;
+    }
+}
+
+
+static int
+_zip_stat_win32(HANDLE h, zip_stat_t *st, _zip_source_win32_read_file_t *ctx)
+{
+    FILETIME mtimeft;
+    time_t mtime;
+    LARGE_INTEGER size;
+    int regularp;
+
+    if (!GetFileTime(h, NULL, NULL, &mtimeft)) {
+       zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError()));
+       return -1;
+    }
+    if (_zip_filetime_to_time_t(mtimeft, &mtime) < 0) {
+       zip_error_set(&ctx->error, ZIP_ER_READ, ERANGE);
+       return -1;
+    }
+
+    regularp = 0;
+    if (GetFileType(h) == FILE_TYPE_DISK) {
+       regularp = 1;
+    }
+
+    if (!GetFileSizeEx(h, &size)) {
+       zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError()));
+       return -1;
+    }
+
+    zip_stat_init(st);
+    st->mtime = mtime;
+    st->valid |= ZIP_STAT_MTIME;
+    if (ctx->end != 0) {
+       st->size = ctx->end - ctx->start;
+       st->valid |= ZIP_STAT_SIZE;
+    }
+    else if (regularp) {
+       st->size = (zip_uint64_t)size.QuadPart;
+       st->valid |= ZIP_STAT_SIZE;
+    }
+
+    return 0;
+}
+
+
+static int
+_zip_filetime_to_time_t(FILETIME ft, time_t *t)
+{
+    /*
+    Inspired by http://stackoverflow.com/questions/6161776/convert-windows-filetime-to-second-in-unix-linux
+    */
+    const zip_int64_t WINDOWS_TICK = 10000000LL;
+    const zip_int64_t SEC_TO_UNIX_EPOCH = 11644473600LL;
+    ULARGE_INTEGER li;
+    zip_int64_t secs;
+    time_t temp;
+
+    li.LowPart = ft.dwLowDateTime;
+    li.HighPart = ft.dwHighDateTime;
+    secs = (li.QuadPart / WINDOWS_TICK - SEC_TO_UNIX_EPOCH);
+
+    temp = (time_t)secs;
+    if (secs != (zip_int64_t)temp)
+       return -1;
+
+    *t = temp;
+    return 0;
+}
diff --git a/ext/zip/lib/zip_source_win32utf8.c b/ext/zip/lib/zip_source_win32utf8.c
new file mode 100644 (file)
index 0000000..e11214b
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+zip_source_win32utf8.c -- create data source from Windows file (UTF-8)
+Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
+
+This file is part of libzip, a library to manipulate ZIP archives.
+The authors can be contacted at <libzip@nih.at>
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+3. The names of the authors may not be used to endorse or promote
+products derived from this software without specific prior
+written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include <errno.h>
+#include <stdio.h>
+
+#include "zipint.h"
+#include "zipwin32.h"
+
+
+ZIP_EXTERN zip_source_t *
+zip_source_file(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t len)
+{
+    if (za == NULL)
+       return NULL;
+
+    return zip_source_file_create(fname, start, len, &za->error);
+}
+
+
+ZIP_EXTERN zip_source_t *
+zip_source_file_create(const char *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error)
+{
+    int size;
+    wchar_t *wfname;
+    zip_source_t *source;
+
+    if (fname == NULL || length < -1) {
+       zip_error_set(error, ZIP_ER_INVAL, 0);
+       return NULL;
+    }
+
+    /* Convert fname from UTF-8 to Windows-friendly UTF-16. */
+    size = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, fname, -1, NULL, 0);
+    if (size == 0) {
+       zip_error_set(error, ZIP_ER_INVAL, 0);
+       return NULL;
+    }
+    if ((wfname = (wchar_t *)malloc(sizeof(wchar_t) * size)) == NULL) {
+       zip_error_set(error, ZIP_ER_MEMORY, 0);
+       return NULL;
+    }
+    MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, fname, -1, wfname, size);
+
+    source = zip_source_win32w_create(wfname, start, length, error);
+
+    free(wfname);
+    return source;
+}
diff --git a/ext/zip/lib/zip_source_win32w.c b/ext/zip/lib/zip_source_win32w.c
new file mode 100644 (file)
index 0000000..27cdf91
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+zip_source_win32w.c -- create data source from Windows file (UTF-16)
+Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
+
+This file is part of libzip, a library to manipulate ZIP archives.
+The authors can be contacted at <libzip@nih.at>
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+3. The names of the authors may not be used to endorse or promote
+products derived from this software without specific prior
+written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include <errno.h>
+#include <stdio.h>
+
+#include "zipint.h"
+#include "zipwin32.h"
+
+static void * _win32_strdup_w(const void *str);
+static HANDLE _win32_open_w(_zip_source_win32_read_file_t *ctx);
+static HANDLE _win32_create_temp_w(_zip_source_win32_read_file_t *ctx, void **temp, zip_uint32_t value, PSECURITY_ATTRIBUTES sa);
+static int _win32_rename_temp_w(_zip_source_win32_read_file_t *ctx);
+static int _win32_remove_w(const void *fname);
+
+static _zip_source_win32_file_ops_t win32_ops_w = {
+    .op_strdup       = _win32_strdup_w,
+    .op_open         = _win32_open_w,
+    .op_create_temp  = _win32_create_temp_w,
+    .op_rename_temp  = _win32_rename_temp_w,
+    .op_remove       = _win32_remove_w
+};
+
+ZIP_EXTERN zip_source_t *
+zip_source_win32w(zip_t *za, const wchar_t *fname, zip_uint64_t start, zip_int64_t len)
+{
+    if (za == NULL)
+       return NULL;
+
+    return zip_source_win32w_create(fname, start, len, &za->error);
+}
+
+
+ZIP_EXTERN zip_source_t *
+zip_source_win32w_create(const wchar_t *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error)
+{
+    if (fname == NULL || length < -1) {
+       zip_error_set(error, ZIP_ER_INVAL, 0);
+       return NULL;
+    }
+
+    return _zip_source_win32_handle_or_name(fname, INVALID_HANDLE_VALUE, start, length, 1, NULL, &win32_ops_w, error);
+}
+
+
+static void *
+_win32_strdup_w(const void *str)
+{
+    return _wcsdup((const wchar_t *)str);
+}
+
+
+static HANDLE
+_win32_open_w(_zip_source_win32_read_file_t *ctx)
+{
+    return CreateFileW(ctx->fname, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+}
+
+
+static HANDLE
+_win32_create_temp_w(_zip_source_win32_read_file_t *ctx, void **temp, zip_uint32_t value, PSECURITY_ATTRIBUTES sa)
+{
+    int len;
+
+    len = wcslen((const wchar_t *)ctx->fname) + 10;
+    if (*temp == NULL) {
+       if ((*temp = malloc(sizeof(wchar_t) * len)) == NULL) {
+           zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
+           return INVALID_HANDLE_VALUE;
+       }
+    }
+    if (swprintf((wchar_t *)*temp, len, L"%s.%08x", (const wchar_t *)ctx->fname, value) != len - 1) {
+       return INVALID_HANDLE_VALUE;
+    }
+
+    return CreateFileW((const wchar_t *)*temp, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, sa, CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_TEMPORARY, NULL);
+}
+
+
+static int
+_win32_rename_temp_w(_zip_source_win32_read_file_t *ctx)
+{
+    if (!MoveFileExW(ctx->tmpname, ctx->fname, MOVEFILE_REPLACE_EXISTING))
+       return -1;
+    return 0;
+}
+
+
+static int
+_win32_remove_w(const void *fname)
+{
+    DeleteFileW((const wchar_t *)fname);
+    return 0;
+}
index 83f017e674a81eea61971381499ec1264ca9679e..f02d048c0c6eee82a68db943b2161be9f46ba651 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_window.c -- return part of lower source
-  Copyright (C) 2012-2015 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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <stdlib.h>
 #include <string.h>
 
 #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;
+    bool 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(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t);
+
 
+zip_source_t *
+zip_source_window(zip_t *za, zip_source_t *src, zip_uint64_t start, zip_uint64_t len)
+{
+    return _zip_source_window_new(src, start, len, NULL, &za->error);
+}
 
 
-struct zip_source *
-zip_source_window(struct zip *za, struct zip_source *src, zip_uint64_t start, zip_uint64_t len)
+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_SUPPORTS_SEEKABLE) | (zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1));
+    ctx->needs_seek = (ctx->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK)) ? true : false;
+    
+    if (st) {
+        if (_zip_stat_merge(&ctx->stat, st, error) < 0) {
+            free(ctx);
+            return NULL;
+        }
     }
+    
+    return zip_source_layered_create(src, window_read, ctx, error);
+}
 
-    ctx->skip = start;
-    ctx->len = len;
-    ctx->left = len;
 
-    return zip_source_layered(za, src, window_read, ctx);
+int
+_zip_source_set_source_archive(zip_source_t *src, zip_t *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(zip_source_t *src)
+{
+    src->source_closed = 1;
+
+    if (zip_error_code_zip(&src->error) == ZIP_ER_OK) {
+        zip_error_set(&src->error, ZIP_ER_ZIPCLOSED, 0);
+    }
+}
+
 
 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(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
 {
     struct window *ctx;
     zip_int64_t ret;
@@ -86,65 +121,133 @@ window_read(struct zip_source *src, void *_ctx, void *data,
     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;
-               return -1;
-           }
-       }
-       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;
-
-           st = (struct zip_stat *)data;
-
-           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;
-
-    default:
-       return -1;
+        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_seek_compute_offset(ctx->offset - ctx->start, ctx->end - ctx->start, data, len, &ctx->error);
+
+            if (new_offset < 0) {
+                return -1;
+            }
+            
+            ctx->offset = (zip_uint64_t)new_offset + ctx->start;
+            return 0;
+        }
+
+       case ZIP_SOURCE_STAT:
+        {
+            zip_stat_t *st;
+            
+           st = (zip_stat_t *)data;
+            
+            if (_zip_stat_merge(st, &ctx->stat, &ctx->error) < 0) {
+                return -1;
+            }
+            return 0;
+        }
+            
+        case ZIP_SOURCE_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;
+    }
+}
+
+
+void
+_zip_deregister_source(zip_t *za, zip_source_t *src)
+{
+    unsigned int i;
+    
+    for (i=0; i<za->nopen_source; i++) {
+        if (za->open_source[i] == src) {
+            za->open_source[i] = za->open_source[za->nopen_source-1];
+            za->nopen_source--;
+            break;
+        }
     }
+}
 
+
+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 = (zip_source_t **)realloc(za->open_source, n*sizeof(zip_source_t *));
+        if (open_source == NULL) {
+            zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+            return -1;
+        }
+        za->nopen_source_alloc = n;
+        za->open_source = open_source;
+    }
+    
+    za->open_source[za->nopen_source++] = src;
+    
+    return 0;
 }
diff --git a/ext/zip/lib/zip_source_write.c b/ext/zip/lib/zip_source_write.c
new file mode 100644 (file)
index 0000000..c98f567
--- /dev/null
@@ -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_EXTERN zip_int64_t
+zip_source_write(zip_source_t *src, const void *data, zip_uint64_t length)
+{
+    if (!ZIP_SOURCE_IS_OPEN_WRITING(src) || length > ZIP_INT64_MAX) {
+        zip_error_set(&src->error, ZIP_ER_INVAL, 0);
+        return -1;
+    }
+    
+    return _zip_source_call(src, (void *)data, length, ZIP_SOURCE_WRITE);
+}
index 0c3559e3427b6df9ab37db9c29835d7d14d07e94..e172ca208ee76aaa67e5bd205c8a1edb866e7002 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <stdlib.h>
 #include <string.h>
 
 #include "zipint.h"
 
 
-
-ZIP_EXTERN struct zip_source *
-zip_source_zip(struct zip *za, struct zip *srcza, zip_uint64_t srcidx,
+ZIP_EXTERN zip_source_t *
+zip_source_zip(zip_t *za, zip_t *srcza, zip_uint64_t srcidx,
               zip_flags_t flags, zip_uint64_t start, zip_int64_t len)
 {
     if (len < -1) {
-        _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
         return NULL;
     }
-
+        
     if (len == -1)
        len = 0;
-
+    
     if (start == 0 && len == 0)
        flags |= ZIP_FL_COMPRESSED;
     else
index 4b62721ca367e117db22178952c8026a04acc5b9..40f1195f155f040574c3968607950d47f2bbc613 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_zip_new.c -- prepare data structures for zip_fopen/zip_source_zip
-  Copyright (C) 2012 Dieter Baron and Thomas Klausner
+  Copyright (C) 2012-2015 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <stdlib.h>
 
 #include "zipint.h"
 
 
-
-struct zip_source *
-_zip_source_zip_new(struct zip *za, struct zip *srcza, zip_uint64_t srcidx, zip_flags_t flags,
-                   zip_uint64_t start, zip_uint64_t len, const char *password)
+zip_source_t *
+_zip_source_zip_new(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_uint64_t len, const char *password)
 {
     zip_compression_implementation comp_impl;
     zip_encryption_implementation enc_impl;
-    struct zip_source *src, *s2;
+    zip_source_t *src, *s2;
     zip_uint64_t offset;
     struct zip_stat st;
 
     if (za == NULL)
        return NULL;
 
-    if (srcza == NULL ||  srcidx >= srcza->nentry) {
-       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+    if (srcza == NULL || srcidx >= srcza->nentry) {
+       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;
     }
 
@@ -72,24 +69,24 @@ _zip_source_zip_new(struct zip *za, struct zip *srcza, zip_uint64_t srcidx, zip_
        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;
        }
     }
@@ -98,7 +95,7 @@ _zip_source_zip_new(struct zip *za, struct zip *srcza, zip_uint64_t srcidx, zip_
     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;
            }
        }
@@ -108,64 +105,68 @@ _zip_source_zip_new(struct zip *za, struct zip *srcza, zip_uint64_t srcidx, zip_
        return NULL;
 
     if (st.comp_size == 0) {
-       if ((src=zip_source_buffer(za, NULL, 0, 0)) == NULL)
-           return NULL;
+       return zip_source_buffer(za, NULL, 0, 0);
     }
-    else {
-       if (start+len > 0 && enc_impl == NULL && comp_impl == NULL) {
-           struct zip_stat st2;
-
-           st2.size = len ? len : st.size-start;
-           st2.comp_size = st2.size;
-           st2.comp_method = ZIP_CM_STORE;
-           st2.mtime = st.mtime;
-           st2.valid = ZIP_STAT_SIZE|ZIP_STAT_COMP_SIZE|ZIP_STAT_COMP_METHOD|ZIP_STAT_MTIME;
 
-            /* 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 (start+len > 0 && enc_impl == NULL && comp_impl == NULL) {
+       struct zip_stat st2;
+       
+       st2.size = len ? len : st.size-start;
+       st2.comp_size = st2.size;
+       st2.comp_method = ZIP_CM_STORE;
+       st2.mtime = st.mtime;
+       st2.valid = ZIP_STAT_SIZE|ZIP_STAT_COMP_SIZE|ZIP_STAT_COMP_METHOD|ZIP_STAT_MTIME;
+       
+       if ((src = _zip_source_window_new(srcza->src, offset+start, st2.size, &st2, &za->error)) == NULL) {
+           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;
+    }
+    else {
+       if ((src = _zip_source_window_new(srcza->src, offset, st.comp_size, &st, &za->error)) == NULL) {
+           return NULL;
        }
+    }
+       
+    if (_zip_source_set_source_archive(src, srcza) < 0) {
+       zip_source_free(src);
+       return NULL;
+    }
 
-       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;
+    /* creating a layered source calls zip_keep() on the lower layer, so we free it */
+       
+    if (enc_impl) {
+       s2 = enc_impl(za, src, st.encryption_method, 0, password);
+       zip_source_free(src);
+       if (s2 == NULL) {
+           return NULL;
        }
-       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;
+       src = s2;
+    }
+    if (comp_impl) {
+       s2 = comp_impl(za, src, st.comp_method, 0);
+       zip_source_free(src);
+       if (s2 == NULL) {
+           return NULL;
        }
-       if (((flags & ZIP_FL_COMPRESSED) == 0 || st.comp_method == ZIP_CM_STORE)
-           && (len == 0 || len == st.comp_size)) {
-           /* when reading the whole file, check for crc errors */
-           if ((s2=zip_source_crc(za, src, 1)) == NULL) {
-               zip_source_free(src);
-               /* TODO: set error (how?) */
-               return NULL;
-           }
-           src = s2;
+       src = s2;
+    }
+    if (((flags & ZIP_FL_COMPRESSED) == 0 || st.comp_method == ZIP_CM_STORE) && (len == 0 || len == st.comp_size)) {
+       /* when reading the whole file, check for CRC errors */
+       s2 = zip_source_crc(za, src, 1);
+       zip_source_free(src);
+       if (s2 == NULL) {
+           return NULL;
        }
+       src = s2;
+    }
 
-       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;
+    if (start+len > 0 && (comp_impl || enc_impl)) {
+       s2 = zip_source_window(za, src, start, len ? len : st.size-start);
+       zip_source_free(src);
+       if (s2 == NULL) {
+           return NULL;
        }
+       src = s2;
     }
 
     return src;
index f6ba171d8da7d9be4c897b15531697864d3df5ab..cf8e56613cf635e1526a794cb5c255d233bae722 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
 
-
 ZIP_EXTERN int
-zip_stat(struct zip *za, const char *fname, zip_flags_t flags, struct zip_stat *st)
+zip_stat(zip_t *za, const char *fname, zip_flags_t flags, zip_stat_t *st)
 {
     zip_int64_t idx;
 
index c5712b6d0bc72f8bb58f4721ae033288814b1831..601e3f70b76ef6d9613a62b28ad5628ee23dc981 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
 
-
 ZIP_EXTERN int
-zip_stat_index(struct zip *za, zip_uint64_t index, zip_flags_t flags,
-              struct zip_stat *st)
+zip_stat_index(zip_t *za, zip_uint64_t index, zip_flags_t flags,
+              zip_stat_t *st)
 {
     const char *name;
-    struct zip_dirent *de;
+    zip_dirent_t *de;
 
     if ((de=_zip_get_dirent(za, index, flags, NULL)) == NULL)
        return -1;
 
     if ((name=zip_get_name(za, index, flags)) == NULL)
        return -1;
-
+    
 
     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;
        }
     }
@@ -83,6 +81,6 @@ zip_stat_index(struct zip *za, zip_uint64_t index, zip_flags_t flags,
     st->index = index;
     st->name = name;
     st->valid |= ZIP_STAT_INDEX|ZIP_STAT_NAME;
-
+    
     return 0;
 }
index 21841668d79a09f43500dec42a41d029ffeba117..6b7d633744792d59d27852409a80aea00d36b4de 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   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
   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-
+#include <string.h>
 
 #include "zipint.h"
 
 
-
 ZIP_EXTERN void
-zip_stat_init(struct zip_stat *st)
+zip_stat_init(zip_stat_t *st)
 {
     st->valid = 0;
     st->name = NULL;
@@ -50,3 +49,37 @@ zip_stat_init(struct zip_stat *st)
     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;
+}
index 37774b23ec7f766d28b197a763f8fa356bab675a..98c4f6b1cc45dc5b572615ec99ad30304318272b 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
 
-
 ZIP_EXTERN const char *
-zip_strerror(struct zip *za)
+zip_strerror(zip_t *za)
 {
-    return _zip_error_strerror(&za->error);
+    return zip_error_strerror(&za->error);
 }
index e3905da01b1cd4a2daaa2556a6b4ccea42a5ed10..307a425f78a69ae4937e9607a0ec56b7858110e1 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <stdlib.h>
 #include <string.h>
 
 #include "zipint.h"
 
 
-
 zip_uint32_t
-_zip_string_crc32(const struct zip_string *s)
+_zip_string_crc32(const zip_string_t *s)
 {
     zip_uint32_t crc;
-
+    
     crc = (zip_uint32_t)crc32(0L, Z_NULL, 0);
 
-    if (s != NULL)
+    if (s != NULL)    
        crc = (zip_uint32_t)crc32(crc, s->raw, s->length);
 
     return crc;
 }
 
 
-
 int
-_zip_string_equal(const struct zip_string *a, const struct zip_string *b)
+_zip_string_equal(const zip_string_t *a, const zip_string_t *b)
 {
     if (a == NULL || b == NULL)
        return a == b;
@@ -70,9 +67,8 @@ _zip_string_equal(const struct zip_string *a, const struct zip_string *b)
 }
 
 
-
 void
-_zip_string_free(struct zip_string *s)
+_zip_string_free(zip_string_t *s)
 {
     if (s == NULL)
        return;
@@ -83,9 +79,8 @@ _zip_string_free(struct zip_string *s)
 }
 
 
-
 const zip_uint8_t *
-_zip_string_get(struct zip_string *string, zip_uint32_t *lenp, zip_flags_t flags, struct zip_error *error)
+_zip_string_get(zip_string_t *string, zip_uint32_t *lenp, zip_flags_t flags, zip_error_t *error)
 {
     static const zip_uint8_t empty[1] = "";
 
@@ -113,16 +108,15 @@ _zip_string_get(struct zip_string *string, zip_uint32_t *lenp, zip_flags_t flags
            return string->converted;
        }
     }
-
+    
     if (lenp)
        *lenp = string->length;
     return string->raw;
 }
 
 
-
 zip_uint16_t
-_zip_string_length(const struct zip_string *s)
+_zip_string_length(const zip_string_t *s)
 {
     if (s == NULL)
        return 0;
@@ -131,13 +125,12 @@ _zip_string_length(const struct zip_string *s)
 }
 
 
-
-struct zip_string *
-_zip_string_new(const zip_uint8_t *raw, zip_uint16_t length, zip_flags_t flags, struct zip_error *error)
+zip_string_t *
+_zip_string_new(const zip_uint8_t *raw, zip_uint16_t length, zip_flags_t flags, zip_error_t *error)
 {
-    struct zip_string *s;
-    enum zip_encoding_type expected_encoding;
-
+    zip_string_t *s;
+    zip_encoding_type_t expected_encoding;
+    
     if (length == 0)
        return NULL;
 
@@ -152,16 +145,16 @@ _zip_string_new(const zip_uint8_t *raw, zip_uint16_t length, zip_flags_t flags,
        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);
+       
+    if ((s=(zip_string_t *)malloc(sizeof(*s))) == NULL) {
+       zip_error_set(error, ZIP_ER_MEMORY, 0);
        return NULL;
     }
 
-    if ((s->raw=(zip_uint8_t *)malloc(length+1)) == NULL) {
+    if ((s->raw=(zip_uint8_t *)malloc((size_t)(length+1))) == NULL) {
        free(s);
        return NULL;
     }
@@ -176,21 +169,20 @@ _zip_string_new(const zip_uint8_t *raw, zip_uint16_t length, zip_flags_t flags,
     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;
        }
     }
-
+    
     return s;
 }
 
 
-
-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;
-
-    fwrite(s->raw, s->length, 1, f);
+       return 0;
+    
+    return _zip_write(za, s->raw, s->length);
 }
index 9730bd2ce3e243cda3b61c733d5ad9bfe43bce95..6c8a495c78d9c207c2317423cc4278fa723b090d 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <stdlib.h>
 
 #include "zipint.h"
 
 
-
 ZIP_EXTERN int
-zip_unchange(struct zip *za, zip_uint64_t idx)
+zip_unchange(zip_t *za, zip_uint64_t idx)
 {
     return _zip_unchange(za, idx, 0);
 }
 
 
-
 int
-_zip_unchange(struct zip *za, zip_uint64_t idx, int allow_duplicates)
+_zip_unchange(zip_t *za, zip_uint64_t idx, int allow_duplicates)
 {
     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;
        }
     }
index 7fbb92467aff26c466f9e8a3c58950ad1991a50b..60076838d4e1ab776270e39e5dfdeccce415e625 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <stdlib.h>
 
 #include "zipint.h"
 
 
-
 ZIP_EXTERN int
-zip_unchange_all(struct zip *za)
+zip_unchange_all(zip_t *za)
 {
     int ret;
     zip_uint64_t i;
index 432070219138aaad6f6ffb45de0017742e09c56c..920255cc7e591d384a6275dde2757c64d61e44b3 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include <stdlib.h>
 
 #include "zipint.h"
 
 
-
 ZIP_EXTERN int
-zip_unchange_archive(struct zip *za)
+zip_unchange_archive(zip_t *za)
 {
     if (za->comment_changed) {
        _zip_string_free(za->comment_changes);
        za->comment_changes = NULL;
        za->comment_changed = 0;
     }
-
+    
     za->ch_flags = za->flags;
 
     return 0;
index b924f2cb23e53f229f46e618e5d1ee3c0b0691ee..839d9a3cb9c86c704736d1921ba1c2815a5dc688 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
 void
-_zip_unchange_data(struct zip_entry *ze)
+_zip_unchange_data(zip_entry_t *ze)
 {
     if (ze->source) {
        zip_source_free(ze->source);
index ad2c5627a5c5bda4fcf06264179bfd35393a4d32..f38eea04d27bbe811f94f45bf0de88805c9c4dc9 100644 (file)
@@ -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>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 */
 
 
-
 #include "zipint.h"
 
 #include <stdlib.h>
 
 
-
 static const zip_uint16_t _cp437_to_unicode[256] = {
     /* 0x00 - 0x0F */
     0x2007, 0x263A, 0x263B, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
@@ -115,11 +113,10 @@ static const zip_uint16_t _cp437_to_unicode[256] = {
 #define UTF_8_CONTINUE_MATCH 0x80
 
 
-
-enum zip_encoding_type
-_zip_guess_encoding(struct zip_string *str, enum zip_encoding_type expected_encoding)
+zip_encoding_type_t
+_zip_guess_encoding(zip_string_t *str, zip_encoding_type_t expected_encoding)
 {
-    enum zip_encoding_type enc;
+    zip_encoding_type_t enc;
     const zip_uint8_t *name;
     zip_uint32_t i, j, ulen;
 
@@ -173,12 +170,11 @@ done:
        if (expected_encoding != enc && enc != ZIP_ENCODING_ASCII)
            return ZIP_ENCODING_ERROR;
     }
-
+    
     return enc;
 }
 
 
-
 static zip_uint32_t
 _zip_unicode_to_utf8_len(zip_uint32_t codepoint)
 {
@@ -192,7 +188,6 @@ _zip_unicode_to_utf8_len(zip_uint32_t codepoint)
 }
 
 
-
 static zip_uint32_t
 _zip_unicode_to_utf8(zip_uint32_t codepoint, zip_uint8_t *buf)
 {
@@ -201,28 +196,27 @@ _zip_unicode_to_utf8(zip_uint32_t codepoint, zip_uint8_t *buf)
        return 1;
     }
     if (codepoint < 0x0800) {
-       buf[0] = UTF_8_LEN_2_MATCH | ((codepoint >> 6) & 0x1f);
-       buf[1] = UTF_8_CONTINUE_MATCH | (codepoint & 0x3f);
+       buf[0] = (zip_uint8_t)(UTF_8_LEN_2_MATCH | ((codepoint >> 6) & 0x1f));
+       buf[1] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | (codepoint & 0x3f));
        return 2;
     }
     if (codepoint < 0x10000) {
-       buf[0] = UTF_8_LEN_3_MATCH | ((codepoint >> 12) & 0x0f);
-       buf[1] = UTF_8_CONTINUE_MATCH | ((codepoint >> 6) & 0x3f);
-       buf[2] = UTF_8_CONTINUE_MATCH | (codepoint & 0x3f);
+       buf[0] = (zip_uint8_t)(UTF_8_LEN_3_MATCH | ((codepoint >> 12) & 0x0f));
+       buf[1] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | ((codepoint >> 6) & 0x3f));
+       buf[2] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | (codepoint & 0x3f));
        return 3;
     }
-    buf[0] = UTF_8_LEN_4_MATCH | ((codepoint >> 18) & 0x07);
-    buf[1] = UTF_8_CONTINUE_MATCH | ((codepoint >> 12) & 0x3f);
-    buf[2] = UTF_8_CONTINUE_MATCH | ((codepoint >> 6) & 0x3f);
-    buf[3] = UTF_8_CONTINUE_MATCH | (codepoint & 0x3f);
+    buf[0] = (zip_uint8_t)(UTF_8_LEN_4_MATCH | ((codepoint >> 18) & 0x07));
+    buf[1] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | ((codepoint >> 12) & 0x3f));
+    buf[2] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | ((codepoint >> 6) & 0x3f));
+    buf[3] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | (codepoint & 0x3f));
     return 4;
 }
 
 
-
 zip_uint8_t *
 _zip_cp437_to_utf8(const zip_uint8_t * const _cp437buf, zip_uint32_t len,
-                  zip_uint32_t *utf8_lenp, struct zip_error *error)
+                  zip_uint32_t *utf8_lenp, zip_error_t *error)
 {
     zip_uint8_t *cp437buf = (zip_uint8_t *)_cp437buf;
     zip_uint8_t *utf8buf;
@@ -239,7 +233,7 @@ _zip_cp437_to_utf8(const zip_uint8_t * const _cp437buf, zip_uint32_t len,
        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;
     }
 
index 1f8f075f504405ee1fce387548e92a3cad457fb9..c8716fb952bf9eddb2e14c3e7b97760af47f70b6 100644 (file)
@@ -7,7 +7,11 @@
    This file was generated automatically by CMake
    based on ../cmake-zipconf.h.in.
  */
-#define LIBZIP_VERSION "0.11.2"
+#define LIBZIP_VERSION "1.0.1"
+#define LIBZIP_VERSION_MAJOR 1
+#define LIBZIP_VERSION_MINOR 0
+#define LIBZIP_VERSION_MICRO 1
+
 /* #undef HAVE_INTTYPES_H_LIBZIP */
 
 #if defined(_WIN32)
index 1577d6085ff1af3423c56137253adad12ee00066..40f43af09c27d19724b50ba5b7b82eb50daef2e9 100644 (file)
@@ -20,7 +20,7 @@
   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
   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
+#ifdef PHP_WIN32
+# include "php_zip_config.w32.h"
+#else
+# include "config.h"
+#endif
+
 /* to have *_MAX definitions for all types when compiling with g++ */
 #define __STDC_LIMIT_MACROS
 
 #endif
 
 #include "zip.h"
-#ifdef PHP_WIN32
-# include "php_zip_config.w32.h"
-#else
-# include "config.h"
-#endif
 
-#ifdef HAVE_MOVEFILEEXA
-#include <windows.h>
-#define _zip_rename(s, t)      (!MoveFileExA((s), (t), MOVEFILE_COPY_ALLOWED|MOVEFILE_REPLACE_EXISTING))
+#ifdef HAVE_STDBOOL_H
+#include <stdbool.h>
 #else
-#define _zip_rename    rename
+typedef char bool;
+#define true    1
+#define false   0
 #endif
 
 #ifdef _WIN32
 #if defined(HAVE__OPEN)
 #define open(a, b, c)  _open((a), (b))
 #endif
-#if defined(HAVE__SNPRINTF) && !defined(PHP_WIN32)
+#if defined(HAVE__SNPRINTF)
 #define snprintf       _snprintf
 #endif
-#if defined(HAVE__STRDUP) && !defined(HAVE_STRDUP)
+#if defined(HAVE__STRDUP)
+#if !defined(HAVE_STRDUP) || defined(_WIN32)
+#undef strdup
 #define strdup         _strdup
 #endif
 #endif
+#endif
 
 #ifndef HAVE_FSEEKO
 #define fseeko(s, o, w)        (fseek((s), (long int)(o), (w)))
@@ -110,14 +115,25 @@ int _zip_mkstemp(char *);
 
 #if SIZEOF_OFF_T == 8
 #define ZIP_OFF_MAX ZIP_INT64_MAX
+#define ZIP_OFF_MIN ZIP_INT64_MIN
 #elif SIZEOF_OFF_T == 4
 #define ZIP_OFF_MAX ZIP_INT32_MAX
+#define ZIP_OFF_MIN ZIP_INT32_MIN
 #elif SIZEOF_OFF_T == 2
 #define ZIP_OFF_MAX ZIP_INT16_MAX
+#define ZIP_OFF_MIN ZIP_INT16_MIN
 #else
 #error unsupported size of off_t
 #endif
 
+#if defined(HAVE_FTELLO) && defined(HAVE_FSEEKO)
+#define ZIP_FSEEK_MAX ZIP_OFF_MAX
+#define ZIP_FSEEK_MIN ZIP_OFF_MIN
+#else
+#define ZIP_FSEEK_MAX LONG_MAX
+#define ZIP_FSEEK_MIN LONG_MIN
+#endif
+
 #ifndef SIZE_MAX
 #if SIZEOF_SIZE_T == 8
 #define SIZE_MAX ZIP_INT64_MAX
@@ -136,10 +152,6 @@ int _zip_mkstemp(char *);
 #define DATADES_MAGIC "PK\7\8"
 #define EOCD64LOC_MAGIC "PK\6\7"
 #define EOCD64_MAGIC  "PK\6\6"
-#define TORRENT_SIG    "TORRENTZIPPED-"
-#define TORRENT_SIG_LEN        14
-#define TORRENT_CRC_LEN 8
-#define TORRENT_MEM_LEVEL      8
 #define CDENTRYSIZE         46u
 #define LENTRYSIZE          30
 #define MAXCOMLEN        65536
@@ -149,8 +161,9 @@ int _zip_mkstemp(char *);
 #define EOCD64LEN          56
 #define CDBUFSIZE       (MAXCOMLEN+EOCDLEN+EOCD64LOCLEN)
 #define BUFSIZE                8192
+#define EFZIP64SIZE 28
 
-#define ZIP_CM_REPLACED_DEFAULT (-2)
+#define ZIP_CM_REPLACED_DEFAULT        (-2)
 
 #define ZIP_CM_IS_DEFAULT(x)   ((x) == ZIP_CM_DEFAULT || (x) == ZIP_CM_REPLACED_DEFAULT)
 
@@ -161,69 +174,48 @@ int _zip_mkstemp(char *);
 #define ZIP_EF_IS_INTERNAL(id) ((id) == ZIP_EF_UTF_8_COMMENT || (id) == ZIP_EF_UTF_8_NAME || (id) == ZIP_EF_ZIP64)
 
 /* according to unzip-6.0's zipinfo.c, this corresponds to a regular file with rw permissions for everyone */
-#define ZIP_EXT_ATTRIB_DEFAULT         (0100666<<16)
+#define ZIP_EXT_ATTRIB_DEFAULT         (0100666u<<16)
 /* according to unzip-6.0's zipinfo.c, this corresponds to a directory with rwx permissions for everyone */
-#define ZIP_EXT_ATTRIB_DEFAULT_DIR     (0040777<<16)
+#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 *,
-                                                    zip_int32_t, int);
-typedef struct zip_source *(*zip_encryption_implementation)(struct zip *,
-                                                   struct zip_source *,
-                                                   zip_uint16_t, int,
-                                                   const char *);
+/* flags for compression and encryption sources */
+
+#define ZIP_CODEC_DECODE       0 /* decompress/decrypt (encode flag not set) */
+#define ZIP_CODEC_ENCODE       1 /* compress/encrypt */
+
+
+typedef zip_source_t *(*zip_compression_implementation)(zip_t *, zip_source_t *, zip_int32_t, int);
+typedef zip_source_t *(*zip_encryption_implementation)(zip_t *, zip_source_t *, zip_uint16_t, int, const char *);
 
 zip_compression_implementation _zip_get_compression_implementation(zip_int32_t);
 zip_encryption_implementation _zip_get_encryption_implementation(zip_uint16_t);
 
 
 
-
 /* This API is not final yet, but we need it internally, so it's private for now. */
 
-const zip_uint8_t *zip_get_extra_field_by_id(struct zip *, int, int, zip_uint16_t, int, zip_uint16_t *);
+const zip_uint8_t *zip_get_extra_field_by_id(zip_t *, int, int, zip_uint16_t, int, zip_uint16_t *);
 
 /* This section contains API that is of limited use until support for
    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);
-
-
-/* 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 *);
-
+typedef zip_int64_t (*zip_source_layered_callback)(zip_source_t *, void *, void *, zip_uint64_t, enum zip_source_cmd);
+zip_source_t *zip_source_crc(zip_t *, zip_source_t *, int);
+zip_source_t *zip_source_deflate(zip_t *, zip_source_t *, zip_int32_t, int);
+zip_source_t *zip_source_layered(zip_t *, zip_source_t *, zip_source_layered_callback, void *);
+zip_source_t *zip_source_layered_create(zip_source_t *src, zip_source_layered_callback cb, void *ud, zip_error_t *error);
+zip_source_t *zip_source_pkware(zip_t *, zip_source_t *, zip_uint16_t, int, const char *);
+int zip_source_remove(zip_source_t *);
+zip_int64_t zip_source_supports(zip_source_t *src);
+zip_source_t *zip_source_window(zip_t *, zip_source_t *, zip_uint64_t, zip_uint64_t);
 
 
 /* error source for layered sources */
@@ -258,49 +250,50 @@ enum zip_encoding_type {
     ZIP_ENCODING_ERROR          /* should be UTF-8 but isn't */
 };
 
-/* error information */
+typedef enum zip_encoding_type zip_encoding_type_t;
+
+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;
+typedef struct zip_buffer zip_buffer_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 */
-};
 
 /* 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 */
-    int comment_changed;               /* whether archive comment was changed */
+    zip_string_t *comment_orig;         /* archive comment */
+    zip_string_t *comment_changes;  /* changed archive comment */
+    bool 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 */
-
-    unsigned int nfile;                        /* number of opened files within archive */
-    unsigned int nfile_alloc;          /* number of files allocated */
-    struct zip_file **file;            /* opened files within archive */
+    zip_entry_t *entry;                 /* entries */
 
+    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) */
 };
 
 /* file in zip archive, part of API */
 
 struct zip_file {
-    struct zip *za;            /* zip archive containing this file */
-    struct zip_error error;    /* error information */
-    int eof;
-    struct zip_source *src;    /* data source */
+    zip_t *za;         /* zip archive containing this file */
+    zip_error_t error; /* error information */
+    bool eof;
+    zip_source_t *src; /* data source */
 };
 
 /* zip archive directory entry (central or local) */
@@ -310,74 +303,89 @@ struct zip_file {
 #define ZIP_DIRENT_COMMENT     0x0004u
 #define ZIP_DIRENT_EXTRA_FIELD 0x0008u
 #define ZIP_DIRENT_ATTRIBUTES  0x0010u
+#define ZIP_DIRENT_LAST_MOD    0x0020u
 #define ZIP_DIRENT_ALL         0xffffu
 
 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 */
-
-    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 */
+    bool local_extra_fields_read;      /*      whether we already read in local header extra fields */
+    bool 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 */
+    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;
+    zip_int64_t supports;       /* supported commands */
+    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 */
+    bool source_closed;         /* set if source archive is closed */
+    zip_t *source_archive;      /* zip archive we're reading from, NULL if not from archive */
+    unsigned int refcount;
 };
 
+#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;
-    int deleted;
+    zip_dirent_t *orig;
+    zip_dirent_t *changes;
+    zip_source_t *source;
+    bool deleted;
 };
 
 
-
 /* file or archive comment, or filename */
 
 struct zip_string {
@@ -389,14 +397,25 @@ struct zip_string {
 };
 
 
+/* bounds checked access to memory buffer */
+
+struct zip_buffer {
+    bool ok;
+    bool free_data;
+    
+    zip_uint8_t *data;
+    zip_uint64_t size;
+    zip_uint64_t offset;
+};
 
-/* which files to write, and in which order (name is for torrentzip sorting) */
+/* which files to write in which order */
 
 struct zip_filelist {
     zip_uint64_t idx;
-    const char *name;
+// TODO    const char *name;
 };
 
+typedef struct zip_filelist zip_filelist_t;
 
 
 extern const char * const _zip_err_str[];
@@ -404,7 +423,6 @@ extern const int _zip_nerr_str;
 extern const int _zip_err_type[];
 
 
-
 #define ZIP_ENTRY_CHANGED(e, f)        ((e)->changes && ((e)->changes->changed & (f)))
 
 #define ZIP_ENTRY_DATA_CHANGED(x)      ((x)->source != NULL)
@@ -412,104 +430,118 @@ extern const int _zip_err_type[];
 #define ZIP_IS_RDONLY(za)      ((za)->ch_flags & ZIP_AFL_RDONLY)
 
 
-
-zip_int64_t _zip_add_entry(struct zip *);
-
-int _zip_cdir_compute_crc(struct zip *, uLong *);
-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 *);
-
-struct zip_dirent *_zip_dirent_clone(const struct zip_dirent *);
-void _zip_dirent_free(struct zip_dirent *);
-void _zip_dirent_finalize(struct zip_dirent *);
-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 *);
-void _zip_dirent_torrent_normalize(struct zip_dirent *);
-int _zip_dirent_write(struct zip_dirent *, FILE *, zip_flags_t, struct zip_error *);
-
-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);
-void _zip_ef_free(struct zip_extra_field *);
-const zip_uint8_t *_zip_ef_get_by_id(const struct zip_extra_field *, zip_uint16_t *, zip_uint16_t, zip_uint16_t, zip_flags_t, struct zip_error *);
-struct zip_extra_field *_zip_ef_merge(struct zip_extra_field *, struct zip_extra_field *);
-struct zip_extra_field *_zip_ef_new(zip_uint16_t, zip_uint16_t, const zip_uint8_t *, zip_flags_t);
-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 *);
-
-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 *);
-
-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 *);
-
-int _zip_file_extra_field_prepare_for_change(struct zip *, zip_uint64_t);
-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 *);
-
-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 *error);
-
-struct zip *_zip_open(const char *, FILE *, unsigned int, int *);
-
-int _zip_read_local_ef(struct zip *, zip_uint64_t);
-
-struct zip_source *_zip_source_file_or_p(struct zip *, const char *, FILE *,
-                                        zip_uint64_t, zip_int64_t, int,
-                                        const struct zip_stat *);
-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 *);
-
-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_changed(const struct zip *, zip_uint64_t *);
-const char *_zip_get_name(struct zip *, zip_uint64_t, zip_flags_t, struct zip_error *);
-int _zip_local_header_read(struct zip *, int);
-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);
-int _zip_set_name(struct zip *, zip_uint64_t, const char *, zip_flags_t);
+zip_int64_t _zip_add_entry(zip_t *);
+
+zip_uint8_t *_zip_buffer_data(zip_buffer_t *buffer);
+bool _zip_buffer_eof(zip_buffer_t *buffer);
+void _zip_buffer_free(zip_buffer_t *buffer);
+zip_uint8_t *_zip_buffer_get(zip_buffer_t *buffer, zip_uint64_t length);
+zip_uint16_t _zip_buffer_get_16(zip_buffer_t *buffer);
+zip_uint32_t _zip_buffer_get_32(zip_buffer_t *buffer);
+zip_uint64_t _zip_buffer_get_64(zip_buffer_t *buffer);
+zip_uint8_t _zip_buffer_get_8(zip_buffer_t *buffer);
+zip_uint64_t _zip_buffer_left(zip_buffer_t *buffer);
+zip_buffer_t *_zip_buffer_new(zip_uint8_t *data, zip_uint64_t size);
+zip_buffer_t *_zip_buffer_new_from_source(zip_source_t *src, zip_uint64_t size, zip_uint8_t *buf, zip_error_t *error);
+zip_uint64_t _zip_buffer_offset(zip_buffer_t *buffer);
+bool _zip_buffer_ok(zip_buffer_t *buffer);
+int _zip_buffer_put(zip_buffer_t *buffer, const void *src, size_t length);
+int _zip_buffer_put_16(zip_buffer_t *buffer, zip_uint16_t i);
+int _zip_buffer_put_32(zip_buffer_t *buffer, zip_uint32_t i);
+int _zip_buffer_put_64(zip_buffer_t *buffer, zip_uint64_t i);
+int _zip_buffer_put_8(zip_buffer_t *buffer, zip_uint8_t i);
+int _zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset);
+zip_uint64_t _zip_buffer_size(zip_buffer_t *buffer);
+
+int _zip_cdir_compute_crc(zip_t *, uLong *);
+void _zip_cdir_free(zip_cdir_t *);
+zip_cdir_t *_zip_cdir_new(zip_uint64_t, zip_error_t *);
+zip_int64_t _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors);
+void _zip_deregister_source(zip_t *za, zip_source_t *src);
+
+zip_dirent_t *_zip_dirent_clone(const zip_dirent_t *);
+void _zip_dirent_free(zip_dirent_t *);
+void _zip_dirent_finalize(zip_dirent_t *);
+void _zip_dirent_init(zip_dirent_t *);
+bool _zip_dirent_needs_zip64(const zip_dirent_t *, zip_flags_t);
+zip_dirent_t *_zip_dirent_new(void);
+zip_int64_t _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, bool local, zip_error_t *error);
+zip_int32_t _zip_dirent_size(zip_source_t *src, zip_uint16_t, zip_error_t *);
+int _zip_dirent_write(zip_t *za, zip_dirent_t *dirent, zip_flags_t flags);
+
+zip_extra_field_t *_zip_ef_clone(const zip_extra_field_t *, zip_error_t *);
+zip_extra_field_t *_zip_ef_delete_by_id(zip_extra_field_t *, zip_uint16_t, zip_uint16_t, zip_flags_t);
+void _zip_ef_free(zip_extra_field_t *);
+const zip_uint8_t *_zip_ef_get_by_id(const zip_extra_field_t *, zip_uint16_t *, zip_uint16_t, zip_uint16_t, zip_flags_t, zip_error_t *);
+zip_extra_field_t *_zip_ef_merge(zip_extra_field_t *, zip_extra_field_t *);
+zip_extra_field_t *_zip_ef_new(zip_uint16_t, zip_uint16_t, const zip_uint8_t *, zip_flags_t);
+zip_extra_field_t *_zip_ef_parse(const zip_uint8_t *, zip_uint16_t, zip_flags_t, zip_error_t *);
+zip_extra_field_t *_zip_ef_remove_internal(zip_extra_field_t *);
+zip_uint16_t _zip_ef_size(const zip_extra_field_t *, zip_flags_t);
+int _zip_ef_write(zip_t *za, const zip_extra_field_t *ef, zip_flags_t flags);
+
+void _zip_entry_finalize(zip_entry_t *);
+void _zip_entry_init(zip_entry_t *);
+
+void _zip_error_clear(zip_error_t *);
+void _zip_error_get(const zip_error_t *, int *, int *);
+
+void _zip_error_copy(zip_error_t *dst, const zip_error_t *src);
+void _zip_error_set_from_source(zip_error_t *, zip_source_t *);
+
+const zip_uint8_t *_zip_extract_extra_field_by_id(zip_error_t *, zip_uint16_t, int, const zip_uint8_t *, zip_uint16_t, zip_uint16_t *);
+
+int _zip_file_extra_field_prepare_for_change(zip_t *, zip_uint64_t);
+int _zip_file_fillbuf(void *, size_t, zip_file_t *);
+zip_uint64_t _zip_file_get_offset(const zip_t *, zip_uint64_t, zip_error_t *);
+
+int _zip_filerange_crc(zip_source_t *src, zip_uint64_t offset, zip_uint64_t length, uLong *crcp, zip_error_t *error);
+
+zip_dirent_t *_zip_get_dirent(zip_t *, zip_uint64_t, zip_flags_t, zip_error_t *);
+
+enum zip_encoding_type _zip_guess_encoding(zip_string_t *, enum zip_encoding_type);
+zip_uint8_t *_zip_cp437_to_utf8(const zip_uint8_t * const, zip_uint32_t, zip_uint32_t *, zip_error_t *);
+
+zip_t *_zip_open(zip_source_t *, unsigned int, zip_error_t *);
+
+int _zip_read(zip_source_t *src, zip_uint8_t *data, zip_uint64_t length, zip_error_t *error);
+int _zip_read_at_offset(zip_source_t *src, zip_uint64_t offset, unsigned char *b, size_t length, zip_error_t *error);
+zip_uint8_t *_zip_read_data(zip_buffer_t *buffer, zip_source_t *src, size_t length, bool nulp, zip_error_t *error);
+int _zip_read_local_ef(zip_t *, zip_uint64_t);
+zip_string_t *_zip_read_string(zip_buffer_t *buffer, zip_source_t *src, zip_uint16_t lenght, bool nulp, zip_error_t *error);
+int _zip_register_source(zip_t *za, zip_source_t *src);
+
+void _zip_set_open_error(int *zep, const zip_error_t *err, int ze);
+
+zip_int64_t _zip_source_call(zip_source_t *src, void *data, zip_uint64_t length, zip_source_cmd_t command);
+zip_source_t *_zip_source_file_or_p(const char *, FILE *, zip_uint64_t, zip_int64_t, const zip_stat_t *, zip_error_t *error);
+void _zip_source_invalidate(zip_source_t *src);
+zip_source_t *_zip_source_new(zip_error_t *error);
+int _zip_source_set_source_archive(zip_source_t *, zip_t *);
+zip_source_t *_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_error_t *error);
+zip_source_t *_zip_source_zip_new(zip_t *, zip_t *, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_uint64_t, const char *);
+
+int _zip_stat_merge(zip_stat_t *dst, const zip_stat_t *src, zip_error_t *error);
+int _zip_string_equal(const zip_string_t *, const zip_string_t *);
+void _zip_string_free(zip_string_t *);
+zip_uint32_t _zip_string_crc32(const zip_string_t *);
+const zip_uint8_t *_zip_string_get(zip_string_t *, zip_uint32_t *, zip_flags_t, zip_error_t *);
+zip_uint16_t _zip_string_length(const zip_string_t *);
+zip_string_t *_zip_string_new(const zip_uint8_t *, zip_uint16_t, zip_flags_t, zip_error_t *);
+int _zip_string_write(zip_t *za, const zip_string_t *string);
+
+int _zip_changed(const zip_t *, zip_uint64_t *);
+const char *_zip_get_name(zip_t *, zip_uint64_t, zip_flags_t, zip_error_t *);
+int _zip_local_header_read(zip_t *, int);
+void *_zip_memdup(const void *, size_t, zip_error_t *);
+zip_int64_t _zip_name_locate(zip_t *, const char *, zip_flags_t, zip_error_t *);
+zip_t *_zip_new(zip_error_t *);
+
+zip_int64_t _zip_file_replace(zip_t *, zip_uint64_t, const char *, zip_source_t *, zip_flags_t);
+int _zip_set_name(zip_t *, 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_unchange(zip_t *, zip_uint64_t, int);
+void _zip_unchange_data(zip_entry_t *);
+int _zip_write(zip_t *za, const void *data, zip_uint64_t length);
 
 #endif /* zipint.h */
diff --git a/ext/zip/lib/zipwin32.h b/ext/zip/lib/zipwin32.h
new file mode 100644 (file)
index 0000000..4fa29cc
--- /dev/null
@@ -0,0 +1,80 @@
+#ifndef _HAD_ZIPWIN32_H
+#define _HAD_ZIPWIN32_H
+
+/*
+  zipwin32.h -- internal declarations for Windows.
+  Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
+
+  This file is part of libzip, a library to manipulate ZIP archives.
+  The authors can be contacted at <libzip@nih.at>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+  3. The names of the authors may not be used to endorse or promote
+     products derived from this software without specific prior
+     written permission.
+  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <windows.h>
+
+/* context for Win32 source */
+
+struct _zip_source_win32_file_ops;
+
+struct _zip_source_win32_read_file {
+    zip_error_t error;      /* last error information */
+    zip_int64_t supports;
+
+    /* operations */
+    struct _zip_source_win32_file_ops *ops;
+
+    /* reading */
+    void *fname;            /* name of file to read from - ANSI (char *) or Unicode (wchar_t *) */
+    void *h;                /* HANDLE for 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 */
+    void *tmpname;          /* name of temp file - ANSI (char *) or Unicode (wchar_t *) */
+    void *hout;             /* HANDLE for output file */
+};
+
+typedef struct _zip_source_win32_read_file _zip_source_win32_read_file_t;
+
+/* internal operations for Win32 source */
+
+struct _zip_source_win32_file_ops {
+    void *(*op_strdup)(const void *);
+    void *(*op_open)(_zip_source_win32_read_file_t *);
+    void *(*op_create_temp)(_zip_source_win32_read_file_t *, void **, zip_uint32_t, PSECURITY_ATTRIBUTES);
+    int (*op_rename_temp)(_zip_source_win32_read_file_t *);
+    int (*op_remove)(const void *);
+};
+
+typedef struct _zip_source_win32_file_ops _zip_source_win32_file_ops_t;
+
+zip_source_t *_zip_source_win32_handle_or_name(const void *, void *, zip_uint64_t, zip_int64_t, int, const zip_stat_t *, _zip_source_win32_file_ops_t *, zip_error_t *);
+
+#endif /* zipwin32.h */