mirror of
https://github.com/veracrypt/VeraCrypt
synced 2024-11-30 23:13:31 +01:00
Windows: Update libzip to version 1.5.0 that include fixes for some security issues.
This commit is contained in:
parent
49a8e52139
commit
cd7a01c34f
@ -23,6 +23,7 @@
|
||||
<ClCompile Include="libzip\zip_add.c" />
|
||||
<ClCompile Include="libzip\zip_add_dir.c" />
|
||||
<ClCompile Include="libzip\zip_add_entry.c" />
|
||||
<ClCompile Include="libzip\zip_algorithm_deflate.c" />
|
||||
<ClCompile Include="libzip\zip_buffer.c" />
|
||||
<ClCompile Include="libzip\zip_close.c" />
|
||||
<ClCompile Include="libzip\zip_delete.c" />
|
||||
@ -60,7 +61,6 @@
|
||||
<ClCompile Include="libzip\zip_fread.c" />
|
||||
<ClCompile Include="libzip\zip_get_archive_comment.c" />
|
||||
<ClCompile Include="libzip\zip_get_archive_flag.c" />
|
||||
<ClCompile Include="libzip\zip_get_compression_implementation.c" />
|
||||
<ClCompile Include="libzip\zip_get_encryption_implementation.c" />
|
||||
<ClCompile Include="libzip\zip_get_file_comment.c" />
|
||||
<ClCompile Include="libzip\zip_get_name.c" />
|
||||
@ -72,6 +72,7 @@
|
||||
<ClCompile Include="libzip\zip_name_locate.c" />
|
||||
<ClCompile Include="libzip\zip_new.c" />
|
||||
<ClCompile Include="libzip\zip_open.c" />
|
||||
<ClCompile Include="libzip\zip_progress.c" />
|
||||
<ClCompile Include="libzip\zip_rename.c" />
|
||||
<ClCompile Include="libzip\zip_replace.c" />
|
||||
<ClCompile Include="libzip\zip_set_archive_comment.c" />
|
||||
@ -81,16 +82,19 @@
|
||||
<ClCompile Include="libzip\zip_set_file_compression.c" />
|
||||
<ClCompile Include="libzip\zip_set_name.c" />
|
||||
<ClCompile Include="libzip\zip_source_begin_write.c" />
|
||||
<ClCompile Include="libzip\zip_source_begin_write_cloning.c" />
|
||||
<ClCompile Include="libzip\zip_source_buffer.c" />
|
||||
<ClCompile Include="libzip\zip_source_call.c" />
|
||||
<ClCompile Include="libzip\zip_source_close.c" />
|
||||
<ClCompile Include="libzip\zip_source_commit_write.c" />
|
||||
<ClCompile Include="libzip\zip_source_compress.c" />
|
||||
<ClCompile Include="libzip\zip_source_crc.c" />
|
||||
<ClCompile Include="libzip\zip_source_deflate.c" />
|
||||
<ClCompile Include="libzip\zip_source_error.c" />
|
||||
<ClCompile Include="libzip\zip_source_filep.c" />
|
||||
<ClCompile Include="libzip\zip_source_free.c" />
|
||||
<ClCompile Include="libzip\zip_source_function.c" />
|
||||
<ClCompile Include="libzip\zip_source_get_compression_flags.c" />
|
||||
<ClCompile Include="libzip\zip_source_is_deleted.c" />
|
||||
<ClCompile Include="libzip\zip_source_layered.c" />
|
||||
<ClCompile Include="libzip\zip_source_open.c" />
|
||||
|
@ -132,9 +132,6 @@
|
||||
<ClCompile Include="libzip\zip_get_archive_flag.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_get_compression_implementation.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_get_encryption_implementation.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
@ -348,6 +345,21 @@
|
||||
<ClCompile Include="zlib\uncompr.c">
|
||||
<Filter>zlib</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_progress.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_source_begin_write_cloning.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_source_compress.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_algorithm_deflate.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_source_get_compression_flags.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="libzip\compat.h">
|
||||
|
@ -1,4 +1,4 @@
|
||||
Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
|
||||
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
@ -29,38 +29,3 @@ 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.
|
||||
|
||||
|
||||
|
||||
For AES encryption support, files under the following license are used:
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK.
|
||||
All rights reserved.
|
||||
|
||||
LICENSE TERMS
|
||||
|
||||
The free distribution and use of this software in both source and binary
|
||||
form is allowed (with or without changes) provided that:
|
||||
|
||||
1. distributions of this source code include the above copyright
|
||||
notice, this list of conditions and the following disclaimer;
|
||||
|
||||
2. distributions in binary form include the above copyright
|
||||
notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other associated materials;
|
||||
|
||||
3. the copyright holder's name is not used to endorse products
|
||||
built using this software without specific written permission.
|
||||
|
||||
ALTERNATIVELY, provided that this notice is retained in full, this product
|
||||
may be distributed under the terms of the GNU General Public License (GPL),
|
||||
in which case the provisions of the GPL apply INSTEAD OF those given above.
|
||||
|
||||
DISCLAIMER
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its properties, including, but not limited to, correctness
|
||||
and/or fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
Issue Date: 18th November 2008
|
||||
|
@ -1,18 +1,56 @@
|
||||
1.5.0 [2018-03-11]
|
||||
==================
|
||||
|
||||
* Use standard cryptographic library instead of custom AES implementation.
|
||||
This also simplifies the license.
|
||||
* Use `clang-format` to format the source code.
|
||||
* More Windows improvements.
|
||||
|
||||
1.4.0 [2017-12-29]
|
||||
==================
|
||||
|
||||
* Improve build with cmake
|
||||
* Retire autoconf/automake build system
|
||||
* Add `zip_source_buffer_fragment()`.
|
||||
* Add support to clone unchanged beginning of archive (instead of rewriting it).
|
||||
Supported for buffer sources and on Apple File System.
|
||||
* Add support for Microsoft Universal Windows Platform.
|
||||
|
||||
1.3.2 [2017-11-20]
|
||||
==================
|
||||
* Fix bug introduced in last: zip_t was erroneously freed if zip_close() failed.
|
||||
|
||||
1.3.1 [2017-11-19]
|
||||
==================
|
||||
|
||||
* Install zipconf.h into ${PREFIX}/include
|
||||
* Add zip_libzip_version()
|
||||
* Fix AES tests on Linux
|
||||
|
||||
1.3.0 [2017-09-02]
|
||||
==================
|
||||
|
||||
* Support bzip2 compressed zip archives
|
||||
* Improve file progress callback code
|
||||
* Fix zip_fdopen()
|
||||
* CVE-2017-12858: Fix double free()
|
||||
* CVE-2017-14107: Improve EOCD64 parsing
|
||||
|
||||
1.2.0 [2017-02-19]
|
||||
==================
|
||||
|
||||
* Support for AES encryption (Winzip version), both encryption
|
||||
and decryption.
|
||||
* Support legacy zip files with >64k entries.
|
||||
* Fix seeking in zip_source_file if start > 0.
|
||||
* Add zip_fseek() for seeking in uncompressed data.
|
||||
* Add zip_ftell() for telling position in uncompressed data.
|
||||
and decryption
|
||||
* Support legacy zip files with >64k entries
|
||||
* Fix seeking in zip_source_file if start > 0
|
||||
* Add zip_fseek() for seeking in uncompressed data
|
||||
* Add zip_ftell() for telling position in uncompressed data
|
||||
* Add zip_register_progress_callback() for UI updates during zip_close()
|
||||
|
||||
1.1.3 [2016-05-28]
|
||||
==================
|
||||
|
||||
* Fix build on Windows when using autoconf.
|
||||
* Fix build on Windows when using autoconf
|
||||
|
||||
1.1.2 [2016-02-19]
|
||||
==================
|
||||
@ -40,33 +78,33 @@
|
||||
1.0.1 [2015-05-04]
|
||||
==================
|
||||
|
||||
* Build fixes for Windows.
|
||||
* Build fixes for Windows
|
||||
|
||||
1.0 [2015-05-03]
|
||||
================
|
||||
|
||||
* Implemented an I/O abstraction layer.
|
||||
* Added support for native Windows API for files.
|
||||
* Added support for setting the last modification time for a file.
|
||||
* Added a new type zip_error_t for errors.
|
||||
* Added more typedefs for structs.
|
||||
* Torrentzip support was removed.
|
||||
* CVE-2015-2331 was fixed.
|
||||
* Addressed all Coverity CIDs.
|
||||
* Implemented an I/O abstraction layer
|
||||
* Added support for native Windows API for files
|
||||
* Added support for setting the last modification time for a file
|
||||
* Added a new type zip_error_t for errors
|
||||
* Added more typedefs for structs
|
||||
* Torrentzip support was removed
|
||||
* CVE-2015-2331 was fixed
|
||||
* Addressed all Coverity CIDs
|
||||
|
||||
0.11.2 [2013-12-19]
|
||||
===================
|
||||
|
||||
* Support querying/setting operating system and external attributes.
|
||||
* Support querying/setting operating system and external attributes
|
||||
* For newly added files, set operating system to UNIX, permissions
|
||||
to 0666 (0777 for directories).
|
||||
* Fix bug when writing zip archives containing files bigger than 4GB.
|
||||
to 0666 (0777 for directories)
|
||||
* Fix bug when writing zip archives containing files bigger than 4GB
|
||||
|
||||
0.11.1 [2013-04-27]
|
||||
===================
|
||||
|
||||
* Fix bugs in zip_set_file_compression().
|
||||
* Include Xcode build infrastructure.
|
||||
* Fix bugs in zip_set_file_compression()
|
||||
* Include Xcode build infrastructure
|
||||
|
||||
0.11 [2013-03-23]
|
||||
=================
|
||||
@ -92,34 +130,34 @@
|
||||
0.10 [2010-03-18]
|
||||
=================
|
||||
|
||||
* Added zip_get_num_entries(), deprecated zip_get_num_files().
|
||||
* Better windows support.
|
||||
* Support for traditional PKWARE encryption added.
|
||||
* Fix opening archives with more than 65535 entries.
|
||||
* Fix some memory leaks.
|
||||
* Added zip_get_num_entries(), deprecated zip_get_num_files()
|
||||
* Better windows support
|
||||
* Support for traditional PKWARE encryption added
|
||||
* Fix opening archives with more than 65535 entries
|
||||
* Fix some memory leaks
|
||||
* Fix cmake build and installation
|
||||
* Fix memory leak in error case in zip_open()
|
||||
* Fixed CVE-2011-0421 (no security implications though)
|
||||
* More documentation.
|
||||
* More documentation
|
||||
|
||||
0.9.3 [2010-02-01]
|
||||
==================
|
||||
|
||||
* Include m4/ directory in distribution; some packagers need it.
|
||||
* Include m4/ directory in distribution; some packagers need it
|
||||
|
||||
0.9.2 [2010-01-31]
|
||||
==================
|
||||
|
||||
* Avoid passing uninitialized data to deflate().
|
||||
* Fix memory leak when closing zip archives.
|
||||
* Avoid passing uninitialized data to deflate()
|
||||
* Fix memory leak when closing zip archives
|
||||
|
||||
0.9.1 [2010-01-24]
|
||||
==================
|
||||
|
||||
* Fix infinite loop on reading some broken files.
|
||||
* Optimization in time conversion (don't call localtime()).
|
||||
* Clear data descriptor flag in central directory, fixing Open Office files.
|
||||
* Allow more than 64k entries.
|
||||
* Fix infinite loop on reading some broken files
|
||||
* Optimization in time conversion (don't call localtime())
|
||||
* Clear data descriptor flag in central directory, fixing Open Office files
|
||||
* Allow more than 64k entries
|
||||
|
||||
0.9 [2008-07-25]
|
||||
==================
|
||||
@ -151,7 +189,7 @@
|
||||
* struct zip_stat increased for future encryption support
|
||||
* zip_add return value changed (now returns new index of added file)
|
||||
* shared library major bump because of previous two
|
||||
* added functions for reading and writing file and archive comments.
|
||||
* added functions for reading and writing file and archive comments
|
||||
New functions: zip_get_archive_comment, zip_get_file_comment,
|
||||
zip_set_archive_comment, zip_set_file_comment, zip_unchange_archive
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
/*
|
||||
compat.h -- compatibility defines.
|
||||
Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
@ -34,6 +34,8 @@
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "zipconf.h"
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
@ -42,10 +44,12 @@
|
||||
#define __STDC_LIMIT_MACROS
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef ZIP_STATIC
|
||||
#define ZIP_EXTERN
|
||||
#else
|
||||
#ifndef ZIP_EXTERN
|
||||
#ifndef ZIP_STATIC
|
||||
#define ZIP_EXTERN __declspec(dllexport)
|
||||
#else
|
||||
#define ZIP_EXTERN
|
||||
#endif
|
||||
#endif
|
||||
/* for dup(), close(), etc. */
|
||||
#include <io.h>
|
||||
@ -54,10 +58,12 @@
|
||||
#ifdef HAVE_STDBOOL_H
|
||||
#include <stdbool.h>
|
||||
#else
|
||||
#ifndef __cplusplus
|
||||
typedef char bool;
|
||||
#define true 1
|
||||
#define false 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
@ -76,6 +82,9 @@ typedef char bool;
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(HAVE__CHMOD)
|
||||
#define chmod _chmod
|
||||
#endif
|
||||
#if defined(HAVE__CLOSE)
|
||||
#define close _close
|
||||
#endif
|
||||
@ -111,6 +120,12 @@ typedef char bool;
|
||||
#if !defined(HAVE_STRTOULL) && defined(HAVE__STRTOUI64)
|
||||
#define strtoull _strtoui64
|
||||
#endif
|
||||
#if defined(HAVE__UMASK)
|
||||
#define umask _umask
|
||||
#endif
|
||||
#if defined(HAVE__UNLINK)
|
||||
#define unlink _unlink
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_FSEEKO
|
||||
@ -185,7 +200,7 @@ int _zip_mkstemp(char *);
|
||||
#endif
|
||||
|
||||
#ifndef S_ISDIR
|
||||
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
|
||||
#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
|
||||
#endif /* compat.h */
|
||||
|
@ -5,6 +5,7 @@
|
||||
#endif
|
||||
/* BEGIN DEFINES */
|
||||
/* #undef HAVE___PROGNAME */
|
||||
#define HAVE__CHMOD
|
||||
#define HAVE__CLOSE
|
||||
#define HAVE__DUP
|
||||
#define HAVE__FDOPEN
|
||||
@ -16,11 +17,20 @@
|
||||
#define HAVE__STRICMP
|
||||
#define HAVE__STRTOI64
|
||||
#define HAVE__STRTOUI64
|
||||
#define HAVE__UMASK
|
||||
#define HAVE__UNLINK
|
||||
/* #undef HAVE_CLONEFILE */
|
||||
/* #undef HAVE_COMMONCRYPTO */
|
||||
/* #undef HAVE_CRYPTO */
|
||||
/* #undef HAVE_FICLONERANGE */
|
||||
#define HAVE_FILENO
|
||||
/* #undef HAVE_FSEEKO */
|
||||
/* #undef HAVE_FTELLO */
|
||||
/* #undef HAVE_GETPROGNAME */
|
||||
/* #undef HAVE_GNUTLS */
|
||||
/* #undef HAVE_LIBBZ2 */
|
||||
#define HAVE_OPEN
|
||||
/* #undef HAVE_OPENSSL */
|
||||
/* #undef HAVE_MKSTEMP */
|
||||
#define HAVE_SETMODE
|
||||
/* #undef HAVE_SNPRINTF */
|
||||
@ -46,6 +56,10 @@
|
||||
#define __INT64_LIBZIP 8
|
||||
#define INT64_T_LIBZIP 8
|
||||
#define UINT64_T_LIBZIP 8
|
||||
#define SHORT_LIBZIP 2
|
||||
#define INT_LIBZIP 4
|
||||
#define LONG_LIBZIP 4
|
||||
#define LONG_LONG_LIBZIP 8
|
||||
#define SIZEOF_OFF_T 4
|
||||
#ifdef _WIN64
|
||||
#define SIZE_T_LIBZIP 8
|
||||
@ -54,13 +68,15 @@
|
||||
#endif
|
||||
/* #undef SSIZE_T_LIBZIP */
|
||||
/* #undef HAVE_DIRENT_H */
|
||||
/* #undef HAVE_FTS_H */
|
||||
/* #undef HAVE_NDIR_H */
|
||||
/* #undef HAVE_SYS_DIR_H */
|
||||
/* #undef HAVE_SYS_NDIR_H */
|
||||
/* #undef WORDS_BIGENDIAN */
|
||||
#define HAVE_SHARED
|
||||
/* END DEFINES */
|
||||
#define PACKAGE "libzip"
|
||||
#define VERSION "1.2.0"
|
||||
#define VERSION "1.5.0a"
|
||||
|
||||
#ifndef HAVE_SSIZE_T_LIBZIP
|
||||
# if SIZE_T_LIBZIP == INT_LIBZIP
|
||||
|
@ -31,8 +31,8 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
@ -40,6 +40,9 @@
|
||||
#include <fcntl.h>
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#include <process.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -50,14 +53,14 @@
|
||||
|
||||
|
||||
int
|
||||
_zip_mkstemp(char *path)
|
||||
{
|
||||
_zip_mkstemp(char *path) {
|
||||
#ifdef _WIN32
|
||||
int ret;
|
||||
ret = _creat(_mktemp(path), _S_IREAD|_S_IWRITE);
|
||||
ret = _creat(_mktemp(path), _S_IREAD | _S_IWRITE);
|
||||
if (ret == -1) {
|
||||
return 0;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
@ -125,7 +128,7 @@ _zip_mkstemp(char *path)
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if ((fd=open(path, O_CREAT|O_EXCL|O_RDWR|O_BINARY, 0600)) >= 0)
|
||||
if ((fd = open(path, O_CREAT | O_EXCL | O_RDWR | O_BINARY, 0600)) >= 0)
|
||||
return (fd);
|
||||
if (errno != EEXIST)
|
||||
return (0);
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
/*
|
||||
zip.h -- exported declarations.
|
||||
Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
@ -35,20 +35,6 @@
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ZIP_EXTERN
|
||||
# ifndef ZIP_STATIC
|
||||
# ifdef _WIN32
|
||||
# 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
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#if 0
|
||||
@ -58,8 +44,22 @@ extern "C" {
|
||||
|
||||
#include <zipconf.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifndef ZIP_EXTERN
|
||||
#ifndef ZIP_STATIC
|
||||
#ifdef _WIN32
|
||||
#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
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
|
||||
/* flags for zip_open */
|
||||
@ -133,6 +133,7 @@ extern "C" {
|
||||
#define ZIP_ER_OPNOTSUPP 28 /* N Operation not supported */
|
||||
#define ZIP_ER_INUSE 29 /* N Resource still in use */
|
||||
#define ZIP_ER_TELL 30 /* S Tell error */
|
||||
#define ZIP_ER_COMPRESSED_DATA 31 /* N Compressed data invalid */
|
||||
|
||||
/* type of system error value */
|
||||
|
||||
@ -226,11 +227,15 @@ enum zip_source_cmd {
|
||||
ZIP_SOURCE_SEEK_WRITE, /* set position for writing */
|
||||
ZIP_SOURCE_TELL_WRITE, /* get write position */
|
||||
ZIP_SOURCE_SUPPORTS, /* check whether source supports command */
|
||||
ZIP_SOURCE_REMOVE /* remove file */
|
||||
ZIP_SOURCE_REMOVE, /* remove file */
|
||||
ZIP_SOURCE_GET_COMPRESSION_FLAGS, /* get compression flags, internal only */
|
||||
ZIP_SOURCE_BEGIN_WRITE_CLONING /* like ZIP_SOURCE_BEGIN_WRITE, but keep part of original file */
|
||||
};
|
||||
typedef enum zip_source_cmd zip_source_cmd_t;
|
||||
|
||||
#define ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd) (1<<(cmd))
|
||||
#define ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd) (((zip_int64_t)1) << (cmd))
|
||||
|
||||
// clang-format off
|
||||
|
||||
#define ZIP_SOURCE_SUPPORTS_READABLE (ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_OPEN) \
|
||||
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_READ) \
|
||||
@ -253,6 +258,8 @@ typedef enum zip_source_cmd zip_source_cmd_t;
|
||||
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_TELL_WRITE) \
|
||||
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_REMOVE))
|
||||
|
||||
// clang-format on
|
||||
|
||||
/* for use by sources */
|
||||
struct zip_source_args_seek {
|
||||
zip_int64_t offset;
|
||||
@ -294,6 +301,11 @@ struct zip_stat {
|
||||
zip_uint32_t flags; /* reserved for future use */
|
||||
};
|
||||
|
||||
struct zip_buffer_fragment {
|
||||
zip_uint8_t *data;
|
||||
zip_uint64_t length;
|
||||
};
|
||||
|
||||
struct zip;
|
||||
struct zip_file;
|
||||
struct zip_source;
|
||||
@ -303,14 +315,17 @@ 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 struct zip_buffer_fragment zip_buffer_fragment_t;
|
||||
|
||||
typedef zip_uint32_t zip_flags_t;
|
||||
|
||||
typedef zip_int64_t (*zip_source_callback)(void *, void *, zip_uint64_t, zip_source_cmd_t);
|
||||
typedef void (*zip_progress_callback_t)(double);
|
||||
|
||||
typedef void (*zip_progress_callback)(zip_t *, double, void *);
|
||||
|
||||
#ifndef ZIP_DISABLE_DEPRECATED
|
||||
typedef void (*zip_progress_callback_t)(double);
|
||||
ZIP_EXTERN void zip_register_progress_callback(zip_t *, zip_progress_callback_t); /* use zip_register_progress_callback_with_state */
|
||||
|
||||
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 */
|
||||
@ -320,7 +335,7 @@ ZIP_EXTERN int zip_replace(zip_t *, zip_uint64_t, zip_source_t *); /* use zip_fi
|
||||
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 int zip_error_to_str(char *, zip_uint64_t, int, int); /* use zip_error_init_with_code / zip_error_strerror */
|
||||
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
|
||||
|
||||
@ -373,17 +388,21 @@ 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 const char *zip_libzip_version(void);
|
||||
ZIP_EXTERN zip_int64_t zip_name_locate(zip_t *, const char *, zip_flags_t);
|
||||
ZIP_EXTERN zip_t *zip_open(const char *, int, int *);
|
||||
ZIP_EXTERN zip_t *zip_open_from_source(zip_source_t *, int, zip_error_t *);
|
||||
ZIP_EXTERN void zip_register_progress_callback(zip_t *, zip_progress_callback_t);
|
||||
ZIP_EXTERN int zip_register_progress_callback_with_state(zip_t *, double, zip_progress_callback, void (*)(void *), void *);
|
||||
ZIP_EXTERN int zip_set_archive_comment(zip_t *, const char *, zip_uint16_t);
|
||||
ZIP_EXTERN int zip_set_archive_flag(zip_t *, zip_flags_t, int);
|
||||
ZIP_EXTERN int zip_set_default_password(zip_t *, const char *);
|
||||
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 int zip_source_begin_write_cloning(zip_source_t *, zip_uint64_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 zip_source_t *zip_source_buffer_fragment(zip_t *, const zip_buffer_fragment_t *, zip_uint64_t, int);
|
||||
ZIP_EXTERN zip_source_t *zip_source_buffer_fragment_create(const zip_buffer_fragment_t *, 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 *);
|
||||
|
@ -44,7 +44,6 @@
|
||||
*/
|
||||
|
||||
ZIP_EXTERN zip_int64_t
|
||||
zip_add(zip_t *za, const char *name, zip_source_t *source)
|
||||
{
|
||||
zip_add(zip_t *za, const char *name, zip_source_t *source) {
|
||||
return zip_file_add(za, name, source, 0);
|
||||
}
|
||||
|
@ -39,7 +39,6 @@
|
||||
/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */
|
||||
|
||||
ZIP_EXTERN zip_int64_t
|
||||
zip_add_dir(zip_t *za, const char *name)
|
||||
{
|
||||
zip_add_dir(zip_t *za, const char *name) {
|
||||
return zip_dir_add(za, name, 0);
|
||||
}
|
||||
|
@ -40,11 +40,10 @@
|
||||
/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */
|
||||
|
||||
zip_int64_t
|
||||
_zip_add_entry(zip_t *za)
|
||||
{
|
||||
_zip_add_entry(zip_t *za) {
|
||||
zip_uint64_t idx;
|
||||
|
||||
if (za->nentry+1 >= za->nentry_alloc) {
|
||||
if (za->nentry + 1 >= za->nentry_alloc) {
|
||||
zip_entry_t *rentries;
|
||||
zip_uint64_t nalloc = za->nentry_alloc;
|
||||
zip_uint64_t additional_entries = 2 * nalloc;
|
||||
@ -75,7 +74,7 @@ _zip_add_entry(zip_t *za)
|
||||
|
||||
idx = za->nentry++;
|
||||
|
||||
_zip_entry_init(za->entry+idx);
|
||||
_zip_entry_init(za->entry + idx);
|
||||
|
||||
return (zip_int64_t)idx;
|
||||
}
|
||||
|
247
src/Common/libzip/zip_algorithm_deflate.c
Normal file
247
src/Common/libzip/zip_algorithm_deflate.c
Normal file
@ -0,0 +1,247 @@
|
||||
/*
|
||||
zip_algorithm_deflate.c -- deflate (de)compression routines
|
||||
Copyright (C) 2017 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <zlib.h>
|
||||
|
||||
struct ctx {
|
||||
zip_error_t *error;
|
||||
bool compress;
|
||||
int compression_flags;
|
||||
bool end_of_input;
|
||||
z_stream zstr;
|
||||
};
|
||||
|
||||
|
||||
static void *
|
||||
allocate(bool compress, int compression_flags, zip_error_t *error) {
|
||||
struct ctx *ctx;
|
||||
|
||||
if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->error = error;
|
||||
ctx->compress = compress;
|
||||
ctx->compression_flags = compression_flags;
|
||||
if (ctx->compression_flags < 1 || ctx->compression_flags > 9) {
|
||||
ctx->compression_flags = Z_BEST_COMPRESSION;
|
||||
}
|
||||
ctx->end_of_input = false;
|
||||
|
||||
ctx->zstr.zalloc = Z_NULL;
|
||||
ctx->zstr.zfree = Z_NULL;
|
||||
ctx->zstr.opaque = NULL;
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
compress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
|
||||
return allocate(true, compression_flags, error);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
decompress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
|
||||
return allocate(false, compression_flags, error);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
deallocate(void *ud) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
compression_flags(void *ud) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
|
||||
if (!ctx->compress) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->compression_flags < 3) {
|
||||
return 2;
|
||||
}
|
||||
else if (ctx->compression_flags > 7) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
start(void *ud) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
int ret;
|
||||
|
||||
ctx->zstr.avail_in = 0;
|
||||
ctx->zstr.next_in = NULL;
|
||||
ctx->zstr.avail_out = 0;
|
||||
ctx->zstr.next_out = NULL;
|
||||
|
||||
if (ctx->compress) {
|
||||
/* negative value to tell zlib not to write a header */
|
||||
ret = deflateInit2(&ctx->zstr, ctx->compression_flags, Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
|
||||
}
|
||||
else {
|
||||
ret = inflateInit2(&ctx->zstr, -MAX_WBITS);
|
||||
}
|
||||
|
||||
if (ret != Z_OK) {
|
||||
zip_error_set(ctx->error, ZIP_ER_ZLIB, ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
end(void *ud) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
int err;
|
||||
|
||||
if (ctx->compress) {
|
||||
err = deflateEnd(&ctx->zstr);
|
||||
}
|
||||
else {
|
||||
err = inflateEnd(&ctx->zstr);
|
||||
}
|
||||
|
||||
if (err != Z_OK) {
|
||||
zip_error_set(ctx->error, ZIP_ER_ZLIB, err);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
input(void *ud, zip_uint8_t *data, zip_uint64_t length) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
|
||||
if (length > UINT_MAX || ctx->zstr.avail_in > 0) {
|
||||
zip_error_set(ctx->error, ZIP_ER_INVAL, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
ctx->zstr.avail_in = (uInt)length;
|
||||
ctx->zstr.next_in = (Bytef *)data;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
end_of_input(void *ud) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
|
||||
ctx->end_of_input = true;
|
||||
}
|
||||
|
||||
|
||||
static zip_compression_status_t
|
||||
process(void *ud, zip_uint8_t *data, zip_uint64_t *length) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
|
||||
int ret;
|
||||
|
||||
ctx->zstr.avail_out = (uInt)ZIP_MIN(UINT_MAX, *length);
|
||||
ctx->zstr.next_out = (Bytef *)data;
|
||||
|
||||
if (ctx->compress) {
|
||||
ret = deflate(&ctx->zstr, ctx->end_of_input ? Z_FINISH : 0);
|
||||
}
|
||||
else {
|
||||
ret = inflate(&ctx->zstr, Z_SYNC_FLUSH);
|
||||
}
|
||||
|
||||
*length = *length - ctx->zstr.avail_out;
|
||||
|
||||
switch (ret) {
|
||||
case Z_OK:
|
||||
return ZIP_COMPRESSION_OK;
|
||||
|
||||
case Z_STREAM_END:
|
||||
return ZIP_COMPRESSION_END;
|
||||
|
||||
case Z_BUF_ERROR:
|
||||
if (ctx->zstr.avail_in == 0) {
|
||||
return ZIP_COMPRESSION_NEED_DATA;
|
||||
}
|
||||
|
||||
/* fallthrough */
|
||||
|
||||
default:
|
||||
zip_error_set(ctx->error, ZIP_ER_ZLIB, ret);
|
||||
return ZIP_COMPRESSION_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
|
||||
zip_compression_algorithm_t zip_algorithm_deflate_compress = {
|
||||
compress_allocate,
|
||||
deallocate,
|
||||
compression_flags,
|
||||
start,
|
||||
end,
|
||||
input,
|
||||
end_of_input,
|
||||
process
|
||||
};
|
||||
|
||||
|
||||
zip_compression_algorithm_t zip_algorithm_deflate_decompress = {
|
||||
decompress_allocate,
|
||||
deallocate,
|
||||
compression_flags,
|
||||
start,
|
||||
end,
|
||||
input,
|
||||
end_of_input,
|
||||
process
|
||||
};
|
||||
|
||||
// clang-format on
|
@ -37,15 +37,13 @@
|
||||
#include "zipint.h"
|
||||
|
||||
zip_uint8_t *
|
||||
_zip_buffer_data(zip_buffer_t *buffer)
|
||||
{
|
||||
_zip_buffer_data(zip_buffer_t *buffer) {
|
||||
return buffer->data;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_zip_buffer_free(zip_buffer_t *buffer)
|
||||
{
|
||||
_zip_buffer_free(zip_buffer_t *buffer) {
|
||||
if (buffer == NULL) {
|
||||
return;
|
||||
}
|
||||
@ -59,15 +57,13 @@ _zip_buffer_free(zip_buffer_t *buffer)
|
||||
|
||||
|
||||
bool
|
||||
_zip_buffer_eof(zip_buffer_t *buffer)
|
||||
{
|
||||
_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_buffer_get(zip_buffer_t *buffer, zip_uint64_t length) {
|
||||
zip_uint8_t *data;
|
||||
|
||||
data = _zip_buffer_peek(buffer, length);
|
||||
@ -81,8 +77,7 @@ _zip_buffer_get(zip_buffer_t *buffer, zip_uint64_t length)
|
||||
|
||||
|
||||
zip_uint16_t
|
||||
_zip_buffer_get_16(zip_buffer_t *buffer)
|
||||
{
|
||||
_zip_buffer_get_16(zip_buffer_t *buffer) {
|
||||
zip_uint8_t *data = _zip_buffer_get(buffer, 2);
|
||||
|
||||
if (data == NULL) {
|
||||
@ -94,8 +89,7 @@ _zip_buffer_get_16(zip_buffer_t *buffer)
|
||||
|
||||
|
||||
zip_uint32_t
|
||||
_zip_buffer_get_32(zip_buffer_t *buffer)
|
||||
{
|
||||
_zip_buffer_get_32(zip_buffer_t *buffer) {
|
||||
zip_uint8_t *data = _zip_buffer_get(buffer, 4);
|
||||
|
||||
if (data == NULL) {
|
||||
@ -107,8 +101,7 @@ _zip_buffer_get_32(zip_buffer_t *buffer)
|
||||
|
||||
|
||||
zip_uint64_t
|
||||
_zip_buffer_get_64(zip_buffer_t *buffer)
|
||||
{
|
||||
_zip_buffer_get_64(zip_buffer_t *buffer) {
|
||||
zip_uint8_t *data = _zip_buffer_get(buffer, 8);
|
||||
|
||||
if (data == NULL) {
|
||||
@ -119,10 +112,8 @@ _zip_buffer_get_64(zip_buffer_t *buffer)
|
||||
}
|
||||
|
||||
|
||||
|
||||
zip_uint8_t
|
||||
_zip_buffer_get_8(zip_buffer_t *buffer)
|
||||
{
|
||||
_zip_buffer_get_8(zip_buffer_t *buffer) {
|
||||
zip_uint8_t *data = _zip_buffer_get(buffer, 1);
|
||||
|
||||
if (data == NULL) {
|
||||
@ -134,15 +125,13 @@ _zip_buffer_get_8(zip_buffer_t *buffer)
|
||||
|
||||
|
||||
zip_uint64_t
|
||||
_zip_buffer_left(zip_buffer_t *buffer)
|
||||
{
|
||||
_zip_buffer_left(zip_buffer_t *buffer) {
|
||||
return buffer->ok ? buffer->size - buffer->offset : 0;
|
||||
}
|
||||
|
||||
|
||||
zip_uint64_t
|
||||
_zip_buffer_read(zip_buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length)
|
||||
{
|
||||
_zip_buffer_read(zip_buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length) {
|
||||
if (_zip_buffer_left(buffer) < length) {
|
||||
length = _zip_buffer_left(buffer);
|
||||
}
|
||||
@ -154,8 +143,7 @@ _zip_buffer_read(zip_buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length)
|
||||
|
||||
|
||||
zip_buffer_t *
|
||||
_zip_buffer_new(zip_uint8_t *data, zip_uint64_t size)
|
||||
{
|
||||
_zip_buffer_new(zip_uint8_t *data, zip_uint64_t size) {
|
||||
bool free_data = (data == NULL);
|
||||
zip_buffer_t *buffer;
|
||||
|
||||
@ -183,8 +171,7 @@ _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_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) {
|
||||
@ -202,23 +189,19 @@ _zip_buffer_new_from_source(zip_source_t *src, zip_uint64_t size, zip_uint8_t *b
|
||||
|
||||
|
||||
zip_uint64_t
|
||||
_zip_buffer_offset(zip_buffer_t *buffer)
|
||||
{
|
||||
_zip_buffer_offset(zip_buffer_t *buffer) {
|
||||
return buffer->ok ? buffer->offset : 0;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
_zip_buffer_ok(zip_buffer_t *buffer)
|
||||
{
|
||||
_zip_buffer_ok(zip_buffer_t *buffer) {
|
||||
return buffer->ok;
|
||||
}
|
||||
|
||||
|
||||
|
||||
zip_uint8_t *
|
||||
_zip_buffer_peek(zip_buffer_t *buffer, zip_uint64_t length)
|
||||
{
|
||||
_zip_buffer_peek(zip_buffer_t *buffer, zip_uint64_t length) {
|
||||
zip_uint8_t *data;
|
||||
|
||||
if (!buffer->ok || buffer->offset + length < length || buffer->offset + length > buffer->size) {
|
||||
@ -231,8 +214,7 @@ _zip_buffer_peek(zip_buffer_t *buffer, zip_uint64_t length)
|
||||
}
|
||||
|
||||
int
|
||||
_zip_buffer_put(zip_buffer_t *buffer, const void *src, size_t length)
|
||||
{
|
||||
_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) {
|
||||
@ -245,8 +227,7 @@ _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)
|
||||
{
|
||||
_zip_buffer_put_16(zip_buffer_t *buffer, zip_uint16_t i) {
|
||||
zip_uint8_t *data = _zip_buffer_get(buffer, 2);
|
||||
|
||||
if (data == NULL) {
|
||||
@ -261,8 +242,7 @@ _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)
|
||||
{
|
||||
_zip_buffer_put_32(zip_buffer_t *buffer, zip_uint32_t i) {
|
||||
zip_uint8_t *data = _zip_buffer_get(buffer, 4);
|
||||
|
||||
if (data == NULL) {
|
||||
@ -279,8 +259,7 @@ _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)
|
||||
{
|
||||
_zip_buffer_put_64(zip_buffer_t *buffer, zip_uint64_t i) {
|
||||
zip_uint8_t *data = _zip_buffer_get(buffer, 8);
|
||||
|
||||
if (data == NULL) {
|
||||
@ -301,8 +280,7 @@ _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)
|
||||
{
|
||||
_zip_buffer_put_8(zip_buffer_t *buffer, zip_uint8_t i) {
|
||||
zip_uint8_t *data = _zip_buffer_get(buffer, 1);
|
||||
|
||||
if (data == NULL) {
|
||||
@ -316,8 +294,7 @@ _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_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset) {
|
||||
if (offset > buffer->size) {
|
||||
buffer->ok = false;
|
||||
return -1;
|
||||
@ -342,7 +319,6 @@ _zip_buffer_skip(zip_buffer_t *buffer, zip_uint64_t length) {
|
||||
}
|
||||
|
||||
zip_uint64_t
|
||||
_zip_buffer_size(zip_buffer_t *buffer)
|
||||
{
|
||||
_zip_buffer_size(zip_buffer_t *buffer) {
|
||||
return buffer->size;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
zip_close.c -- close zip archive and update changes
|
||||
Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
@ -43,27 +43,22 @@
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* max deflate size increase: size + ceil(size/16k)*5+6 */
|
||||
#define MAX_DEFLATE_SIZE_32 4293656963u
|
||||
|
||||
static int add_data(zip_t *, zip_source_t *, zip_dirent_t *);
|
||||
static int copy_data(zip_t *, zip_uint64_t);
|
||||
static int copy_source(zip_t *, zip_source_t *);
|
||||
static int copy_source(zip_t *, zip_source_t *, zip_int64_t);
|
||||
static int write_cdir(zip_t *, const zip_filelist_t *, zip_uint64_t);
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_close(zip_t *za)
|
||||
{
|
||||
zip_uint64_t i, j, survivors;
|
||||
zip_close(zip_t *za) {
|
||||
zip_uint64_t i, j, survivors, unchanged_offset;
|
||||
zip_int64_t off;
|
||||
int error;
|
||||
zip_filelist_t *filelist;
|
||||
@ -96,13 +91,18 @@ zip_close(zip_t *za)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((filelist=(zip_filelist_t *)malloc(sizeof(filelist[0])*(size_t)survivors)) == NULL)
|
||||
if ((filelist = (zip_filelist_t *)malloc(sizeof(filelist[0]) * (size_t)survivors)) == NULL)
|
||||
return -1;
|
||||
|
||||
unchanged_offset = ZIP_UINT64_MAX;
|
||||
/* create list of files with index into original archive */
|
||||
for (i=j=0; i<za->nentry; i++) {
|
||||
if (za->entry[i].deleted)
|
||||
for (i = j = 0; i < za->nentry; i++) {
|
||||
if (za->entry[i].orig != NULL && ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) {
|
||||
unchanged_offset = ZIP_MIN(unchanged_offset, za->entry[i].orig->offset);
|
||||
}
|
||||
if (za->entry[i].deleted) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (j >= survivors) {
|
||||
free(filelist);
|
||||
@ -119,30 +119,67 @@ zip_close(zip_t *za)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((zip_source_supports(za->src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING)) == 0) {
|
||||
unchanged_offset = 0;
|
||||
}
|
||||
else {
|
||||
if (unchanged_offset == ZIP_UINT64_MAX) {
|
||||
/* we're keeping all file data, find the end of the last one */
|
||||
zip_uint64_t last_index = ZIP_UINT64_MAX;
|
||||
unchanged_offset = 0;
|
||||
|
||||
for (i = 0; i < za->nentry; i++) {
|
||||
if (za->entry[i].orig != NULL) {
|
||||
if (za->entry[i].orig->offset >= unchanged_offset) {
|
||||
unchanged_offset = za->entry[i].orig->offset;
|
||||
last_index = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (last_index != ZIP_UINT64_MAX) {
|
||||
if ((unchanged_offset = _zip_file_get_end(za, last_index, &za->error)) == 0) {
|
||||
free(filelist);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (unchanged_offset > 0) {
|
||||
if (zip_source_begin_write_cloning(za->src, unchanged_offset) < 0) {
|
||||
/* cloning not supported, need to copy everything */
|
||||
unchanged_offset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (unchanged_offset == 0) {
|
||||
if (zip_source_begin_write(za->src) < 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
free(filelist);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
_zip_progress_start(za->progress);
|
||||
error = 0;
|
||||
for (j=0; j<survivors; j++) {
|
||||
for (j = 0; j < survivors; j++) {
|
||||
int new_data;
|
||||
zip_entry_t *entry;
|
||||
zip_dirent_t *de;
|
||||
|
||||
if (za->progress_callback) {
|
||||
za->progress_callback((double)j/survivors);
|
||||
}
|
||||
_zip_progress_subrange(za->progress, (double)j / (double)survivors, (double)(j + 1) / (double)survivors);
|
||||
|
||||
i = filelist[j].idx;
|
||||
entry = za->entry+i;
|
||||
entry = za->entry + i;
|
||||
|
||||
if (entry->orig != NULL && entry->orig->offset < unchanged_offset) {
|
||||
/* already implicitly copied by cloning */
|
||||
continue;
|
||||
}
|
||||
|
||||
new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_ENCRYPTION_METHOD));
|
||||
|
||||
/* create new local directory entry */
|
||||
if (entry->changes == NULL) {
|
||||
if ((entry->changes=_zip_dirent_clone(entry->orig)) == NULL) {
|
||||
if ((entry->changes = _zip_dirent_clone(entry->orig)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
error = 1;
|
||||
break;
|
||||
@ -166,7 +203,7 @@ zip_close(zip_t *za)
|
||||
|
||||
zs = NULL;
|
||||
if (!ZIP_ENTRY_DATA_CHANGED(entry)) {
|
||||
if ((zs=_zip_source_zip_new(za, za, i, ZIP_FL_UNCHANGED, 0, 0, NULL)) == NULL) {
|
||||
if ((zs = _zip_source_zip_new(za, za, i, ZIP_FL_UNCHANGED, 0, 0, NULL)) == NULL) {
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
@ -191,7 +228,7 @@ zip_close(zip_t *za)
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
if ((offset=_zip_file_get_offset(za, i, &za->error)) == 0) {
|
||||
if ((offset = _zip_file_get_offset(za, i, &za->error)) == 0) {
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
@ -221,15 +258,13 @@ zip_close(zip_t *za)
|
||||
}
|
||||
}
|
||||
|
||||
_zip_progress_end(za->progress);
|
||||
|
||||
if (error) {
|
||||
zip_source_rollback_write(za->src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (za->progress_callback) {
|
||||
za->progress_callback(1);
|
||||
}
|
||||
|
||||
zip_discard(za);
|
||||
|
||||
return 0;
|
||||
@ -237,14 +272,14 @@ zip_close(zip_t *za)
|
||||
|
||||
|
||||
static int
|
||||
add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de)
|
||||
{
|
||||
zip_int64_t offstart, offdata, offend;
|
||||
add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) {
|
||||
zip_int64_t offstart, offdata, offend, data_length;
|
||||
struct zip_stat st;
|
||||
zip_source_t *src_final, *src_tmp;
|
||||
int ret;
|
||||
int is_zip64;
|
||||
zip_flags_t flags;
|
||||
zip_int8_t compression_flags;
|
||||
bool needs_recompress, needs_decompress, needs_crc, needs_compress, needs_reencrypt, needs_decrypt, needs_encrypt;
|
||||
|
||||
if (zip_source_stat(src, &st) < 0) {
|
||||
@ -275,30 +310,58 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de)
|
||||
|
||||
flags = ZIP_EF_LOCAL;
|
||||
|
||||
if ((st.valid & ZIP_STAT_SIZE) == 0)
|
||||
if ((st.valid & ZIP_STAT_SIZE) == 0) {
|
||||
flags |= ZIP_FL_FORCE_ZIP64;
|
||||
data_length = -1;
|
||||
}
|
||||
else {
|
||||
de->uncomp_size = st.size;
|
||||
/* this is technically incorrect (copy_source counts compressed data), but it's the best we have */
|
||||
data_length = (zip_int64_t)st.size;
|
||||
|
||||
if ((st.valid & ZIP_STAT_COMP_SIZE) == 0) {
|
||||
if (( ((de->comp_method == ZIP_CM_DEFLATE || ZIP_CM_IS_DEFAULT(de->comp_method)) && st.size > MAX_DEFLATE_SIZE_32)
|
||||
|| (de->comp_method != ZIP_CM_STORE && de->comp_method != ZIP_CM_DEFLATE && !ZIP_CM_IS_DEFAULT(de->comp_method))))
|
||||
zip_uint64_t max_size;
|
||||
|
||||
switch (ZIP_CM_ACTUAL(de->comp_method)) {
|
||||
case ZIP_CM_BZIP2:
|
||||
/* computed by looking at increase of 10 random files of size 1MB when
|
||||
* compressed with bzip2, rounded up: 1.006 */
|
||||
max_size = 4269351188u;
|
||||
break;
|
||||
|
||||
case ZIP_CM_DEFLATE:
|
||||
/* max deflate size increase: size + ceil(size/16k)*5+6 */
|
||||
max_size = 4293656963u;
|
||||
break;
|
||||
|
||||
case ZIP_CM_STORE:
|
||||
max_size = 0xffffffffu;
|
||||
break;
|
||||
|
||||
default:
|
||||
max_size = 0;
|
||||
}
|
||||
|
||||
if (st.size > max_size) {
|
||||
flags |= ZIP_FL_FORCE_ZIP64;
|
||||
}
|
||||
}
|
||||
else
|
||||
de->comp_size = st.comp_size;
|
||||
}
|
||||
|
||||
if ((offstart = zip_source_tell_write(za->src)) < 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* as long as we don't support non-seekable output, clear data descriptor bit */
|
||||
de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
|
||||
if ((is_zip64=_zip_dirent_write(za, de, flags)) < 0)
|
||||
if ((is_zip64 = _zip_dirent_write(za, de, flags)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
needs_recompress = !((st.comp_method == de->comp_method) || (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method == ZIP_CM_DEFLATE));
|
||||
needs_recompress = st.comp_method != ZIP_CM_ACTUAL(de->comp_method);
|
||||
needs_decompress = needs_recompress && (st.comp_method != ZIP_CM_STORE);
|
||||
needs_crc = (st.comp_method == ZIP_CM_STORE) || needs_decompress;
|
||||
needs_compress = needs_recompress && (de->comp_method != ZIP_CM_STORE);
|
||||
@ -329,15 +392,7 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de)
|
||||
}
|
||||
|
||||
if (needs_decompress) {
|
||||
zip_compression_implementation comp_impl;
|
||||
|
||||
if ((comp_impl = _zip_get_compression_implementation(st.comp_method, ZIP_CODEC_DECODE)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
if ((src_tmp = comp_impl(za, src_final, st.comp_method, ZIP_CODEC_DECODE)) == NULL) {
|
||||
/* error set by comp_impl */
|
||||
if ((src_tmp = zip_source_decompress(za, src_final, st.comp_method)) == NULL) {
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
@ -357,14 +412,7 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de)
|
||||
}
|
||||
|
||||
if (needs_compress) {
|
||||
zip_compression_implementation comp_impl;
|
||||
|
||||
if ((comp_impl = _zip_get_compression_implementation(de->comp_method, ZIP_CODEC_ENCODE)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
if ((src_tmp = comp_impl(za, src_final, de->comp_method, ZIP_CODEC_ENCODE)) == NULL) {
|
||||
if ((src_tmp = zip_source_compress(za, src_final, de->comp_method, de->compression_level)) == NULL) {
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
@ -380,7 +428,8 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de)
|
||||
|
||||
if (de->password) {
|
||||
password = de->password;
|
||||
} else if (za->default_password) {
|
||||
}
|
||||
else if (za->default_password) {
|
||||
password = za->default_password;
|
||||
}
|
||||
|
||||
@ -401,12 +450,19 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de)
|
||||
|
||||
|
||||
if ((offdata = zip_source_tell_write(za->src)) < 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = copy_source(za, src_final);
|
||||
ret = copy_source(za, src_final, data_length);
|
||||
|
||||
if (zip_source_stat(src_final, &st) < 0) {
|
||||
_zip_error_set_from_source(&za->error, src_final);
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if ((compression_flags = zip_source_get_compression_flags(src_final)) < 0) {
|
||||
_zip_error_set_from_source(&za->error, src_final);
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
@ -417,6 +473,7 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de)
|
||||
}
|
||||
|
||||
if ((offend = zip_source_tell_write(za->src)) < 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -425,7 +482,7 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de)
|
||||
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)) {
|
||||
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);
|
||||
return -1;
|
||||
}
|
||||
@ -440,8 +497,10 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de)
|
||||
de->crc = st.crc;
|
||||
de->uncomp_size = st.size;
|
||||
de->comp_size = (zip_uint64_t)(offend - offdata);
|
||||
de->bitflags = (zip_uint16_t)((de->bitflags & (zip_uint16_t)~6) | ((zip_uint8_t)compression_flags << 1));
|
||||
_zip_dirent_set_version_needed(de, (flags & ZIP_FL_FORCE_ZIP64) != 0);
|
||||
|
||||
if ((ret=_zip_dirent_write(za, de, flags)) < 0)
|
||||
if ((ret = _zip_dirent_write(za, de, flags)) < 0)
|
||||
return -1;
|
||||
|
||||
if (is_zip64 != ret) {
|
||||
@ -450,7 +509,6 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de)
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (zip_source_seek_write(za->src, offend, SEEK_SET) < 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
@ -461,10 +519,10 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de)
|
||||
|
||||
|
||||
static int
|
||||
copy_data(zip_t *za, zip_uint64_t len)
|
||||
{
|
||||
copy_data(zip_t *za, zip_uint64_t len) {
|
||||
zip_uint8_t buf[BUFSIZE];
|
||||
size_t n;
|
||||
double total = (double)len;
|
||||
|
||||
while (len > 0) {
|
||||
n = len > sizeof(buf) ? sizeof(buf) : len;
|
||||
@ -477,6 +535,8 @@ copy_data(zip_t *za, zip_uint64_t len)
|
||||
}
|
||||
|
||||
len -= n;
|
||||
|
||||
_zip_progress_update(za->progress, (total - (double)len) / total);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -484,10 +544,9 @@ copy_data(zip_t *za, zip_uint64_t len)
|
||||
|
||||
|
||||
static int
|
||||
copy_source(zip_t *za, zip_source_t *src)
|
||||
{
|
||||
copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length) {
|
||||
zip_uint8_t buf[BUFSIZE];
|
||||
zip_int64_t n;
|
||||
zip_int64_t n, current;
|
||||
int ret;
|
||||
|
||||
if (zip_source_open(src) < 0) {
|
||||
@ -496,11 +555,16 @@ copy_source(zip_t *za, zip_source_t *src)
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
while ((n=zip_source_read(src, buf, sizeof(buf))) > 0) {
|
||||
current = 0;
|
||||
while ((n = zip_source_read(src, buf, sizeof(buf))) > 0) {
|
||||
if (_zip_write(za, buf, (zip_uint64_t)n) < 0) {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
if (n == sizeof(buf) && za->progress && data_length > 0) {
|
||||
current += n;
|
||||
_zip_progress_update(za->progress, (double)current / (double)data_length);
|
||||
}
|
||||
}
|
||||
|
||||
if (n < 0) {
|
||||
@ -513,17 +577,15 @@ copy_source(zip_t *za, zip_source_t *src)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
write_cdir(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors)
|
||||
{
|
||||
write_cdir(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors) {
|
||||
zip_int64_t cd_start, end, size;
|
||||
|
||||
if ((cd_start = zip_source_tell_write(za->src)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((size=_zip_cdir_write(za, filelist, survivors)) < 0) {
|
||||
if ((size = _zip_cdir_write(za, filelist, survivors)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -536,26 +598,29 @@ write_cdir(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors)
|
||||
|
||||
|
||||
int
|
||||
_zip_changed(const zip_t *za, zip_uint64_t *survivorsp)
|
||||
{
|
||||
_zip_changed(const zip_t *za, zip_uint64_t *survivorsp) {
|
||||
int changed;
|
||||
zip_uint64_t i, survivors;
|
||||
|
||||
changed = 0;
|
||||
survivors = 0;
|
||||
|
||||
if (za->comment_changed || za->ch_flags != za->flags)
|
||||
if (za->comment_changed || za->ch_flags != za->flags) {
|
||||
changed = 1;
|
||||
|
||||
for (i=0; i<za->nentry; i++) {
|
||||
if (za->entry[i].deleted || za->entry[i].source || (za->entry[i].changes && za->entry[i].changes->changed != 0))
|
||||
changed = 1;
|
||||
if (!za->entry[i].deleted)
|
||||
survivors++;
|
||||
}
|
||||
|
||||
if (survivorsp)
|
||||
for (i = 0; i < za->nentry; i++) {
|
||||
if (ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) {
|
||||
changed = 1;
|
||||
}
|
||||
if (!za->entry[i].deleted) {
|
||||
survivors++;
|
||||
}
|
||||
}
|
||||
|
||||
if (survivorsp) {
|
||||
*survivorsp = survivors;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
@ -36,8 +36,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_delete(zip_t *za, zip_uint64_t idx)
|
||||
{
|
||||
zip_delete(zip_t *za, zip_uint64_t idx) {
|
||||
const char *name;
|
||||
|
||||
if (idx >= za->nentry) {
|
||||
@ -50,7 +49,7 @@ zip_delete(zip_t *za, zip_uint64_t idx)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((name=_zip_get_name(za, idx, 0, &za->error)) == NULL) {
|
||||
if ((name = _zip_get_name(za, idx, 0, &za->error)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -67,4 +66,3 @@ zip_delete(zip_t *za, zip_uint64_t idx)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -41,8 +41,7 @@
|
||||
/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */
|
||||
|
||||
ZIP_EXTERN zip_int64_t
|
||||
zip_dir_add(zip_t *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;
|
||||
@ -61,17 +60,17 @@ zip_dir_add(zip_t *za, const char *name, zip_flags_t flags)
|
||||
s = NULL;
|
||||
len = strlen(name);
|
||||
|
||||
if (name[len-1] != '/') {
|
||||
if ((s=(char *)malloc(len+2)) == NULL) {
|
||||
if (name[len - 1] != '/') {
|
||||
if ((s = (char *)malloc(len + 2)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
strcpy(s, name);
|
||||
s[len] = '/';
|
||||
s[len+1] = '\0';
|
||||
s[len + 1] = '\0';
|
||||
}
|
||||
|
||||
if ((source=zip_source_buffer(za, NULL, 0, 0)) == NULL) {
|
||||
if ((source = zip_source_buffer(za, NULL, 0, 0)) == NULL) {
|
||||
free(s);
|
||||
return -1;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
zip_dirent.c -- read directory entry (local or central), clean dirent
|
||||
Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
@ -35,8 +35,8 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "zipint.h"
|
||||
@ -48,15 +48,14 @@ static bool _zip_dirent_process_winzip_aes(zip_dirent_t *de, zip_error_t *error)
|
||||
|
||||
|
||||
void
|
||||
_zip_cdir_free(zip_cdir_t *cd)
|
||||
{
|
||||
_zip_cdir_free(zip_cdir_t *cd) {
|
||||
zip_uint64_t i;
|
||||
|
||||
if (!cd)
|
||||
return;
|
||||
|
||||
for (i=0; i<cd->nentry; i++)
|
||||
_zip_entry_finalize(cd->entry+i);
|
||||
for (i = 0; i < cd->nentry; i++)
|
||||
_zip_entry_finalize(cd->entry + i);
|
||||
free(cd->entry);
|
||||
_zip_string_free(cd->comment);
|
||||
free(cd);
|
||||
@ -64,11 +63,10 @@ _zip_cdir_free(zip_cdir_t *cd)
|
||||
|
||||
|
||||
zip_cdir_t *
|
||||
_zip_cdir_new(zip_uint64_t nentry, zip_error_t *error)
|
||||
{
|
||||
_zip_cdir_new(zip_uint64_t nentry, zip_error_t *error) {
|
||||
zip_cdir_t *cd;
|
||||
|
||||
if ((cd=(zip_cdir_t *)malloc(sizeof(*cd))) == NULL) {
|
||||
if ((cd = (zip_cdir_t *)malloc(sizeof(*cd))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
@ -89,8 +87,7 @@ _zip_cdir_new(zip_uint64_t nentry, zip_error_t *error)
|
||||
|
||||
|
||||
bool
|
||||
_zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *error)
|
||||
{
|
||||
_zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *error) {
|
||||
zip_uint64_t i, new_alloc;
|
||||
zip_entry_t *new_entry;
|
||||
|
||||
@ -100,12 +97,12 @@ _zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *err
|
||||
|
||||
new_alloc = cd->nentry_alloc + additional_entries;
|
||||
|
||||
if (new_alloc < additional_entries || new_alloc > SIZE_MAX/sizeof(*(cd->entry))) {
|
||||
if (new_alloc < additional_entries || new_alloc > SIZE_MAX / sizeof(*(cd->entry))) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((new_entry = (zip_entry_t *)realloc(cd->entry, sizeof(*(cd->entry))*(size_t)new_alloc)) == NULL) {
|
||||
if ((new_entry = (zip_entry_t *)realloc(cd->entry, sizeof(*(cd->entry)) * (size_t)new_alloc)) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return false;
|
||||
}
|
||||
@ -113,7 +110,7 @@ _zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *err
|
||||
cd->entry = new_entry;
|
||||
|
||||
for (i = cd->nentry; i < new_alloc; i++) {
|
||||
_zip_entry_init(cd->entry+i);
|
||||
_zip_entry_init(cd->entry + i);
|
||||
}
|
||||
|
||||
cd->nentry = cd->nentry_alloc = new_alloc;
|
||||
@ -123,8 +120,7 @@ _zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *err
|
||||
|
||||
|
||||
zip_int64_t
|
||||
_zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors)
|
||||
{
|
||||
_zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors) {
|
||||
zip_uint64_t offset, size;
|
||||
zip_string_t *comment;
|
||||
zip_uint8_t buf[EOCDLEN + EOCD64LEN + EOCD64LOCLEN];
|
||||
@ -142,10 +138,10 @@ _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivor
|
||||
|
||||
is_zip64 = false;
|
||||
|
||||
for (i=0; i<survivors; i++) {
|
||||
zip_entry_t *entry = za->entry+filelist[i].idx;
|
||||
for (i = 0; i < survivors; i++) {
|
||||
zip_entry_t *entry = za->entry + filelist[i].idx;
|
||||
|
||||
if ((ret=_zip_dirent_write(za, entry->changes ? entry->changes : entry->orig, ZIP_FL_CENTRAL)) < 0)
|
||||
if ((ret = _zip_dirent_write(za, entry->changes ? entry->changes : entry->orig, ZIP_FL_CENTRAL)) < 0)
|
||||
return -1;
|
||||
if (ret)
|
||||
is_zip64 = true;
|
||||
@ -168,7 +164,7 @@ _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivor
|
||||
|
||||
if (is_zip64) {
|
||||
_zip_buffer_put(buffer, EOCD64_MAGIC, 4);
|
||||
_zip_buffer_put_64(buffer, EOCD64LEN-12);
|
||||
_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);
|
||||
@ -179,7 +175,7 @@ _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivor
|
||||
_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_64(buffer, offset + size);
|
||||
_zip_buffer_put_32(buffer, 1);
|
||||
}
|
||||
|
||||
@ -218,11 +214,10 @@ _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivor
|
||||
|
||||
|
||||
zip_dirent_t *
|
||||
_zip_dirent_clone(const zip_dirent_t *sde)
|
||||
{
|
||||
_zip_dirent_clone(const zip_dirent_t *sde) {
|
||||
zip_dirent_t *tde;
|
||||
|
||||
if ((tde=(zip_dirent_t *)malloc(sizeof(*tde))) == NULL)
|
||||
if ((tde = (zip_dirent_t *)malloc(sizeof(*tde))) == NULL)
|
||||
return NULL;
|
||||
|
||||
if (sde)
|
||||
@ -238,8 +233,7 @@ _zip_dirent_clone(const zip_dirent_t *sde)
|
||||
|
||||
|
||||
void
|
||||
_zip_dirent_finalize(zip_dirent_t *zde)
|
||||
{
|
||||
_zip_dirent_finalize(zip_dirent_t *zde) {
|
||||
if (!zde->cloned || zde->changed & ZIP_DIRENT_FILENAME) {
|
||||
_zip_string_free(zde->filename);
|
||||
zde->filename = NULL;
|
||||
@ -263,8 +257,7 @@ _zip_dirent_finalize(zip_dirent_t *zde)
|
||||
|
||||
|
||||
void
|
||||
_zip_dirent_free(zip_dirent_t *zde)
|
||||
{
|
||||
_zip_dirent_free(zip_dirent_t *zde) {
|
||||
if (zde == NULL)
|
||||
return;
|
||||
|
||||
@ -274,15 +267,14 @@ _zip_dirent_free(zip_dirent_t *zde)
|
||||
|
||||
|
||||
void
|
||||
_zip_dirent_init(zip_dirent_t *de)
|
||||
{
|
||||
_zip_dirent_init(zip_dirent_t *de) {
|
||||
de->changed = 0;
|
||||
de->local_extra_fields_read = 0;
|
||||
de->cloned = 0;
|
||||
|
||||
de->crc_valid = true;
|
||||
de->version_madeby = 20 | (ZIP_OPSYS_DEFAULT << 8);
|
||||
de->version_needed = 20; /* 2.0 */
|
||||
de->version_madeby = 63 | (ZIP_OPSYS_DEFAULT << 8);
|
||||
de->version_needed = 10; /* 1.0 */
|
||||
de->bitflags = 0;
|
||||
de->comp_method = ZIP_CM_DEFAULT;
|
||||
de->last_mod = 0;
|
||||
@ -296,16 +288,15 @@ _zip_dirent_init(zip_dirent_t *de)
|
||||
de->int_attrib = 0;
|
||||
de->ext_attrib = ZIP_EXT_ATTRIB_DEFAULT;
|
||||
de->offset = 0;
|
||||
de->compression_level = 0;
|
||||
de->encryption_method = ZIP_EM_NONE;
|
||||
de->password = NULL;
|
||||
}
|
||||
|
||||
|
||||
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))
|
||||
_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 true;
|
||||
|
||||
return false;
|
||||
@ -313,11 +304,10 @@ _zip_dirent_needs_zip64(const zip_dirent_t *de, zip_flags_t flags)
|
||||
|
||||
|
||||
zip_dirent_t *
|
||||
_zip_dirent_new(void)
|
||||
{
|
||||
_zip_dirent_new(void) {
|
||||
zip_dirent_t *de;
|
||||
|
||||
if ((de=(zip_dirent_t *)malloc(sizeof(*de))) == NULL)
|
||||
if ((de = (zip_dirent_t *)malloc(sizeof(*de))) == NULL)
|
||||
return NULL;
|
||||
|
||||
_zip_dirent_init(de);
|
||||
@ -336,8 +326,7 @@ _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_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, bool local, zip_error_t *error) {
|
||||
zip_uint8_t buf[CDENTRYSIZE];
|
||||
zip_uint16_t dostime, dosdate;
|
||||
zip_uint32_t size, variable_size;
|
||||
@ -396,7 +385,8 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
|
||||
zde->int_attrib = 0;
|
||||
zde->ext_attrib = 0;
|
||||
zde->offset = 0;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
comment_len = _zip_buffer_get_16(buffer);
|
||||
zde->disk_number = _zip_buffer_get_16(buffer);
|
||||
zde->int_attrib = _zip_buffer_get_16(buffer);
|
||||
@ -429,7 +419,7 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
|
||||
zde->extra_fields = NULL;
|
||||
zde->comment = NULL;
|
||||
|
||||
variable_size = (zip_uint32_t)filename_len+(zip_uint32_t)ef_len+(zip_uint32_t)comment_len;
|
||||
variable_size = (zip_uint32_t)filename_len + (zip_uint32_t)ef_len + (zip_uint32_t)comment_len;
|
||||
|
||||
if (from_buffer) {
|
||||
if (_zip_buffer_left(buffer) < variable_size) {
|
||||
@ -578,9 +568,6 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
|
||||
}
|
||||
|
||||
if (!_zip_dirent_process_winzip_aes(zde, error)) {
|
||||
if (!from_buffer) {
|
||||
_zip_buffer_free(buffer);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -591,8 +578,7 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
|
||||
|
||||
|
||||
static zip_string_t *
|
||||
_zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string_t *str)
|
||||
{
|
||||
_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;
|
||||
@ -627,8 +613,7 @@ _zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string
|
||||
|
||||
|
||||
static bool
|
||||
_zip_dirent_process_winzip_aes(zip_dirent_t *de, zip_error_t *error)
|
||||
{
|
||||
_zip_dirent_process_winzip_aes(zip_dirent_t *de, zip_error_t *error) {
|
||||
zip_uint16_t ef_len;
|
||||
zip_buffer_t *buffer;
|
||||
const zip_uint8_t *ef;
|
||||
@ -711,8 +696,7 @@ _zip_dirent_process_winzip_aes(zip_dirent_t *de, zip_error_t *error)
|
||||
|
||||
|
||||
zip_int32_t
|
||||
_zip_dirent_size(zip_source_t *src, zip_uint16_t flags, zip_error_t *error)
|
||||
{
|
||||
_zip_dirent_size(zip_source_t *src, zip_uint16_t flags, zip_error_t *error) {
|
||||
zip_int32_t size;
|
||||
bool local = (flags & ZIP_EF_LOCAL) != 0;
|
||||
int i;
|
||||
@ -730,7 +714,7 @@ _zip_dirent_size(zip_source_t *src, zip_uint16_t flags, zip_error_t *error)
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i=0; i<(local ? 2 : 3); i++) {
|
||||
for (i = 0; i < (local ? 2 : 3); i++) {
|
||||
size += _zip_buffer_get_16(buffer);
|
||||
}
|
||||
|
||||
@ -756,8 +740,7 @@ _zip_dirent_size(zip_source_t *src, zip_uint16_t flags, zip_error_t *error)
|
||||
*/
|
||||
|
||||
int
|
||||
_zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags)
|
||||
{
|
||||
_zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) {
|
||||
zip_uint16_t dostime, dosdate;
|
||||
zip_encoding_type_t com_enc, name_enc;
|
||||
zip_extra_field_t *ef;
|
||||
@ -774,9 +757,7 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags)
|
||||
name_enc = _zip_guess_encoding(de->filename, ZIP_ENCODING_UNKNOWN);
|
||||
com_enc = _zip_guess_encoding(de->comment, ZIP_ENCODING_UNKNOWN);
|
||||
|
||||
if ((name_enc == ZIP_ENCODING_UTF8_KNOWN && com_enc == ZIP_ENCODING_ASCII) ||
|
||||
(name_enc == ZIP_ENCODING_ASCII && com_enc == ZIP_ENCODING_UTF8_KNOWN) ||
|
||||
(name_enc == ZIP_ENCODING_UTF8_KNOWN && com_enc == ZIP_ENCODING_UTF8_KNOWN))
|
||||
if ((name_enc == ZIP_ENCODING_UTF8_KNOWN && com_enc == ZIP_ENCODING_ASCII) || (name_enc == ZIP_ENCODING_ASCII && com_enc == ZIP_ENCODING_UTF8_KNOWN) || (name_enc == ZIP_ENCODING_UTF8_KNOWN && com_enc == ZIP_ENCODING_UTF8_KNOWN))
|
||||
de->bitflags |= ZIP_GPBF_ENCODING_UTF_8;
|
||||
else {
|
||||
de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCODING_UTF_8;
|
||||
@ -785,7 +766,7 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags)
|
||||
if (ef == NULL)
|
||||
return -1;
|
||||
}
|
||||
if ((flags & ZIP_FL_LOCAL) == 0 && com_enc == ZIP_ENCODING_UTF8_KNOWN){
|
||||
if ((flags & ZIP_FL_LOCAL) == 0 && com_enc == ZIP_ENCODING_UTF8_KNOWN) {
|
||||
zip_extra_field_t *ef2 = _zip_ef_utf8(ZIP_EF_UTF_8_COMMENT, de->comment, &za->error);
|
||||
if (ef2 == NULL) {
|
||||
_zip_ef_free(ef);
|
||||
@ -797,14 +778,14 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags)
|
||||
}
|
||||
|
||||
if (de->encryption_method == ZIP_EM_NONE) {
|
||||
de->bitflags &= ~ZIP_GPBF_ENCRYPTED;
|
||||
de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCRYPTED;
|
||||
}
|
||||
else {
|
||||
de->bitflags |= ZIP_GPBF_ENCRYPTED;
|
||||
de->bitflags |= (zip_uint16_t)ZIP_GPBF_ENCRYPTED;
|
||||
}
|
||||
|
||||
is_really_zip64 = _zip_dirent_needs_zip64(de, flags);
|
||||
is_zip64 = (flags & (ZIP_FL_LOCAL|ZIP_FL_FORCE_ZIP64)) == (ZIP_FL_LOCAL|ZIP_FL_FORCE_ZIP64) || is_really_zip64;
|
||||
is_zip64 = (flags & (ZIP_FL_LOCAL | ZIP_FL_FORCE_ZIP64)) == (ZIP_FL_LOCAL | ZIP_FL_FORCE_ZIP64) || is_really_zip64;
|
||||
is_winzip_aes = de->encryption_method == ZIP_EM_AES_128 || de->encryption_method == ZIP_EM_AES_192 || de->encryption_method == ZIP_EM_AES_256;
|
||||
|
||||
if (is_zip64) {
|
||||
@ -862,7 +843,7 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags)
|
||||
|
||||
_zip_buffer_put_16(ef_buffer, 2);
|
||||
_zip_buffer_put(ef_buffer, "AE", 2);
|
||||
_zip_buffer_put_8(ef_buffer, (de->encryption_method & 0xff));
|
||||
_zip_buffer_put_8(ef_buffer, (zip_uint8_t)(de->encryption_method & 0xff));
|
||||
_zip_buffer_put_16(ef_buffer, (zip_uint16_t)de->comp_method);
|
||||
|
||||
if (!_zip_buffer_ok(ef_buffer)) {
|
||||
@ -890,7 +871,7 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags)
|
||||
_zip_buffer_put_16(buffer, (zip_uint16_t)(is_really_zip64 ? 45 : de->version_madeby));
|
||||
}
|
||||
_zip_buffer_put_16(buffer, (zip_uint16_t)(is_really_zip64 ? 45 : de->version_needed));
|
||||
_zip_buffer_put_16(buffer, de->bitflags&0xfff9); /* clear compression method specific flags */
|
||||
_zip_buffer_put_16(buffer, de->bitflags);
|
||||
if (is_winzip_aes) {
|
||||
_zip_buffer_put_16(buffer, ZIP_CM_WINZIP_AES);
|
||||
}
|
||||
@ -998,8 +979,7 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags)
|
||||
|
||||
|
||||
static time_t
|
||||
_zip_d2u_time(zip_uint16_t dtime, zip_uint16_t ddate)
|
||||
{
|
||||
_zip_d2u_time(zip_uint16_t dtime, zip_uint16_t ddate) {
|
||||
struct tm tm;
|
||||
|
||||
memset(&tm, 0, sizeof(tm));
|
||||
@ -1007,37 +987,36 @@ _zip_d2u_time(zip_uint16_t dtime, zip_uint16_t ddate)
|
||||
/* 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;
|
||||
tm.tm_year = ((ddate >> 9) & 127) + 1980 - 1900;
|
||||
tm.tm_mon = ((ddate >> 5) & 15) - 1;
|
||||
tm.tm_mday = ddate & 31;
|
||||
|
||||
tm.tm_hour = (dtime>>11)&31;
|
||||
tm.tm_min = (dtime>>5)&63;
|
||||
tm.tm_sec = (dtime<<1)&62;
|
||||
tm.tm_hour = (dtime >> 11) & 31;
|
||||
tm.tm_min = (dtime >> 5) & 63;
|
||||
tm.tm_sec = (dtime << 1) & 62;
|
||||
|
||||
return mktime(&tm);
|
||||
}
|
||||
|
||||
|
||||
static zip_extra_field_t *
|
||||
_zip_ef_utf8(zip_uint16_t id, zip_string_t *str, zip_error_t *error)
|
||||
{
|
||||
_zip_ef_utf8(zip_uint16_t id, zip_string_t *str, zip_error_t *error) {
|
||||
const zip_uint8_t *raw;
|
||||
zip_uint32_t len;
|
||||
zip_buffer_t *buffer;
|
||||
zip_extra_field_t *ef;
|
||||
|
||||
if ((raw=_zip_string_get(str, &len, ZIP_FL_ENC_RAW, NULL)) == NULL) {
|
||||
if ((raw = _zip_string_get(str, &len, ZIP_FL_ENC_RAW, NULL)) == NULL) {
|
||||
/* error already set */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (len+5 > ZIP_UINT16_MAX) {
|
||||
if (len + 5 > ZIP_UINT16_MAX) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0); /* TODO: better error code? */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((buffer = _zip_buffer_new(NULL, len+5)) == NULL) {
|
||||
if ((buffer = _zip_buffer_new(NULL, len + 5)) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
@ -1060,8 +1039,7 @@ _zip_ef_utf8(zip_uint16_t id, zip_string_t *str, zip_error_t *error)
|
||||
|
||||
|
||||
zip_dirent_t *
|
||||
_zip_get_dirent(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *error)
|
||||
{
|
||||
_zip_get_dirent(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *error) {
|
||||
if (error == NULL)
|
||||
error = &za->error;
|
||||
|
||||
@ -1086,11 +1064,8 @@ _zip_get_dirent(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *err
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
_zip_u2d_time(time_t intime, 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(&intime);
|
||||
@ -1098,8 +1073,44 @@ _zip_u2d_time(time_t intime, zip_uint16_t *dtime, zip_uint16_t *ddate)
|
||||
tm->tm_year = 80;
|
||||
}
|
||||
|
||||
*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));
|
||||
*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));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_zip_dirent_set_version_needed(zip_dirent_t *de, bool force_zip64) {
|
||||
zip_uint16_t length;
|
||||
|
||||
if (de->comp_method == ZIP_CM_LZMA) {
|
||||
de->version_needed = 63;
|
||||
return;
|
||||
}
|
||||
|
||||
if (de->comp_method == ZIP_CM_BZIP2) {
|
||||
de->version_needed = 46;
|
||||
return;
|
||||
}
|
||||
|
||||
if (force_zip64 || _zip_dirent_needs_zip64(de, 0)) {
|
||||
de->version_needed = 45;
|
||||
return;
|
||||
}
|
||||
|
||||
if (de->comp_method == ZIP_CM_DEFLATE || de->encryption_method == ZIP_EM_TRAD_PKWARE) {
|
||||
de->version_needed = 20;
|
||||
return;
|
||||
}
|
||||
|
||||
/* directory */
|
||||
if ((length = _zip_string_length(de->filename)) > 0) {
|
||||
if (de->filename->raw[length - 1] == '/') {
|
||||
de->version_needed = 20;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
de->version_needed = 10;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
zip_discard.c -- discard and free struct zip
|
||||
Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
@ -42,8 +42,7 @@
|
||||
corresponding file. */
|
||||
|
||||
void
|
||||
zip_discard(zip_t *za)
|
||||
{
|
||||
zip_discard(zip_t *za) {
|
||||
zip_uint64_t i;
|
||||
|
||||
if (za == NULL)
|
||||
@ -61,16 +60,18 @@ zip_discard(zip_t *za)
|
||||
_zip_hash_free(za->names);
|
||||
|
||||
if (za->entry) {
|
||||
for (i=0; i<za->nentry; i++)
|
||||
_zip_entry_finalize(za->entry+i);
|
||||
for (i = 0; i < za->nentry; i++)
|
||||
_zip_entry_finalize(za->entry + i);
|
||||
free(za->entry);
|
||||
}
|
||||
|
||||
for (i=0; i<za->nopen_source; i++) {
|
||||
for (i = 0; i < za->nopen_source; i++) {
|
||||
_zip_source_invalidate(za->open_source[i]);
|
||||
}
|
||||
free(za->open_source);
|
||||
|
||||
_zip_progress_free(za->progress);
|
||||
|
||||
zip_error_fini(&za->error);
|
||||
|
||||
free(za);
|
||||
|
@ -35,8 +35,7 @@
|
||||
#include "zipint.h"
|
||||
|
||||
void
|
||||
_zip_entry_finalize(zip_entry_t *e)
|
||||
{
|
||||
_zip_entry_finalize(zip_entry_t *e) {
|
||||
_zip_unchange_data(e);
|
||||
_zip_dirent_free(e->orig);
|
||||
_zip_dirent_free(e->changes);
|
||||
@ -44,8 +43,7 @@ _zip_entry_finalize(zip_entry_t *e)
|
||||
|
||||
|
||||
void
|
||||
_zip_entry_init(zip_entry_t *e)
|
||||
{
|
||||
_zip_entry_init(zip_entry_t *e) {
|
||||
e->orig = NULL;
|
||||
e->changes = NULL;
|
||||
e->source = NULL;
|
||||
|
@ -5,76 +5,16 @@
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
const char * const _zip_err_str[] = {
|
||||
"No error",
|
||||
"Multi-disk zip archives not supported",
|
||||
"Renaming temporary file failed",
|
||||
"Closing zip archive failed",
|
||||
"Seek error",
|
||||
"Read error",
|
||||
"Write error",
|
||||
"CRC error",
|
||||
"Containing zip archive was closed",
|
||||
"No such file",
|
||||
"File already exists",
|
||||
"Can't open file",
|
||||
"Failure to create temporary file",
|
||||
"Zlib error",
|
||||
"Malloc failure",
|
||||
"Entry has been changed",
|
||||
"Compression method not supported",
|
||||
"Premature end of file",
|
||||
"Invalid argument",
|
||||
"Not a zip archive",
|
||||
"Internal error",
|
||||
"Zip archive inconsistent",
|
||||
"Can't remove file",
|
||||
"Entry has been deleted",
|
||||
"Encryption method not supported",
|
||||
"Read-only archive",
|
||||
"No password provided",
|
||||
"Wrong password provided",
|
||||
"Operation not supported",
|
||||
"Resource still in use",
|
||||
"Tell error",
|
||||
const char *const _zip_err_str[] = {
|
||||
"No error", "Multi-disk zip archives not supported", "Renaming temporary file failed", "Closing zip archive failed", "Seek error", "Read error", "Write error", "CRC error", "Containing zip archive was closed", "No such file", "File already exists", "Can't open file", "Failure to create temporary file", "Zlib error", "Malloc failure", "Entry has been changed", "Compression method not supported", "Premature end of file", "Invalid argument", "Not a zip archive", "Internal error", "Zip archive inconsistent", "Can't remove file", "Entry has been deleted", "Encryption method not supported", "Read-only archive", "No password provided", "Wrong password provided", "Operation not supported", "Resource still in use", "Tell error", "Compressed data invalid",
|
||||
};
|
||||
|
||||
const int _zip_nerr_str = sizeof(_zip_err_str)/sizeof(_zip_err_str[0]);
|
||||
const int _zip_nerr_str = sizeof(_zip_err_str) / sizeof(_zip_err_str[0]);
|
||||
|
||||
#define N ZIP_ET_NONE
|
||||
#define S ZIP_ET_SYS
|
||||
#define Z ZIP_ET_ZLIB
|
||||
|
||||
const int _zip_err_type[] = {
|
||||
N,
|
||||
N,
|
||||
S,
|
||||
S,
|
||||
S,
|
||||
S,
|
||||
S,
|
||||
N,
|
||||
N,
|
||||
N,
|
||||
N,
|
||||
S,
|
||||
S,
|
||||
Z,
|
||||
N,
|
||||
N,
|
||||
N,
|
||||
N,
|
||||
N,
|
||||
N,
|
||||
N,
|
||||
N,
|
||||
S,
|
||||
N,
|
||||
N,
|
||||
N,
|
||||
N,
|
||||
N,
|
||||
N,
|
||||
N,
|
||||
S,
|
||||
N, N, S, S, S, S, S, N, N, N, N, S, S, Z, N, N, N, N, N, N, N, N, S, N, N, N, N, N, N, N, S, N,
|
||||
};
|
||||
|
@ -49,24 +49,21 @@ zip_error_code_zip(const zip_error_t *error) {
|
||||
|
||||
|
||||
ZIP_EXTERN void
|
||||
zip_error_fini(zip_error_t *err)
|
||||
{
|
||||
zip_error_fini(zip_error_t *err) {
|
||||
free(err->str);
|
||||
err->str = NULL;
|
||||
}
|
||||
|
||||
|
||||
ZIP_EXTERN void
|
||||
zip_error_init(zip_error_t *err)
|
||||
{
|
||||
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_with_code(zip_error_t *error, int ze) {
|
||||
zip_error_init(error);
|
||||
error->zip_err = ze;
|
||||
switch (zip_error_system_type(error)) {
|
||||
@ -91,8 +88,7 @@ zip_error_system_type(const zip_error_t *error) {
|
||||
|
||||
|
||||
void
|
||||
_zip_error_clear(zip_error_t *err)
|
||||
{
|
||||
_zip_error_clear(zip_error_t *err) {
|
||||
if (err == NULL)
|
||||
return;
|
||||
|
||||
@ -102,16 +98,18 @@ _zip_error_clear(zip_error_t *err)
|
||||
|
||||
|
||||
void
|
||||
_zip_error_copy(zip_error_t *dst, const zip_error_t *src)
|
||||
{
|
||||
_zip_error_copy(zip_error_t *dst, const zip_error_t *src) {
|
||||
if (dst == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
dst->zip_err = src->zip_err;
|
||||
dst->sys_err = src->sys_err;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_zip_error_get(const zip_error_t *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) {
|
||||
@ -124,8 +122,7 @@ _zip_error_get(const zip_error_t *err, int *zep, int *sep)
|
||||
|
||||
|
||||
void
|
||||
zip_error_set(zip_error_t *err, int ze, int se)
|
||||
{
|
||||
zip_error_set(zip_error_t *err, int ze, int se) {
|
||||
if (err) {
|
||||
err->zip_err = ze;
|
||||
err->sys_err = se;
|
||||
@ -134,22 +131,20 @@ zip_error_set(zip_error_t *err, int ze, int se)
|
||||
|
||||
|
||||
void
|
||||
_zip_error_set_from_source(zip_error_t *err, zip_source_t *src)
|
||||
{
|
||||
_zip_error_set_from_source(zip_error_t *err, zip_source_t *src) {
|
||||
_zip_error_copy(err, zip_source_error(src));
|
||||
}
|
||||
|
||||
|
||||
zip_int64_t
|
||||
zip_error_to_data(const zip_error_t *error, void *data, zip_uint64_t length)
|
||||
{
|
||||
zip_error_to_data(const zip_error_t *error, void *data, zip_uint64_t length) {
|
||||
int *e = (int *)data;
|
||||
|
||||
if (length < sizeof(int)*2) {
|
||||
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;
|
||||
return sizeof(int) * 2;
|
||||
}
|
||||
|
@ -36,8 +36,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN void
|
||||
zip_error_clear(zip_t *za)
|
||||
{
|
||||
zip_error_clear(zip_t *za) {
|
||||
if (za == NULL)
|
||||
return;
|
||||
|
||||
|
@ -37,21 +37,18 @@
|
||||
|
||||
|
||||
ZIP_EXTERN void
|
||||
zip_error_get(zip_t *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)
|
||||
{
|
||||
zip_get_error(zip_t *za) {
|
||||
return &za->error;
|
||||
}
|
||||
|
||||
|
||||
ZIP_EXTERN zip_error_t *
|
||||
zip_file_get_error(zip_file_t *f)
|
||||
{
|
||||
zip_file_get_error(zip_file_t *f) {
|
||||
return &f->error;
|
||||
}
|
||||
|
@ -36,8 +36,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_error_get_sys_type(int ze)
|
||||
{
|
||||
zip_error_get_sys_type(int ze) {
|
||||
if (ze < 0 || ze >= _zip_nerr_str)
|
||||
return 0;
|
||||
|
||||
|
@ -40,8 +40,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN const char *
|
||||
zip_error_strerror(zip_error_t *err)
|
||||
{
|
||||
zip_error_strerror(zip_error_t *err) {
|
||||
const char *zs, *ss;
|
||||
char buf[128], *s;
|
||||
|
||||
@ -72,14 +71,10 @@ zip_error_strerror(zip_error_t *err)
|
||||
if (ss == NULL)
|
||||
return zs;
|
||||
else {
|
||||
if ((s=(char *)malloc(strlen(ss)
|
||||
+ (zs ? strlen(zs)+2 : 0) + 1)) == NULL)
|
||||
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 ? ": " : ""),
|
||||
ss);
|
||||
sprintf(s, "%s%s%s", (zs ? zs : ""), (zs ? ": " : ""), ss);
|
||||
err->str = s;
|
||||
|
||||
return s;
|
||||
|
@ -41,8 +41,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_error_to_str(char *buf, zip_uint64_t len, int ze, int se)
|
||||
{
|
||||
zip_error_to_str(char *buf, zip_uint64_t len, int ze, int se) {
|
||||
const char *zs, *ss;
|
||||
|
||||
if (ze < 0 || ze >= _zip_nerr_str)
|
||||
@ -63,6 +62,5 @@ zip_error_to_str(char *buf, zip_uint64_t len, int ze, int se)
|
||||
ss = NULL;
|
||||
}
|
||||
|
||||
return snprintf(buf, len, "%s%s%s",
|
||||
zs, (ss ? ": " : ""), (ss ? ss : ""));
|
||||
return snprintf(buf, len, "%s%s%s", zs, (ss ? ": " : ""), (ss ? ss : ""));
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
zip_extra_field.c -- manipulate extra fields
|
||||
Copyright (C) 2012-2016 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2012-2017 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
@ -38,14 +38,13 @@
|
||||
|
||||
|
||||
zip_extra_field_t *
|
||||
_zip_ef_clone(const zip_extra_field_t *ef, zip_error_t *error)
|
||||
{
|
||||
_zip_ef_clone(const zip_extra_field_t *ef, zip_error_t *error) {
|
||||
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) {
|
||||
if ((def = _zip_ef_new(ef->id, ef->size, ef->data, ef->flags)) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
_zip_ef_free(head);
|
||||
return NULL;
|
||||
@ -65,15 +64,14 @@ _zip_ef_clone(const zip_extra_field_t *ef, zip_error_t *error)
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
_zip_ef_delete_by_id(zip_extra_field_t *ef, zip_uint16_t id, zip_uint16_t id_idx, zip_flags_t flags) {
|
||||
zip_extra_field_t *head, *prev;
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
head = ef;
|
||||
prev = NULL;
|
||||
for (; ef; ef=(prev ? prev->next : head)) {
|
||||
for (; ef; ef = (prev ? prev->next : head)) {
|
||||
if ((ef->flags & flags & ZIP_EF_BOTH) && ((ef->id == id) || (id == ZIP_EXTRA_FIELD_ALL))) {
|
||||
if (id_idx == ZIP_EXTRA_FIELD_ALL || i == id_idx) {
|
||||
ef->flags &= ~(flags & ZIP_EF_BOTH);
|
||||
@ -101,10 +99,8 @@ _zip_ef_delete_by_id(zip_extra_field_t *ef, zip_uint16_t id, zip_uint16_t id_idx
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
_zip_ef_free(zip_extra_field_t *ef)
|
||||
{
|
||||
_zip_ef_free(zip_extra_field_t *ef) {
|
||||
zip_extra_field_t *ef2;
|
||||
|
||||
while (ef) {
|
||||
@ -117,14 +113,13 @@ _zip_ef_free(zip_extra_field_t *ef)
|
||||
|
||||
|
||||
const zip_uint8_t *
|
||||
_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' };
|
||||
_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;
|
||||
for (; ef; ef=ef->next) {
|
||||
for (; ef; ef = ef->next) {
|
||||
if (ef->id == id && (ef->flags & flags & ZIP_EF_BOTH)) {
|
||||
if (i < id_idx) {
|
||||
i++;
|
||||
@ -146,23 +141,22 @@ _zip_ef_get_by_id(const zip_extra_field_t *ef, zip_uint16_t *lenp, zip_uint16_t
|
||||
|
||||
|
||||
zip_extra_field_t *
|
||||
_zip_ef_merge(zip_extra_field_t *to, zip_extra_field_t *from)
|
||||
{
|
||||
_zip_ef_merge(zip_extra_field_t *to, zip_extra_field_t *from) {
|
||||
zip_extra_field_t *ef2, *tt, *tail;
|
||||
int duplicate;
|
||||
|
||||
if (to == NULL)
|
||||
return from;
|
||||
|
||||
for (tail=to; tail->next; tail=tail->next)
|
||||
for (tail = to; tail->next; tail = tail->next)
|
||||
;
|
||||
|
||||
for (; from; from=ef2) {
|
||||
for (; from; from = ef2) {
|
||||
ef2 = from->next;
|
||||
|
||||
duplicate = 0;
|
||||
for (tt=to; tt; tt=tt->next) {
|
||||
if (tt->id == from->id && tt->size == from->size && memcmp(tt->data, from->data, tt->size) == 0) {
|
||||
for (tt = to; tt; tt = tt->next) {
|
||||
if (tt->id == from->id && tt->size == from->size && (tt->size == 0 || memcmp(tt->data, from->data, tt->size) == 0)) {
|
||||
tt->flags |= (from->flags & ZIP_EF_BOTH);
|
||||
duplicate = 1;
|
||||
break;
|
||||
@ -181,11 +175,10 @@ _zip_ef_merge(zip_extra_field_t *to, zip_extra_field_t *from)
|
||||
|
||||
|
||||
zip_extra_field_t *
|
||||
_zip_ef_new(zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, zip_flags_t flags)
|
||||
{
|
||||
_zip_ef_new(zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, zip_flags_t flags) {
|
||||
zip_extra_field_t *ef;
|
||||
|
||||
if ((ef=(zip_extra_field_t *)malloc(sizeof(*ef))) == NULL)
|
||||
if ((ef = (zip_extra_field_t *)malloc(sizeof(*ef))) == NULL)
|
||||
return NULL;
|
||||
|
||||
ef->next = NULL;
|
||||
@ -193,7 +186,7 @@ _zip_ef_new(zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, zip_fla
|
||||
ef->id = id;
|
||||
ef->size = size;
|
||||
if (size > 0) {
|
||||
if ((ef->data=(zip_uint8_t *)_zip_memdup(data, size, NULL)) == NULL) {
|
||||
if ((ef->data = (zip_uint8_t *)_zip_memdup(data, size, NULL)) == NULL) {
|
||||
free(ef);
|
||||
return NULL;
|
||||
}
|
||||
@ -206,8 +199,7 @@ _zip_ef_new(zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, zip_fla
|
||||
|
||||
|
||||
bool
|
||||
_zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_extra_field_t **ef_head_p, zip_error_t *error)
|
||||
{
|
||||
_zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_extra_field_t **ef_head_p, zip_error_t *error) {
|
||||
zip_buffer_t *buffer;
|
||||
zip_extra_field_t *ef, *ef2, *ef_head;
|
||||
|
||||
@ -233,7 +225,7 @@ _zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((ef2=_zip_ef_new(fid, flen, ef_data, flags)) == NULL) {
|
||||
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);
|
||||
@ -276,8 +268,7 @@ _zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_
|
||||
|
||||
|
||||
zip_extra_field_t *
|
||||
_zip_ef_remove_internal(zip_extra_field_t *ef)
|
||||
{
|
||||
_zip_ef_remove_internal(zip_extra_field_t *ef) {
|
||||
zip_extra_field_t *ef_head;
|
||||
zip_extra_field_t *prev, *next;
|
||||
|
||||
@ -306,14 +297,13 @@ _zip_ef_remove_internal(zip_extra_field_t *ef)
|
||||
|
||||
|
||||
zip_uint16_t
|
||||
_zip_ef_size(const zip_extra_field_t *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) {
|
||||
for (; ef; ef = ef->next) {
|
||||
if (ef->flags & flags & ZIP_EF_BOTH)
|
||||
size = (zip_uint16_t)(size+4+ef->size);
|
||||
size = (zip_uint16_t)(size + 4 + ef->size);
|
||||
}
|
||||
|
||||
return size;
|
||||
@ -321,8 +311,7 @@ _zip_ef_size(const zip_extra_field_t *ef, zip_flags_t flags)
|
||||
|
||||
|
||||
int
|
||||
_zip_ef_write(zip_t *za, const zip_extra_field_t *ef, zip_flags_t flags)
|
||||
{
|
||||
_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));
|
||||
|
||||
@ -330,7 +319,7 @@ _zip_ef_write(zip_t *za, const zip_extra_field_t *ef, zip_flags_t flags)
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (; ef; ef=ef->next) {
|
||||
for (; ef; ef = ef->next) {
|
||||
if (ef->flags & flags & ZIP_EF_BOTH) {
|
||||
_zip_buffer_set_offset(buffer, 0);
|
||||
_zip_buffer_put_16(buffer, ef->id);
|
||||
@ -359,8 +348,7 @@ _zip_ef_write(zip_t *za, const zip_extra_field_t *ef, zip_flags_t flags)
|
||||
|
||||
|
||||
int
|
||||
_zip_read_local_ef(zip_t *za, zip_uint64_t idx)
|
||||
{
|
||||
_zip_read_local_ef(zip_t *za, zip_uint64_t idx) {
|
||||
zip_entry_t *e;
|
||||
unsigned char b[4];
|
||||
zip_buffer_t *buffer;
|
||||
@ -371,7 +359,7 @@ _zip_read_local_ef(zip_t *za, zip_uint64_t idx)
|
||||
return -1;
|
||||
}
|
||||
|
||||
e = za->entry+idx;
|
||||
e = za->entry + idx;
|
||||
|
||||
if (e->orig == NULL || e->orig->local_extra_fields_read)
|
||||
return 0;
|
||||
|
@ -36,8 +36,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_file_extra_field_delete(zip_t *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) {
|
||||
zip_dirent_t *de;
|
||||
|
||||
if ((flags & ZIP_EF_BOTH) == 0) {
|
||||
@ -69,8 +68,7 @@ zip_file_extra_field_delete(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_idx, zi
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
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)
|
||||
{
|
||||
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) {
|
||||
zip_dirent_t *de;
|
||||
|
||||
if ((flags & ZIP_EF_BOTH) == 0) {
|
||||
@ -102,9 +100,8 @@ zip_file_extra_field_delete_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_i
|
||||
|
||||
|
||||
ZIP_EXTERN const zip_uint8_t *
|
||||
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' };
|
||||
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'};
|
||||
|
||||
zip_dirent_t *de;
|
||||
zip_extra_field_t *ef;
|
||||
@ -115,7 +112,7 @@ zip_file_extra_field_get(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_u
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((de=_zip_get_dirent(za, idx, flags, &za->error)) == NULL)
|
||||
if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL)
|
||||
return NULL;
|
||||
|
||||
if (flags & ZIP_FL_LOCAL)
|
||||
@ -123,7 +120,7 @@ zip_file_extra_field_get(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_u
|
||||
return NULL;
|
||||
|
||||
i = 0;
|
||||
for (ef=de->extra_fields; ef; ef=ef->next) {
|
||||
for (ef = de->extra_fields; ef; ef = ef->next) {
|
||||
if (ef->flags & flags & ZIP_EF_BOTH) {
|
||||
if (i < ef_idx) {
|
||||
i++;
|
||||
@ -143,13 +140,11 @@ zip_file_extra_field_get(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_u
|
||||
|
||||
zip_error_set(&za->error, ZIP_ER_NOENT, 0);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
|
||||
ZIP_EXTERN const zip_uint8_t *
|
||||
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)
|
||||
{
|
||||
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) {
|
||||
zip_dirent_t *de;
|
||||
|
||||
if ((flags & ZIP_EF_BOTH) == 0) {
|
||||
@ -157,7 +152,7 @@ zip_file_extra_field_get_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((de=_zip_get_dirent(za, idx, flags, &za->error)) == NULL)
|
||||
if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL)
|
||||
return NULL;
|
||||
|
||||
if (flags & ZIP_FL_LOCAL)
|
||||
@ -169,8 +164,7 @@ zip_file_extra_field_get_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id,
|
||||
|
||||
|
||||
ZIP_EXTERN zip_int16_t
|
||||
zip_file_extra_fields_count(zip_t *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) {
|
||||
zip_dirent_t *de;
|
||||
zip_extra_field_t *ef;
|
||||
zip_uint16_t n;
|
||||
@ -180,7 +174,7 @@ zip_file_extra_fields_count(zip_t *za, zip_uint64_t idx, zip_flags_t flags)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((de=_zip_get_dirent(za, idx, flags, &za->error)) == NULL)
|
||||
if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL)
|
||||
return -1;
|
||||
|
||||
if (flags & ZIP_FL_LOCAL)
|
||||
@ -188,7 +182,7 @@ zip_file_extra_fields_count(zip_t *za, zip_uint64_t idx, zip_flags_t flags)
|
||||
return -1;
|
||||
|
||||
n = 0;
|
||||
for (ef=de->extra_fields; ef; ef=ef->next)
|
||||
for (ef = de->extra_fields; ef; ef = ef->next)
|
||||
if (ef->flags & flags & ZIP_EF_BOTH)
|
||||
n++;
|
||||
|
||||
@ -197,8 +191,7 @@ zip_file_extra_fields_count(zip_t *za, zip_uint64_t idx, zip_flags_t flags)
|
||||
|
||||
|
||||
ZIP_EXTERN zip_int16_t
|
||||
zip_file_extra_fields_count_by_id(zip_t *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) {
|
||||
zip_dirent_t *de;
|
||||
zip_extra_field_t *ef;
|
||||
zip_uint16_t n;
|
||||
@ -208,7 +201,7 @@ zip_file_extra_fields_count_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_i
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((de=_zip_get_dirent(za, idx, flags, &za->error)) == NULL)
|
||||
if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL)
|
||||
return -1;
|
||||
|
||||
if (flags & ZIP_FL_LOCAL)
|
||||
@ -216,7 +209,7 @@ zip_file_extra_fields_count_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_i
|
||||
return -1;
|
||||
|
||||
n = 0;
|
||||
for (ef=de->extra_fields; ef; ef=ef->next)
|
||||
for (ef = de->extra_fields; ef; ef = ef->next)
|
||||
if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH))
|
||||
n++;
|
||||
|
||||
@ -225,8 +218,7 @@ zip_file_extra_fields_count_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_i
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
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)
|
||||
{
|
||||
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) {
|
||||
zip_dirent_t *de;
|
||||
zip_uint16_t ls, cs;
|
||||
zip_extra_field_t *ef, *ef_prev, *ef_new;
|
||||
@ -260,7 +252,7 @@ zip_file_extra_field_set(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_ui
|
||||
i = 0;
|
||||
found = 0;
|
||||
|
||||
for (; ef; ef=ef->next) {
|
||||
for (; ef; ef = ef->next) {
|
||||
if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH)) {
|
||||
if (i == ef_idx) {
|
||||
found = 1;
|
||||
@ -295,7 +287,7 @@ zip_file_extra_field_set(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_ui
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((ef_new=_zip_ef_new(ef_id, len, data, flags)) == NULL) {
|
||||
if ((ef_new = _zip_ef_new(ef_id, len, data, flags)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
@ -327,10 +319,8 @@ zip_file_extra_field_set(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_ui
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
_zip_file_extra_field_prepare_for_change(zip_t *za, zip_uint64_t idx)
|
||||
{
|
||||
_zip_file_extra_field_prepare_for_change(zip_t *za, zip_uint64_t idx) {
|
||||
zip_entry_t *e;
|
||||
|
||||
if (idx >= za->nentry) {
|
||||
@ -338,7 +328,7 @@ _zip_file_extra_field_prepare_for_change(zip_t *za, zip_uint64_t idx)
|
||||
return -1;
|
||||
}
|
||||
|
||||
e = za->entry+idx;
|
||||
e = za->entry + idx;
|
||||
|
||||
if (e->changes && (e->changes->changed & ZIP_DIRENT_EXTRA_FIELD))
|
||||
return 0;
|
||||
@ -349,18 +339,17 @@ _zip_file_extra_field_prepare_for_change(zip_t *za, zip_uint64_t idx)
|
||||
}
|
||||
|
||||
if (e->changes == NULL) {
|
||||
if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) {
|
||||
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
|
||||
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)
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -38,8 +38,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_fclose(zip_file_t *zf)
|
||||
{
|
||||
zip_fclose(zip_file_t *zf) {
|
||||
int ret;
|
||||
|
||||
if (zf->src)
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
zip_fdopen.c -- open read-only archive from file descriptor
|
||||
Copyright (C) 2009-2016 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2009-2017 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
@ -39,15 +39,14 @@
|
||||
|
||||
|
||||
ZIP_EXTERN zip_t *
|
||||
zip_fdopen(int fd_orig, int _flags, int *zep)
|
||||
{
|
||||
zip_fdopen(int fd_orig, int _flags, int *zep) {
|
||||
int fd;
|
||||
FILE *fp;
|
||||
zip_t *za;
|
||||
zip_source_t *src;
|
||||
struct zip_error error;
|
||||
|
||||
if (_flags < 0 || (_flags & ZIP_TRUNCATE)) {
|
||||
if (_flags < 0 || (_flags & ~(ZIP_CHECKCONS | ZIP_RDONLY))) {
|
||||
_zip_set_open_error(zep, NULL, ZIP_ER_INVAL);
|
||||
return NULL;
|
||||
}
|
||||
@ -55,12 +54,12 @@ zip_fdopen(int fd_orig, int _flags, int *zep)
|
||||
/* 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) {
|
||||
if ((fd = dup(fd_orig)) < 0) {
|
||||
_zip_set_open_error(zep, NULL, ZIP_ER_OPEN);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((fp=fdopen(fd, "rb")) == NULL) {
|
||||
if ((fp = fdopen(fd, "rb")) == NULL) {
|
||||
close(fd);
|
||||
_zip_set_open_error(zep, NULL, ZIP_ER_OPEN);
|
||||
return NULL;
|
||||
|
@ -42,8 +42,7 @@
|
||||
*/
|
||||
|
||||
ZIP_EXTERN zip_int64_t
|
||||
zip_file_add(zip_t *za, const char *name, zip_source_t *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);
|
||||
return -1;
|
||||
|
@ -36,8 +36,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN void
|
||||
zip_file_error_clear(zip_file_t *zf)
|
||||
{
|
||||
zip_file_error_clear(zip_file_t *zf) {
|
||||
if (zf == NULL)
|
||||
return;
|
||||
|
||||
|
@ -36,7 +36,6 @@
|
||||
|
||||
|
||||
ZIP_EXTERN void
|
||||
zip_file_error_get(zip_file_t *zf, int *zep, int *sep)
|
||||
{
|
||||
zip_file_error_get(zip_file_t *zf, int *zep, int *sep) {
|
||||
_zip_error_get(&zf->error, zep, sep);
|
||||
}
|
||||
|
@ -37,16 +37,15 @@
|
||||
/* lenp is 32 bit because converted comment can be longer than ZIP_UINT16_MAX */
|
||||
|
||||
ZIP_EXTERN const char *
|
||||
zip_file_get_comment(zip_t *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) {
|
||||
zip_dirent_t *de;
|
||||
zip_uint32_t len;
|
||||
const zip_uint8_t *str;
|
||||
|
||||
if ((de=_zip_get_dirent(za, idx, flags, NULL)) == NULL)
|
||||
if ((de = _zip_get_dirent(za, idx, flags, NULL)) == NULL)
|
||||
return NULL;
|
||||
|
||||
if ((str=_zip_string_get(de->comment, &len, flags, &za->error)) == NULL)
|
||||
if ((str = _zip_string_get(de->comment, &len, flags, &za->error)) == NULL)
|
||||
return NULL;
|
||||
|
||||
if (lenp)
|
||||
|
@ -34,11 +34,10 @@
|
||||
#include "zipint.h"
|
||||
|
||||
int
|
||||
zip_file_get_external_attributes(zip_t *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) {
|
||||
zip_dirent_t *de;
|
||||
|
||||
if ((de=_zip_get_dirent(za, idx, flags, NULL)) == NULL)
|
||||
if ((de = _zip_get_dirent(za, idx, flags, NULL)) == NULL)
|
||||
return -1;
|
||||
|
||||
if (opsys)
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
zip_file_get_offset.c -- get offset of file data in archive.
|
||||
Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
@ -35,8 +35,8 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
@ -48,11 +48,15 @@
|
||||
*/
|
||||
|
||||
zip_uint64_t
|
||||
_zip_file_get_offset(const zip_t *za, zip_uint64_t idx, zip_error_t *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;
|
||||
|
||||
if (za->entry[idx].orig == NULL) {
|
||||
zip_error_set(error, ZIP_ER_INTERNAL, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
offset = za->entry[idx].orig->offset;
|
||||
|
||||
if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) {
|
||||
@ -61,13 +65,56 @@ _zip_file_get_offset(const zip_t *za, zip_uint64_t idx, zip_error_t *error)
|
||||
}
|
||||
|
||||
/* TODO: cache? */
|
||||
if ((size=_zip_dirent_size(za->src, 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_INT64_MAX) {
|
||||
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;
|
||||
}
|
||||
|
||||
zip_uint64_t
|
||||
_zip_file_get_end(const zip_t *za, zip_uint64_t index, zip_error_t *error) {
|
||||
zip_uint64_t offset;
|
||||
zip_dirent_t *entry;
|
||||
|
||||
if ((offset = _zip_file_get_offset(za, index, error)) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
entry = za->entry[index].orig;
|
||||
|
||||
if (offset + entry->comp_size < offset || offset + entry->comp_size > ZIP_INT64_MAX) {
|
||||
zip_error_set(error, ZIP_ER_SEEK, EFBIG);
|
||||
return 0;
|
||||
}
|
||||
offset += entry->comp_size;
|
||||
|
||||
if (entry->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
|
||||
zip_uint8_t buf[4];
|
||||
if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) {
|
||||
_zip_error_set_from_source(error, za->src);
|
||||
return 0;
|
||||
}
|
||||
if (zip_source_read(za->src, buf, 4) != 4) {
|
||||
_zip_error_set_from_source(error, za->src);
|
||||
return 0;
|
||||
}
|
||||
if (memcmp(buf, DATADES_MAGIC, 4) == 0) {
|
||||
offset += 4;
|
||||
}
|
||||
offset += 12;
|
||||
if (_zip_dirent_needs_zip64(entry, 0)) {
|
||||
offset += 8;
|
||||
}
|
||||
if (offset > ZIP_INT64_MAX) {
|
||||
zip_error_set(error, ZIP_ER_SEEK, EFBIG);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
@ -38,8 +38,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_file_rename(zip_t *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;
|
||||
|
||||
@ -53,11 +52,11 @@ zip_file_rename(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((old_name=zip_get_name(za, idx, 0)) == NULL)
|
||||
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] == '/');
|
||||
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);
|
||||
|
@ -36,8 +36,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_file_replace(zip_t *za, zip_uint64_t idx, zip_source_t *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);
|
||||
return -1;
|
||||
@ -50,12 +49,10 @@ zip_file_replace(zip_t *za, zip_uint64_t idx, zip_source_t *source, zip_flags_t
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */
|
||||
|
||||
zip_int64_t
|
||||
_zip_file_replace(zip_t *za, zip_uint64_t idx, const char *name, zip_source_t *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)) {
|
||||
@ -72,7 +69,7 @@ _zip_file_replace(zip_t *za, zip_uint64_t idx, const char *name, zip_source_t *s
|
||||
|
||||
if (i == -1) {
|
||||
/* create and use new entry, used by zip_add */
|
||||
if ((i=_zip_add_entry(za)) < 0)
|
||||
if ((i = _zip_add_entry(za)) < 0)
|
||||
return -1;
|
||||
}
|
||||
idx = (zip_uint64_t)i;
|
||||
@ -80,7 +77,7 @@ _zip_file_replace(zip_t *za, zip_uint64_t idx, const char *name, zip_source_t *s
|
||||
|
||||
if (name && _zip_set_name(za, idx, name, flags) != 0) {
|
||||
if (za->nentry != za_nentry_prev) {
|
||||
_zip_entry_finalize(za->entry+idx);
|
||||
_zip_entry_finalize(za->entry + idx);
|
||||
za->nentry = za_nentry_prev;
|
||||
}
|
||||
return -1;
|
||||
@ -88,11 +85,11 @@ _zip_file_replace(zip_t *za, zip_uint64_t idx, const char *name, zip_source_t *s
|
||||
|
||||
/* does not change any name related data, so we can do it here;
|
||||
* needed for a double add of the same file name */
|
||||
_zip_unchange_data(za->entry+idx);
|
||||
_zip_unchange_data(za->entry + idx);
|
||||
|
||||
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) {
|
||||
if ((za->entry[idx].changes = _zip_dirent_clone(za->entry[idx].orig)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
@ -38,9 +38,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_file_set_comment(zip_t *za, zip_uint64_t idx,
|
||||
const char *comment, zip_uint16_t len, zip_flags_t flags)
|
||||
{
|
||||
zip_file_set_comment(zip_t *za, zip_uint64_t idx, const char *comment, zip_uint16_t len, zip_flags_t flags) {
|
||||
zip_entry_t *e;
|
||||
zip_string_t *cstr;
|
||||
int changed;
|
||||
@ -59,7 +57,7 @@ zip_file_set_comment(zip_t *za, zip_uint64_t idx,
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
if ((cstr=_zip_string_new((const zip_uint8_t *)comment, len, flags, &za->error)) == NULL)
|
||||
if ((cstr = _zip_string_new((const zip_uint8_t *)comment, len, flags, &za->error)) == NULL)
|
||||
return -1;
|
||||
if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED)
|
||||
cstr->encoding = ZIP_ENCODING_UTF8_KNOWN;
|
||||
@ -67,7 +65,7 @@ zip_file_set_comment(zip_t *za, zip_uint64_t idx,
|
||||
else
|
||||
cstr = NULL;
|
||||
|
||||
e = za->entry+idx;
|
||||
e = za->entry + idx;
|
||||
|
||||
if (e->changes) {
|
||||
_zip_string_free(e->changes->comment);
|
||||
@ -82,7 +80,7 @@ zip_file_set_comment(zip_t *za, zip_uint64_t idx,
|
||||
|
||||
if (changed) {
|
||||
if (e->changes == NULL) {
|
||||
if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) {
|
||||
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
_zip_string_free(cstr);
|
||||
return -1;
|
||||
|
@ -34,8 +34,7 @@
|
||||
#include "zipint.h"
|
||||
|
||||
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)
|
||||
{
|
||||
zip_file_set_external_attributes(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_uint8_t opsys, zip_uint32_t attributes) {
|
||||
zip_entry_t *e;
|
||||
int changed;
|
||||
zip_uint8_t unchanged_opsys;
|
||||
@ -49,16 +48,16 @@ zip_file_set_external_attributes(zip_t *za, zip_uint64_t idx, zip_flags_t flags,
|
||||
return -1;
|
||||
}
|
||||
|
||||
e = za->entry+idx;
|
||||
e = za->entry + idx;
|
||||
|
||||
unchanged_opsys = (e->orig ? (zip_uint8_t)(e->orig->version_madeby>>8) : (zip_uint8_t)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);
|
||||
|
||||
if (changed) {
|
||||
if (e->changes == NULL) {
|
||||
if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) {
|
||||
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
@ -33,8 +33,8 @@
|
||||
|
||||
#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_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;
|
||||
|
||||
@ -46,13 +46,13 @@ ZIP_EXTERN int zip_file_set_mtime(zip_t *za, zip_uint64_t idx, time_t mtime, zip
|
||||
return -1;
|
||||
}
|
||||
|
||||
e = za->entry+idx;
|
||||
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) {
|
||||
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
@ -36,7 +36,6 @@
|
||||
|
||||
|
||||
ZIP_EXTERN const char *
|
||||
zip_file_strerror(zip_file_t *zf)
|
||||
{
|
||||
zip_file_strerror(zip_file_t *zf) {
|
||||
return zip_error_strerror(&zf->error);
|
||||
}
|
||||
|
@ -37,10 +37,8 @@
|
||||
#include "zipint.h"
|
||||
|
||||
|
||||
|
||||
int
|
||||
_zip_filerange_crc(zip_source_t *src, zip_uint64_t start, zip_uint64_t len, uLong *crcp, zip_error_t *error)
|
||||
{
|
||||
_zip_filerange_crc(zip_source_t *src, zip_uint64_t start, zip_uint64_t len, uLong *crcp, zip_error_t *error) {
|
||||
Bytef buf[BUFSIZE];
|
||||
zip_int64_t n;
|
||||
|
||||
|
@ -36,11 +36,10 @@
|
||||
|
||||
|
||||
ZIP_EXTERN zip_file_t *
|
||||
zip_fopen(zip_t *za, const char *fname, zip_flags_t flags)
|
||||
{
|
||||
zip_fopen(zip_t *za, const char *fname, zip_flags_t flags) {
|
||||
zip_int64_t idx;
|
||||
|
||||
if ((idx=zip_name_locate(za, fname, flags)) < 0)
|
||||
if ((idx = zip_name_locate(za, fname, flags)) < 0)
|
||||
return NULL;
|
||||
|
||||
return zip_fopen_index_encrypted(za, (zip_uint64_t)idx, flags, za->default_password);
|
||||
|
@ -36,11 +36,10 @@
|
||||
|
||||
|
||||
ZIP_EXTERN zip_file_t *
|
||||
zip_fopen_encrypted(zip_t *za, const char *fname, zip_flags_t flags, const char *password)
|
||||
{
|
||||
zip_fopen_encrypted(zip_t *za, const char *fname, zip_flags_t flags, const char *password) {
|
||||
zip_int64_t idx;
|
||||
|
||||
if ((idx=zip_name_locate(za, fname, flags)) < 0)
|
||||
if ((idx = zip_name_locate(za, fname, flags)) < 0)
|
||||
return NULL;
|
||||
|
||||
return zip_fopen_index_encrypted(za, (zip_uint64_t)idx, flags, password);
|
||||
|
@ -39,7 +39,6 @@
|
||||
|
||||
|
||||
ZIP_EXTERN zip_file_t *
|
||||
zip_fopen_index(zip_t *za, zip_uint64_t index, zip_flags_t flags)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
@ -41,13 +41,11 @@ static zip_file_t *_zip_file_new(zip_t *za);
|
||||
|
||||
|
||||
ZIP_EXTERN zip_file_t *
|
||||
zip_fopen_index_encrypted(zip_t *za, zip_uint64_t index, zip_flags_t flags,
|
||||
const char *password)
|
||||
{
|
||||
zip_fopen_index_encrypted(zip_t *za, zip_uint64_t index, zip_flags_t flags, const char *password) {
|
||||
zip_file_t *zf;
|
||||
zip_source_t *src;
|
||||
|
||||
if ((src=_zip_source_zip_new(za, za, index, flags, 0, 0, password)) == NULL)
|
||||
if ((src = _zip_source_zip_new(za, za, index, flags, 0, 0, password)) == NULL)
|
||||
return NULL;
|
||||
|
||||
if (zip_source_open(src) < 0) {
|
||||
@ -56,7 +54,7 @@ zip_fopen_index_encrypted(zip_t *za, zip_uint64_t index, zip_flags_t flags,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((zf=_zip_file_new(za)) == NULL) {
|
||||
if ((zf = _zip_file_new(za)) == NULL) {
|
||||
zip_source_free(src);
|
||||
return NULL;
|
||||
}
|
||||
@ -68,11 +66,10 @@ zip_fopen_index_encrypted(zip_t *za, zip_uint64_t index, zip_flags_t flags,
|
||||
|
||||
|
||||
static zip_file_t *
|
||||
_zip_file_new(zip_t *za)
|
||||
{
|
||||
_zip_file_new(zip_t *za) {
|
||||
zip_file_t *zf;
|
||||
|
||||
if ((zf=(zip_file_t *)malloc(sizeof(struct zip_file))) == NULL) {
|
||||
if ((zf = (zip_file_t *)malloc(sizeof(struct zip_file))) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -36,8 +36,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN zip_int64_t
|
||||
zip_fread(zip_file_t *zf, void *outbuf, zip_uint64_t toread)
|
||||
{
|
||||
zip_fread(zip_file_t *zf, void *outbuf, zip_uint64_t toread) {
|
||||
zip_int64_t n;
|
||||
|
||||
if (!zf)
|
||||
@ -54,7 +53,7 @@ zip_fread(zip_file_t *zf, void *outbuf, zip_uint64_t toread)
|
||||
if ((zf->eof) || (toread == 0))
|
||||
return 0;
|
||||
|
||||
if ((n=zip_source_read(zf->src, outbuf, toread)) < 0) {
|
||||
if ((n = zip_source_read(zf->src, outbuf, toread)) < 0) {
|
||||
_zip_error_set_from_source(&zf->error, zf->src);
|
||||
return -1;
|
||||
}
|
||||
|
@ -38,8 +38,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN const char *
|
||||
zip_get_archive_comment(zip_t *za, int *lenp, zip_flags_t flags)
|
||||
{
|
||||
zip_get_archive_comment(zip_t *za, int *lenp, zip_flags_t flags) {
|
||||
zip_string_t *comment;
|
||||
zip_uint32_t len;
|
||||
const zip_uint8_t *str;
|
||||
@ -49,7 +48,7 @@ zip_get_archive_comment(zip_t *za, int *lenp, zip_flags_t flags)
|
||||
else
|
||||
comment = za->comment_changes;
|
||||
|
||||
if ((str=_zip_string_get(comment, &len, flags, &za->error)) == NULL)
|
||||
if ((str = _zip_string_get(comment, &len, flags, &za->error)) == NULL)
|
||||
return NULL;
|
||||
|
||||
if (lenp)
|
||||
|
@ -36,8 +36,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_get_archive_flag(zip_t *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;
|
||||
|
||||
fl = (flags & ZIP_FL_UNCHANGED) ? za->flags : za->ch_flags;
|
||||
|
@ -36,20 +36,21 @@
|
||||
|
||||
|
||||
zip_encryption_implementation
|
||||
_zip_get_encryption_implementation(zip_uint16_t em, int operation)
|
||||
{
|
||||
_zip_get_encryption_implementation(zip_uint16_t em, int operation) {
|
||||
switch (em) {
|
||||
case ZIP_EM_TRAD_PKWARE:
|
||||
if (operation == ZIP_CODEC_ENCODE) {
|
||||
return NULL;
|
||||
}
|
||||
return zip_source_pkware;
|
||||
/*
|
||||
|
||||
#if defined(HAVE_CRYPTO)
|
||||
case ZIP_EM_AES_128:
|
||||
case ZIP_EM_AES_192:
|
||||
case ZIP_EM_AES_256:
|
||||
return operation == ZIP_CODEC_DECODE ? zip_source_winzip_aes_decode : zip_source_winzip_aes_encode;
|
||||
*/
|
||||
#endif
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
@ -37,12 +37,11 @@
|
||||
|
||||
|
||||
ZIP_EXTERN const char *
|
||||
zip_get_file_comment(zip_t *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;
|
||||
|
||||
if ((s=zip_file_get_comment(za, idx, &len, (zip_flags_t)flags)) != NULL) {
|
||||
if ((s = zip_file_get_comment(za, idx, &len, (zip_flags_t)flags)) != NULL) {
|
||||
if (lenp)
|
||||
*lenp = (int)len;
|
||||
}
|
||||
|
@ -38,22 +38,20 @@
|
||||
|
||||
|
||||
ZIP_EXTERN const char *
|
||||
zip_get_name(zip_t *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(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *error)
|
||||
{
|
||||
_zip_get_name(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *error) {
|
||||
zip_dirent_t *de;
|
||||
const zip_uint8_t *str;
|
||||
|
||||
if ((de=_zip_get_dirent(za, idx, flags, error)) == NULL)
|
||||
if ((de = _zip_get_dirent(za, idx, flags, error)) == NULL)
|
||||
return NULL;
|
||||
|
||||
if ((str=_zip_string_get(de->filename, NULL, flags, error)) == NULL)
|
||||
if ((str = _zip_string_get(de->filename, NULL, flags, error)) == NULL)
|
||||
return NULL;
|
||||
|
||||
return (const char *)str;
|
||||
|
@ -36,8 +36,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN zip_int64_t
|
||||
zip_get_num_entries(zip_t *za, zip_flags_t flags)
|
||||
{
|
||||
zip_get_num_entries(zip_t *za, zip_flags_t flags) {
|
||||
zip_uint64_t n;
|
||||
|
||||
if (za == NULL)
|
||||
@ -45,7 +44,7 @@ zip_get_num_entries(zip_t *za, zip_flags_t flags)
|
||||
|
||||
if (flags & ZIP_FL_UNCHANGED) {
|
||||
n = za->nentry;
|
||||
while (n>0 && za->entry[n-1].orig == NULL)
|
||||
while (n > 0 && za->entry[n - 1].orig == NULL)
|
||||
--n;
|
||||
return (zip_int64_t)n;
|
||||
}
|
||||
|
@ -38,8 +38,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_get_num_files(zip_t *za)
|
||||
{
|
||||
zip_get_num_files(zip_t *za) {
|
||||
if (za == NULL)
|
||||
return -1;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
zip_hash.c -- hash table string -> uint64
|
||||
Copyright (C) 2015-2016 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2015-2017 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
@ -31,98 +31,179 @@
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "zipint.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "zipint.h"
|
||||
|
||||
/* parameter for the string hash function */
|
||||
#define HASH_MULTIPLIER 33
|
||||
#define HASH_START 5381
|
||||
|
||||
/* hash table's fill ratio is kept between these by doubling/halfing its size as necessary */
|
||||
#define HASH_MAX_FILL .75
|
||||
#define HASH_MIN_FILL .01
|
||||
|
||||
/* but hash table size is kept between these */
|
||||
#define HASH_MIN_SIZE 256
|
||||
#define HASH_MAX_SIZE 0x80000000ul
|
||||
|
||||
struct zip_hash_entry {
|
||||
const zip_uint8_t *name;
|
||||
zip_int64_t orig_index;
|
||||
zip_int64_t current_index;
|
||||
struct zip_hash_entry *next;
|
||||
zip_uint32_t hash_value;
|
||||
};
|
||||
typedef struct zip_hash_entry zip_hash_entry_t;
|
||||
|
||||
struct zip_hash {
|
||||
zip_uint16_t table_size;
|
||||
zip_uint32_t table_size;
|
||||
zip_uint64_t nentries;
|
||||
zip_hash_entry_t **table;
|
||||
};
|
||||
|
||||
|
||||
/* free list of entries */
|
||||
static void
|
||||
free_list(zip_hash_entry_t *entry) {
|
||||
while (entry != NULL) {
|
||||
zip_hash_entry_t *next = entry->next;
|
||||
free(entry);
|
||||
entry = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* compute hash of string, full 32 bit value */
|
||||
static zip_uint32_t
|
||||
hash_string(const zip_uint8_t *name) {
|
||||
zip_uint64_t value = HASH_START;
|
||||
|
||||
if (name == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (*name != 0) {
|
||||
value = (zip_uint64_t)(((value * HASH_MULTIPLIER) + (zip_uint8_t)*name) % 0x100000000ul);
|
||||
name++;
|
||||
}
|
||||
|
||||
return (zip_uint32_t)value;
|
||||
}
|
||||
|
||||
|
||||
/* resize hash table; new_size must be a power of 2, can be larger or smaller than current size */
|
||||
static bool
|
||||
hash_resize(zip_hash_t *hash, zip_uint32_t new_size, zip_error_t *error) {
|
||||
zip_hash_entry_t **new_table;
|
||||
|
||||
if (new_size == hash->table_size) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((new_table = (zip_hash_entry_t **)calloc(new_size, sizeof(zip_hash_entry_t *))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hash->nentries > 0) {
|
||||
zip_uint32_t i;
|
||||
|
||||
for (i = 0; i < hash->table_size; i++) {
|
||||
zip_hash_entry_t *entry = hash->table[i];
|
||||
while (entry) {
|
||||
zip_hash_entry_t *next = entry->next;
|
||||
|
||||
zip_uint32_t new_index = entry->hash_value % new_size;
|
||||
|
||||
entry->next = new_table[new_index];
|
||||
new_table[new_index] = entry;
|
||||
|
||||
entry = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(hash->table);
|
||||
hash->table = new_table;
|
||||
hash->table_size = new_size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static zip_uint32_t
|
||||
size_for_capacity(zip_uint64_t capacity) {
|
||||
double needed_size = capacity / HASH_MAX_FILL;
|
||||
zip_uint32_t v;
|
||||
|
||||
if (needed_size > ZIP_UINT32_MAX) {
|
||||
v = ZIP_UINT32_MAX;
|
||||
}
|
||||
else {
|
||||
v = (zip_uint32_t)needed_size;
|
||||
}
|
||||
|
||||
if (v > HASH_MAX_SIZE) {
|
||||
return HASH_MAX_SIZE;
|
||||
}
|
||||
|
||||
/* From Bit Twiddling Hacks by Sean Eron Anderson <seander@cs.stanford.edu>
|
||||
(http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2). */
|
||||
|
||||
v--;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
v++;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
zip_hash_t *
|
||||
_zip_hash_new(zip_uint16_t table_size, zip_error_t *error)
|
||||
{
|
||||
_zip_hash_new(zip_error_t *error) {
|
||||
zip_hash_t *hash;
|
||||
|
||||
if (table_size == 0) {
|
||||
zip_error_set(error, ZIP_ER_INTERNAL, 0);
|
||||
if ((hash = (zip_hash_t *)malloc(sizeof(zip_hash_t))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((hash=(zip_hash_t *)malloc(sizeof(zip_hash_t))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
hash->table_size = table_size;
|
||||
if ((hash->table=(zip_hash_entry_t**)calloc(table_size, sizeof(zip_hash_entry_t *))) == NULL) {
|
||||
free(hash);
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
hash->table_size = 0;
|
||||
hash->nentries = 0;
|
||||
hash->table = NULL;
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
static void
|
||||
_free_list(zip_hash_entry_t *entry)
|
||||
{
|
||||
zip_hash_entry_t *next;
|
||||
do {
|
||||
next = entry->next;
|
||||
free(entry);
|
||||
entry = next;
|
||||
} while (entry != NULL);
|
||||
}
|
||||
|
||||
void
|
||||
_zip_hash_free(zip_hash_t *hash)
|
||||
{
|
||||
zip_uint16_t i;
|
||||
_zip_hash_free(zip_hash_t *hash) {
|
||||
zip_uint32_t i;
|
||||
|
||||
if (hash == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i=0; i<hash->table_size; i++) {
|
||||
if (hash->table != NULL) {
|
||||
for (i = 0; i < hash->table_size; i++) {
|
||||
if (hash->table[i] != NULL) {
|
||||
_free_list(hash->table[i]);
|
||||
free_list(hash->table[i]);
|
||||
}
|
||||
}
|
||||
free(hash->table);
|
||||
}
|
||||
free(hash);
|
||||
}
|
||||
|
||||
static zip_uint16_t
|
||||
_hash_string(const zip_uint8_t *name, zip_uint16_t size)
|
||||
{
|
||||
#define HASH_MULTIPLIER 33
|
||||
zip_uint16_t value = 5381;
|
||||
|
||||
if (name == NULL)
|
||||
return 0;
|
||||
|
||||
while (*name != 0) {
|
||||
value = (zip_uint16_t)(((value * HASH_MULTIPLIER) + (zip_uint8_t)*name) % size);
|
||||
name++;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* insert into hash, return error on existence or memory issues */
|
||||
bool
|
||||
_zip_hash_add(zip_hash_t *hash, const zip_uint8_t *name, zip_uint64_t index, zip_flags_t flags, zip_error_t *error)
|
||||
{
|
||||
zip_uint16_t hash_value;
|
||||
_zip_hash_add(zip_hash_t *hash, const zip_uint8_t *name, zip_uint64_t index, zip_flags_t flags, zip_error_t *error) {
|
||||
zip_uint32_t hash_value, table_index;
|
||||
zip_hash_entry_t *entry;
|
||||
|
||||
if (hash == NULL || name == NULL || index > ZIP_INT64_MAX) {
|
||||
@ -130,9 +211,17 @@ _zip_hash_add(zip_hash_t *hash, const zip_uint8_t *name, zip_uint64_t index, zip
|
||||
return false;
|
||||
}
|
||||
|
||||
hash_value = _hash_string(name, hash->table_size);
|
||||
for (entry = hash->table[hash_value]; entry != NULL; entry = entry->next) {
|
||||
if (strcmp((const char *)name, (const char *)entry->name) == 0) {
|
||||
if (hash->table_size == 0) {
|
||||
if (!hash_resize(hash, HASH_MIN_SIZE, error)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
hash_value = hash_string(name);
|
||||
table_index = hash_value % hash->table_size;
|
||||
|
||||
for (entry = hash->table[table_index]; entry != NULL; entry = entry->next) {
|
||||
if (entry->hash_value == hash_value && strcmp((const char *)name, (const char *)entry->name) == 0) {
|
||||
if (((flags & ZIP_FL_UNCHANGED) && entry->orig_index != -1) || entry->current_index != -1) {
|
||||
zip_error_set(error, ZIP_ER_EXISTS, 0);
|
||||
return false;
|
||||
@ -144,14 +233,21 @@ _zip_hash_add(zip_hash_t *hash, const zip_uint8_t *name, zip_uint64_t index, zip
|
||||
}
|
||||
|
||||
if (entry == NULL) {
|
||||
if ((entry=(zip_hash_entry_t *)malloc(sizeof(zip_hash_entry_t))) == NULL) {
|
||||
if ((entry = (zip_hash_entry_t *)malloc(sizeof(zip_hash_entry_t))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return false;
|
||||
}
|
||||
entry->name = name;
|
||||
entry->next = hash->table[hash_value];
|
||||
hash->table[hash_value] = entry;
|
||||
entry->next = hash->table[table_index];
|
||||
hash->table[table_index] = entry;
|
||||
entry->hash_value = hash_value;
|
||||
entry->orig_index = -1;
|
||||
hash->nentries++;
|
||||
if (hash->nentries > hash->table_size * HASH_MAX_FILL && hash->table_size < HASH_MAX_SIZE) {
|
||||
if (!hash_resize(hash, hash->table_size * 2, error)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & ZIP_FL_UNCHANGED) {
|
||||
@ -162,11 +258,11 @@ _zip_hash_add(zip_hash_t *hash, const zip_uint8_t *name, zip_uint64_t index, zip
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* remove entry from hash, error if not found */
|
||||
bool
|
||||
_zip_hash_delete(zip_hash_t *hash, const zip_uint8_t *name, zip_error_t *error)
|
||||
{
|
||||
zip_uint16_t hash_value;
|
||||
_zip_hash_delete(zip_hash_t *hash, const zip_uint8_t *name, zip_error_t *error) {
|
||||
zip_uint32_t hash_value, index;
|
||||
zip_hash_entry_t *entry, *previous;
|
||||
|
||||
if (hash == NULL || name == NULL) {
|
||||
@ -174,19 +270,27 @@ _zip_hash_delete(zip_hash_t *hash, const zip_uint8_t *name, zip_error_t *error)
|
||||
return false;
|
||||
}
|
||||
|
||||
hash_value = _hash_string(name, hash->table_size);
|
||||
if (hash->nentries > 0) {
|
||||
hash_value = hash_string(name);
|
||||
index = hash_value % hash->table_size;
|
||||
previous = NULL;
|
||||
entry = hash->table[hash_value];
|
||||
entry = hash->table[index];
|
||||
while (entry) {
|
||||
if (strcmp((const char *)name, (const char *)entry->name) == 0) {
|
||||
if (entry->hash_value == hash_value && strcmp((const char *)name, (const char *)entry->name) == 0) {
|
||||
if (entry->orig_index == -1) {
|
||||
if (previous) {
|
||||
previous->next = entry->next;
|
||||
}
|
||||
else {
|
||||
hash->table[hash_value] = entry->next;
|
||||
hash->table[index] = entry->next;
|
||||
}
|
||||
free(entry);
|
||||
hash->nentries--;
|
||||
if (hash->nentries < hash->table_size * HASH_MIN_FILL && hash->table_size > HASH_MIN_SIZE) {
|
||||
if (!hash_resize(hash, hash->table_size / 2, error)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
entry->current_index = -1;
|
||||
@ -195,17 +299,18 @@ _zip_hash_delete(zip_hash_t *hash, const zip_uint8_t *name, zip_error_t *error)
|
||||
}
|
||||
previous = entry;
|
||||
entry = entry->next;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
zip_error_set(error, ZIP_ER_NOENT, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* find value for entry in hash, -1 if not found */
|
||||
zip_int64_t
|
||||
_zip_hash_lookup(zip_hash_t *hash, const zip_uint8_t *name, zip_flags_t flags, zip_error_t *error)
|
||||
{
|
||||
zip_uint16_t hash_value;
|
||||
_zip_hash_lookup(zip_hash_t *hash, const zip_uint8_t *name, zip_flags_t flags, zip_error_t *error) {
|
||||
zip_uint32_t hash_value, index;
|
||||
zip_hash_entry_t *entry;
|
||||
|
||||
if (hash == NULL || name == NULL) {
|
||||
@ -213,8 +318,10 @@ _zip_hash_lookup(zip_hash_t *hash, const zip_uint8_t *name, zip_flags_t flags, z
|
||||
return -1;
|
||||
}
|
||||
|
||||
hash_value = _hash_string(name, hash->table_size);
|
||||
for (entry = hash->table[hash_value]; entry != NULL; entry = entry->next) {
|
||||
if (hash->nentries > 0) {
|
||||
hash_value = hash_string(name);
|
||||
index = hash_value % hash->table_size;
|
||||
for (entry = hash->table[index]; entry != NULL; entry = entry->next) {
|
||||
if (strcmp((const char *)name, (const char *)entry->name) == 0) {
|
||||
if (flags & ZIP_FL_UNCHANGED) {
|
||||
if (entry->orig_index != -1) {
|
||||
@ -229,15 +336,38 @@ _zip_hash_lookup(zip_hash_t *hash, const zip_uint8_t *name, zip_flags_t flags, z
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
zip_error_set(error, ZIP_ER_NOENT, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
_zip_hash_revert(zip_hash_t *hash)
|
||||
{
|
||||
zip_uint16_t i;
|
||||
|
||||
bool
|
||||
_zip_hash_reserve_capacity(zip_hash_t *hash, zip_uint64_t capacity, zip_error_t *error) {
|
||||
zip_uint32_t new_size;
|
||||
|
||||
if (capacity == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
new_size = size_for_capacity(capacity);
|
||||
|
||||
if (new_size <= hash->table_size) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!hash_resize(hash, new_size, error)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
_zip_hash_revert(zip_hash_t *hash, zip_error_t *error) {
|
||||
zip_uint32_t i;
|
||||
zip_hash_entry_t *entry, *previous;
|
||||
|
||||
for (i = 0; i < hash->table_size; i++) {
|
||||
@ -256,6 +386,7 @@ _zip_hash_revert(zip_hash_t *hash)
|
||||
entry = entry->next;
|
||||
/* previous does not change */
|
||||
free(p);
|
||||
hash->nentries--;
|
||||
}
|
||||
else {
|
||||
entry->current_index = entry->orig_index;
|
||||
@ -264,4 +395,16 @@ _zip_hash_revert(zip_hash_t *hash)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hash->nentries < hash->table_size * HASH_MIN_FILL && hash->table_size > HASH_MIN_SIZE) {
|
||||
zip_uint32_t new_size = hash->table_size / 2;
|
||||
while (hash->nentries < new_size * HASH_MIN_FILL && new_size > HASH_MIN_SIZE) {
|
||||
new_size /= 2;
|
||||
}
|
||||
if (!hash_resize(hash, new_size, error)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -37,8 +37,7 @@
|
||||
#include "zipint.h"
|
||||
|
||||
int
|
||||
_zip_read(zip_source_t *src, zip_uint8_t *b, zip_uint64_t length, zip_error_t *error)
|
||||
{
|
||||
_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) {
|
||||
@ -61,8 +60,7 @@ _zip_read(zip_source_t *src, zip_uint8_t *b, zip_uint64_t length, zip_error_t *e
|
||||
|
||||
|
||||
zip_uint8_t *
|
||||
_zip_read_data(zip_buffer_t *buffer, zip_source_t *src, size_t length, bool nulp, zip_error_t *error)
|
||||
{
|
||||
_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) {
|
||||
@ -96,7 +94,7 @@ _zip_read_data(zip_buffer_t *buffer, zip_source_t *src, size_t length, bool nulp
|
||||
zip_uint8_t *o;
|
||||
/* replace any in-string NUL characters with spaces */
|
||||
r[length] = 0;
|
||||
for (o=r; o<r+length; o++)
|
||||
for (o = r; o < r + length; o++)
|
||||
if (*o == '\0')
|
||||
*o = ' ';
|
||||
}
|
||||
@ -106,12 +104,11 @@ _zip_read_data(zip_buffer_t *buffer, zip_source_t *src, size_t length, bool nulp
|
||||
|
||||
|
||||
zip_string_t *
|
||||
_zip_read_string(zip_buffer_t *buffer, zip_source_t *src, zip_uint16_t len, bool nulp, zip_error_t *error)
|
||||
{
|
||||
_zip_read_string(zip_buffer_t *buffer, zip_source_t *src, zip_uint16_t len, bool nulp, zip_error_t *error) {
|
||||
zip_uint8_t *raw;
|
||||
zip_string_t *s;
|
||||
|
||||
if ((raw=_zip_read_data(buffer, src, len, nulp, error)) == NULL)
|
||||
if ((raw = _zip_read_data(buffer, src, len, nulp, error)) == NULL)
|
||||
return NULL;
|
||||
|
||||
s = _zip_string_new(raw, len, ZIP_FL_ENC_GUESS, error);
|
||||
@ -121,8 +118,7 @@ _zip_read_string(zip_buffer_t *buffer, zip_source_t *src, zip_uint16_t len, bool
|
||||
|
||||
|
||||
int
|
||||
_zip_write(zip_t *za, const void *data, zip_uint64_t length)
|
||||
{
|
||||
_zip_write(zip_t *za, const void *data, zip_uint64_t length) {
|
||||
zip_int64_t n;
|
||||
|
||||
if ((n = zip_source_write(za->src, data, length)) < 0) {
|
||||
|
@ -38,8 +38,7 @@
|
||||
|
||||
|
||||
void *
|
||||
_zip_memdup(const void *mem, size_t len, zip_error_t *error)
|
||||
{
|
||||
_zip_memdup(const void *mem, size_t len, zip_error_t *error) {
|
||||
void *ret;
|
||||
|
||||
if (len == 0)
|
||||
|
@ -41,15 +41,13 @@
|
||||
|
||||
|
||||
ZIP_EXTERN zip_int64_t
|
||||
zip_name_locate(zip_t *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(zip_t *za, const char *fname, zip_flags_t flags, zip_error_t *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;
|
||||
zip_uint64_t i;
|
||||
@ -62,11 +60,11 @@ _zip_name_locate(zip_t *za, const char *fname, zip_flags_t flags, zip_error_t *e
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags & (ZIP_FL_NOCASE|ZIP_FL_NODIR|ZIP_FL_ENC_CP437)) {
|
||||
if (flags & (ZIP_FL_NOCASE | ZIP_FL_NODIR | ZIP_FL_ENC_CP437)) {
|
||||
/* can't use hash table */
|
||||
cmp = (flags & ZIP_FL_NOCASE) ? strcasecmp : strcmp;
|
||||
|
||||
for (i=0; i<za->nentry; i++) {
|
||||
for (i = 0; i < za->nentry; i++) {
|
||||
fn = _zip_get_name(za, i, flags, error);
|
||||
|
||||
/* newly added (partially filled) entry or error */
|
||||
@ -76,7 +74,7 @@ _zip_name_locate(zip_t *za, const char *fname, zip_flags_t flags, zip_error_t *e
|
||||
if (flags & ZIP_FL_NODIR) {
|
||||
p = strrchr(fn, '/');
|
||||
if (p)
|
||||
fn = p+1;
|
||||
fn = p + 1;
|
||||
}
|
||||
|
||||
if (cmp(fname, fn) == 0) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
zip_new.c -- create and init struct zip
|
||||
Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
@ -42,8 +42,7 @@
|
||||
the new struct. */
|
||||
|
||||
zip_t *
|
||||
_zip_new(zip_error_t *error)
|
||||
{
|
||||
_zip_new(zip_error_t *error) {
|
||||
zip_t *za;
|
||||
|
||||
za = (zip_t *)malloc(sizeof(struct zip));
|
||||
@ -52,7 +51,7 @@ _zip_new(zip_error_t *error)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((za->names = _zip_hash_new(ZIP_HASH_TABLE_SIZE, error)) == NULL) {
|
||||
if ((za->names = _zip_hash_new(error)) == NULL) {
|
||||
free(za);
|
||||
return NULL;
|
||||
}
|
||||
@ -68,7 +67,7 @@ _zip_new(zip_error_t *error)
|
||||
za->entry = NULL;
|
||||
za->nopen_source = za->nopen_source_alloc = 0;
|
||||
za->open_source = NULL;
|
||||
za->progress_callback = NULL;
|
||||
za->progress = NULL;
|
||||
|
||||
return za;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
zip_open.c -- open zip archive by name
|
||||
Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
@ -32,11 +32,11 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
@ -58,8 +58,7 @@ static zip_cdir_t *_zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip
|
||||
|
||||
|
||||
ZIP_EXTERN zip_t *
|
||||
zip_open(const char *fn, int _flags, int *zep)
|
||||
{
|
||||
zip_open(const char *fn, int _flags, int *zep) {
|
||||
zip_t *za;
|
||||
zip_source_t *src;
|
||||
struct zip_error error;
|
||||
@ -84,8 +83,7 @@ zip_open(const char *fn, int _flags, int *zep)
|
||||
|
||||
|
||||
ZIP_EXTERN zip_t *
|
||||
zip_open_from_source(zip_source_t *src, int _flags, zip_error_t *error)
|
||||
{
|
||||
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;
|
||||
|
||||
@ -112,7 +110,7 @@ zip_open_from_source(zip_source_t *src, int _flags, zip_error_t *error)
|
||||
flags |= ZIP_RDONLY;
|
||||
}
|
||||
|
||||
if ((flags & (ZIP_RDONLY|ZIP_TRUNCATE)) == (ZIP_RDONLY|ZIP_TRUNCATE)) {
|
||||
if ((flags & (ZIP_RDONLY | ZIP_TRUNCATE)) == (ZIP_RDONLY | ZIP_TRUNCATE)) {
|
||||
zip_error_set(error, ZIP_ER_RDONLY, 0);
|
||||
return NULL;
|
||||
}
|
||||
@ -157,16 +155,9 @@ zip_open_from_source(zip_source_t *src, int _flags, zip_error_t *error)
|
||||
}
|
||||
}
|
||||
|
||||
ZIP_EXTERN void
|
||||
zip_register_progress_callback(zip_t *za, zip_progress_callback_t progress_callback)
|
||||
{
|
||||
za->progress_callback = progress_callback;
|
||||
}
|
||||
|
||||
|
||||
zip_t *
|
||||
_zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error)
|
||||
{
|
||||
_zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error) {
|
||||
zip_t *za;
|
||||
zip_cdir_t *cdir;
|
||||
struct zip_stat st;
|
||||
@ -185,7 +176,7 @@ _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error)
|
||||
|
||||
/* treat empty files as empty archives */
|
||||
if (len == 0) {
|
||||
if ((za=_zip_allocate_new(src, flags, error)) == NULL) {
|
||||
if ((za = _zip_allocate_new(src, flags, error)) == NULL) {
|
||||
zip_source_free(src);
|
||||
return NULL;
|
||||
}
|
||||
@ -193,7 +184,7 @@ _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error)
|
||||
return za;
|
||||
}
|
||||
|
||||
if ((za=_zip_allocate_new(src, flags, error)) == NULL) {
|
||||
if ((za = _zip_allocate_new(src, flags, error)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -212,6 +203,8 @@ _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error)
|
||||
|
||||
free(cdir);
|
||||
|
||||
_zip_hash_reserve_capacity(za->names, za->nentry, &za->error);
|
||||
|
||||
for (idx = 0; idx < za->nentry; idx++) {
|
||||
const zip_uint8_t *name = _zip_string_get(za->entry[idx].orig->filename, NULL, 0, error);
|
||||
if (name == NULL) {
|
||||
@ -239,8 +232,7 @@ _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error)
|
||||
|
||||
|
||||
void
|
||||
_zip_set_open_error(int *zep, const zip_error_t *err, int ze)
|
||||
{
|
||||
_zip_set_open_error(int *zep, const zip_error_t *err, int ze) {
|
||||
if (err) {
|
||||
ze = zip_error_code_zip(err);
|
||||
if (zip_error_system_type(err) == ZIP_ET_SYS) {
|
||||
@ -260,8 +252,7 @@ _zip_set_open_error(int *zep, const zip_error_t *err, int ze)
|
||||
entries, or NULL if unsuccessful. */
|
||||
|
||||
static zip_cdir_t *
|
||||
_zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_error_t *error)
|
||||
{
|
||||
_zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_error_t *error) {
|
||||
zip_cdir_t *cd;
|
||||
zip_uint16_t comment_len;
|
||||
zip_uint64_t i, left;
|
||||
@ -315,7 +306,7 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_err
|
||||
}
|
||||
|
||||
if (comment_len) {
|
||||
if ((cd->comment=_zip_string_new(_zip_buffer_get(buffer, comment_len), comment_len, ZIP_FL_ENC_GUESS, error)) == NULL) {
|
||||
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;
|
||||
}
|
||||
@ -356,7 +347,7 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_err
|
||||
}
|
||||
|
||||
left = (zip_uint64_t)cd->size;
|
||||
i=0;
|
||||
i = 0;
|
||||
while (left > 0) {
|
||||
bool grown = false;
|
||||
zip_int64_t entry_size;
|
||||
@ -377,7 +368,7 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_err
|
||||
grown = true;
|
||||
}
|
||||
|
||||
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) {
|
||||
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) {
|
||||
if (grown && zip_error_code_zip(error) == ZIP_ER_NOZIP) {
|
||||
zip_error_set(error, ZIP_ER_INCONS, 0);
|
||||
}
|
||||
@ -407,7 +398,6 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_err
|
||||
|
||||
if (offset < 0) {
|
||||
_zip_error_set_from_source(error, za->src);
|
||||
_zip_buffer_free(cd_buffer);
|
||||
_zip_cdir_free(cd);
|
||||
return NULL;
|
||||
}
|
||||
@ -434,8 +424,7 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_err
|
||||
difference between the lowest and the highest fileposition reached */
|
||||
|
||||
static zip_int64_t
|
||||
_zip_checkcons(zip_t *za, zip_cdir_t *cd, zip_error_t *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;
|
||||
@ -448,7 +437,7 @@ _zip_checkcons(zip_t *za, zip_cdir_t *cd, zip_error_t *error)
|
||||
else
|
||||
min = max = 0;
|
||||
|
||||
for (i=0; i<cd->nentry; i++) {
|
||||
for (i = 0; i < cd->nentry; i++) {
|
||||
if (cd->entry[i].orig->offset < min)
|
||||
min = cd->entry[i].orig->offset;
|
||||
if (min > (zip_uint64_t)cd->offset) {
|
||||
@ -456,8 +445,7 @@ _zip_checkcons(zip_t *za, zip_cdir_t *cd, zip_error_t *error)
|
||||
return -1;
|
||||
}
|
||||
|
||||
j = cd->entry[i].orig->offset + cd->entry[i].orig->comp_size
|
||||
+ _zip_string_length(cd->entry[i].orig->filename) + LENTRYSIZE;
|
||||
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) {
|
||||
@ -488,7 +476,7 @@ _zip_checkcons(zip_t *za, zip_cdir_t *cd, zip_error_t *error)
|
||||
_zip_dirent_finalize(&temp);
|
||||
}
|
||||
|
||||
return (max-min) < ZIP_INT64_MAX ? (zip_int64_t)(max-min) : ZIP_INT64_MAX;
|
||||
return (max - min) < ZIP_INT64_MAX ? (zip_int64_t)(max - min) : ZIP_INT64_MAX;
|
||||
}
|
||||
|
||||
|
||||
@ -497,25 +485,20 @@ _zip_checkcons(zip_t *za, zip_cdir_t *cd, zip_error_t *error)
|
||||
Return 0 if they are consistent, -1 if not. */
|
||||
|
||||
static int
|
||||
_zip_headercomp(const zip_dirent_t *central, const zip_dirent_t *local)
|
||||
{
|
||||
_zip_headercomp(const zip_dirent_t *central, const zip_dirent_t *local) {
|
||||
if ((central->version_needed < local->version_needed)
|
||||
#if 0
|
||||
/* some zip-files have different values in local
|
||||
and global headers for the bitflags */
|
||||
|| (central->bitflags != local->bitflags)
|
||||
#endif
|
||||
|| (central->comp_method != local->comp_method)
|
||||
|| (central->last_mod != local->last_mod)
|
||||
|| !_zip_string_equal(central->filename, local->filename))
|
||||
|| (central->comp_method != local->comp_method) || (central->last_mod != local->last_mod) || !_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)) {
|
||||
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.
|
||||
This is in violation of the appnote. */
|
||||
if (((local->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) == 0
|
||||
|| local->crc != 0 || local->comp_size != 0 || local->uncomp_size != 0))
|
||||
if (((local->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) == 0 || local->crc != 0 || local->comp_size != 0 || local->uncomp_size != 0))
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -524,8 +507,7 @@ _zip_headercomp(const zip_dirent_t *central, const zip_dirent_t *local)
|
||||
|
||||
|
||||
static zip_t *
|
||||
_zip_allocate_new(zip_source_t *src, unsigned int flags, zip_error_t *error)
|
||||
{
|
||||
_zip_allocate_new(zip_source_t *src, unsigned int flags, zip_error_t *error) {
|
||||
zip_t *za;
|
||||
|
||||
if ((za = _zip_new(error)) == NULL) {
|
||||
@ -546,8 +528,7 @@ _zip_allocate_new(zip_source_t *src, unsigned int flags, zip_error_t *error)
|
||||
* tests for file existence
|
||||
*/
|
||||
static exists_t
|
||||
_zip_file_exists(zip_source_t *src, zip_error_t *error)
|
||||
{
|
||||
_zip_file_exists(zip_source_t *src, zip_error_t *error) {
|
||||
struct zip_stat st;
|
||||
|
||||
zip_stat_init(&st);
|
||||
@ -565,8 +546,7 @@ _zip_file_exists(zip_source_t *src, zip_error_t *error)
|
||||
|
||||
|
||||
static zip_cdir_t *
|
||||
_zip_find_central_dir(zip_t *za, zip_uint64_t len)
|
||||
{
|
||||
_zip_find_central_dir(zip_t *za, zip_uint64_t len) {
|
||||
zip_cdir_t *cdir, *cdirnew;
|
||||
zip_uint8_t *match;
|
||||
zip_int64_t buf_offset;
|
||||
@ -608,7 +588,7 @@ _zip_find_central_dir(zip_t *za, zip_uint64_t len)
|
||||
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) {
|
||||
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) {
|
||||
@ -654,16 +634,14 @@ _zip_find_central_dir(zip_t *za, zip_uint64_t len)
|
||||
|
||||
|
||||
static unsigned char *
|
||||
_zip_memmem(const unsigned char *big, size_t biglen, const unsigned char *little, size_t littlelen)
|
||||
{
|
||||
_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;
|
||||
while ((p=(const unsigned char *)
|
||||
memchr(p+1, little[0], (size_t)(big-(p+1))+(size_t)(biglen-littlelen)+1)) != NULL) {
|
||||
if (memcmp(p+1, little+1, littlelen-1)==0)
|
||||
p = big - 1;
|
||||
while ((p = (const unsigned char *)memchr(p + 1, little[0], (size_t)(big - (p + 1)) + (size_t)(biglen - littlelen) + 1)) != NULL) {
|
||||
if (memcmp(p + 1, little + 1, littlelen - 1) == 0)
|
||||
return (unsigned char *)p;
|
||||
}
|
||||
|
||||
@ -672,8 +650,7 @@ _zip_memmem(const unsigned char *big, size_t biglen, const unsigned char *little
|
||||
|
||||
|
||||
static zip_cdir_t *
|
||||
_zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error)
|
||||
{
|
||||
_zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error) {
|
||||
zip_cdir_t *cd;
|
||||
zip_uint64_t i, nentry, size, offset, eocd_offset;
|
||||
|
||||
@ -704,23 +681,23 @@ _zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags
|
||||
size = _zip_buffer_get_32(buffer);
|
||||
offset = _zip_buffer_get_32(buffer);
|
||||
|
||||
if (offset+size < offset) {
|
||||
if (offset + size < offset) {
|
||||
zip_error_set(error, ZIP_ER_SEEK, EFBIG);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (offset+size > buf_offset + eocd_offset) {
|
||||
if (offset + size > buf_offset + eocd_offset) {
|
||||
/* cdir spans past EOCD record */
|
||||
zip_error_set(error, ZIP_ER_INCONS, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((flags & ZIP_CHECKCONS) && offset+size != buf_offset + eocd_offset) {
|
||||
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)
|
||||
if ((cd = _zip_cdir_new(nentry, error)) == NULL)
|
||||
return NULL;
|
||||
|
||||
cd->is_zip64 = false;
|
||||
@ -732,8 +709,7 @@ _zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags
|
||||
|
||||
|
||||
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_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error) {
|
||||
zip_cdir_t *cd;
|
||||
zip_uint64_t offset;
|
||||
zip_uint8_t eocd[EOCD64LEN];
|
||||
@ -809,10 +785,16 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse
|
||||
}
|
||||
if ((flags & ZIP_CHECKCONS) && (eocd_disk != eocd_disk64 || num_disks != num_disks64)) {
|
||||
zip_error_set(error, ZIP_ER_INCONS, 0);
|
||||
if (free_buffer) {
|
||||
_zip_buffer_free(buffer);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
if (num_disks != 0 || eocd_disk != 0) {
|
||||
zip_error_set(error, ZIP_ER_MULTIDISK, 0);
|
||||
if (free_buffer) {
|
||||
_zip_buffer_free(buffer);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -842,16 +824,21 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse
|
||||
_zip_buffer_free(buffer);
|
||||
}
|
||||
|
||||
if (offset > ZIP_INT64_MAX || offset+size < offset) {
|
||||
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) {
|
||||
if (offset + size > buf_offset + eocd_offset) {
|
||||
/* cdir spans past EOCD record */
|
||||
zip_error_set(error, ZIP_ER_INCONS, 0);
|
||||
return NULL;
|
||||
}
|
||||
if ((flags & ZIP_CHECKCONS) && offset + size != buf_offset + eocd_offset) {
|
||||
zip_error_set(error, ZIP_ER_INCONS, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((cd=_zip_cdir_new(nentry, error)) == NULL)
|
||||
if ((cd = _zip_cdir_new(nentry, error)) == NULL)
|
||||
return NULL;
|
||||
|
||||
cd->is_zip64 = true;
|
||||
|
183
src/Common/libzip/zip_progress.c
Normal file
183
src/Common/libzip/zip_progress.c
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
zip_progress.c -- progress reporting
|
||||
Copyright (C) 2017 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#define _ZIP_COMPILING_DEPRECATED
|
||||
#include "zipint.h"
|
||||
|
||||
struct zip_progress {
|
||||
zip_t *za;
|
||||
zip_progress_callback callback;
|
||||
void (*ud_free)(void *);
|
||||
|
||||
void *ud;
|
||||
|
||||
double precision;
|
||||
|
||||
/* state */
|
||||
double last_update; /* last value callback function was called with */
|
||||
|
||||
double start; /* start of sub-progress section */
|
||||
double end; /* end of sub-progress section */
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
_zip_progress_end(zip_progress_t *progress) {
|
||||
_zip_progress_update(progress, 1.0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_zip_progress_free(zip_progress_t *progress) {
|
||||
if (progress == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (progress->ud_free) {
|
||||
progress->ud_free(progress->ud);
|
||||
}
|
||||
|
||||
free(progress);
|
||||
}
|
||||
|
||||
|
||||
zip_progress_t *
|
||||
_zip_progress_new(zip_t *za, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud) {
|
||||
zip_progress_t *progress = (zip_progress_t *)malloc(sizeof(*progress));
|
||||
|
||||
if (progress == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
progress->za = za;
|
||||
progress->callback = callback;
|
||||
progress->ud_free = ud_free;
|
||||
progress->ud = ud;
|
||||
progress->precision = precision;
|
||||
|
||||
return progress;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_zip_progress_start(zip_progress_t *progress) {
|
||||
if (progress == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
progress->last_update = 0.0;
|
||||
progress->callback(progress->za, 0.0, progress->ud);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_zip_progress_subrange(zip_progress_t *progress, double start, double end) {
|
||||
if (progress == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
progress->start = start;
|
||||
progress->end = end;
|
||||
|
||||
_zip_progress_update(progress, 0.0);
|
||||
}
|
||||
|
||||
void
|
||||
_zip_progress_update(zip_progress_t *progress, double sub_current) {
|
||||
double current;
|
||||
|
||||
if (progress == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
current = ZIP_MIN(ZIP_MAX(sub_current, 0.0), 1.0) * (progress->end - progress->start) + progress->start;
|
||||
|
||||
if (current - progress->last_update > progress->precision) {
|
||||
progress->callback(progress->za, current, progress->ud);
|
||||
progress->last_update = current;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_register_progress_callback_with_state(zip_t *za, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud) {
|
||||
zip_progress_t *progress = NULL;
|
||||
|
||||
if (callback != NULL) {
|
||||
if ((progress = _zip_progress_new(za, precision, callback, ud_free, ud)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
_zip_progress_free(za->progress);
|
||||
za->progress = progress;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct legacy_ud {
|
||||
zip_progress_callback_t callback;
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
_zip_legacy_progress_callback(zip_t *za, double progress, void *vud) {
|
||||
struct legacy_ud *ud = (struct legacy_ud *)vud;
|
||||
|
||||
ud->callback(progress);
|
||||
}
|
||||
|
||||
ZIP_EXTERN void
|
||||
zip_register_progress_callback(zip_t *za, zip_progress_callback_t progress_callback) {
|
||||
struct legacy_ud *ud;
|
||||
|
||||
if (progress_callback == NULL) {
|
||||
zip_register_progress_callback_with_state(za, 0, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
if ((ud = (struct legacy_ud *)malloc(sizeof(*ud))) == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
ud->callback = progress_callback;
|
||||
|
||||
if (zip_register_progress_callback_with_state(za, 0.001, _zip_legacy_progress_callback, free, ud) < 0) {
|
||||
free(ud);
|
||||
}
|
||||
}
|
@ -39,7 +39,6 @@
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_rename(zip_t *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);
|
||||
}
|
||||
|
@ -37,7 +37,6 @@
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_replace(zip_t *za, zip_uint64_t idx, zip_source_t *source)
|
||||
{
|
||||
zip_replace(zip_t *za, zip_uint64_t idx, zip_source_t *source) {
|
||||
return zip_file_replace(za, idx, source, 0);
|
||||
}
|
||||
|
@ -38,8 +38,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_set_archive_comment(zip_t *za, const char *comment, zip_uint16_t len)
|
||||
{
|
||||
zip_set_archive_comment(zip_t *za, const char *comment, zip_uint16_t len) {
|
||||
zip_string_t *cstr;
|
||||
|
||||
if (ZIP_IS_RDONLY(za)) {
|
||||
@ -53,7 +52,7 @@ zip_set_archive_comment(zip_t *za, const char *comment, zip_uint16_t len)
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
if ((cstr=_zip_string_new((const zip_uint8_t *)comment, len, ZIP_FL_ENC_GUESS, &za->error)) == NULL)
|
||||
if ((cstr = _zip_string_new((const zip_uint8_t *)comment, len, ZIP_FL_ENC_GUESS, &za->error)) == NULL)
|
||||
return -1;
|
||||
|
||||
if (_zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_CP437) {
|
||||
@ -68,8 +67,7 @@ zip_set_archive_comment(zip_t *za, const char *comment, zip_uint16_t len)
|
||||
_zip_string_free(za->comment_changes);
|
||||
za->comment_changes = NULL;
|
||||
|
||||
if (((za->comment_orig && _zip_string_equal(za->comment_orig, cstr))
|
||||
|| (za->comment_orig == NULL && cstr == NULL))) {
|
||||
if (((za->comment_orig && _zip_string_equal(za->comment_orig, cstr)) || (za->comment_orig == NULL && cstr == NULL))) {
|
||||
_zip_string_free(cstr);
|
||||
za->comment_changed = 0;
|
||||
}
|
||||
|
@ -36,8 +36,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_set_archive_flag(zip_t *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)
|
||||
@ -53,8 +52,7 @@ zip_set_archive_flag(zip_t *za, zip_flags_t flag, int value)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((flag & ZIP_AFL_RDONLY) && value
|
||||
&& (za->ch_flags & ZIP_AFL_RDONLY) == 0) {
|
||||
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);
|
||||
return -1;
|
||||
|
@ -39,15 +39,14 @@
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_set_default_password(zip_t *za, const char *passwd)
|
||||
{
|
||||
zip_set_default_password(zip_t *za, const char *passwd) {
|
||||
if (za == NULL)
|
||||
return -1;
|
||||
|
||||
free(za->default_password);
|
||||
|
||||
if (passwd) {
|
||||
if ((za->default_password=strdup(passwd)) == NULL) {
|
||||
if ((za->default_password = strdup(passwd)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
@ -39,8 +39,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_set_file_comment(zip_t *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);
|
||||
return -1;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
zip_set_file_compression.c -- set compression for file in archive
|
||||
Copyright (C) 2012-2014 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2012-2017 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
@ -36,12 +36,11 @@
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_set_file_compression(zip_t *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) {
|
||||
zip_entry_t *e;
|
||||
zip_int32_t old_method;
|
||||
|
||||
if (idx >= za->nentry) {
|
||||
if (idx >= za->nentry || flags > 9) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
@ -51,20 +50,24 @@ zip_set_file_compression(zip_t *za, zip_uint64_t idx, zip_int32_t method, zip_ui
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (method != ZIP_CM_DEFAULT && method != ZIP_CM_STORE && method != ZIP_CM_DEFLATE) {
|
||||
if (!zip_compression_method_supported(method, true)) {
|
||||
zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
e = za->entry+idx;
|
||||
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 */
|
||||
/* TODO: do we want to recompress if level is set? Only if it's
|
||||
* different than what bit flags tell us, but those are not
|
||||
* defined for all compression methods, or not directly mappable
|
||||
* to levels */
|
||||
|
||||
if (method == old_method) {
|
||||
if (e->changes) {
|
||||
e->changes->changed &= ~ZIP_DIRENT_COMP_METHOD;
|
||||
e->changes->compression_level = 0;
|
||||
if (e->changes->changed == 0) {
|
||||
_zip_dirent_free(e->changes);
|
||||
e->changes = NULL;
|
||||
@ -73,13 +76,14 @@ zip_set_file_compression(zip_t *za, zip_uint64_t idx, zip_int32_t method, zip_ui
|
||||
}
|
||||
else {
|
||||
if (e->changes == NULL) {
|
||||
if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) {
|
||||
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
e->changes->comp_method = method;
|
||||
e->changes->compression_level = (zip_uint16_t)flags;
|
||||
e->changes->changed |= ZIP_DIRENT_COMP_METHOD;
|
||||
}
|
||||
|
||||
|
@ -39,8 +39,7 @@
|
||||
|
||||
|
||||
int
|
||||
_zip_set_name(zip_t *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) {
|
||||
zip_entry_t *e;
|
||||
zip_string_t *str;
|
||||
bool same_as_orig;
|
||||
@ -60,7 +59,7 @@ _zip_set_name(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags)
|
||||
|
||||
if (name && name[0] != '\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)
|
||||
if ((str = _zip_string_new((const zip_uint8_t *)name, (zip_uint16_t)strlen(name), flags, &za->error)) == NULL)
|
||||
return -1;
|
||||
if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(str, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED)
|
||||
str->encoding = ZIP_ENCODING_UTF8_KNOWN;
|
||||
@ -69,19 +68,19 @@ _zip_set_name(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags)
|
||||
str = NULL;
|
||||
|
||||
/* TODO: encoding flags needed for CP437? */
|
||||
if ((i=_zip_name_locate(za, name, 0, NULL)) >= 0 && (zip_uint64_t)i != idx) {
|
||||
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);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* no effective name change */
|
||||
if (i>=0 && (zip_uint64_t)i == idx) {
|
||||
if (i >= 0 && (zip_uint64_t)i == idx) {
|
||||
_zip_string_free(str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
e = za->entry+idx;
|
||||
e = za->entry + idx;
|
||||
|
||||
if (e->orig)
|
||||
same_as_orig = _zip_string_equal(e->orig->filename, str);
|
||||
@ -89,7 +88,7 @@ _zip_set_name(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags)
|
||||
same_as_orig = false;
|
||||
|
||||
if (!same_as_orig && e->changes == NULL) {
|
||||
if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) {
|
||||
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
_zip_string_free(str);
|
||||
return -1;
|
||||
|
@ -36,8 +36,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_source_begin_write(zip_source_t *src)
|
||||
{
|
||||
zip_source_begin_write(zip_source_t *src) {
|
||||
if (ZIP_SOURCE_IS_OPEN_WRITING(src)) {
|
||||
zip_error_set(&src->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
zip_get_compression_implementation.c -- get compression implementation
|
||||
Copyright (C) 2009-2016 Dieter Baron and Thomas Klausner
|
||||
zip_source_begin_write_cloning.c -- clone part of file for writing
|
||||
Copyright (C) 2017 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
@ -35,10 +35,18 @@
|
||||
#include "zipint.h"
|
||||
|
||||
|
||||
zip_compression_implementation
|
||||
_zip_get_compression_implementation(zip_int32_t cm, int operation)
|
||||
{
|
||||
if (cm == ZIP_CM_DEFLATE || ZIP_CM_IS_DEFAULT(cm))
|
||||
return zip_source_deflate;
|
||||
return NULL;
|
||||
ZIP_EXTERN int
|
||||
zip_source_begin_write_cloning(zip_source_t *src, zip_uint64_t offset) {
|
||||
if (ZIP_SOURCE_IS_OPEN_WRITING(src)) {
|
||||
zip_error_set(&src->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_zip_source_call(src, NULL, offset, ZIP_SOURCE_BEGIN_WRITE_CLONING) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
src->write_state = ZIP_SOURCE_WRITE_OPEN;
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
zip_source_buffer.c -- create zip data source from buffer
|
||||
Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
@ -37,18 +37,23 @@
|
||||
#include "zipint.h"
|
||||
|
||||
#ifndef WRITE_FRAGMENT_SIZE
|
||||
#define WRITE_FRAGMENT_SIZE 64*1024
|
||||
#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_buffer_fragment_t *fragments; /* fragments */
|
||||
zip_uint64_t *fragment_offsets; /* offset of each fragment from start of buffer, nfragments+1 entries */
|
||||
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;
|
||||
|
||||
zip_uint64_t first_owned_fragment; /* first fragment to free data from */
|
||||
|
||||
zip_uint64_t shared_fragments; /* number of shared fragments */
|
||||
struct buffer *shared_buffer; /* buffer fragments are shared with */
|
||||
zip_uint64_t size; /* size of buffer */
|
||||
|
||||
zip_uint64_t offset; /* current offset in buffer */
|
||||
zip_uint64_t current_fragment; /* fragment current offset is in */
|
||||
};
|
||||
|
||||
typedef struct buffer buffer_t;
|
||||
@ -60,10 +65,14 @@ struct read_data {
|
||||
buffer_t *out;
|
||||
};
|
||||
|
||||
#define buffer_capacity(buffer) ((buffer)->fragment_offsets[(buffer)->nfragments])
|
||||
#define buffer_size(buffer) ((buffer)->size)
|
||||
|
||||
static buffer_t *buffer_clone(buffer_t *buffer, zip_uint64_t length, zip_error_t *error);
|
||||
static zip_uint64_t buffer_find_fragment(const buffer_t *buffer, zip_uint64_t offset);
|
||||
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 bool buffer_grow_fragments(buffer_t *buffer, zip_uint64_t capacity, zip_error_t *error);
|
||||
static buffer_t *buffer_new(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int free_data, zip_error_t *error);
|
||||
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 *);
|
||||
@ -72,8 +81,7 @@ static zip_int64_t read_data(void *, void *, zip_uint64_t, zip_source_cmd_t);
|
||||
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_buffer(zip_t *za, const void *data, zip_uint64_t len, int freep)
|
||||
{
|
||||
zip_source_buffer(zip_t *za, const void *data, zip_uint64_t len, int freep) {
|
||||
if (za == NULL)
|
||||
return NULL;
|
||||
|
||||
@ -82,32 +90,58 @@ zip_source_buffer(zip_t *za, const void *data, zip_uint64_t len, int freep)
|
||||
|
||||
|
||||
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;
|
||||
zip_source_buffer_create(const void *data, zip_uint64_t len, int freep, zip_error_t *error) {
|
||||
zip_buffer_fragment_t fragment;
|
||||
|
||||
if (data == NULL && len > 0) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((ctx=(struct read_data *)malloc(sizeof(*ctx))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
fragment.data = (zip_uint8_t *)data;
|
||||
fragment.length = len;
|
||||
|
||||
return zip_source_buffer_fragment_create(&fragment, 1, freep, error);
|
||||
}
|
||||
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_buffer_fragment(zip_t *za, const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep) {
|
||||
if (za == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((ctx->in = buffer_new_read(data, len, freep)) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
free(ctx);
|
||||
return zip_source_buffer_fragment_create(fragments, nfragments, freep, &za->error);
|
||||
}
|
||||
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_buffer_fragment_create(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep, zip_error_t *error) {
|
||||
struct read_data *ctx;
|
||||
zip_source_t *zs;
|
||||
buffer_t *buffer;
|
||||
|
||||
if (fragments == NULL && nfragments > 0) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((buffer = buffer_new(fragments, nfragments, freep, error)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((ctx = (struct read_data *)malloc(sizeof(*ctx))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
buffer_free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->in = buffer;
|
||||
ctx->out = NULL;
|
||||
ctx->mtime = time(NULL);
|
||||
zip_error_init(&ctx->error);
|
||||
|
||||
if ((zs=zip_source_function_create(read_data, ctx, error)) == NULL) {
|
||||
if ((zs = zip_source_function_create(read_data, ctx, error)) == NULL) {
|
||||
buffer_free(ctx->in);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
@ -118,16 +152,24 @@ zip_source_buffer_create(const void *data, zip_uint64_t len, int freep, zip_erro
|
||||
|
||||
|
||||
static zip_int64_t
|
||||
read_data(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
|
||||
{
|
||||
read_data(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
|
||||
struct read_data *ctx = (struct read_data *)state;
|
||||
|
||||
switch (cmd) {
|
||||
case ZIP_SOURCE_BEGIN_WRITE:
|
||||
if ((ctx->out = buffer_new_write(WRITE_FRAGMENT_SIZE)) == NULL) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
|
||||
if ((ctx->out = buffer_new(NULL, 0, 0, &ctx->error)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
ctx->out->offset = 0;
|
||||
ctx->out->current_fragment = 0;
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_BEGIN_WRITE_CLONING:
|
||||
if ((ctx->out = buffer_clone(ctx->in, len, &ctx->error)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
ctx->out->offset = len;
|
||||
ctx->out->current_fragment = ctx->out->nfragments;
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_CLOSE:
|
||||
@ -150,6 +192,7 @@ read_data(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
|
||||
|
||||
case ZIP_SOURCE_OPEN:
|
||||
ctx->in->offset = 0;
|
||||
ctx->in->current_fragment = 0;
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_READ:
|
||||
@ -159,11 +202,9 @@ read_data(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
|
||||
}
|
||||
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);
|
||||
case ZIP_SOURCE_REMOVE: {
|
||||
buffer_t *empty = buffer_new(NULL, 0, 0, &ctx->error);
|
||||
if (empty == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -183,8 +224,7 @@ read_data(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
|
||||
case ZIP_SOURCE_SEEK_WRITE:
|
||||
return buffer_seek(ctx->out, data, len, &ctx->error);
|
||||
|
||||
case ZIP_SOURCE_STAT:
|
||||
{
|
||||
case ZIP_SOURCE_STAT: {
|
||||
zip_stat_t *st;
|
||||
|
||||
if (len < sizeof(*st)) {
|
||||
@ -200,13 +240,13 @@ read_data(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
|
||||
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_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);
|
||||
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_BEGIN_WRITE_CLONING, 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) {
|
||||
@ -237,97 +277,195 @@ read_data(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
|
||||
}
|
||||
|
||||
|
||||
static buffer_t *
|
||||
buffer_clone(buffer_t *buffer, zip_uint64_t offset, zip_error_t *error) {
|
||||
zip_uint64_t fragment, fragment_offset, waste;
|
||||
buffer_t *clone;
|
||||
|
||||
if (offset == 0) {
|
||||
return buffer_new(NULL, 0, 1, error);
|
||||
}
|
||||
|
||||
if (offset > buffer->size) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
if (buffer->shared_buffer != NULL) {
|
||||
zip_error_set(error, ZIP_ER_INUSE, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fragment = buffer_find_fragment(buffer, offset);
|
||||
fragment_offset = offset - buffer->fragment_offsets[fragment];
|
||||
|
||||
if (fragment_offset == 0) {
|
||||
fragment--;
|
||||
fragment_offset = buffer->fragments[fragment].length;
|
||||
}
|
||||
|
||||
waste = buffer->fragments[fragment].length - fragment_offset;
|
||||
if (waste > offset) {
|
||||
zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((clone = buffer_new(buffer->fragments, fragment + 1, 0, error)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef __clang_analyzer__
|
||||
/* clone->fragments can't be null, since it was created with at least one fragment */
|
||||
clone->fragments[clone->nfragments - 1].length = fragment_offset;
|
||||
#endif
|
||||
clone->fragment_offsets[clone->nfragments] = offset;
|
||||
clone->size = offset;
|
||||
|
||||
clone->first_owned_fragment = ZIP_MIN(buffer->first_owned_fragment, clone->nfragments - 1);
|
||||
|
||||
buffer->shared_buffer = clone;
|
||||
clone->shared_buffer = buffer;
|
||||
buffer->shared_fragments = clone->nfragments;
|
||||
clone->shared_fragments = fragment + 1;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
||||
static zip_uint64_t
|
||||
buffer_find_fragment(const buffer_t *buffer, zip_uint64_t offset) {
|
||||
zip_uint64_t low, high, mid;
|
||||
|
||||
low = 0;
|
||||
high = buffer->nfragments - 1;
|
||||
|
||||
while (low < high) {
|
||||
mid = (high - low) / 2 + low;
|
||||
if (buffer->fragment_offsets[mid] > offset) {
|
||||
high = mid - 1;
|
||||
}
|
||||
else if (mid == buffer->nfragments || buffer->fragment_offsets[mid + 1] > offset) {
|
||||
return mid;
|
||||
}
|
||||
else {
|
||||
low = mid + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return low;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
buffer_free(buffer_t *buffer)
|
||||
{
|
||||
buffer_free(buffer_t *buffer) {
|
||||
zip_uint64_t i;
|
||||
|
||||
if (buffer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (buffer->free_data) {
|
||||
zip_uint64_t i;
|
||||
if (buffer->shared_buffer != NULL) {
|
||||
buffer->shared_buffer->shared_buffer = NULL;
|
||||
buffer->shared_buffer->shared_fragments = 0;
|
||||
|
||||
for (i=0; i < buffer->nfragments; i++) {
|
||||
free(buffer->fragments[i]);
|
||||
buffer->first_owned_fragment = ZIP_MAX(buffer->first_owned_fragment, buffer->shared_fragments);
|
||||
}
|
||||
|
||||
for (i = buffer->first_owned_fragment; i < buffer->nfragments; i++) {
|
||||
free(buffer->fragments[i].data);
|
||||
}
|
||||
free(buffer->fragments);
|
||||
free(buffer->fragment_offsets);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
buffer_grow_fragments(buffer_t *buffer, zip_uint64_t capacity, zip_error_t *error) {
|
||||
zip_buffer_fragment_t *fragments;
|
||||
zip_uint64_t *offsets;
|
||||
|
||||
if (capacity < buffer->fragments_capacity) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((fragments = realloc(buffer->fragments, sizeof(buffer->fragments[0]) * capacity)) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return false;
|
||||
}
|
||||
buffer->fragments = fragments;
|
||||
if ((offsets = realloc(buffer->fragment_offsets, sizeof(buffer->fragment_offsets[0]) * (capacity + 1))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return false;
|
||||
}
|
||||
buffer->fragment_offsets = offsets;
|
||||
buffer->fragments_capacity = capacity;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static buffer_t *
|
||||
buffer_new(zip_uint64_t fragment_size)
|
||||
{
|
||||
buffer_new(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int free_data, zip_error_t *error) {
|
||||
buffer_t *buffer;
|
||||
|
||||
if ((buffer = malloc(sizeof(*buffer))) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer->fragment_size = fragment_size;
|
||||
buffer->offset = 0;
|
||||
buffer->free_data = 0;
|
||||
buffer->first_owned_fragment = 0;
|
||||
buffer->size = 0;
|
||||
buffer->fragments = NULL;
|
||||
buffer->fragment_offsets = NULL;
|
||||
buffer->nfragments = 0;
|
||||
buffer->fragments_capacity = 0;
|
||||
buffer->fragments = NULL;
|
||||
buffer->size = 0;
|
||||
buffer->shared_buffer = NULL;
|
||||
buffer->shared_fragments = 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) {
|
||||
if (nfragments == 0) {
|
||||
if ((buffer->fragment_offsets = malloc(sizeof(buffer->fragment_offsets[0]))) == NULL) {
|
||||
free(buffer);
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
buffer->fragment_offsets[0] = 0;
|
||||
}
|
||||
else {
|
||||
zip_uint64_t i, j, offset;
|
||||
|
||||
buffer->size = length;
|
||||
|
||||
if (length > 0) {
|
||||
if ((buffer->fragments = malloc(sizeof(*(buffer->fragments)))) == NULL) {
|
||||
if (!buffer_grow_fragments(buffer, nfragments, NULL)) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
buffer_free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
buffer->fragments_capacity = 1;
|
||||
|
||||
buffer->nfragments = 1;
|
||||
buffer->fragments[0] = (zip_uint8_t *)data;
|
||||
buffer->free_data = free_data;
|
||||
offset = 0;
|
||||
for (i = 0, j = 0; i < nfragments; i++) {
|
||||
if (fragments[i].length == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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) {
|
||||
if (fragments[i].data == NULL) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
buffer_free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
buffer->fragments_capacity = 1;
|
||||
buffer->nfragments = 0;
|
||||
buffer->free_data = 1;
|
||||
buffer->fragments[j].data = fragments[i].data;
|
||||
buffer->fragments[j].length = fragments[i].length;
|
||||
buffer->fragment_offsets[i] = offset;
|
||||
offset += fragments[i].length;
|
||||
j++;
|
||||
}
|
||||
buffer->nfragments = j;
|
||||
buffer->first_owned_fragment = free_data ? 0 : buffer->nfragments;
|
||||
buffer->fragment_offsets[nfragments] = offset;
|
||||
buffer->size = offset;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
static zip_int64_t
|
||||
buffer_read(buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length)
|
||||
{
|
||||
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);
|
||||
@ -339,27 +477,29 @@ buffer_read(buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length)
|
||||
return -1;
|
||||
}
|
||||
|
||||
i = buffer->offset / buffer->fragment_size;
|
||||
fragment_offset = buffer->offset % buffer->fragment_size;
|
||||
i = buffer->current_fragment;
|
||||
fragment_offset = buffer->offset - buffer->fragment_offsets[i];
|
||||
n = 0;
|
||||
while (n < length) {
|
||||
zip_uint64_t left = ZIP_MIN(length - n, buffer->fragment_size - fragment_offset);
|
||||
zip_uint64_t left = ZIP_MIN(length - n, buffer->fragments[i].length - fragment_offset);
|
||||
|
||||
memcpy(data + n, buffer->fragments[i] + fragment_offset, left);
|
||||
memcpy(data + n, buffer->fragments[i].data + fragment_offset, left);
|
||||
|
||||
n += left;
|
||||
if (left == buffer->fragments[i].length - fragment_offset) {
|
||||
i++;
|
||||
}
|
||||
n += left;
|
||||
fragment_offset = 0;
|
||||
}
|
||||
|
||||
buffer->offset += n;
|
||||
buffer->current_fragment = i;
|
||||
return (zip_int64_t)n;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
buffer_seek(buffer_t *buffer, void *data, zip_uint64_t len, zip_error_t *error)
|
||||
{
|
||||
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) {
|
||||
@ -367,66 +507,70 @@ buffer_seek(buffer_t *buffer, void *data, zip_uint64_t len, zip_error_t *error)
|
||||
}
|
||||
|
||||
buffer->offset = (zip_uint64_t)new_offset;
|
||||
buffer->current_fragment = buffer_find_fragment(buffer, buffer->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;
|
||||
zip_uint8_t **fragments;
|
||||
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, capacity;
|
||||
|
||||
if (buffer->offset + length + buffer->fragment_size - 1 < length) {
|
||||
if (buffer->offset + length + WRITE_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;
|
||||
capacity = buffer_capacity(buffer);
|
||||
if (buffer->offset + length > capacity) {
|
||||
zip_uint64_t needed_fragments = buffer->nfragments + (length - (capacity - buffer->offset) + WRITE_FRAGMENT_SIZE - 1) / WRITE_FRAGMENT_SIZE;
|
||||
|
||||
if (needed_fragments > buffer->fragments_capacity) {
|
||||
zip_uint64_t new_capacity = buffer->fragments_capacity;
|
||||
|
||||
if (new_capacity == 0) {
|
||||
new_capacity = 16;
|
||||
}
|
||||
while (new_capacity < needed_fragments) {
|
||||
new_capacity *= 2;
|
||||
}
|
||||
|
||||
fragments = realloc(buffer->fragments, new_capacity * sizeof(*fragments));
|
||||
|
||||
if (fragments == NULL) {
|
||||
if (!buffer_grow_fragments(buffer, new_capacity, error)) {
|
||||
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) {
|
||||
if ((buffer->fragments[buffer->nfragments].data = malloc(WRITE_FRAGMENT_SIZE)) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
buffer->fragments[buffer->nfragments].length = WRITE_FRAGMENT_SIZE;
|
||||
buffer->nfragments++;
|
||||
capacity += WRITE_FRAGMENT_SIZE;
|
||||
buffer->fragment_offsets[buffer->nfragments] = capacity;
|
||||
}
|
||||
}
|
||||
|
||||
i = buffer->offset / buffer->fragment_size;
|
||||
fragment_offset = buffer->offset % buffer->fragment_size;
|
||||
i = buffer->current_fragment;
|
||||
fragment_offset = buffer->offset - buffer->fragment_offsets[i];
|
||||
n = 0;
|
||||
while (n < length) {
|
||||
zip_uint64_t left = ZIP_MIN(length - n, buffer->fragment_size - fragment_offset);
|
||||
zip_uint64_t left = ZIP_MIN(length - n, buffer->fragments[i].length - fragment_offset);
|
||||
|
||||
memcpy(buffer->fragments[i] + fragment_offset, data + n, left);
|
||||
memcpy(buffer->fragments[i].data + fragment_offset, data + n, left);
|
||||
|
||||
n += left;
|
||||
if (n == buffer->fragments[i].length - fragment_offset) {
|
||||
i++;
|
||||
}
|
||||
n += left;
|
||||
fragment_offset = 0;
|
||||
}
|
||||
|
||||
buffer->offset += n;
|
||||
buffer->current_fragment = i;
|
||||
if (buffer->offset > buffer->size) {
|
||||
buffer->size = buffer->offset;
|
||||
}
|
||||
|
@ -36,8 +36,7 @@
|
||||
|
||||
|
||||
zip_int64_t
|
||||
_zip_source_call(zip_source_t *src, void *data, zip_uint64_t length, zip_source_cmd_t command)
|
||||
{
|
||||
_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) {
|
||||
|
@ -36,8 +36,7 @@
|
||||
|
||||
|
||||
int
|
||||
zip_source_close(zip_source_t *src)
|
||||
{
|
||||
zip_source_close(zip_source_t *src) {
|
||||
if (!ZIP_SOURCE_IS_OPEN_READING(src)) {
|
||||
zip_error_set(&src->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
|
@ -36,8 +36,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_source_commit_write(zip_source_t *src)
|
||||
{
|
||||
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;
|
||||
|
367
src/Common/libzip/zip_source_compress.c
Normal file
367
src/Common/libzip/zip_source_compress.c
Normal file
@ -0,0 +1,367 @@
|
||||
/*
|
||||
zip_source_compress.c -- (de)compression routines
|
||||
Copyright (C) 2017 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
struct context {
|
||||
zip_error_t error;
|
||||
|
||||
bool end_of_input;
|
||||
bool end_of_stream;
|
||||
bool can_store;
|
||||
bool is_stored; /* only valid if end_of_stream is true */
|
||||
bool compress;
|
||||
zip_int32_t method;
|
||||
|
||||
zip_uint64_t size;
|
||||
zip_int64_t first_read;
|
||||
zip_uint8_t buffer[BUFSIZE];
|
||||
|
||||
zip_compression_algorithm_t *algorithm;
|
||||
void *ud;
|
||||
};
|
||||
|
||||
|
||||
struct implementation {
|
||||
zip_uint16_t method;
|
||||
zip_compression_algorithm_t *compress;
|
||||
zip_compression_algorithm_t *decompress;
|
||||
};
|
||||
|
||||
static struct implementation implementations[] = {
|
||||
{ZIP_CM_DEFLATE, &zip_algorithm_deflate_compress, &zip_algorithm_deflate_decompress},
|
||||
#if defined(HAVE_LIBBZ2)
|
||||
{ZIP_CM_BZIP2, &zip_algorithm_bzip2_compress, &zip_algorithm_bzip2_decompress},
|
||||
#endif
|
||||
};
|
||||
|
||||
static size_t implementations_size = sizeof(implementations) / sizeof(implementations[0]);
|
||||
|
||||
static zip_source_t *compression_source_new(zip_t *za, zip_source_t *src, zip_int32_t method, bool compress, int compression_flags);
|
||||
static zip_int64_t compress_callback(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t);
|
||||
static void context_free(struct context *ctx);
|
||||
static struct context *context_new(zip_int32_t method, bool compress, int compression_flags, zip_compression_algorithm_t *algorithm);
|
||||
static zip_int64_t compress_read(zip_source_t *, struct context *, void *, zip_uint64_t);
|
||||
|
||||
static zip_compression_algorithm_t *
|
||||
get_algorithm(zip_int32_t method, bool compress) {
|
||||
size_t i;
|
||||
zip_uint16_t real_method = ZIP_CM_ACTUAL(method);
|
||||
|
||||
for (i = 0; i < implementations_size; i++) {
|
||||
if (implementations[i].method == real_method) {
|
||||
if (compress) {
|
||||
return implementations[i].compress;
|
||||
}
|
||||
else {
|
||||
return implementations[i].decompress;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
zip_compression_method_supported(zip_int32_t method, bool compress) {
|
||||
if (method == ZIP_CM_STORE) {
|
||||
return true;
|
||||
}
|
||||
return get_algorithm(method, compress) != NULL;
|
||||
}
|
||||
|
||||
zip_source_t *
|
||||
zip_source_compress(zip_t *za, zip_source_t *src, zip_int32_t method, int compression_flags) {
|
||||
return compression_source_new(za, src, method, true, compression_flags);
|
||||
}
|
||||
|
||||
zip_source_t *
|
||||
zip_source_decompress(zip_t *za, zip_source_t *src, zip_int32_t method) {
|
||||
return compression_source_new(za, src, method, false, 0);
|
||||
}
|
||||
|
||||
|
||||
static zip_source_t *
|
||||
compression_source_new(zip_t *za, zip_source_t *src, zip_int32_t method, bool compress, int compression_flags) {
|
||||
struct context *ctx;
|
||||
zip_source_t *s2;
|
||||
zip_compression_algorithm_t *algorithm = NULL;
|
||||
|
||||
if (src == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((algorithm = get_algorithm(method, compress)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((ctx = context_new(method, compress, compression_flags, algorithm)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((s2 = zip_source_layered(za, src, compress_callback, ctx)) == NULL) {
|
||||
context_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return s2;
|
||||
}
|
||||
|
||||
|
||||
static struct context *
|
||||
context_new(zip_int32_t method, bool compress, int compression_flags, zip_compression_algorithm_t *algorithm) {
|
||||
struct context *ctx;
|
||||
|
||||
if ((ctx = (struct context *)malloc(sizeof(*ctx))) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
zip_error_init(&ctx->error);
|
||||
ctx->can_store = compress ? ZIP_CM_IS_DEFAULT(method) : false;
|
||||
ctx->algorithm = algorithm;
|
||||
ctx->method = method;
|
||||
ctx->compress = compress;
|
||||
ctx->end_of_input = false;
|
||||
ctx->end_of_stream = false;
|
||||
ctx->is_stored = false;
|
||||
|
||||
if ((ctx->ud = ctx->algorithm->allocate(ZIP_CM_ACTUAL(method), compression_flags, &ctx->error)) == NULL) {
|
||||
zip_error_fini(&ctx->error);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
context_free(struct context *ctx) {
|
||||
if (ctx == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->algorithm->deallocate(ctx->ud);
|
||||
zip_error_fini(&ctx->error);
|
||||
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
|
||||
static zip_int64_t
|
||||
compress_read(zip_source_t *src, struct context *ctx, void *data, zip_uint64_t len) {
|
||||
zip_compression_status_t ret;
|
||||
bool end;
|
||||
zip_int64_t n;
|
||||
zip_uint64_t out_offset;
|
||||
zip_uint64_t out_len;
|
||||
|
||||
if (zip_error_code_zip(&ctx->error) != ZIP_ER_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len == 0 || ctx->end_of_stream) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
out_offset = 0;
|
||||
|
||||
end = false;
|
||||
while (!end && out_offset < len) {
|
||||
out_len = len - out_offset;
|
||||
ret = ctx->algorithm->process(ctx->ud, (zip_uint8_t *)data + out_offset, &out_len);
|
||||
|
||||
if (ret != ZIP_COMPRESSION_ERROR) {
|
||||
out_offset += out_len;
|
||||
}
|
||||
|
||||
switch (ret) {
|
||||
case ZIP_COMPRESSION_END:
|
||||
ctx->end_of_stream = true;
|
||||
|
||||
if (!ctx->end_of_input) {
|
||||
/* TODO: garbage after stream, or compression ended before all data read */
|
||||
}
|
||||
|
||||
if (ctx->first_read < 0) {
|
||||
/* we got end of processed stream before reading any input data */
|
||||
zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
if (ctx->can_store && (zip_uint64_t)ctx->first_read <= out_offset) {
|
||||
ctx->is_stored = true;
|
||||
ctx->size = (zip_uint64_t)ctx->first_read;
|
||||
memcpy(data, ctx->buffer, ctx->size);
|
||||
return (zip_int64_t)ctx->size;
|
||||
}
|
||||
end = true;
|
||||
break;
|
||||
|
||||
case ZIP_COMPRESSION_OK:
|
||||
break;
|
||||
|
||||
case ZIP_COMPRESSION_NEED_DATA:
|
||||
if (ctx->end_of_input) {
|
||||
/* TODO: error: stream not ended, but no more input */
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((n = zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
|
||||
_zip_error_set_from_source(&ctx->error, src);
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
else if (n == 0) {
|
||||
ctx->end_of_input = true;
|
||||
ctx->algorithm->end_of_input(ctx->ud);
|
||||
if (ctx->first_read < 0) {
|
||||
ctx->first_read = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ctx->first_read >= 0) {
|
||||
/* we overwrote a previously filled ctx->buffer */
|
||||
ctx->can_store = false;
|
||||
}
|
||||
else {
|
||||
ctx->first_read = n;
|
||||
}
|
||||
|
||||
ctx->algorithm->input(ctx->ud, ctx->buffer, (zip_uint64_t)n);
|
||||
}
|
||||
break;
|
||||
|
||||
case ZIP_COMPRESSION_ERROR:
|
||||
/* error set by algorithm */
|
||||
if (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
|
||||
}
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (out_offset > 0) {
|
||||
ctx->can_store = false;
|
||||
ctx->size += out_offset;
|
||||
return (zip_int64_t)out_offset;
|
||||
}
|
||||
|
||||
return (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) ? 0 : -1;
|
||||
}
|
||||
|
||||
|
||||
static zip_int64_t
|
||||
compress_callback(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
|
||||
struct context *ctx;
|
||||
|
||||
ctx = (struct context *)ud;
|
||||
|
||||
switch (cmd) {
|
||||
case ZIP_SOURCE_OPEN:
|
||||
ctx->size = 0;
|
||||
ctx->end_of_input = false;
|
||||
ctx->end_of_stream = false;
|
||||
ctx->is_stored = false;
|
||||
ctx->first_read = -1;
|
||||
|
||||
if (!ctx->algorithm->start(ctx->ud)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_READ:
|
||||
return compress_read(src, ctx, data, len);
|
||||
|
||||
case ZIP_SOURCE_CLOSE:
|
||||
if (!ctx->algorithm->end(ctx->ud)) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_STAT: {
|
||||
zip_stat_t *st;
|
||||
|
||||
st = (zip_stat_t *)data;
|
||||
|
||||
if (ctx->compress) {
|
||||
if (ctx->end_of_stream) {
|
||||
st->comp_method = ctx->is_stored ? ZIP_CM_STORE : ZIP_CM_ACTUAL(ctx->method);
|
||||
st->comp_size = ctx->size;
|
||||
st->valid |= ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD;
|
||||
}
|
||||
else {
|
||||
st->valid &= ~(ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD);
|
||||
}
|
||||
}
|
||||
else {
|
||||
st->comp_method = ZIP_CM_STORE;
|
||||
st->valid |= ZIP_STAT_COMP_METHOD;
|
||||
if (ctx->end_of_stream) {
|
||||
st->size = ctx->size;
|
||||
st->valid |= ZIP_STAT_SIZE;
|
||||
}
|
||||
else {
|
||||
st->valid &= ~ZIP_STAT_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_GET_COMPRESSION_FLAGS:
|
||||
return ctx->is_stored ? 0 : ctx->algorithm->compression_flags(ctx->ud);
|
||||
|
||||
case ZIP_SOURCE_ERROR:
|
||||
return zip_error_to_data(&ctx->error, data, len);
|
||||
|
||||
case ZIP_SOURCE_FREE:
|
||||
context_free(ctx);
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_SUPPORTS:
|
||||
return ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_GET_COMPRESSION_FLAGS, -1);
|
||||
|
||||
default:
|
||||
zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
zip_source_crc.c -- pass-through source that calculates CRC32 and size
|
||||
Copyright (C) 2009-2016 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2009-2017 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
@ -32,9 +32,9 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
@ -52,8 +52,7 @@ static zip_int64_t crc_read(zip_source_t *, void *, void *, zip_uint64_t, zip_so
|
||||
|
||||
|
||||
zip_source_t *
|
||||
zip_source_crc(zip_t *za, zip_source_t *src, int validate)
|
||||
{
|
||||
zip_source_crc(zip_t *za, zip_source_t *src, int validate) {
|
||||
struct crc_context *ctx;
|
||||
|
||||
if (src == NULL) {
|
||||
@ -61,7 +60,7 @@ zip_source_crc(zip_t *za, zip_source_t *src, int validate)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((ctx=(struct crc_context *)malloc(sizeof(*ctx))) == NULL) {
|
||||
if ((ctx = (struct crc_context *)malloc(sizeof(*ctx))) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
@ -78,8 +77,7 @@ zip_source_crc(zip_t *za, zip_source_t *src, int validate)
|
||||
|
||||
|
||||
static zip_int64_t
|
||||
crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source_cmd_t 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;
|
||||
|
||||
@ -124,9 +122,9 @@ crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source
|
||||
zip_uint64_t i, nn;
|
||||
|
||||
for (i = ctx->crc_position - ctx->position; i < (zip_uint64_t)n; i += nn) {
|
||||
nn = ZIP_MIN(UINT_MAX, (zip_uint64_t)n-i);
|
||||
nn = ZIP_MIN(UINT_MAX, (zip_uint64_t)n - i);
|
||||
|
||||
ctx->crc = (zip_uint32_t)crc32(ctx->crc, (const Bytef *)data+i, (uInt)nn);
|
||||
ctx->crc = (zip_uint32_t)crc32(ctx->crc, (const Bytef *)data + i, (uInt)nn);
|
||||
ctx->crc_position += nn;
|
||||
}
|
||||
}
|
||||
@ -136,8 +134,7 @@ crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source
|
||||
case ZIP_SOURCE_CLOSE:
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_STAT:
|
||||
{
|
||||
case ZIP_SOURCE_STAT: {
|
||||
zip_stat_t *st;
|
||||
|
||||
st = (zip_stat_t *)data;
|
||||
@ -150,7 +147,8 @@ crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source
|
||||
st->comp_size = ctx->size;
|
||||
st->comp_method = ZIP_CM_STORE;
|
||||
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;;
|
||||
st->valid |= ZIP_STAT_SIZE | ZIP_STAT_CRC | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_ENCRYPTION_METHOD;
|
||||
;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -162,8 +160,7 @@ crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source
|
||||
free(ctx);
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_SUPPORTS:
|
||||
{
|
||||
case ZIP_SOURCE_SUPPORTS: {
|
||||
zip_int64_t mask = zip_source_supports(src);
|
||||
|
||||
if (mask < 0) {
|
||||
@ -171,11 +168,10 @@ crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source
|
||||
return -1;
|
||||
}
|
||||
|
||||
return mask & ~zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, -1);
|
||||
return mask & ~zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, ZIP_SOURCE_GET_COMPRESSION_FLAGS, -1);
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_SEEK:
|
||||
{
|
||||
case ZIP_SOURCE_SEEK: {
|
||||
zip_int64_t new_position;
|
||||
zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);
|
||||
|
||||
|
@ -36,13 +36,11 @@
|
||||
|
||||
|
||||
zip_error_t *
|
||||
zip_source_error(zip_source_t *src)
|
||||
{
|
||||
zip_source_error(zip_source_t *src) {
|
||||
return &src->error;
|
||||
}
|
||||
|
||||
bool
|
||||
_zip_source_had_error(zip_source_t *src)
|
||||
{
|
||||
_zip_source_had_error(zip_source_t *src) {
|
||||
return zip_source_error(src)->zip_err != ZIP_ER_OK;
|
||||
}
|
||||
|
@ -42,8 +42,7 @@
|
||||
#endif
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_file(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t len)
|
||||
{
|
||||
zip_source_file(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t len) {
|
||||
if (za == NULL)
|
||||
return NULL;
|
||||
|
||||
@ -52,8 +51,7 @@ zip_source_file(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t le
|
||||
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_file_create(const char *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error)
|
||||
{
|
||||
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;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
zip_source_filep.c -- create data source from FILE *
|
||||
Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
@ -31,10 +31,10 @@
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
@ -42,6 +42,17 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CLONEFILE
|
||||
#include <sys/attr.h>
|
||||
#include <sys/clonefile.h>
|
||||
#define CAN_CLONE
|
||||
#endif
|
||||
#ifdef HAVE_FICLONERANGE
|
||||
#include <linux/fs.h>
|
||||
#include <sys/ioctl.h>
|
||||
#define CAN_CLONE
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
/* WIN32 needs <fcntl.h> for _O_BINARY */
|
||||
#include <fcntl.h>
|
||||
@ -49,7 +60,7 @@
|
||||
|
||||
/* Windows sys/types.h does not provide these */
|
||||
#ifndef S_ISREG
|
||||
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
||||
#define S_ISREG(m) (((m)&S_IFMT) == S_IFREG)
|
||||
#endif
|
||||
#if defined(S_IXUSR) && defined(S_IRWXG) && defined(S_IRWXO)
|
||||
#define _SAFE_MASK (S_IXUSR | S_IRWXG | S_IRWXO)
|
||||
@ -84,13 +95,15 @@ struct read_file {
|
||||
|
||||
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);
|
||||
#ifdef CAN_CLONE
|
||||
static zip_int64_t create_temp_output_cloning(struct read_file *ctx, zip_uint64_t offset);
|
||||
#endif
|
||||
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 zip_source_t *
|
||||
zip_source_filep(zip_t *za, FILE *file, zip_uint64_t start, zip_int64_t len)
|
||||
{
|
||||
zip_source_filep(zip_t *za, FILE *file, zip_uint64_t start, zip_int64_t len) {
|
||||
if (za == NULL)
|
||||
return NULL;
|
||||
|
||||
@ -99,8 +112,7 @@ zip_source_filep(zip_t *za, FILE *file, zip_uint64_t start, zip_int64_t len)
|
||||
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_filep_create(FILE *file, zip_uint64_t start, zip_int64_t length, zip_error_t *error)
|
||||
{
|
||||
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;
|
||||
@ -111,10 +123,11 @@ zip_source_filep_create(FILE *file, zip_uint64_t start, zip_int64_t length, zip_
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
_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 *ctx;
|
||||
zip_source_t *zs;
|
||||
struct stat sb;
|
||||
bool stat_valid;
|
||||
|
||||
if (file == NULL && fname == NULL) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
@ -130,14 +143,14 @@ _zip_source_file_or_p(const char *fname, FILE *file, zip_uint64_t start, zip_int
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((ctx=(struct read_file *)malloc(sizeof(struct read_file))) == NULL) {
|
||||
if ((ctx = (struct read_file *)malloc(sizeof(struct read_file))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->fname = NULL;
|
||||
if (fname) {
|
||||
if ((ctx->fname=strdup(fname)) == NULL) {
|
||||
if ((ctx->fname = strdup(fname)) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
@ -170,13 +183,21 @@ _zip_source_file_or_p(const char *fname, FILE *file, zip_uint64_t start, zip_int
|
||||
ctx->supports = ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1);
|
||||
|
||||
if (ctx->fname) {
|
||||
struct stat sb;
|
||||
if (stat(ctx->fname, &sb) < 0) {
|
||||
zip_error_set(&ctx->stat_error, ZIP_ER_READ, errno);
|
||||
stat_valid = stat(ctx->fname, &sb) >= 0;
|
||||
|
||||
if (!stat_valid) {
|
||||
if (ctx->start == 0 && ctx->end == 0) {
|
||||
ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
stat_valid = fstat(fileno(ctx->f), &sb) >= 0;
|
||||
}
|
||||
|
||||
if (!stat_valid) {
|
||||
zip_error_set(&ctx->stat_error, ZIP_ER_READ, errno);
|
||||
}
|
||||
else {
|
||||
if ((ctx->st.valid & ZIP_STAT_MTIME) == 0) {
|
||||
ctx->st.mtime = sb.st_mtime;
|
||||
@ -196,18 +217,20 @@ _zip_source_file_or_p(const char *fname, FILE *file, zip_uint64_t start, zip_int
|
||||
ctx->st.size = (zip_uint64_t)sb.st_size - ctx->start;
|
||||
ctx->st.valid |= ZIP_STAT_SIZE;
|
||||
|
||||
if (start == 0) {
|
||||
if (ctx->fname && start == 0) {
|
||||
ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (fseeko(ctx->f, 0, SEEK_CUR) == 0) {
|
||||
ctx->supports = ZIP_SOURCE_SUPPORTS_SEEKABLE;
|
||||
}
|
||||
|
||||
if ((zs=zip_source_function_create(read_file, ctx, error)) == NULL) {
|
||||
#ifdef CAN_CLONE
|
||||
if (ctx->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE)) {
|
||||
ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((zs = zip_source_function_create(read_file, ctx, error)) == NULL) {
|
||||
free(ctx->fname);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
@ -218,21 +241,20 @@ _zip_source_file_or_p(const char *fname, FILE *file, zip_uint64_t start, zip_int
|
||||
|
||||
|
||||
static int
|
||||
create_temp_output(struct read_file *ctx)
|
||||
{
|
||||
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) {
|
||||
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);
|
||||
|
||||
mask = umask(_SAFE_MASK);
|
||||
if ((tfd=mkstemp(temp)) == -1) {
|
||||
if ((tfd = mkstemp(temp)) == -1) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
|
||||
umask(mask);
|
||||
free(temp);
|
||||
@ -240,7 +262,7 @@ create_temp_output(struct read_file *ctx)
|
||||
}
|
||||
umask(mask);
|
||||
|
||||
if ((tfp=fdopen(tfd, "r+b")) == NULL) {
|
||||
if ((tfp = fdopen(tfd, "r+b")) == NULL) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
|
||||
close(tfd);
|
||||
(void)remove(temp);
|
||||
@ -253,7 +275,7 @@ create_temp_output(struct read_file *ctx)
|
||||
According to Pierre Joye, Windows in some environments per
|
||||
default creates text files, so force binary mode.
|
||||
*/
|
||||
_setmode(_fileno(tfp), _O_BINARY );
|
||||
_setmode(_fileno(tfp), _O_BINARY);
|
||||
#endif
|
||||
|
||||
ctx->fout = tfp;
|
||||
@ -262,10 +284,108 @@ create_temp_output(struct read_file *ctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CAN_CLONE
|
||||
zip_int64_t static create_temp_output_cloning(struct read_file *ctx, zip_uint64_t offset) {
|
||||
char *temp;
|
||||
FILE *tfp;
|
||||
|
||||
if (offset > ZIP_OFF_MAX) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_SEEK, E2BIG);
|
||||
return -1;
|
||||
}
|
||||
|
||||
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 HAVE_CLONEFILE
|
||||
#ifndef __clang_analyzer__
|
||||
/* we can't use mkstemp, since clonefile insists on creating the file */
|
||||
if (mktemp(temp) == NULL) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
|
||||
free(temp);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (clonefile(ctx->fname, temp, 0) < 0) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
|
||||
free(temp);
|
||||
return -1;
|
||||
}
|
||||
if ((tfp = fopen(temp, "r+b")) == NULL) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
|
||||
(void)remove(temp);
|
||||
free(temp);
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
{
|
||||
int fd;
|
||||
struct file_clone_range range;
|
||||
struct stat st;
|
||||
|
||||
if (fstat(fileno(ctx->f), &st) < 0) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((fd = mkstemp(temp)) < 0) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
|
||||
free(temp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
range.src_fd = fileno(ctx->f);
|
||||
range.src_offset = 0;
|
||||
range.src_length = ((offset + st.st_blksize - 1) / st.st_blksize) * st.st_blksize;
|
||||
if (range.src_length > st.st_size) {
|
||||
range.src_length = 0;
|
||||
}
|
||||
range.dest_offset = 0;
|
||||
if (ioctl(fd, FICLONERANGE, &range) < 0) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
|
||||
(void)close(fd);
|
||||
(void)remove(temp);
|
||||
free(temp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((tfp = fdopen(fd, "r+b")) == NULL) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
|
||||
(void)close(fd);
|
||||
(void)remove(temp);
|
||||
free(temp);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ftruncate(fileno(tfp), (off_t)offset) < 0) {
|
||||
(void)fclose(tfp);
|
||||
(void)remove(temp);
|
||||
free(temp);
|
||||
return -1;
|
||||
}
|
||||
if (fseeko(tfp, (off_t)offset, SEEK_SET) < 0) {
|
||||
(void)fclose(tfp);
|
||||
(void)remove(temp);
|
||||
free(temp);
|
||||
zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
|
||||
}
|
||||
|
||||
ctx->fout = tfp;
|
||||
ctx->tmpname = temp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static zip_int64_t
|
||||
read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
|
||||
{
|
||||
read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
|
||||
struct read_file *ctx;
|
||||
char *buf;
|
||||
zip_uint64_t n;
|
||||
@ -282,6 +402,15 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
|
||||
}
|
||||
return create_temp_output(ctx);
|
||||
|
||||
#ifdef CAN_CLONE
|
||||
case ZIP_SOURCE_BEGIN_WRITE_CLONING:
|
||||
if (ctx->fname == NULL) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
|
||||
return -1;
|
||||
}
|
||||
return create_temp_output_cloning(ctx, len);
|
||||
#endif
|
||||
|
||||
case ZIP_SOURCE_COMMIT_WRITE: {
|
||||
mode_t mask;
|
||||
|
||||
@ -297,7 +426,7 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
|
||||
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);
|
||||
(void)chmod(ctx->fname, 0666 & ~mask);
|
||||
free(ctx->tmpname);
|
||||
ctx->tmpname = NULL;
|
||||
return 0;
|
||||
@ -323,7 +452,7 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
|
||||
|
||||
case ZIP_SOURCE_OPEN:
|
||||
if (ctx->fname) {
|
||||
if ((ctx->f=fopen(ctx->fname, "rb")) == NULL) {
|
||||
if ((ctx->f = fopen(ctx->fname, "rb")) == NULL) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_OPEN, errno);
|
||||
return -1;
|
||||
}
|
||||
@ -352,7 +481,7 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
|
||||
if (n > SIZE_MAX)
|
||||
n = SIZE_MAX;
|
||||
|
||||
if ((i=fread(buf, 1, (size_t)n, ctx->f)) == 0) {
|
||||
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;
|
||||
@ -420,8 +549,7 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (new_current < 0 || (ctx->end != 0 && (zip_uint64_t)new_current > ctx->end)
|
||||
|| (zip_uint64_t)new_current + ctx->start < ctx->start) {
|
||||
if (new_current < 0 || (ctx->end != 0 && (zip_uint64_t)new_current > ctx->end) || (zip_uint64_t)new_current + ctx->start < ctx->start) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
@ -469,8 +597,7 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
|
||||
case ZIP_SOURCE_TELL:
|
||||
return (zip_int64_t)ctx->current;
|
||||
|
||||
case ZIP_SOURCE_TELL_WRITE:
|
||||
{
|
||||
case ZIP_SOURCE_TELL_WRITE: {
|
||||
off_t ret = ftello(ctx->fout);
|
||||
|
||||
if (ret < 0) {
|
||||
@ -480,8 +607,7 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
|
||||
return ret;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_WRITE:
|
||||
{
|
||||
case ZIP_SOURCE_WRITE: {
|
||||
size_t ret;
|
||||
|
||||
clearerr(ctx->fout);
|
||||
@ -502,8 +628,7 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
|
||||
|
||||
|
||||
static int
|
||||
_zip_fseek_u(FILE *f, zip_uint64_t offset, int whence, zip_error_t *error)
|
||||
{
|
||||
_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;
|
||||
@ -513,8 +638,7 @@ _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_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;
|
||||
|
@ -38,8 +38,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN void
|
||||
zip_source_free(zip_source_t *src)
|
||||
{
|
||||
zip_source_free(zip_source_t *src) {
|
||||
if (src == NULL)
|
||||
return;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
zip_source_function.c -- create zip data source from callback function
|
||||
Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
@ -38,8 +38,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_function(zip_t *za, zip_source_callback zcb, void *ud)
|
||||
{
|
||||
zip_source_function(zip_t *za, zip_source_callback zcb, void *ud) {
|
||||
if (za == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@ -49,11 +48,10 @@ zip_source_function(zip_t *za, zip_source_callback zcb, void *ud)
|
||||
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_function_create(zip_source_callback zcb, void *ud, zip_error_t *error)
|
||||
{
|
||||
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)
|
||||
if ((zs = _zip_source_new(error)) == NULL)
|
||||
return NULL;
|
||||
|
||||
zs->cb.f = zcb;
|
||||
@ -69,18 +67,16 @@ zip_source_function_create(zip_source_callback zcb, void *ud, zip_error_t *error
|
||||
|
||||
|
||||
ZIP_EXTERN void
|
||||
zip_source_keep(zip_source_t *src)
|
||||
{
|
||||
zip_source_keep(zip_source_t *src) {
|
||||
src->refcount++;
|
||||
}
|
||||
|
||||
|
||||
zip_source_t *
|
||||
_zip_source_new(zip_error_t *error)
|
||||
{
|
||||
_zip_source_new(zip_error_t *error) {
|
||||
zip_source_t *src;
|
||||
|
||||
if ((src=(zip_source_t *)malloc(sizeof(*src))) == NULL) {
|
||||
if ((src = (zip_source_t *)malloc(sizeof(*src))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
@ -95,6 +91,7 @@ _zip_source_new(zip_error_t *error)
|
||||
src->refcount = 1;
|
||||
zip_error_init(&src->error);
|
||||
src->eof = false;
|
||||
src->had_read_error = false;
|
||||
|
||||
return src;
|
||||
}
|
||||
|
57
src/Common/libzip/zip_source_get_compression_flags.c
Normal file
57
src/Common/libzip/zip_source_get_compression_flags.c
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
zip_source_get_compression_flags.c -- get compression flags for entry
|
||||
Copyright (C) 2017 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
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"
|
||||
|
||||
#define ZIP_COMPRESSION_BITFLAG_MAX 3
|
||||
|
||||
zip_int8_t
|
||||
zip_source_get_compression_flags(zip_source_t *src) {
|
||||
while (src) {
|
||||
if ((src->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_GET_COMPRESSION_FLAGS))) {
|
||||
zip_int64_t ret = _zip_source_call(src, NULL, 0, ZIP_SOURCE_GET_COMPRESSION_FLAGS);
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (ret > ZIP_COMPRESSION_BITFLAG_MAX) {
|
||||
zip_error_set(&src->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
}
|
||||
return (zip_int8_t)ret;
|
||||
}
|
||||
src = src->src;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -36,7 +36,6 @@
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_source_is_deleted(zip_source_t *src)
|
||||
{
|
||||
zip_source_is_deleted(zip_source_t *src) {
|
||||
return src->write_state == ZIP_SOURCE_WRITE_REMOVED;
|
||||
}
|
||||
|
@ -38,8 +38,7 @@
|
||||
|
||||
|
||||
zip_source_t *
|
||||
zip_source_layered(zip_t *za, zip_source_t *src, zip_source_layered_callback cb, void *ud)
|
||||
{
|
||||
zip_source_layered(zip_t *za, zip_source_t *src, zip_source_layered_callback cb, void *ud) {
|
||||
if (za == NULL)
|
||||
return NULL;
|
||||
|
||||
@ -48,11 +47,10 @@ zip_source_layered(zip_t *za, zip_source_t *src, zip_source_layered_callback cb,
|
||||
|
||||
|
||||
zip_source_t *
|
||||
zip_source_layered_create(zip_source_t *src, zip_source_layered_callback cb, void *ud, zip_error_t *error)
|
||||
{
|
||||
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)
|
||||
if ((zs = _zip_source_new(error)) == NULL)
|
||||
return NULL;
|
||||
|
||||
zip_source_keep(src);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
zip_source_open.c -- open zip_source (prepare for reading)
|
||||
Copyright (C) 2009-2016 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2009-2017 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
@ -35,8 +35,7 @@
|
||||
#include "zipint.h"
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_source_open(zip_source_t *src)
|
||||
{
|
||||
zip_source_open(zip_source_t *src) {
|
||||
if (src->source_closed) {
|
||||
return -1;
|
||||
}
|
||||
@ -68,6 +67,7 @@ zip_source_open(zip_source_t *src)
|
||||
}
|
||||
|
||||
src->eof = false;
|
||||
src->had_read_error = false;
|
||||
_zip_error_clear(&src->error);
|
||||
src->open_count++;
|
||||
|
||||
|
@ -48,18 +48,14 @@ struct trad_pkware {
|
||||
#define KEY2 878082192
|
||||
|
||||
|
||||
static void decrypt(struct trad_pkware *, zip_uint8_t *,
|
||||
const zip_uint8_t *, zip_uint64_t, int);
|
||||
static void decrypt(struct trad_pkware *, zip_uint8_t *, const zip_uint8_t *, zip_uint64_t, int);
|
||||
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 zip_int64_t pkware_decrypt(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t);
|
||||
static void pkware_free(struct trad_pkware *);
|
||||
|
||||
|
||||
zip_source_t *
|
||||
zip_source_pkware(zip_t *za, zip_source_t *src,
|
||||
zip_uint16_t em, int flags, const char *password)
|
||||
{
|
||||
zip_source_pkware(zip_t *za, zip_source_t *src, zip_uint16_t em, int flags, const char *password) {
|
||||
struct trad_pkware *ctx;
|
||||
zip_source_t *s2;
|
||||
|
||||
@ -72,7 +68,7 @@ zip_source_pkware(zip_t *za, zip_source_t *src,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((ctx=(struct trad_pkware *)malloc(sizeof(*ctx))) == NULL) {
|
||||
if ((ctx = (struct trad_pkware *)malloc(sizeof(*ctx))) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
@ -84,7 +80,7 @@ zip_source_pkware(zip_t *za, zip_source_t *src,
|
||||
ctx->key[2] = KEY2;
|
||||
decrypt(ctx, NULL, (const zip_uint8_t *)password, strlen(password), 1);
|
||||
|
||||
if ((s2=zip_source_layered(za, src, pkware_decrypt, ctx)) == NULL) {
|
||||
if ((s2 = zip_source_layered(za, src, pkware_decrypt, ctx)) == NULL) {
|
||||
pkware_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
@ -94,14 +90,12 @@ zip_source_pkware(zip_t *za, zip_source_t *src,
|
||||
|
||||
|
||||
static void
|
||||
decrypt(struct trad_pkware *ctx, zip_uint8_t *out, const zip_uint8_t *in,
|
||||
zip_uint64_t len, int update_only)
|
||||
{
|
||||
decrypt(struct trad_pkware *ctx, zip_uint8_t *out, const zip_uint8_t *in, zip_uint64_t len, int update_only) {
|
||||
zip_uint16_t tmp;
|
||||
zip_uint64_t i;
|
||||
Bytef b;
|
||||
|
||||
for (i=0; i<len; i++) {
|
||||
for (i = 0; i < len; i++) {
|
||||
b = in[i];
|
||||
|
||||
if (!update_only) {
|
||||
@ -125,14 +119,13 @@ decrypt(struct trad_pkware *ctx, zip_uint8_t *out, const zip_uint8_t *in,
|
||||
|
||||
|
||||
static int
|
||||
decrypt_header(zip_source_t *src, struct trad_pkware *ctx)
|
||||
{
|
||||
decrypt_header(zip_source_t *src, struct trad_pkware *ctx) {
|
||||
zip_uint8_t header[HEADERLEN];
|
||||
struct zip_stat st;
|
||||
zip_int64_t n;
|
||||
unsigned short dostime, dosdate;
|
||||
|
||||
if ((n=zip_source_read(src, header, HEADERLEN)) < 0) {
|
||||
if ((n = zip_source_read(src, header, HEADERLEN)) < 0) {
|
||||
_zip_error_set_from_source(&ctx->error, src);
|
||||
return -1;
|
||||
}
|
||||
@ -151,7 +144,7 @@ decrypt_header(zip_source_t *src, struct trad_pkware *ctx)
|
||||
|
||||
_zip_u2d_time(st.mtime, &dostime, &dosdate);
|
||||
|
||||
if (header[HEADERLEN-1] != st.crc>>24 && header[HEADERLEN-1] != dostime>>8) {
|
||||
if (header[HEADERLEN - 1] != st.crc >> 24 && header[HEADERLEN - 1] != dostime >> 8) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_WRONGPASSWD, 0);
|
||||
return -1;
|
||||
}
|
||||
@ -161,9 +154,7 @@ decrypt_header(zip_source_t *src, struct trad_pkware *ctx)
|
||||
|
||||
|
||||
static zip_int64_t
|
||||
pkware_decrypt(zip_source_t *src, void *ud, void *data,
|
||||
zip_uint64_t len, zip_source_cmd_t 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;
|
||||
|
||||
@ -176,7 +167,7 @@ pkware_decrypt(zip_source_t *src, void *ud, void *data,
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_READ:
|
||||
if ((n=zip_source_read(src, data, len)) < 0) {
|
||||
if ((n = zip_source_read(src, data, len)) < 0) {
|
||||
_zip_error_set_from_source(&ctx->error, src);
|
||||
return -1;
|
||||
}
|
||||
@ -187,8 +178,7 @@ pkware_decrypt(zip_source_t *src, void *ud, void *data,
|
||||
case ZIP_SOURCE_CLOSE:
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_STAT:
|
||||
{
|
||||
case ZIP_SOURCE_STAT: {
|
||||
zip_stat_t *st;
|
||||
|
||||
st = (zip_stat_t *)data;
|
||||
@ -220,7 +210,6 @@ pkware_decrypt(zip_source_t *src, void *ud, void *data,
|
||||
|
||||
|
||||
static void
|
||||
pkware_free(struct trad_pkware *ctx)
|
||||
{
|
||||
pkware_free(struct trad_pkware *ctx) {
|
||||
free(ctx);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
zip_source_read.c -- read data from zip_source
|
||||
Copyright (C) 2009-2016 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2009-2017 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
@ -36,8 +36,7 @@
|
||||
|
||||
|
||||
zip_int64_t
|
||||
zip_source_read(zip_source_t *src, void *data, zip_uint64_t len)
|
||||
{
|
||||
zip_source_read(zip_source_t *src, void *data, zip_uint64_t len) {
|
||||
zip_uint64_t bytes_read;
|
||||
zip_int64_t n;
|
||||
|
||||
@ -49,7 +48,7 @@ zip_source_read(zip_source_t *src, void *data, zip_uint64_t len)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_zip_source_had_error(src)) {
|
||||
if (src->had_read_error) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -57,9 +56,14 @@ zip_source_read(zip_source_t *src, void *data, zip_uint64_t len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bytes_read = 0;
|
||||
while (bytes_read < len) {
|
||||
if ((n = _zip_source_call(src, (zip_uint8_t *)data + bytes_read, len - bytes_read, ZIP_SOURCE_READ)) < 0) {
|
||||
src->had_read_error = true;
|
||||
if (bytes_read == 0) {
|
||||
return -1;
|
||||
}
|
||||
@ -81,7 +85,6 @@ zip_source_read(zip_source_t *src, void *data, zip_uint64_t len)
|
||||
|
||||
|
||||
bool
|
||||
_zip_source_eof(zip_source_t *src)
|
||||
{
|
||||
_zip_source_eof(zip_source_t *src) {
|
||||
return src->eof;
|
||||
}
|
||||
|
@ -36,8 +36,7 @@
|
||||
|
||||
|
||||
int
|
||||
zip_source_remove(zip_source_t *src)
|
||||
{
|
||||
zip_source_remove(zip_source_t *src) {
|
||||
if (src->write_state == ZIP_SOURCE_WRITE_REMOVED) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -36,8 +36,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN void
|
||||
zip_source_rollback_write(zip_source_t *src)
|
||||
{
|
||||
zip_source_rollback_write(zip_source_t *src) {
|
||||
if (src->write_state != ZIP_SOURCE_WRITE_OPEN && src->write_state != ZIP_SOURCE_WRITE_FAILED) {
|
||||
return;
|
||||
}
|
||||
|
@ -36,8 +36,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_source_seek(zip_source_t *src, zip_int64_t offset, int whence)
|
||||
{
|
||||
zip_source_seek(zip_source_t *src, zip_int64_t offset, int whence) {
|
||||
zip_source_args_seek_t args;
|
||||
|
||||
if (src->source_closed) {
|
||||
@ -56,8 +55,7 @@ zip_source_seek(zip_source_t *src, zip_int64_t offset, int whence)
|
||||
|
||||
|
||||
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_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);
|
||||
|
||||
|
@ -36,8 +36,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_source_seek_write(zip_source_t *src, zip_int64_t offset, int whence)
|
||||
{
|
||||
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)) {
|
||||
|
@ -36,8 +36,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_source_stat(zip_source_t *src, zip_stat_t *st)
|
||||
{
|
||||
zip_source_stat(zip_source_t *src, zip_stat_t *st) {
|
||||
if (src->source_closed) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -38,22 +38,19 @@
|
||||
|
||||
|
||||
zip_int64_t
|
||||
zip_source_supports(zip_source_t *src)
|
||||
{
|
||||
zip_source_supports(zip_source_t *src) {
|
||||
return src->supports;
|
||||
}
|
||||
|
||||
|
||||
ZIP_EXTERN zip_int64_t
|
||||
zip_source_make_command_bitmap(zip_source_cmd_t cmd0, ...)
|
||||
{
|
||||
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);
|
||||
|
@ -36,8 +36,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN zip_int64_t
|
||||
zip_source_tell(zip_source_t *src)
|
||||
{
|
||||
zip_source_tell(zip_source_t *src) {
|
||||
if (src->source_closed) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -36,8 +36,7 @@
|
||||
|
||||
|
||||
ZIP_EXTERN zip_int64_t
|
||||
zip_source_tell_write(zip_source_t *src)
|
||||
{
|
||||
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;
|
||||
|
@ -1,48 +1,55 @@
|
||||
/*
|
||||
zip_source_win32a.c -- create data source from Windows file (ANSI)
|
||||
Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
|
||||
zip_source_win32a.c -- create data source from Windows file (ANSI)
|
||||
Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
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.
|
||||
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.
|
||||
*/
|
||||
|
||||
/* 0x0501 => Windows XP; needs to be at least this value because of GetFileSizeEx */
|
||||
#if !defined(MS_UWP) && !defined(_WIN32_WINNT)
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#endif
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "zipint.h"
|
||||
#include "zipwin32.h"
|
||||
|
||||
static void * _win32_strdup_a(const void *str);
|
||||
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);
|
||||
|
||||
// clang-format off
|
||||
static _zip_source_win32_file_ops_t win32_ops_a = {
|
||||
_win32_strdup_a,
|
||||
_win32_open_a,
|
||||
@ -50,10 +57,10 @@ static _zip_source_win32_file_ops_t win32_ops_a = {
|
||||
_win32_rename_temp_a,
|
||||
_win32_remove_a
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_win32a(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t len)
|
||||
{
|
||||
zip_source_win32a(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t len) {
|
||||
if (za == NULL)
|
||||
return NULL;
|
||||
|
||||
@ -62,8 +69,7 @@ zip_source_win32a(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t
|
||||
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_win32a_create(const char *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error)
|
||||
{
|
||||
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;
|
||||
@ -74,23 +80,20 @@ zip_source_win32a_create(const char *fname, zip_uint64_t start, zip_int64_t leng
|
||||
|
||||
|
||||
static void *
|
||||
_win32_strdup_a(const void *str)
|
||||
{
|
||||
_win32_strdup_a(const void *str) {
|
||||
return strdup((const char *)str);
|
||||
}
|
||||
|
||||
|
||||
static HANDLE
|
||||
_win32_open_a(_zip_source_win32_read_file_t *ctx)
|
||||
{
|
||||
_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;
|
||||
_win32_create_temp_a(_zip_source_win32_read_file_t *ctx, void **temp, zip_uint32_t value, PSECURITY_ATTRIBUTES sa) {
|
||||
size_t len;
|
||||
|
||||
len = strlen((const char *)ctx->fname) + 10;
|
||||
if (*temp == NULL) {
|
||||
@ -108,8 +111,7 @@ _win32_create_temp_a(_zip_source_win32_read_file_t *ctx, void **temp, zip_uint32
|
||||
|
||||
|
||||
static int
|
||||
_win32_rename_temp_a(_zip_source_win32_read_file_t *ctx)
|
||||
{
|
||||
_win32_rename_temp_a(_zip_source_win32_read_file_t *ctx) {
|
||||
if (!MoveFileExA(ctx->tmpname, ctx->fname, MOVEFILE_REPLACE_EXISTING))
|
||||
return -1;
|
||||
return 0;
|
||||
@ -117,8 +119,7 @@ _win32_rename_temp_a(_zip_source_win32_read_file_t *ctx)
|
||||
|
||||
|
||||
static int
|
||||
_win32_remove_a(const void *fname)
|
||||
{
|
||||
_win32_remove_a(const void *fname) {
|
||||
DeleteFileA((const char *)fname);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,40 +1,41 @@
|
||||
/*
|
||||
zip_source_win32file.c -- create data source from HANDLE (Win32)
|
||||
Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
|
||||
zip_source_win32file.c -- create data source from HANDLE (Win32)
|
||||
Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
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.
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include <wchar.h>
|
||||
#include <aclapi.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "zipint.h"
|
||||
#include "zipwin32.h"
|
||||
@ -48,8 +49,7 @@ 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)
|
||||
{
|
||||
zip_source_win32handle(zip_t *za, HANDLE h, zip_uint64_t start, zip_int64_t len) {
|
||||
if (za == NULL)
|
||||
return NULL;
|
||||
|
||||
@ -58,8 +58,7 @@ zip_source_win32handle(zip_t *za, HANDLE h, zip_uint64_t start, zip_int64_t len)
|
||||
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_win32handle_create(HANDLE h, zip_uint64_t start, zip_int64_t length, zip_error_t *error)
|
||||
{
|
||||
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;
|
||||
@ -70,8 +69,7 @@ zip_source_win32handle_create(HANDLE h, zip_uint64_t start, zip_int64_t length,
|
||||
|
||||
|
||||
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_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;
|
||||
|
||||
@ -140,8 +138,7 @@ _zip_source_win32_handle_or_name(const void *fname, HANDLE h, zip_uint64_t start
|
||||
|
||||
|
||||
static zip_int64_t
|
||||
_win32_read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
|
||||
{
|
||||
_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;
|
||||
@ -376,8 +373,7 @@ _win32_read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd
|
||||
case ZIP_SOURCE_TELL:
|
||||
return (zip_int64_t)ctx->current;
|
||||
|
||||
case ZIP_SOURCE_TELL_WRITE:
|
||||
{
|
||||
case ZIP_SOURCE_TELL_WRITE: {
|
||||
LARGE_INTEGER zero;
|
||||
LARGE_INTEGER offset;
|
||||
|
||||
@ -390,8 +386,7 @@ _win32_read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd
|
||||
return offset.QuadPart;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_WRITE:
|
||||
{
|
||||
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()));
|
||||
@ -409,8 +404,7 @@ _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)
|
||||
{
|
||||
_win32_create_temp_file(_zip_source_win32_read_file_t *ctx) {
|
||||
zip_uint32_t value;
|
||||
/*
|
||||
Windows has GetTempFileName(), but it closes the file after
|
||||
@ -420,12 +414,12 @@ _win32_create_temp_file(_zip_source_win32_read_file_t *ctx)
|
||||
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;
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
SECURITY_INFORMATION si;
|
||||
DWORD success;
|
||||
PACL dacl = NULL;
|
||||
|
||||
/*
|
||||
Read the DACL from the original file, so we can copy it to the temp file.
|
||||
@ -434,16 +428,8 @@ _win32_create_temp_file(_zip_source_win32_read_file_t *ctx)
|
||||
*/
|
||||
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) {
|
||||
success = GetSecurityInfo(ctx->h, SE_FILE_OBJECT, si, NULL, NULL, &dacl, NULL, &psd);
|
||||
if (success == ERROR_SUCCESS) {
|
||||
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
sa.bInheritHandle = FALSE;
|
||||
sa.lpSecurityDescriptor = psd;
|
||||
@ -451,7 +437,13 @@ _win32_create_temp_file(_zip_source_win32_read_file_t *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef MS_UWP
|
||||
value = GetTickCount();
|
||||
#else
|
||||
value = (zip_uint32_t)GetTickCount64();
|
||||
#endif
|
||||
|
||||
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)
|
||||
@ -460,12 +452,12 @@ _win32_create_temp_file(_zip_source_win32_read_file_t *ctx)
|
||||
|
||||
if (th == INVALID_HANDLE_VALUE) {
|
||||
free(temp);
|
||||
free(psd);
|
||||
LocalFree(psd);
|
||||
zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, _zip_win32_error_to_errno(GetLastError()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(psd);
|
||||
LocalFree(psd);
|
||||
ctx->hout = th;
|
||||
ctx->tmpname = temp;
|
||||
|
||||
@ -474,8 +466,7 @@ _win32_create_temp_file(_zip_source_win32_read_file_t *ctx)
|
||||
|
||||
|
||||
static int
|
||||
_zip_seek_win32_u(HANDLE h, zip_uint64_t offset, int whence, zip_error_t *error)
|
||||
{
|
||||
_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;
|
||||
@ -485,8 +476,7 @@ _zip_seek_win32_u(HANDLE h, zip_uint64_t offset, int whence, zip_error_t *error)
|
||||
|
||||
|
||||
static int
|
||||
_zip_seek_win32(HANDLE h, zip_int64_t offset, int whence, zip_error_t *error)
|
||||
{
|
||||
_zip_seek_win32(HANDLE h, zip_int64_t offset, int whence, zip_error_t *error) {
|
||||
LARGE_INTEGER li;
|
||||
DWORD method;
|
||||
|
||||
@ -516,8 +506,7 @@ _zip_seek_win32(HANDLE h, zip_int64_t offset, int whence, zip_error_t *error)
|
||||
|
||||
|
||||
static int
|
||||
_zip_win32_error_to_errno(DWORD win32err)
|
||||
{
|
||||
_zip_win32_error_to_errno(DWORD win32err) {
|
||||
/*
|
||||
Note: This list isn't exhaustive, but should cover common cases.
|
||||
*/
|
||||
@ -543,8 +532,7 @@ _zip_win32_error_to_errno(DWORD win32err)
|
||||
|
||||
|
||||
static int
|
||||
_zip_stat_win32(HANDLE h, zip_stat_t *st, _zip_source_win32_read_file_t *ctx)
|
||||
{
|
||||
_zip_stat_win32(HANDLE h, zip_stat_t *st, _zip_source_win32_read_file_t *ctx) {
|
||||
FILETIME mtimeft;
|
||||
time_t mtime;
|
||||
LARGE_INTEGER size;
|
||||
@ -586,8 +574,7 @@ _zip_stat_win32(HANDLE h, zip_stat_t *st, _zip_source_win32_read_file_t *ctx)
|
||||
|
||||
|
||||
static int
|
||||
_zip_filetime_to_time_t(FILETIME ft, time_t *t)
|
||||
{
|
||||
_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
|
||||
*/
|
||||
|
@ -1,46 +1,50 @@
|
||||
/*
|
||||
zip_source_win32utf8.c -- create data source from Windows file (UTF-8)
|
||||
Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
|
||||
zip_source_win32utf8.c -- create data source from Windows file (UTF-8)
|
||||
Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
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.
|
||||
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.
|
||||
*/
|
||||
|
||||
/* 0x0501 => Windows XP; needs to be at least this value because of GetFileSizeEx */
|
||||
#if !defined(MS_UWP) && !defined(_WIN32_WINNT)
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#endif
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "zipint.h"
|
||||
#include "zipwin32.h"
|
||||
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_file(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t len)
|
||||
{
|
||||
zip_source_file(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t len) {
|
||||
if (za == NULL)
|
||||
return NULL;
|
||||
|
||||
@ -49,8 +53,7 @@ zip_source_file(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t le
|
||||
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_file_create(const char *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error)
|
||||
{
|
||||
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;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user