From 9e0cc7a1d926c1364a834177cadea431cd8b39a7 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 6 May 2015 14:36:18 +0200 Subject: [PATCH] update libzip to version 1.0.1 --- ext/zip/LICENSE_libzip | 18 +- ext/zip/config.m4 | 9 +- ext/zip/config.w32 | 7 +- ext/zip/lib/config.h | 4 +- ext/zip/lib/mkstemp.c | 5 +- ext/zip/lib/php_zip_config.w32.h | 8 + ext/zip/lib/zip.h | 287 +++-- ext/zip/lib/zip_add.c | 8 +- ext/zip/lib/zip_add_dir.c | 8 +- ext/zip/lib/zip_add_entry.c | 21 +- ext/zip/lib/zip_buffer.c | 310 +++++ ext/zip/lib/zip_close.c | 414 ++----- ext/zip/lib/zip_delete.c | 13 +- ext/zip/lib/zip_dir_add.c | 18 +- ext/zip/lib/zip_dirent.c | 1020 ++++++++--------- ext/zip/lib/zip_discard.c | 30 +- ext/zip/lib/zip_entry.c | 10 +- ext/zip/lib/zip_err_str.c | 12 +- ext/zip/lib/zip_error.c | 113 +- ext/zip/lib/zip_error_clear.c | 8 +- ext/zip/lib/zip_error_get.c | 23 +- ext/zip/lib/zip_error_get_sys_type.c | 8 +- ext/zip/lib/zip_error_strerror.c | 16 +- ext/zip/lib/zip_error_to_str.c | 13 +- ext/zip/lib/zip_extra_field.c | 223 ++-- ext/zip/lib/zip_extra_field_api.c | 128 +-- ext/zip/lib/zip_fclose.c | 23 +- ext/zip/lib/zip_fdopen.c | 45 +- ext/zip/lib/zip_file_add.c | 12 +- ext/zip/lib/zip_file_error_clear.c | 8 +- ext/zip/lib/zip_file_error_get.c | 10 +- ext/zip/lib/zip_file_get_comment.c | 10 +- .../lib/zip_file_get_external_attributes.c | 10 +- ext/zip/lib/zip_file_get_offset.c | 20 +- ext/zip/lib/zip_file_rename.c | 18 +- ext/zip/lib/zip_file_replace.c | 25 +- ext/zip/lib/zip_file_set_comment.c | 20 +- .../lib/zip_file_set_external_attributes.c | 20 +- ext/zip/lib/zip_file_set_mtime.c | 74 ++ ext/zip/lib/zip_file_strerror.c | 10 +- ext/zip/lib/zip_filerange_crc.c | 32 +- ext/zip/lib/zip_fopen.c | 10 +- ext/zip/lib/zip_fopen_encrypted.c | 10 +- ext/zip/lib/zip_fopen_index.c | 10 +- ext/zip/lib/zip_fopen_index_encrypted.c | 45 +- ext/zip/lib/zip_fread.c | 10 +- ext/zip/lib/zip_get_archive_comment.c | 10 +- ext/zip/lib/zip_get_archive_flag.c | 8 +- .../lib/zip_get_compression_implementation.c | 6 +- .../lib/zip_get_encryption_implementation.c | 6 +- ext/zip/lib/zip_get_file_comment.c | 8 +- ext/zip/lib/zip_get_name.c | 13 +- ext/zip/lib/zip_get_num_entries.c | 8 +- ext/zip/lib/zip_get_num_files.c | 15 +- ext/zip/lib/zip_io_util.c | 139 +++ ext/zip/lib/zip_memdup.c | 9 +- ext/zip/lib/zip_name_locate.c | 17 +- ext/zip/lib/zip_new.c | 27 +- ext/zip/lib/zip_open.c | 826 +++++++------ ext/zip/lib/zip_rename.c | 8 +- ext/zip/lib/zip_replace.c | 8 +- ext/zip/lib/zip_set_archive_comment.c | 18 +- ext/zip/lib/zip_set_archive_flag.c | 14 +- ext/zip/lib/zip_set_default_password.c | 12 +- ext/zip/lib/zip_set_file_comment.c | 10 +- ext/zip/lib/zip_set_file_compression.c | 27 +- ext/zip/lib/zip_set_name.c | 24 +- ..._source_pop.c => zip_source_begin_write.c} | 40 +- ext/zip/lib/zip_source_buffer.c | 413 +++++-- ext/zip/lib/zip_source_call.c | 69 ++ ext/zip/lib/zip_source_close.c | 34 +- ext/zip/lib/zip_source_commit_write.c | 64 ++ ext/zip/lib/zip_source_crc.c | 156 +-- ext/zip/lib/zip_source_deflate.c | 293 ++--- ext/zip/lib/zip_source_error.c | 52 +- ext/zip/lib/zip_source_file.c | 24 +- ext/zip/lib/zip_source_filep.c | 517 ++++++--- ext/zip/lib/zip_source_free.c | 37 +- ext/zip/lib/zip_source_function.c | 57 +- ext/zip/lib/zip_source_is_deleted.c | 42 + ext/zip/lib/zip_source_layered.c | 34 +- ext/zip/lib/zip_source_open.c | 53 +- ext/zip/lib/zip_source_pkware.c | 124 +- ext/zip/lib/zip_source_read.c | 30 +- ext/zip/lib/zip_source_remove.c | 61 + ext/zip/lib/zip_source_rollback_write.c | 47 + ext/zip/lib/zip_source_seek.c | 92 ++ ext/zip/lib/zip_source_seek_write.c | 52 + ext/zip/lib/zip_source_stat.c | 39 +- ext/zip/lib/zip_source_supports.c | 68 ++ ext/zip/lib/zip_source_tell.c | 50 + ext/zip/lib/zip_source_tell_write.c | 47 + ext/zip/lib/zip_source_win32a.c | 125 ++ ext/zip/lib/zip_source_win32handle.c | 607 ++++++++++ ext/zip/lib/zip_source_win32utf8.c | 80 ++ ext/zip/lib/zip_source_win32w.c | 125 ++ ext/zip/lib/zip_source_window.c | 269 +++-- ext/zip/lib/zip_source_write.c | 47 + ext/zip/lib/zip_source_zip.c | 16 +- ext/zip/lib/zip_source_zip_new.c | 131 +-- ext/zip/lib/zip_stat.c | 8 +- ext/zip/lib/zip_stat_index.c | 18 +- ext/zip/lib/zip_stat_init.c | 43 +- ext/zip/lib/zip_strerror.c | 10 +- ext/zip/lib/zip_string.c | 62 +- ext/zip/lib/zip_unchange.c | 17 +- ext/zip/lib/zip_unchange_all.c | 8 +- ext/zip/lib/zip_unchange_archive.c | 10 +- ext/zip/lib/zip_unchange_data.c | 7 +- ext/zip/lib/zip_utf-8.c | 40 +- ext/zip/lib/zipconf.h | 6 +- ext/zip/lib/zipint.h | 472 ++++---- ext/zip/lib/zipwin32.h | 80 ++ 113 files changed, 5887 insertions(+), 3158 deletions(-) create mode 100644 ext/zip/lib/zip_buffer.c create mode 100644 ext/zip/lib/zip_file_set_mtime.c create mode 100644 ext/zip/lib/zip_io_util.c rename ext/zip/lib/{zip_source_pop.c => zip_source_begin_write.c} (75%) create mode 100644 ext/zip/lib/zip_source_call.c create mode 100644 ext/zip/lib/zip_source_commit_write.c create mode 100644 ext/zip/lib/zip_source_is_deleted.c create mode 100644 ext/zip/lib/zip_source_remove.c create mode 100644 ext/zip/lib/zip_source_rollback_write.c create mode 100644 ext/zip/lib/zip_source_seek.c create mode 100644 ext/zip/lib/zip_source_seek_write.c create mode 100644 ext/zip/lib/zip_source_supports.c create mode 100644 ext/zip/lib/zip_source_tell.c create mode 100644 ext/zip/lib/zip_source_tell_write.c create mode 100644 ext/zip/lib/zip_source_win32a.c create mode 100644 ext/zip/lib/zip_source_win32handle.c create mode 100644 ext/zip/lib/zip_source_win32utf8.c create mode 100644 ext/zip/lib/zip_source_win32w.c create mode 100644 ext/zip/lib/zip_source_write.c create mode 100644 ext/zip/lib/zipwin32.h diff --git a/ext/zip/LICENSE_libzip b/ext/zip/LICENSE_libzip index 9b2fda07b1..bf30801078 100644 --- a/ext/zip/LICENSE_libzip +++ b/ext/zip/LICENSE_libzip @@ -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 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 diff --git a/ext/zip/config.m4 b/ext/zip/config.m4 index a21ad2d3e1..6dbc1e292b 100644 --- a/ext/zip/config.m4 +++ b/ext/zip/config.m4 @@ -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]) diff --git a/ext/zip/config.w32 b/ext/zip/config.w32 index 28de344785..a9a8088fb5 100644 --- a/ext/zip/config.w32 +++ b/ext/zip/config.w32 @@ -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"); diff --git a/ext/zip/lib/config.h b/ext/zip/lib/config.h index 8a4db4039d..ee77c66d43 100644 --- a/ext/zip/lib/config.h +++ b/ext/zip/lib/config.h @@ -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 | diff --git a/ext/zip/lib/mkstemp.c b/ext/zip/lib/mkstemp.c index 3d03ee9acc..2ccd3a4878 100644 --- a/ext/zip/lib/mkstemp.c +++ b/ext/zip/lib/mkstemp.c @@ -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') diff --git a/ext/zip/lib/php_zip_config.w32.h b/ext/zip/lib/php_zip_config.w32.h index b3192cbdd4..31efa7aee4 100644 --- a/ext/zip/lib/php_zip_config.w32.h +++ b/ext/zip/lib/php_zip_config.w32.h @@ -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 */ diff --git a/ext/zip/lib/zip.h b/ext/zip/lib/zip.h index 2eef0548ad..7b243bcd05 100644 --- a/ext/zip/lib/zip.h +++ b/ext/zip/lib/zip.h @@ -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 @@ -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 @@ -35,25 +35,25 @@ */ - -#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 @@ -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 } diff --git a/ext/zip/lib/zip_add.c b/ext/zip/lib/zip_add.c index 6de3cd2cf2..d1be133b6d 100644 --- a/ext/zip/lib/zip_add.c +++ b/ext/zip/lib/zip_add.c @@ -1,6 +1,6 @@ /* zip_add.c -- add file via callback function - Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,12 +32,10 @@ */ - #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); } diff --git a/ext/zip/lib/zip_add_dir.c b/ext/zip/lib/zip_add_dir.c index f84a4edffb..14bdeda112 100644 --- a/ext/zip/lib/zip_add_dir.c +++ b/ext/zip/lib/zip_add_dir.c @@ -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 @@ -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,16 +32,14 @@ */ - #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); } diff --git a/ext/zip/lib/zip_add_entry.c b/ext/zip/lib/zip_add_entry.c index 583efc4561..24dbdaf47c 100644 --- a/ext/zip/lib/zip_add_entry.c +++ b/ext/zip/lib/zip_add_entry.c @@ -1,6 +1,6 @@ /* zip_add_entry.c -- create and init struct zip_entry - Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,27 +32,30 @@ */ - #include #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 index 0000000000..3d79b09f13 --- /dev/null +++ b/ext/zip/lib/zip_buffer.c @@ -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 + + 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 +#include + +#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; +} diff --git a/ext/zip/lib/zip_close.c b/ext/zip/lib/zip_close.c index 79f9dab256..a13e4466b3 100644 --- a/ext/zip/lib/zip_close.c +++ b/ext/zip/lib/zip_close.c @@ -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 @@ -53,36 +52,24 @@ #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; inentry; 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; jentry+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); -} diff --git a/ext/zip/lib/zip_delete.c b/ext/zip/lib/zip_delete.c index 799a81249b..b3e7abb848 100644 --- a/ext/zip/lib/zip_delete.c +++ b/ext/zip/lib/zip_delete.c @@ -1,6 +1,6 @@ /* zip_delete.c -- delete file from zip archive - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,21 +32,19 @@ */ - #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; } - diff --git a/ext/zip/lib/zip_dir_add.c b/ext/zip/lib/zip_dir_add.c index 408f19174f..f535b21f21 100644 --- a/ext/zip/lib/zip_dir_add.c +++ b/ext/zip/lib/zip_dir_add.c @@ -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 @@ -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,31 +32,29 @@ */ - #include #include #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); diff --git a/ext/zip/lib/zip_dirent.c b/ext/zip/lib/zip_dirent.c index 4009d93248..e3a78b3146 100644 --- a/ext/zip/lib/zip_dirent.c +++ b/ext/zip/lib/zip_dirent.c @@ -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 #include #include @@ -43,14 +42,12 @@ #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; inentry_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; ientry+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)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)>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)); diff --git a/ext/zip/lib/zip_discard.c b/ext/zip/lib/zip_discard.c index 5b36df8b0b..db22370842 100644 --- a/ext/zip/lib/zip_discard.c +++ b/ext/zip/lib/zip_discard.c @@ -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 @@ -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,30 +32,27 @@ */ - #include #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; infile; 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; inopen_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; diff --git a/ext/zip/lib/zip_entry.c b/ext/zip/lib/zip_entry.c index 2f41b2a470..6f89006861 100644 --- a/ext/zip/lib/zip_entry.c +++ b/ext/zip/lib/zip_entry.c @@ -1,6 +1,6 @@ /* zip_entry.c -- struct zip_entry helper functions - Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,11 +32,10 @@ */ - #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; diff --git a/ext/zip/lib/zip_err_str.c b/ext/zip/lib/zip_err_str.c index deac7004ba..65698be00e 100644 --- a/ext/zip/lib/zip_err_str.c +++ b/ext/zip/lib/zip_err_str.c @@ -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, }; diff --git a/ext/zip/lib/zip_error.c b/ext/zip/lib/zip_error.c index 9287b968a9..a21a00bc29 100644 --- a/ext/zip/lib/zip_error.c +++ b/ext/zip/lib/zip_error.c @@ -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 @@ -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 @@ -31,51 +31,92 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - - +#include #include #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; } diff --git a/ext/zip/lib/zip_error_clear.c b/ext/zip/lib/zip_error_clear.c index d7b32f9631..ec45e688e5 100644 --- a/ext/zip/lib/zip_error_clear.c +++ b/ext/zip/lib/zip_error_clear.c @@ -1,6 +1,6 @@ /* zip_error_clear.c -- clear zip error - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,13 +32,11 @@ */ - #include "zipint.h" - ZIP_EXTERN void -zip_error_clear(struct zip *za) +zip_error_clear(zip_t *za) { if (za == NULL) return; diff --git a/ext/zip/lib/zip_error_get.c b/ext/zip/lib/zip_error_get.c index 930610df32..c222018993 100644 --- a/ext/zip/lib/zip_error_get.c +++ b/ext/zip/lib/zip_error_get.c @@ -1,6 +1,6 @@ /* zip_error_get.c -- get zip error - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,13 +32,26 @@ */ - +#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; +} diff --git a/ext/zip/lib/zip_error_get_sys_type.c b/ext/zip/lib/zip_error_get_sys_type.c index 22087199b6..7e27bbf332 100644 --- a/ext/zip/lib/zip_error_get_sys_type.c +++ b/ext/zip/lib/zip_error_get_sys_type.c @@ -1,6 +1,6 @@ /* zip_error_get_sys_type.c -- return type of system error code - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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 @@ -31,12 +31,10 @@ 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) { diff --git a/ext/zip/lib/zip_error_strerror.c b/ext/zip/lib/zip_error_strerror.c index 74e49258dd..2f124ccd46 100644 --- a/ext/zip/lib/zip_error_strerror.c +++ b/ext/zip/lib/zip_error_strerror.c @@ -1,6 +1,6 @@ /* zip_error_sterror.c -- get string representation of struct zip_error - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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 #include #include @@ -41,14 +40,13 @@ #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 ? ": " : ""), diff --git a/ext/zip/lib/zip_error_to_str.c b/ext/zip/lib/zip_error_to_str.c index c61e2d0c9e..d4119253f7 100644 --- a/ext/zip/lib/zip_error_to_str.c +++ b/ext/zip/lib/zip_error_to_str.c @@ -1,6 +1,6 @@ /* zip_error_to_str.c -- get string representation of zip error code - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,16 +32,15 @@ */ - #include #include #include #include +#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; } diff --git a/ext/zip/lib/zip_extra_field.c b/ext/zip/lib/zip_extra_field.c index c2d4f30a40..b2566c6887 100644 --- a/ext/zip/lib/zip_extra_field.c +++ b/ext/zip/lib/zip_extra_field.c @@ -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 @@ -40,21 +39,20 @@ #include - -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) { - _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; diff --git a/ext/zip/lib/zip_extra_field_api.c b/ext/zip/lib/zip_extra_field_api.c index d0bba96e04..ed93944ac8 100644 --- a/ext/zip/lib/zip_extra_field_api.c +++ b/ext/zip/lib/zip_extra_field_api.c @@ -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 @@ -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,71 +32,68 @@ */ - #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; } diff --git a/ext/zip/lib/zip_fclose.c b/ext/zip/lib/zip_fclose.c index f24f109cb2..25a201b187 100644 --- a/ext/zip/lib/zip_fclose.c +++ b/ext/zip/lib/zip_fclose.c @@ -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 @@ -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,37 +32,24 @@ */ - #include #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; iza->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; } diff --git a/ext/zip/lib/zip_fdopen.c b/ext/zip/lib/zip_fdopen.c index edeaa56488..c5b55311d2 100644 --- a/ext/zip/lib/zip_fdopen.c +++ b/ext/zip/lib/zip_fdopen.c @@ -1,6 +1,6 @@ /* zip_fdopen.c -- open read-only archive from file descriptor - Copyright (C) 2009-2010 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,44 +32,51 @@ */ - #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; } diff --git a/ext/zip/lib/zip_file_add.c b/ext/zip/lib/zip_file_add.c index a30fd0b0f3..9944c0f122 100644 --- a/ext/zip/lib/zip_file_add.c +++ b/ext/zip/lib/zip_file_add.c @@ -1,6 +1,6 @@ /* zip_file_add.c -- add file via callback function - Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,10 +32,8 @@ */ - #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 @@ -44,12 +42,12 @@ */ 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); } diff --git a/ext/zip/lib/zip_file_error_clear.c b/ext/zip/lib/zip_file_error_clear.c index c433fbcb84..be454982a1 100644 --- a/ext/zip/lib/zip_file_error_clear.c +++ b/ext/zip/lib/zip_file_error_clear.c @@ -1,6 +1,6 @@ /* zip_file_error_clear.c -- clear zip file error - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,13 +32,11 @@ */ - #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; diff --git a/ext/zip/lib/zip_file_error_get.c b/ext/zip/lib/zip_file_error_get.c index 65b08e3b13..be764fd52d 100644 --- a/ext/zip/lib/zip_file_error_get.c +++ b/ext/zip/lib/zip_file_error_get.c @@ -1,6 +1,6 @@ /* zip_file_error_get.c -- get zip file error - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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 @@ -31,14 +31,12 @@ 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); } diff --git a/ext/zip/lib/zip_file_get_comment.c b/ext/zip/lib/zip_file_get_comment.c index 9a7a7b5cb5..55e7dc2890 100644 --- a/ext/zip/lib/zip_file_get_comment.c +++ b/ext/zip/lib/zip_file_get_comment.c @@ -1,6 +1,6 @@ /* zip_file_get_comment.c -- get file comment - Copyright (C) 2006-2012 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,16 +32,14 @@ */ - #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; diff --git a/ext/zip/lib/zip_file_get_external_attributes.c b/ext/zip/lib/zip_file_get_external_attributes.c index 461303f40e..b6526cf23a 100644 --- a/ext/zip/lib/zip_file_get_external_attributes.c +++ b/ext/zip/lib/zip_file_get_external_attributes.c @@ -1,6 +1,6 @@ /* zip_file_get_external_attributes.c -- get opsys/external attributes - Copyright (C) 2013 Dieter Baron and Thomas Klausner + Copyright (C) 2013-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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 @@ -34,15 +34,15 @@ #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; diff --git a/ext/zip/lib/zip_file_get_offset.c b/ext/zip/lib/zip_file_get_offset.c index 40b1f703c7..1aaca712d7 100644 --- a/ext/zip/lib/zip_file_get_offset.c +++ b/ext/zip/lib/zip_file_get_offset.c @@ -1,6 +1,6 @@ /* zip_file_get_offset.c -- get offset of file data in archive. - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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 #include #include @@ -43,7 +42,6 @@ #include "zipint.h" - /* _zip_file_get_offset(za, ze): Returns the offset of the file data for entry ze. @@ -51,26 +49,26 @@ */ 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; } diff --git a/ext/zip/lib/zip_file_rename.c b/ext/zip/lib/zip_file_rename.c index dd4f253457..4400938ab5 100644 --- a/ext/zip/lib/zip_file_rename.c +++ b/ext/zip/lib/zip_file_rename.c @@ -1,6 +1,6 @@ /* zip_file_rename.c -- rename file in zip archive - Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,37 +32,35 @@ */ - #include #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; } diff --git a/ext/zip/lib/zip_file_replace.c b/ext/zip/lib/zip_file_replace.c index 622ef3c992..e430efae9e 100644 --- a/ext/zip/lib/zip_file_replace.c +++ b/ext/zip/lib/zip_file_replace.c @@ -1,6 +1,6 @@ /* zip_file_replace.c -- replace file via callback function - Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,16 +32,14 @@ */ - #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; diff --git a/ext/zip/lib/zip_file_set_comment.c b/ext/zip/lib/zip_file_set_comment.c index 541d3475a8..e455fbd28f 100644 --- a/ext/zip/lib/zip_file_set_comment.c +++ b/ext/zip/lib/zip_file_set_comment.c @@ -1,6 +1,6 @@ /* zip_file_set_comment.c -- set comment for file in archive - Copyright (C) 2006-2012 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,31 +32,29 @@ */ - #include #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; } diff --git a/ext/zip/lib/zip_file_set_external_attributes.c b/ext/zip/lib/zip_file_set_external_attributes.c index 3f2817807f..b772c31e07 100644 --- a/ext/zip/lib/zip_file_set_external_attributes.c +++ b/ext/zip/lib/zip_file_set_external_attributes.c @@ -1,6 +1,6 @@ /* zip_file_set_external_attributes.c -- set external attributes for entry - Copyright (C) 2013 Dieter Baron and Thomas Klausner + Copyright (C) 2013-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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 @@ -33,10 +33,10 @@ #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 index 0000000000..0cdd31a672 --- /dev/null +++ b/ext/zip/lib/zip_file_set_mtime.c @@ -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 + + 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; +} diff --git a/ext/zip/lib/zip_file_strerror.c b/ext/zip/lib/zip_file_strerror.c index f06f698c64..8366f1ea92 100644 --- a/ext/zip/lib/zip_file_strerror.c +++ b/ext/zip/lib/zip_file_strerror.c @@ -1,6 +1,6 @@ /* zip_file_sterror.c -- get string representation of zip file error - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,13 +32,11 @@ */ - #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); } diff --git a/ext/zip/lib/zip_filerange_crc.c b/ext/zip/lib/zip_filerange_crc.c index 789cdd62b9..8e06e8fa8b 100644 --- a/ext/zip/lib/zip_filerange_crc.c +++ b/ext/zip/lib/zip_filerange_crc.c @@ -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 @@ -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 #include @@ -40,31 +39,38 @@ - int -_zip_filerange_crc(FILE *fp, off_t start, off_t len, uLong *crcp, - struct zip_error *errp) +_zip_filerange_crc(zip_source_t *src, zip_uint64_t start, zip_uint64_t len, uLong *crcp, zip_error_t *error) { Bytef buf[BUFSIZE]; - size_t n; + zip_int64_t n; *crcp = crc32(0L, Z_NULL, 0); - if (fseeko(fp, start, SEEK_SET) != 0) { - _zip_error_set(errp, ZIP_ER_SEEK, errno); + if (start > ZIP_INT64_MAX) { + zip_error_set(error, ZIP_ER_SEEK, EFBIG); return -1; } + if (zip_source_seek(src, (zip_int64_t)start, SEEK_SET) != 0) { + _zip_error_set_from_source(error, src); + return -1; + } + while (len > 0) { - n = len > BUFSIZE ? BUFSIZE : (size_t)len; - if ((n=fread(buf, 1, n, fp)) == 0) { - _zip_error_set(errp, ZIP_ER_READ, errno); + n = (zip_int64_t)(len > BUFSIZE ? BUFSIZE : len); + if ((n = zip_source_read(src, buf, (zip_uint64_t)n)) < 0) { + _zip_error_set_from_source(error, src); + return -1; + } + if (n == 0) { + zip_error_set(error, ZIP_ER_EOF, 0); return -1; } *crcp = crc32(*crcp, buf, (uInt)n); - len-= n; + len -= (zip_uint64_t)n; } return 0; diff --git a/ext/zip/lib/zip_fopen.c b/ext/zip/lib/zip_fopen.c index 4bee7e500b..3adb5de651 100644 --- a/ext/zip/lib/zip_fopen.c +++ b/ext/zip/lib/zip_fopen.c @@ -1,6 +1,6 @@ /* zip_fopen.c -- open file in zip archive for reading - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,13 +32,11 @@ */ - #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; diff --git a/ext/zip/lib/zip_fopen_encrypted.c b/ext/zip/lib/zip_fopen_encrypted.c index 18e198d4a9..5eaf2b04b7 100644 --- a/ext/zip/lib/zip_fopen_encrypted.c +++ b/ext/zip/lib/zip_fopen_encrypted.c @@ -1,6 +1,6 @@ /* zip_fopen_encrypted.c -- open file for reading with password - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,13 +32,11 @@ */ - #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; diff --git a/ext/zip/lib/zip_fopen_index.c b/ext/zip/lib/zip_fopen_index.c index a84e97fa26..e9a169a2e1 100644 --- a/ext/zip/lib/zip_fopen_index.c +++ b/ext/zip/lib/zip_fopen_index.c @@ -1,6 +1,6 @@ /* zip_fopen_index.c -- open file in zip archive for reading by index - Copyright (C) 1999-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 @@ -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 #include #include @@ -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); } diff --git a/ext/zip/lib/zip_fopen_index_encrypted.c b/ext/zip/lib/zip_fopen_index_encrypted.c index 756e1e2e6b..21cc43333c 100644 --- a/ext/zip/lib/zip_fopen_index_encrypted.c +++ b/ext/zip/lib/zip_fopen_index_encrypted.c @@ -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 @@ -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,23 +32,21 @@ */ - #include #include #include #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; diff --git a/ext/zip/lib/zip_fread.c b/ext/zip/lib/zip_fread.c index 67717e30d8..9c1cbe0c4e 100644 --- a/ext/zip/lib/zip_fread.c +++ b/ext/zip/lib/zip_fread.c @@ -1,6 +1,6 @@ /* zip_fread.c -- read from file - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,13 +32,11 @@ */ - #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; } diff --git a/ext/zip/lib/zip_get_archive_comment.c b/ext/zip/lib/zip_get_archive_comment.c index 5d6b578b26..78f8ca09d2 100644 --- a/ext/zip/lib/zip_get_archive_comment.c +++ b/ext/zip/lib/zip_get_archive_comment.c @@ -1,6 +1,6 @@ /* zip_get_archive_comment.c -- get archive comment - Copyright (C) 2006-2012 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,17 +32,15 @@ */ - #include #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; diff --git a/ext/zip/lib/zip_get_archive_flag.c b/ext/zip/lib/zip_get_archive_flag.c index 46a2f56694..bffe10c119 100644 --- a/ext/zip/lib/zip_get_archive_flag.c +++ b/ext/zip/lib/zip_get_archive_flag.c @@ -1,6 +1,6 @@ /* zip_get_archive_flag.c -- get archive global flag - Copyright (C) 2008 Dieter Baron and Thomas Klausner + Copyright (C) 2008-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,13 +32,11 @@ */ - #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; diff --git a/ext/zip/lib/zip_get_compression_implementation.c b/ext/zip/lib/zip_get_compression_implementation.c index a2e76e555d..c1120d3ea9 100644 --- a/ext/zip/lib/zip_get_compression_implementation.c +++ b/ext/zip/lib/zip_get_compression_implementation.c @@ -1,6 +1,6 @@ /* zip_get_compression_implementation.c -- get compression implementation - Copyright (C) 2009 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,11 +32,9 @@ */ - #include "zipint.h" - zip_compression_implementation _zip_get_compression_implementation(zip_int32_t cm) { diff --git a/ext/zip/lib/zip_get_encryption_implementation.c b/ext/zip/lib/zip_get_encryption_implementation.c index 1cd12deff6..e2f833b416 100644 --- a/ext/zip/lib/zip_get_encryption_implementation.c +++ b/ext/zip/lib/zip_get_encryption_implementation.c @@ -1,6 +1,6 @@ /* zip_get_encryption_implementation.c -- get encryption implementation - Copyright (C) 2009 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,11 +32,9 @@ */ - #include "zipint.h" - zip_encryption_implementation _zip_get_encryption_implementation(zip_uint16_t em) { diff --git a/ext/zip/lib/zip_get_file_comment.c b/ext/zip/lib/zip_get_file_comment.c index 347b1386a6..d5f50bf2ab 100644 --- a/ext/zip/lib/zip_get_file_comment.c +++ b/ext/zip/lib/zip_get_file_comment.c @@ -1,6 +1,6 @@ /* zip_get_file_comment.c -- get file comment - Copyright (C) 2006-2012 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,14 +32,12 @@ */ - #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; diff --git a/ext/zip/lib/zip_get_name.c b/ext/zip/lib/zip_get_name.c index f000db1815..d29e63658e 100644 --- a/ext/zip/lib/zip_get_name.c +++ b/ext/zip/lib/zip_get_name.c @@ -1,6 +1,6 @@ /* zip_get_name.c -- get filename for a file in zip file - Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,25 +32,22 @@ */ - #include #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) diff --git a/ext/zip/lib/zip_get_num_entries.c b/ext/zip/lib/zip_get_num_entries.c index e57921b9fd..c8644a4c59 100644 --- a/ext/zip/lib/zip_get_num_entries.c +++ b/ext/zip/lib/zip_get_num_entries.c @@ -1,6 +1,6 @@ /* zip_get_num_entries.c -- get number of entries in archive - Copyright (C) 1999-2011 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,13 +32,11 @@ */ - #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; diff --git a/ext/zip/lib/zip_get_num_files.c b/ext/zip/lib/zip_get_num_files.c index cc96ee4333..cf96353fcd 100644 --- a/ext/zip/lib/zip_get_num_files.c +++ b/ext/zip/lib/zip_get_num_files.c @@ -1,6 +1,6 @@ /* zip_get_num_files.c -- get number of files in archive - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,18 +32,21 @@ */ - #define _ZIP_COMPILING_DEPRECATED #include "zipint.h" - +#include 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 index 0000000000..4a6bc1ddc1 --- /dev/null +++ b/ext/zip/lib/zip_io_util.c @@ -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 + + 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 +#include +#include + +#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; osrc, data, length)) < 0) { + _zip_error_set_from_source(&za->error, za->src); + return -1; + } + if ((zip_uint64_t)n != length) { + zip_error_set(&za->error, ZIP_ER_WRITE, EINTR); + return -1; + } + + return 0; +} diff --git a/ext/zip/lib/zip_memdup.c b/ext/zip/lib/zip_memdup.c index 4faa8982cb..cc6d767d91 100644 --- a/ext/zip/lib/zip_memdup.c +++ b/ext/zip/lib/zip_memdup.c @@ -1,6 +1,6 @@ /* zip_memdup.c -- internal zip function, "strdup" with len - Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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; } diff --git a/ext/zip/lib/zip_name_locate.c b/ext/zip/lib/zip_name_locate.c index e527a5cda5..820ea0ca7f 100644 --- a/ext/zip/lib/zip_name_locate.c +++ b/ext/zip/lib/zip_name_locate.c @@ -1,6 +1,6 @@ /* zip_name_locate.c -- get index by name - Copyright (C) 1999-2011 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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 #ifdef HAVE_STRINGS_H #include @@ -41,17 +40,15 @@ #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; } diff --git a/ext/zip/lib/zip_new.c b/ext/zip/lib/zip_new.c index e91282b567..d54a247c29 100644 --- a/ext/zip/lib/zip_new.c +++ b/ext/zip/lib/zip_new.c @@ -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 @@ -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,41 +32,38 @@ */ - #include #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; } diff --git a/ext/zip/lib/zip_open.c b/ext/zip/lib/zip_open.c index 1acaefa30e..fb9c566cb1 100644 --- a/ext/zip/lib/zip_open.c +++ b/ext/zip/lib/zip_open.c @@ -1,6 +1,6 @@ /* zip_open.c -- open zip archive by name - Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted 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 #include #include @@ -42,117 +41,181 @@ #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 (inentry && 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; } diff --git a/ext/zip/lib/zip_rename.c b/ext/zip/lib/zip_rename.c index b1b0be7115..14e101d79b 100644 --- a/ext/zip/lib/zip_rename.c +++ b/ext/zip/lib/zip_rename.c @@ -1,6 +1,6 @@ /* zip_rename.c -- rename file in zip archive - Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,16 +32,14 @@ */ - #include #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); } diff --git a/ext/zip/lib/zip_replace.c b/ext/zip/lib/zip_replace.c index ad643f4948..eed019a097 100644 --- a/ext/zip/lib/zip_replace.c +++ b/ext/zip/lib/zip_replace.c @@ -1,6 +1,6 @@ /* zip_replace.c -- replace file via callback function - Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,14 +32,12 @@ */ - #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); } diff --git a/ext/zip/lib/zip_set_archive_comment.c b/ext/zip/lib/zip_set_archive_comment.c index 52563473da..9090eec956 100644 --- a/ext/zip/lib/zip_set_archive_comment.c +++ b/ext/zip/lib/zip_set_archive_comment.c @@ -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 @@ -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,25 +32,23 @@ */ - #include #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; } diff --git a/ext/zip/lib/zip_set_archive_flag.c b/ext/zip/lib/zip_set_archive_flag.c index 7e1463b000..2625b2e653 100644 --- a/ext/zip/lib/zip_set_archive_flag.c +++ b/ext/zip/lib/zip_set_archive_flag.c @@ -1,6 +1,6 @@ /* zip_get_archive_flag.c -- set archive global flag - Copyright (C) 2008-2009 Dieter Baron and Thomas Klausner + Copyright (C) 2008-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,16 +32,14 @@ */ - #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; } } diff --git a/ext/zip/lib/zip_set_default_password.c b/ext/zip/lib/zip_set_default_password.c index d16a1b9112..ac098dc5fc 100644 --- a/ext/zip/lib/zip_set_default_password.c +++ b/ext/zip/lib/zip_set_default_password.c @@ -1,6 +1,6 @@ /* zip_set_default_password.c -- set default password for decryption - Copyright (C) 2009 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,26 +32,24 @@ */ - #include #include #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; } } diff --git a/ext/zip/lib/zip_set_file_comment.c b/ext/zip/lib/zip_set_file_comment.c index 93ea924f18..d356693741 100644 --- a/ext/zip/lib/zip_set_file_comment.c +++ b/ext/zip/lib/zip_set_file_comment.c @@ -1,6 +1,6 @@ /* zip_set_file_comment.c -- set comment for file in archive - Copyright (C) 2006-2012 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,19 +32,17 @@ */ - #include #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); diff --git a/ext/zip/lib/zip_set_file_compression.c b/ext/zip/lib/zip_set_file_compression.c index a4abca8aff..7bb0bf9450 100644 --- a/ext/zip/lib/zip_set_file_compression.c +++ b/ext/zip/lib/zip_set_file_compression.c @@ -1,6 +1,6 @@ /* zip_set_file_compression.c -- set compression for file in archive - Copyright (C) 2012 Dieter Baron and Thomas Klausner + Copyright (C) 2012-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,39 +32,36 @@ */ - #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; } diff --git a/ext/zip/lib/zip_set_name.c b/ext/zip/lib/zip_set_name.c index 191e9ff449..5a10381753 100644 --- a/ext/zip/lib/zip_set_name.c +++ b/ext/zip/lib/zip_set_name.c @@ -1,6 +1,6 @@ /* zip_set_name.c -- rename helper function - Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,33 +32,31 @@ */ - #include #include #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; } diff --git a/ext/zip/lib/zip_source_pop.c b/ext/zip/lib/zip_source_begin_write.c similarity index 75% rename from ext/zip/lib/zip_source_pop.c rename to ext/zip/lib/zip_source_begin_write.c index 166ded8323..045933771f 100644 --- a/ext/zip/lib/zip_source_pop.c +++ b/ext/zip/lib/zip_source_begin_write.c @@ -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 @@ -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,32 +32,22 @@ */ - -#include - #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; } diff --git a/ext/zip/lib/zip_source_buffer.c b/ext/zip/lib/zip_source_buffer.c index c81590ddcc..aadf6e40b0 100644 --- a/ext/zip/lib/zip_source_buffer.c +++ b/ext/zip/lib/zip_source_buffer.c @@ -1,6 +1,6 @@ /* zip_source_buffer.c -- create zip data source from buffer - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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 @@ -31,49 +31,86 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - - +#include #include #include #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 index 0000000000..21f28bc42c --- /dev/null +++ b/ext/zip/lib/zip_source_call.c @@ -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 + + 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; +} diff --git a/ext/zip/lib/zip_source_close.c b/ext/zip/lib/zip_source_close.c index a8e91daf5c..36bc84235e 100644 --- a/ext/zip/lib/zip_source_close.c +++ b/ext/zip/lib/zip_source_close.c @@ -1,6 +1,6 @@ /* zip_source_close.c -- close zip_source (stop reading) - Copyright (C) 2009 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,23 +32,27 @@ */ - #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 index 0000000000..ba77abc342 --- /dev/null +++ b/ext/zip/lib/zip_source_commit_write.c @@ -0,0 +1,64 @@ +/* + zip_source_commit_write.c -- commit changes to file + Copyright (C) 2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + 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; +} diff --git a/ext/zip/lib/zip_source_crc.c b/ext/zip/lib/zip_source_crc.c index 739be28021..eed726616a 100644 --- a/ext/zip/lib/zip_source_crc.c +++ b/ext/zip/lib/zip_source_crc.c @@ -1,6 +1,6 @@ /* zip_source_crc.c -- pass-through source that calculates CRC32 and size - Copyright (C) 2009 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,54 +32,50 @@ */ - #include #include +#include #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; } - } diff --git a/ext/zip/lib/zip_source_deflate.c b/ext/zip/lib/zip_source_deflate.c index dbb2f2791b..2574ad017e 100644 --- a/ext/zip/lib/zip_source_deflate.c +++ b/ext/zip/lib/zip_source_deflate.c @@ -1,6 +1,6 @@ /* zip_source_deflate.c -- deflate (de)compressoin routines - Copyright (C) 2009 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2015 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted 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 @@ -31,59 +31,53 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - - #include #include +#include #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); } diff --git a/ext/zip/lib/zip_source_error.c b/ext/zip/lib/zip_source_error.c index 87ac7fa141..e09199bbef 100644 --- a/ext/zip/lib/zip_source_error.c +++ b/ext/zip/lib/zip_source_error.c @@ -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 @@ -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,53 +32,11 @@ */ - #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; } diff --git a/ext/zip/lib/zip_source_file.c b/ext/zip/lib/zip_source_file.c index 1f7f7b2366..1465e1700e 100644 --- a/ext/zip/lib/zip_source_file.c +++ b/ext/zip/lib/zip_source_file.c @@ -1,6 +1,6 @@ /* zip_source_file.c -- create data source from file - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted 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,25 +32,29 @@ */ - #include #include #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); } diff --git a/ext/zip/lib/zip_source_filep.c b/ext/zip/lib/zip_source_filep.c index 9b1af4da05..e541305d7f 100644 --- a/ext/zip/lib/zip_source_filep.c +++ b/ext/zip/lib/zip_source_filep.c @@ -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 @@ -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 #include @@ -39,79 +40,128 @@ #include #include -#include "zipint.h" +#ifdef _WIN32 +/* WIN32 needs for _O_BINARY */ +#include +#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; } diff --git a/ext/zip/lib/zip_source_free.c b/ext/zip/lib/zip_source_free.c index ae24ce9299..9070469946 100644 --- a/ext/zip/lib/zip_source_free.c +++ b/ext/zip/lib/zip_source_free.c @@ -1,6 +1,6 @@ /* zip_source_free.c -- free zip data source - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted 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,27 +32,40 @@ */ - #include #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); diff --git a/ext/zip/lib/zip_source_function.c b/ext/zip/lib/zip_source_function.c index 4e9d71e674..1d4be93c69 100644 --- a/ext/zip/lib/zip_source_function.c +++ b/ext/zip/lib/zip_source_function.c @@ -1,6 +1,6 @@ /* zip_source_function.c -- create zip data source from callback function - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,47 +32,68 @@ */ - #include #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 index 0000000000..e50cdd9e32 --- /dev/null +++ b/ext/zip/lib/zip_source_is_deleted.c @@ -0,0 +1,42 @@ +/* + zip_source_is_deleted.c -- was archive was removed? + Copyright (C) 2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_source_is_deleted(zip_source_t *src) +{ + return src->write_state == ZIP_SOURCE_WRITE_REMOVED; +} diff --git a/ext/zip/lib/zip_source_layered.c b/ext/zip/lib/zip_source_layered.c index c53d4fa3da..94b3310109 100644 --- a/ext/zip/lib/zip_source_layered.c +++ b/ext/zip/lib/zip_source_layered.c @@ -1,6 +1,6 @@ /* zip_source_layered.c -- create layered source - Copyright (C) 2009 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,28 +32,38 @@ */ - #include #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; } diff --git a/ext/zip/lib/zip_source_open.c b/ext/zip/lib/zip_source_open.c index 3c2c29e5be..ec5e39d542 100644 --- a/ext/zip/lib/zip_source_open.c +++ b/ext/zip/lib/zip_source_open.c @@ -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 @@ -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,45 +32,42 @@ */ - #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; } diff --git a/ext/zip/lib/zip_source_pkware.c b/ext/zip/lib/zip_source_pkware.c index 905dbc1d26..ce281ac148 100644 --- a/ext/zip/lib/zip_source_pkware.c +++ b/ext/zip/lib/zip_source_pkware.c @@ -1,6 +1,6 @@ /* zip_source_pkware.c -- Traditional PKWARE de/encryption routines - Copyright (C) 2009 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,15 +32,13 @@ */ - #include #include #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) { diff --git a/ext/zip/lib/zip_source_read.c b/ext/zip/lib/zip_source_read.c index 927280e913..061a6f910e 100644 --- a/ext/zip/lib/zip_source_read.c +++ b/ext/zip/lib/zip_source_read.c @@ -1,6 +1,6 @@ /* zip_source_read.c -- read data from zip_source - Copyright (C) 2009 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,33 +32,19 @@ */ - #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 index 0000000000..470a5edaf4 --- /dev/null +++ b/ext/zip/lib/zip_source_remove.c @@ -0,0 +1,61 @@ +/* + zip_source_remove.c -- remove empty archive + Copyright (C) 2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + 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 index 0000000000..c35f30f959 --- /dev/null +++ b/ext/zip/lib/zip_source_rollback_write.c @@ -0,0 +1,47 @@ +/* + zip_source_rollback_write.c -- discard changes + Copyright (C) 2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + 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 index 0000000000..c3f47036ad --- /dev/null +++ b/ext/zip/lib/zip_source_seek.c @@ -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 + + 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 index 0000000000..6660766492 --- /dev/null +++ b/ext/zip/lib/zip_source_seek_write.c @@ -0,0 +1,52 @@ +/* + zip_source_seek_write.c -- seek to offset for writing + Copyright (C) 2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + 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); +} diff --git a/ext/zip/lib/zip_source_stat.c b/ext/zip/lib/zip_source_stat.c index 732db4f55f..34cb05f452 100644 --- a/ext/zip/lib/zip_source_stat.c +++ b/ext/zip/lib/zip_source_stat.c @@ -1,6 +1,6 @@ /* zip_source_stat.c -- get meta information from zip_source - Copyright (C) 2009 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,39 +32,30 @@ */ - #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 index 0000000000..3c100fb71f --- /dev/null +++ b/ext/zip/lib/zip_source_supports.c @@ -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 + + 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 + +#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 index 0000000000..f1c10b5b52 --- /dev/null +++ b/ext/zip/lib/zip_source_tell.c @@ -0,0 +1,50 @@ +/* + zip_source_tell.c -- report current offset + Copyright (C) 2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + 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 index 0000000000..2fa150722d --- /dev/null +++ b/ext/zip/lib/zip_source_tell_write.c @@ -0,0 +1,47 @@ +/* + zip_source_tell_write.c -- report current offset for writing + Copyright (C) 2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + 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 index 0000000000..c20e891b08 --- /dev/null +++ b/ext/zip/lib/zip_source_win32a.c @@ -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 + +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 +#include + +#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 index 0000000000..dd17c021b3 --- /dev/null +++ b/ext/zip/lib/zip_source_win32handle.c @@ -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 + +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 +#include +#include +#include + +#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 index 0000000000..e11214ba05 --- /dev/null +++ b/ext/zip/lib/zip_source_win32utf8.c @@ -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 + +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 +#include + +#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 index 0000000000..27cdf910e0 --- /dev/null +++ b/ext/zip/lib/zip_source_win32w.c @@ -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 + +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 +#include + +#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; +} diff --git a/ext/zip/lib/zip_source_window.c b/ext/zip/lib/zip_source_window.c index 83f017e674..f02d048c0c 100644 --- a/ext/zip/lib/zip_source_window.c +++ b/ext/zip/lib/zip_source_window.c @@ -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 @@ -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,51 +32,86 @@ */ - #include #include #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; nskip; 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; nstart; 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; inopen_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 index 0000000000..c98f5679ae --- /dev/null +++ b/ext/zip/lib/zip_source_write.c @@ -0,0 +1,47 @@ +/* + zip_source_write.c -- start a new file for writing + Copyright (C) 2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + 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); +} diff --git a/ext/zip/lib/zip_source_zip.c b/ext/zip/lib/zip_source_zip.c index 0c3559e342..e172ca208e 100644 --- a/ext/zip/lib/zip_source_zip.c +++ b/ext/zip/lib/zip_source_zip.c @@ -1,6 +1,6 @@ /* zip_source_zip.c -- create data source from zip file - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,26 +32,24 @@ */ - #include #include #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 diff --git a/ext/zip/lib/zip_source_zip_new.c b/ext/zip/lib/zip_source_zip_new.c index 4b62721ca3..40f1195f15 100644 --- a/ext/zip/lib/zip_source_zip_new.c +++ b/ext/zip/lib/zip_source_zip_new.c @@ -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 @@ -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,39 +32,36 @@ */ - #include #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; diff --git a/ext/zip/lib/zip_stat.c b/ext/zip/lib/zip_stat.c index f6ba171d8d..cf8e56613c 100644 --- a/ext/zip/lib/zip_stat.c +++ b/ext/zip/lib/zip_stat.c @@ -1,6 +1,6 @@ /* zip_stat.c -- get information about file by name - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,13 +32,11 @@ */ - #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; diff --git a/ext/zip/lib/zip_stat_index.c b/ext/zip/lib/zip_stat_index.c index c5712b6d0b..601e3f70b7 100644 --- a/ext/zip/lib/zip_stat_index.c +++ b/ext/zip/lib/zip_stat_index.c @@ -1,6 +1,6 @@ /* zip_stat_index.c -- get information about file by index - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,29 +32,27 @@ */ - #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; } diff --git a/ext/zip/lib/zip_stat_init.c b/ext/zip/lib/zip_stat_init.c index 21841668d7..6b7d633744 100644 --- a/ext/zip/lib/zip_stat_init.c +++ b/ext/zip/lib/zip_stat_init.c @@ -1,6 +1,6 @@ /* zip_stat_init.c -- initialize struct zip_stat. - Copyright (C) 2006-2009 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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 @@ -31,14 +31,13 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - +#include #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; +} diff --git a/ext/zip/lib/zip_strerror.c b/ext/zip/lib/zip_strerror.c index 37774b23ec..98c4f6b1cc 100644 --- a/ext/zip/lib/zip_strerror.c +++ b/ext/zip/lib/zip_strerror.c @@ -1,6 +1,6 @@ /* zip_sterror.c -- get string representation of zip error - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,13 +32,11 @@ */ - #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); } diff --git a/ext/zip/lib/zip_string.c b/ext/zip/lib/zip_string.c index e3905da01b..307a425f78 100644 --- a/ext/zip/lib/zip_string.c +++ b/ext/zip/lib/zip_string.c @@ -1,6 +1,6 @@ /* zip_string.c -- string handling (with encoding) - Copyright (C) 2012 Dieter Baron and Thomas Klausner + Copyright (C) 2012-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,31 +32,28 @@ */ - #include #include #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); } diff --git a/ext/zip/lib/zip_unchange.c b/ext/zip/lib/zip_unchange.c index 9730bd2ce3..6c8a495c78 100644 --- a/ext/zip/lib/zip_unchange.c +++ b/ext/zip/lib/zip_unchange.c @@ -1,6 +1,6 @@ /* zip_unchange.c -- undo changes to file in zip archive - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,35 +32,32 @@ */ - #include #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; } } diff --git a/ext/zip/lib/zip_unchange_all.c b/ext/zip/lib/zip_unchange_all.c index 7fbb92467a..60076838d4 100644 --- a/ext/zip/lib/zip_unchange_all.c +++ b/ext/zip/lib/zip_unchange_all.c @@ -1,6 +1,6 @@ /* zip_unchange.c -- undo changes to all files in zip archive - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,15 +32,13 @@ */ - #include #include "zipint.h" - ZIP_EXTERN int -zip_unchange_all(struct zip *za) +zip_unchange_all(zip_t *za) { int ret; zip_uint64_t i; diff --git a/ext/zip/lib/zip_unchange_archive.c b/ext/zip/lib/zip_unchange_archive.c index 4320702191..920255cc7e 100644 --- a/ext/zip/lib/zip_unchange_archive.c +++ b/ext/zip/lib/zip_unchange_archive.c @@ -1,6 +1,6 @@ /* zip_unchange_archive.c -- undo global changes to ZIP archive - Copyright (C) 2006-2008 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,22 +32,20 @@ */ - #include #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; diff --git a/ext/zip/lib/zip_unchange_data.c b/ext/zip/lib/zip_unchange_data.c index b924f2cb23..839d9a3cb9 100644 --- a/ext/zip/lib/zip_unchange_data.c +++ b/ext/zip/lib/zip_unchange_data.c @@ -1,6 +1,6 @@ /* zip_unchange_data.c -- undo helper function - Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,11 +32,10 @@ */ - #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); diff --git a/ext/zip/lib/zip_utf-8.c b/ext/zip/lib/zip_utf-8.c index ad2c5627a5..f38eea04d2 100644 --- a/ext/zip/lib/zip_utf-8.c +++ b/ext/zip/lib/zip_utf-8.c @@ -1,6 +1,6 @@ /* zip_utf-8.c -- UTF-8 support functions for libzip - Copyright (C) 2011-2012 Dieter Baron and Thomas Klausner + Copyright (C) 2011-2014 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -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,13 +32,11 @@ */ - #include "zipint.h" #include - 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; } diff --git a/ext/zip/lib/zipconf.h b/ext/zip/lib/zipconf.h index 1f8f075f50..c8716fb952 100644 --- a/ext/zip/lib/zipconf.h +++ b/ext/zip/lib/zipconf.h @@ -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) diff --git a/ext/zip/lib/zipint.h b/ext/zip/lib/zipint.h index 1577d6085f..40f43af09c 100644 --- a/ext/zip/lib/zipint.h +++ b/ext/zip/lib/zipint.h @@ -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 @@ -34,6 +34,12 @@ 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 @@ -50,17 +56,13 @@ #endif #include "zip.h" -#ifdef PHP_WIN32 -# include "php_zip_config.w32.h" -#else -# include "config.h" -#endif -#ifdef HAVE_MOVEFILEEXA -#include -#define _zip_rename(s, t) (!MoveFileExA((s), (t), MOVEFILE_COPY_ALLOWED|MOVEFILE_REPLACE_EXISTING)) +#ifdef HAVE_STDBOOL_H +#include #else -#define _zip_rename rename +typedef char bool; +#define true 1 +#define false 0 #endif #ifdef _WIN32 @@ -81,13 +83,16 @@ #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 index 0000000000..4fa29cceee --- /dev/null +++ b/ext/zip/lib/zipwin32.h @@ -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 + + 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 + +/* 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 */ -- 2.40.0