Windows: update libzip to latest version 1.7.3 (close issue #656)
This commit is contained in:
parent
5cf7d946d2
commit
948a871c73
|
@ -19,7 +19,6 @@
|
|||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="libzip\mkstemp.c" />
|
||||
<ClCompile Include="libzip\zip_add.c" />
|
||||
<ClCompile Include="libzip\zip_add_dir.c" />
|
||||
<ClCompile Include="libzip\zip_add_entry.c" />
|
||||
|
@ -72,6 +71,7 @@
|
|||
<ClCompile Include="libzip\zip_name_locate.c" />
|
||||
<ClCompile Include="libzip\zip_new.c" />
|
||||
<ClCompile Include="libzip\zip_open.c" />
|
||||
<ClCompile Include="libzip\zip_pkware.c" />
|
||||
<ClCompile Include="libzip\zip_progress.c" />
|
||||
<ClCompile Include="libzip\zip_rename.c" />
|
||||
<ClCompile Include="libzip\zip_replace.c" />
|
||||
|
@ -90,16 +90,21 @@
|
|||
<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_file_common.c" />
|
||||
<ClCompile Include="libzip\zip_source_file_stdio.c" />
|
||||
<ClCompile Include="libzip\zip_source_file_win32.c" />
|
||||
<ClCompile Include="libzip\zip_source_file_win32_named.c" />
|
||||
<ClCompile Include="libzip\zip_source_file_win32_utf16.c" />
|
||||
<ClCompile Include="libzip\zip_source_file_win32_utf8.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_get_file_attributes.c" />
|
||||
<ClCompile Include="libzip\zip_source_is_deleted.c" />
|
||||
<ClCompile Include="libzip\zip_source_layered.c" />
|
||||
<ClCompile Include="libzip\zip_source_open.c" />
|
||||
<ClCompile Include="libzip\zip_source_pkware.c" />
|
||||
<ClCompile Include="libzip\zip_source_pkware_decode.c" />
|
||||
<ClCompile Include="libzip\zip_source_pkware_encode.c" />
|
||||
<ClCompile Include="libzip\zip_source_read.c" />
|
||||
<ClCompile Include="libzip\zip_source_remove.c" />
|
||||
<ClCompile Include="libzip\zip_source_rollback_write.c" />
|
||||
|
@ -109,10 +114,6 @@
|
|||
<ClCompile Include="libzip\zip_source_supports.c" />
|
||||
<ClCompile Include="libzip\zip_source_tell.c" />
|
||||
<ClCompile Include="libzip\zip_source_tell_write.c" />
|
||||
<ClCompile Include="libzip\zip_source_win32a.c" />
|
||||
<ClCompile Include="libzip\zip_source_win32handle.c" />
|
||||
<ClCompile Include="libzip\zip_source_win32utf8.c" />
|
||||
<ClCompile Include="libzip\zip_source_win32w.c" />
|
||||
<ClCompile Include="libzip\zip_source_window.c" />
|
||||
<ClCompile Include="libzip\zip_source_write.c" />
|
||||
<ClCompile Include="libzip\zip_source_zip.c" />
|
||||
|
@ -145,7 +146,9 @@
|
|||
<ClInclude Include="libzip\zip.h" />
|
||||
<ClInclude Include="libzip\zipconf.h" />
|
||||
<ClInclude Include="libzip\zipint.h" />
|
||||
<ClInclude Include="libzip\zipwin32.h" />
|
||||
<ClInclude Include="libzip\zip_source_file.h" />
|
||||
<ClInclude Include="libzip\zip_source_file_stdio.h" />
|
||||
<ClInclude Include="libzip\zip_source_file_win32.h" />
|
||||
<ClInclude Include="zlib\crc32.h" />
|
||||
<ClInclude Include="zlib\deflate.h" />
|
||||
<ClInclude Include="zlib\inffast.h" />
|
||||
|
|
|
@ -9,9 +9,6 @@
|
|||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="libzip\mkstemp.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_add.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
|
@ -57,9 +54,6 @@
|
|||
<ClCompile Include="libzip\zip_error_strerror.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_err_str.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_extra_field.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
|
@ -207,15 +201,9 @@
|
|||
<ClCompile Include="libzip\zip_source_crc.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_source_deflate.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_source_error.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_source_filep.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_source_free.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
|
@ -231,9 +219,6 @@
|
|||
<ClCompile Include="libzip\zip_source_open.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_source_pkware.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_source_read.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
|
@ -261,18 +246,6 @@
|
|||
<ClCompile Include="libzip\zip_source_tell_write.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_source_win32a.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_source_win32handle.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_source_win32utf8.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_source_win32w.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_source_window.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
|
@ -357,10 +330,40 @@
|
|||
<ClCompile Include="libzip\zip_algorithm_deflate.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_source_get_compression_flags.c">
|
||||
<ClCompile Include="libzip\zip_source_accept_empty.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_source_accept_empty.c">
|
||||
<ClCompile Include="libzip\zip_source_get_file_attributes.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_source_pkware_decode.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_source_pkware_encode.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_pkware.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_source_file_common.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_source_file_stdio.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_source_file_win32_named.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_source_file_win32_utf8.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_source_file_win32_utf16.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_source_file_win32.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libzip\zip_err_str.c">
|
||||
<Filter>libzip</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
|
@ -383,9 +386,6 @@
|
|||
<ClInclude Include="libzip\zipint.h">
|
||||
<Filter>libzip</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="libzip\zipwin32.h">
|
||||
<Filter>libzip</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="zlib\crc32.h">
|
||||
<Filter>zlib</Filter>
|
||||
</ClInclude>
|
||||
|
@ -416,5 +416,14 @@
|
|||
<ClInclude Include="zlib\zutil.h">
|
||||
<Filter>zlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="libzip\zip_source_file.h">
|
||||
<Filter>libzip</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="libzip\zip_source_file_stdio.h">
|
||||
<Filter>libzip</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="libzip\zip_source_file_win32.h">
|
||||
<Filter>libzip</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -1,4 +1,4 @@
|
|||
Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner
|
||||
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
|
|
|
@ -1,5 +1,52 @@
|
|||
1.7.3 [2020-07-15]
|
||||
==================
|
||||
|
||||
* Support cmake < 3.17 again.
|
||||
* Fix pkgconfig file (regression in 1.7.2).
|
||||
|
||||
1.7.2 [2020-07-11]
|
||||
==================
|
||||
|
||||
* Fixes for the CMake `find_project()` files.
|
||||
* libzip moved to the CMake `libzip::` `NAMESPACE`.
|
||||
* CMake usage best practice cleanups.
|
||||
|
||||
1.7.1 [2020-06-13]
|
||||
==================
|
||||
|
||||
* Restore `LIBZIP_VERSION_{MAJOR,MINOR,MICRO}` symbols.
|
||||
* Fixes warnings reported by PVS-Studio.
|
||||
* Add `LIBZIP_DO_INSTALL` build setting to make it easier to use
|
||||
libzip as subproject.
|
||||
|
||||
1.7.0 [2020-06-05]
|
||||
==================
|
||||
|
||||
* Add support for encrypting using traditional PKWare encryption.
|
||||
* Add `zip_compression_method_supported()`.
|
||||
* Add `zip_encryption_method_supported()`.
|
||||
* Add the `ZIP_SOURCE_GET_FILE_ATTRIBUTES` source command.
|
||||
* Refactor stdio file backend.
|
||||
* Add CMake find_project() support.
|
||||
|
||||
1.6.1 [2020-02-03]
|
||||
==================
|
||||
|
||||
* Bugfix for double-free in `zipcmp(1)` during cleanup.
|
||||
|
||||
1.6.0 [2020-01-24]
|
||||
==================
|
||||
|
||||
* Avoid using `umask()` since it's not thread-safe.
|
||||
* Set close-on-exec flag when opening files.
|
||||
* Do not accept empty files as valid zip archives any longer.
|
||||
* Add support for XZ compressed files (using liblzma).
|
||||
* Add support for cancelling while closing zip archives.
|
||||
* Add support for setting the time in the on-disk format.
|
||||
|
||||
1.5.2 [2019-03-12]
|
||||
==================
|
||||
|
||||
* Fix bug in AES encryption affecting certain file sizes
|
||||
* Keep file permissions when modifying zip archives
|
||||
* Support systems with small stack size.
|
||||
|
@ -37,6 +84,7 @@
|
|||
|
||||
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]
|
||||
|
@ -181,7 +229,7 @@
|
|||
0.9 [2008-07-25]
|
||||
==================
|
||||
|
||||
* on Windows, explictly set dllimport/dllexport
|
||||
* on Windows, explicitly set dllimport/dllexport
|
||||
* remove erroneous references to GPL
|
||||
* add support for torrentzip
|
||||
* new functions: zip_get_archive_flag, zip_set_archive_flag
|
||||
|
|
|
@ -36,9 +36,7 @@
|
|||
|
||||
#include "zipconf.h"
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/* to have *_MAX definitions for all types when compiling with g++ */
|
||||
#define __STDC_LIMIT_MACROS
|
||||
|
@ -103,10 +101,6 @@ typedef char bool;
|
|||
#if !defined(HAVE_FILENO) && defined(HAVE__FILENO)
|
||||
#define fileno _fileno
|
||||
#endif
|
||||
/* Windows' open() doesn't understand Unix permissions */
|
||||
#if defined(HAVE__OPEN)
|
||||
#define open(a, b, c) _open((a), (b))
|
||||
#endif
|
||||
#if defined(HAVE__SNPRINTF)
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
|
|
@ -76,7 +76,7 @@
|
|||
#define HAVE_SHARED
|
||||
/* END DEFINES */
|
||||
#define PACKAGE "libzip"
|
||||
#define VERSION "1.5.2"
|
||||
#define VERSION "1.7.3"
|
||||
|
||||
#ifndef HAVE_SSIZE_T_LIBZIP
|
||||
# if SIZE_T_LIBZIP == INT_LIBZIP
|
||||
|
|
|
@ -1,153 +0,0 @@
|
|||
/* Adapted from NetBSB libc by Dieter Baron */
|
||||
|
||||
/* NetBSD: gettemp.c,v 1.13 2003/12/05 00:57:36 uebayasi Exp */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1987, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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 <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#include <process.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
_zip_mkstemp(char *path) {
|
||||
#ifdef _WIN32
|
||||
int ret;
|
||||
ret = _creat(_mktemp(path), _S_IREAD | _S_IWRITE);
|
||||
if (ret == -1) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
int fd;
|
||||
char *start, *trv;
|
||||
struct stat sbuf;
|
||||
pid_t pid;
|
||||
|
||||
/* To guarantee multiple calls generate unique names even if
|
||||
the file is not created. 676 different possibilities with 7
|
||||
or more X's, 26 with 6 or less. */
|
||||
static char xtra[2] = "aa";
|
||||
int xcnt = 0;
|
||||
|
||||
pid = getpid();
|
||||
|
||||
/* Move to end of path and count trailing X's. */
|
||||
for (trv = path; *trv; ++trv)
|
||||
if (*trv == 'X')
|
||||
xcnt++;
|
||||
else
|
||||
xcnt = 0;
|
||||
|
||||
/* Use at least one from xtra. Use 2 if more than 6 X's. */
|
||||
if (*(trv - 1) == 'X')
|
||||
*--trv = xtra[0];
|
||||
if (xcnt > 6 && *(trv - 1) == 'X')
|
||||
*--trv = xtra[1];
|
||||
|
||||
/* Set remaining X's to pid digits with 0's to the left. */
|
||||
while (*--trv == 'X') {
|
||||
*trv = (pid % 10) + '0';
|
||||
pid /= 10;
|
||||
}
|
||||
|
||||
/* update xtra for next call. */
|
||||
if (xtra[0] != 'z')
|
||||
xtra[0]++;
|
||||
else {
|
||||
xtra[0] = 'a';
|
||||
if (xtra[1] != 'z')
|
||||
xtra[1]++;
|
||||
else
|
||||
xtra[1] = 'a';
|
||||
}
|
||||
|
||||
/*
|
||||
* check the target directory; if you have six X's and it
|
||||
* doesn't exist this runs for a *very* long time.
|
||||
*/
|
||||
for (start = trv + 1;; --trv) {
|
||||
if (trv <= path)
|
||||
break;
|
||||
if (*trv == '/') {
|
||||
*trv = '\0';
|
||||
if (stat(path, &sbuf))
|
||||
return (0);
|
||||
if (!S_ISDIR(sbuf.st_mode)) {
|
||||
errno = ENOTDIR;
|
||||
return (0);
|
||||
}
|
||||
*trv = '/';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if ((fd = open(path, O_CREAT | O_EXCL | O_RDWR | O_BINARY, 0600)) >= 0)
|
||||
return (fd);
|
||||
if (errno != EEXIST)
|
||||
return (0);
|
||||
|
||||
/* tricky little algorithm for backward compatibility */
|
||||
for (trv = start;;) {
|
||||
if (!*trv)
|
||||
return (0);
|
||||
if (*trv == 'z')
|
||||
*trv++ = 'a';
|
||||
else {
|
||||
if (isdigit((unsigned char)*trv))
|
||||
*trv = 'a';
|
||||
else
|
||||
++*trv;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
#endif
|
||||
}
|
|
@ -58,6 +58,9 @@ extern "C" {
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#define _Nullable
|
||||
#define _Nonnull
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
|
@ -161,8 +164,8 @@ extern "C" {
|
|||
/* 13 - Reserved by PKWARE */
|
||||
#define ZIP_CM_LZMA 14 /* LZMA (EFS) */
|
||||
/* 15-17 - Reserved by PKWARE */
|
||||
#define ZIP_CM_TERSE 18 /* compressed using IBM TERSE (new) */
|
||||
#define ZIP_CM_LZ77 19 /* IBM LZ77 z Architecture (PFS) */
|
||||
#define ZIP_CM_TERSE 18 /* compressed using IBM TERSE (new) */
|
||||
#define ZIP_CM_LZ77 19 /* IBM LZ77 z Architecture (PFS) */
|
||||
#define ZIP_CM_LZMA2 33
|
||||
#define ZIP_CM_XZ 95 /* XZ compressed data */
|
||||
#define ZIP_CM_JPEG 96 /* Compressed Jpeg data */
|
||||
|
@ -214,31 +217,32 @@ extern "C" {
|
|||
|
||||
|
||||
enum zip_source_cmd {
|
||||
ZIP_SOURCE_OPEN, /* prepare for reading */
|
||||
ZIP_SOURCE_READ, /* read data */
|
||||
ZIP_SOURCE_CLOSE, /* reading is done */
|
||||
ZIP_SOURCE_STAT, /* get meta information */
|
||||
ZIP_SOURCE_ERROR, /* get error information */
|
||||
ZIP_SOURCE_FREE, /* cleanup and free resources */
|
||||
ZIP_SOURCE_SEEK, /* set position for reading */
|
||||
ZIP_SOURCE_TELL, /* get read position */
|
||||
ZIP_SOURCE_BEGIN_WRITE, /* prepare for writing */
|
||||
ZIP_SOURCE_COMMIT_WRITE, /* writing is done */
|
||||
ZIP_SOURCE_ROLLBACK_WRITE, /* discard written changes */
|
||||
ZIP_SOURCE_WRITE, /* write data */
|
||||
ZIP_SOURCE_SEEK_WRITE, /* set position for writing */
|
||||
ZIP_SOURCE_TELL_WRITE, /* get write position */
|
||||
ZIP_SOURCE_SUPPORTS, /* check whether source supports command */
|
||||
ZIP_SOURCE_REMOVE, /* remove file */
|
||||
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 */
|
||||
ZIP_SOURCE_ACCEPT_EMPTY /* whether empty files are valid archives */
|
||||
ZIP_SOURCE_OPEN, /* prepare for reading */
|
||||
ZIP_SOURCE_READ, /* read data */
|
||||
ZIP_SOURCE_CLOSE, /* reading is done */
|
||||
ZIP_SOURCE_STAT, /* get meta information */
|
||||
ZIP_SOURCE_ERROR, /* get error information */
|
||||
ZIP_SOURCE_FREE, /* cleanup and free resources */
|
||||
ZIP_SOURCE_SEEK, /* set position for reading */
|
||||
ZIP_SOURCE_TELL, /* get read position */
|
||||
ZIP_SOURCE_BEGIN_WRITE, /* prepare for writing */
|
||||
ZIP_SOURCE_COMMIT_WRITE, /* writing is done */
|
||||
ZIP_SOURCE_ROLLBACK_WRITE, /* discard written changes */
|
||||
ZIP_SOURCE_WRITE, /* write data */
|
||||
ZIP_SOURCE_SEEK_WRITE, /* set position for writing */
|
||||
ZIP_SOURCE_TELL_WRITE, /* get write position */
|
||||
ZIP_SOURCE_SUPPORTS, /* check whether source supports command */
|
||||
ZIP_SOURCE_REMOVE, /* remove file */
|
||||
ZIP_SOURCE_RESERVED_1, /* previously used internally */
|
||||
ZIP_SOURCE_BEGIN_WRITE_CLONING, /* like ZIP_SOURCE_BEGIN_WRITE, but keep part of original file */
|
||||
ZIP_SOURCE_ACCEPT_EMPTY, /* whether empty files are valid archives */
|
||||
ZIP_SOURCE_GET_FILE_ATTRIBUTES /* get additional file attributes */
|
||||
};
|
||||
typedef enum zip_source_cmd zip_source_cmd_t;
|
||||
|
||||
#define ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd) (((zip_int64_t)1) << (cmd))
|
||||
|
||||
// clang-format off
|
||||
/* clang-format off */
|
||||
|
||||
#define ZIP_SOURCE_SUPPORTS_READABLE (ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_OPEN) \
|
||||
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_READ) \
|
||||
|
@ -261,7 +265,7 @@ 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
|
||||
/* clang-format on */
|
||||
|
||||
/* for use by sources */
|
||||
struct zip_source_args_seek {
|
||||
|
@ -276,9 +280,9 @@ typedef struct zip_source_args_seek zip_source_args_seek_t;
|
|||
/* error information */
|
||||
/* use zip_error_*() to access */
|
||||
struct zip_error {
|
||||
int zip_err; /* libzip error code (ZIP_ER_*) */
|
||||
int sys_err; /* copy of errno (E*) or zlib error code */
|
||||
char *str; /* string representation or NULL */
|
||||
int zip_err; /* libzip error code (ZIP_ER_*) */
|
||||
int sys_err; /* copy of errno (E*) or zlib error code */
|
||||
char *_Nullable str; /* string representation or NULL */
|
||||
};
|
||||
|
||||
#define ZIP_STAT_NAME 0x0001u
|
||||
|
@ -293,7 +297,7 @@ struct zip_error {
|
|||
|
||||
struct zip_stat {
|
||||
zip_uint64_t valid; /* which fields have valid values */
|
||||
const char * name; /* name of the file */
|
||||
const char *_Nullable name; /* name of the file */
|
||||
zip_uint64_t index; /* index within archive */
|
||||
zip_uint64_t size; /* size of file (uncompressed) */
|
||||
zip_uint64_t comp_size; /* size of file (compressed) */
|
||||
|
@ -305,10 +309,27 @@ struct zip_stat {
|
|||
};
|
||||
|
||||
struct zip_buffer_fragment {
|
||||
zip_uint8_t * data;
|
||||
zip_uint8_t *_Nonnull data;
|
||||
zip_uint64_t length;
|
||||
};
|
||||
|
||||
struct zip_file_attributes {
|
||||
zip_uint64_t valid; /* which fields have valid values */
|
||||
zip_uint8_t version; /* version of this struct, currently 1 */
|
||||
zip_uint8_t host_system; /* host system on which file was created */
|
||||
zip_uint8_t ascii; /* flag whether file is ASCII text */
|
||||
zip_uint8_t version_needed; /* minimum version needed to extract file */
|
||||
zip_uint32_t external_file_attributes; /* external file attributes (host-system specific) */
|
||||
zip_uint16_t general_purpose_bit_flags; /* general purpose big flags, only some bits are honored */
|
||||
zip_uint16_t general_purpose_bit_mask; /* which bits in general_purpose_bit_flags are valid */
|
||||
};
|
||||
|
||||
#define ZIP_FILE_ATTRIBUTES_HOST_SYSTEM 0x0001u
|
||||
#define ZIP_FILE_ATTRIBUTES_ASCII 0x0002u
|
||||
#define ZIP_FILE_ATTRIBUTES_VERSION_NEEDED 0x0004u
|
||||
#define ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES 0x0008u
|
||||
#define ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS 0x0010u
|
||||
|
||||
struct zip;
|
||||
struct zip_file;
|
||||
struct zip_source;
|
||||
|
@ -316,121 +337,124 @@ struct zip_source;
|
|||
typedef struct zip zip_t;
|
||||
typedef struct zip_error zip_error_t;
|
||||
typedef struct zip_file zip_file_t;
|
||||
typedef struct zip_file_attributes zip_file_attributes_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)(zip_t *, double, void *);
|
||||
typedef int (*zip_cancel_callback)(zip_t *, void *);
|
||||
typedef zip_int64_t (*zip_source_callback)(void *_Nullable, void *_Nullable, zip_uint64_t, zip_source_cmd_t);
|
||||
typedef void (*zip_progress_callback)(zip_t *_Nonnull, double, void *_Nullable);
|
||||
typedef int (*zip_cancel_callback)(zip_t *_Nonnull, void *_Nullable);
|
||||
|
||||
#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 void zip_register_progress_callback(zip_t *_Nonnull, zip_progress_callback_t _Nullable); /* 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 */
|
||||
ZIP_EXTERN int zip_get_num_files(zip_t *); /* use zip_get_num_entries instead */
|
||||
ZIP_EXTERN int zip_rename(zip_t *, zip_uint64_t, const char *); /* use zip_file_rename */
|
||||
ZIP_EXTERN int zip_replace(zip_t *, zip_uint64_t, zip_source_t *); /* use zip_file_replace */
|
||||
ZIP_EXTERN int zip_set_file_comment(zip_t *, zip_uint64_t, const char *, int); /* use zip_file_set_comment */
|
||||
ZIP_EXTERN int zip_error_get_sys_type(int); /* use zip_error_system_type */
|
||||
ZIP_EXTERN void zip_error_get(zip_t *, int *, int *); /* use zip_get_error, zip_error_code_zip / zip_error_code_system */
|
||||
ZIP_EXTERN int zip_error_to_str(char *, zip_uint64_t, int, int); /* 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 */
|
||||
ZIP_EXTERN zip_int64_t zip_add(zip_t *_Nonnull, const char *_Nonnull, zip_source_t *_Nonnull); /* use zip_file_add */
|
||||
ZIP_EXTERN zip_int64_t zip_add_dir(zip_t *_Nonnull, const char *_Nonnull); /* use zip_dir_add */
|
||||
ZIP_EXTERN const char *_Nullable zip_get_file_comment(zip_t *_Nonnull, zip_uint64_t, int *_Nullable, int); /* use zip_file_get_comment */
|
||||
ZIP_EXTERN int zip_get_num_files(zip_t *_Nonnull); /* use zip_get_num_entries instead */
|
||||
ZIP_EXTERN int zip_rename(zip_t *_Nonnull, zip_uint64_t, const char *_Nonnull); /* use zip_file_rename */
|
||||
ZIP_EXTERN int zip_replace(zip_t *_Nonnull, zip_uint64_t, zip_source_t *_Nonnull); /* use zip_file_replace */
|
||||
ZIP_EXTERN int zip_set_file_comment(zip_t *_Nonnull, zip_uint64_t, const char *_Nullable, 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 *_Nonnull, int *_Nullable, int *_Nullable); /* use zip_get_error, zip_error_code_zip / zip_error_code_system */
|
||||
ZIP_EXTERN int zip_error_to_str(char *_Nonnull, zip_uint64_t, int, int); /* use zip_error_init_with_code / zip_error_strerror */
|
||||
ZIP_EXTERN void zip_file_error_get(zip_file_t *_Nonnull, int *_Nullable, int *_Nullable); /* use zip_file_get_error, zip_error_code_zip / zip_error_code_system */
|
||||
#endif
|
||||
|
||||
ZIP_EXTERN int zip_close(zip_t *);
|
||||
ZIP_EXTERN int zip_delete(zip_t *, zip_uint64_t);
|
||||
ZIP_EXTERN zip_int64_t zip_dir_add(zip_t *, const char *, zip_flags_t);
|
||||
ZIP_EXTERN void zip_discard(zip_t *);
|
||||
ZIP_EXTERN int zip_close(zip_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_delete(zip_t *_Nonnull, zip_uint64_t);
|
||||
ZIP_EXTERN zip_int64_t zip_dir_add(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t);
|
||||
ZIP_EXTERN void zip_discard(zip_t *_Nonnull);
|
||||
|
||||
ZIP_EXTERN zip_error_t * zip_get_error(zip_t *);
|
||||
ZIP_EXTERN void zip_error_clear(zip_t *);
|
||||
ZIP_EXTERN int zip_error_code_zip(const zip_error_t *);
|
||||
ZIP_EXTERN int zip_error_code_system(const zip_error_t *);
|
||||
ZIP_EXTERN void zip_error_fini(zip_error_t *);
|
||||
ZIP_EXTERN void zip_error_init(zip_error_t *);
|
||||
ZIP_EXTERN void zip_error_init_with_code(zip_error_t *, int);
|
||||
ZIP_EXTERN void zip_error_set(zip_error_t *, int, int);
|
||||
ZIP_EXTERN const char * zip_error_strerror(zip_error_t *);
|
||||
ZIP_EXTERN int zip_error_system_type(const zip_error_t *);
|
||||
ZIP_EXTERN zip_int64_t zip_error_to_data(const zip_error_t *, void *, zip_uint64_t);
|
||||
ZIP_EXTERN zip_error_t *_Nonnull zip_get_error(zip_t *_Nonnull);
|
||||
ZIP_EXTERN void zip_error_clear(zip_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_error_code_zip(const zip_error_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_error_code_system(const zip_error_t *_Nonnull);
|
||||
ZIP_EXTERN void zip_error_fini(zip_error_t *_Nonnull);
|
||||
ZIP_EXTERN void zip_error_init(zip_error_t *_Nonnull);
|
||||
ZIP_EXTERN void zip_error_init_with_code(zip_error_t *_Nonnull, int);
|
||||
ZIP_EXTERN void zip_error_set(zip_error_t *_Nullable, int, int);
|
||||
ZIP_EXTERN const char *_Nonnull zip_error_strerror(zip_error_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_error_system_type(const zip_error_t *_Nonnull);
|
||||
ZIP_EXTERN zip_int64_t zip_error_to_data(const zip_error_t *_Nonnull, void *_Nonnull, zip_uint64_t);
|
||||
|
||||
ZIP_EXTERN int zip_fclose(zip_file_t *);
|
||||
ZIP_EXTERN zip_t * zip_fdopen(int, int, int *);
|
||||
ZIP_EXTERN zip_int64_t zip_file_add(zip_t *, const char *, zip_source_t *, zip_flags_t);
|
||||
ZIP_EXTERN void zip_file_error_clear(zip_file_t *);
|
||||
ZIP_EXTERN int zip_file_extra_field_delete(zip_t *, zip_uint64_t, zip_uint16_t, zip_flags_t);
|
||||
ZIP_EXTERN int zip_file_extra_field_delete_by_id(zip_t *, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_flags_t);
|
||||
ZIP_EXTERN int zip_file_extra_field_set(zip_t *, zip_uint64_t, zip_uint16_t, zip_uint16_t, const zip_uint8_t *, zip_uint16_t, zip_flags_t);
|
||||
ZIP_EXTERN zip_int16_t zip_file_extra_fields_count(zip_t *, zip_uint64_t, zip_flags_t);
|
||||
ZIP_EXTERN zip_int16_t zip_file_extra_fields_count_by_id(zip_t *, zip_uint64_t, zip_uint16_t, zip_flags_t);
|
||||
ZIP_EXTERN const zip_uint8_t * zip_file_extra_field_get(zip_t *, zip_uint64_t, zip_uint16_t, zip_uint16_t *, zip_uint16_t *, zip_flags_t);
|
||||
ZIP_EXTERN const zip_uint8_t * zip_file_extra_field_get_by_id(zip_t *, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_uint16_t *, zip_flags_t);
|
||||
ZIP_EXTERN const char * zip_file_get_comment(zip_t *, zip_uint64_t, zip_uint32_t *, zip_flags_t);
|
||||
ZIP_EXTERN zip_error_t * zip_file_get_error(zip_file_t *);
|
||||
ZIP_EXTERN int zip_file_get_external_attributes(zip_t *, zip_uint64_t, zip_flags_t, zip_uint8_t *, zip_uint32_t *);
|
||||
ZIP_EXTERN int zip_file_rename(zip_t *, zip_uint64_t, const char *, zip_flags_t);
|
||||
ZIP_EXTERN int zip_file_replace(zip_t *, zip_uint64_t, zip_source_t *, zip_flags_t);
|
||||
ZIP_EXTERN int zip_file_set_comment(zip_t *, zip_uint64_t, const char *, zip_uint16_t, zip_flags_t);
|
||||
ZIP_EXTERN int zip_file_set_dostime(zip_t *, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_flags_t);
|
||||
ZIP_EXTERN int zip_file_set_encryption(zip_t *, zip_uint64_t, zip_uint16_t, const char *);
|
||||
ZIP_EXTERN int zip_file_set_external_attributes(zip_t *, zip_uint64_t, zip_flags_t, zip_uint8_t, zip_uint32_t);
|
||||
ZIP_EXTERN int zip_file_set_mtime(zip_t *, zip_uint64_t, time_t, zip_flags_t);
|
||||
ZIP_EXTERN const char * zip_file_strerror(zip_file_t *);
|
||||
ZIP_EXTERN zip_file_t * zip_fopen(zip_t *, const char *, zip_flags_t);
|
||||
ZIP_EXTERN zip_file_t * zip_fopen_encrypted(zip_t *, const char *, zip_flags_t, const char *);
|
||||
ZIP_EXTERN zip_file_t * zip_fopen_index(zip_t *, zip_uint64_t, zip_flags_t);
|
||||
ZIP_EXTERN zip_file_t * zip_fopen_index_encrypted(zip_t *, zip_uint64_t, zip_flags_t, const char *);
|
||||
ZIP_EXTERN zip_int64_t zip_fread(zip_file_t *, void *, zip_uint64_t);
|
||||
ZIP_EXTERN zip_int8_t zip_fseek(zip_file_t *, zip_int64_t, int);
|
||||
ZIP_EXTERN zip_int64_t zip_ftell(zip_file_t *);
|
||||
ZIP_EXTERN const char * zip_get_archive_comment(zip_t *, int *, zip_flags_t);
|
||||
ZIP_EXTERN int zip_get_archive_flag(zip_t *, zip_flags_t, zip_flags_t);
|
||||
ZIP_EXTERN const char * zip_get_name(zip_t *, zip_uint64_t, zip_flags_t);
|
||||
ZIP_EXTERN zip_int64_t zip_get_num_entries(zip_t *, zip_flags_t);
|
||||
ZIP_EXTERN 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 int zip_register_progress_callback_with_state(zip_t *, double, zip_progress_callback, void (*)(void *), void *);
|
||||
ZIP_EXTERN int zip_register_cancel_callback_with_state(zip_t *, zip_cancel_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 *);
|
||||
ZIP_EXTERN zip_source_t * zip_source_file(zip_t *, const char *, zip_uint64_t, zip_int64_t);
|
||||
ZIP_EXTERN zip_source_t * zip_source_file_create(const char *, zip_uint64_t, zip_int64_t, zip_error_t *);
|
||||
ZIP_EXTERN zip_source_t * zip_source_filep(zip_t *, FILE *, zip_uint64_t, zip_int64_t);
|
||||
ZIP_EXTERN zip_source_t * zip_source_filep_create(FILE *, zip_uint64_t, zip_int64_t, zip_error_t *);
|
||||
ZIP_EXTERN void zip_source_free(zip_source_t *);
|
||||
ZIP_EXTERN zip_source_t * zip_source_function(zip_t *, zip_source_callback , void *);
|
||||
ZIP_EXTERN zip_source_t * zip_source_function_create(zip_source_callback , void *, zip_error_t *);
|
||||
ZIP_EXTERN int zip_source_is_deleted(zip_source_t *);
|
||||
ZIP_EXTERN void zip_source_keep(zip_source_t *);
|
||||
ZIP_EXTERN int zip_fclose(zip_file_t *_Nonnull);
|
||||
ZIP_EXTERN zip_t *_Nullable zip_fdopen(int, int, int *_Nullable);
|
||||
ZIP_EXTERN zip_int64_t zip_file_add(zip_t *_Nonnull, const char *_Nonnull, zip_source_t *_Nonnull, zip_flags_t);
|
||||
ZIP_EXTERN void zip_file_attributes_init(zip_file_attributes_t *_Nonnull);
|
||||
ZIP_EXTERN void zip_file_error_clear(zip_file_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_file_extra_field_delete(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_flags_t);
|
||||
ZIP_EXTERN int zip_file_extra_field_delete_by_id(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_flags_t);
|
||||
ZIP_EXTERN int zip_file_extra_field_set(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t, const zip_uint8_t *_Nullable, zip_uint16_t, zip_flags_t);
|
||||
ZIP_EXTERN zip_int16_t zip_file_extra_fields_count(zip_t *_Nonnull, zip_uint64_t, zip_flags_t);
|
||||
ZIP_EXTERN zip_int16_t zip_file_extra_fields_count_by_id(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_flags_t);
|
||||
ZIP_EXTERN const zip_uint8_t *_Nullable zip_file_extra_field_get(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t *_Nullable, zip_uint16_t *_Nullable, zip_flags_t);
|
||||
ZIP_EXTERN const zip_uint8_t *_Nullable zip_file_extra_field_get_by_id(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_uint16_t *_Nullable, zip_flags_t);
|
||||
ZIP_EXTERN const char *_Nullable zip_file_get_comment(zip_t *_Nonnull, zip_uint64_t, zip_uint32_t *_Nullable, zip_flags_t);
|
||||
ZIP_EXTERN zip_error_t *_Nonnull zip_file_get_error(zip_file_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_file_get_external_attributes(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint8_t *_Nullable, zip_uint32_t *_Nullable);
|
||||
ZIP_EXTERN int zip_file_rename(zip_t *_Nonnull, zip_uint64_t, const char *_Nonnull, zip_flags_t);
|
||||
ZIP_EXTERN int zip_file_replace(zip_t *_Nonnull, zip_uint64_t, zip_source_t *_Nonnull, zip_flags_t);
|
||||
ZIP_EXTERN int zip_file_set_comment(zip_t *_Nonnull, zip_uint64_t, const char *_Nullable, zip_uint16_t, zip_flags_t);
|
||||
ZIP_EXTERN int zip_file_set_dostime(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_flags_t);
|
||||
ZIP_EXTERN int zip_file_set_encryption(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, const char *_Nullable);
|
||||
ZIP_EXTERN int zip_file_set_external_attributes(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint8_t, zip_uint32_t);
|
||||
ZIP_EXTERN int zip_file_set_mtime(zip_t *_Nonnull, zip_uint64_t, time_t, zip_flags_t);
|
||||
ZIP_EXTERN const char *_Nonnull zip_file_strerror(zip_file_t *_Nonnull);
|
||||
ZIP_EXTERN zip_file_t *_Nullable zip_fopen(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t);
|
||||
ZIP_EXTERN zip_file_t *_Nullable zip_fopen_encrypted(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t, const char *_Nullable);
|
||||
ZIP_EXTERN zip_file_t *_Nullable zip_fopen_index(zip_t *_Nonnull, zip_uint64_t, zip_flags_t);
|
||||
ZIP_EXTERN zip_file_t *_Nullable zip_fopen_index_encrypted(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, const char *_Nullable);
|
||||
ZIP_EXTERN zip_int64_t zip_fread(zip_file_t *_Nonnull, void *_Nonnull, zip_uint64_t);
|
||||
ZIP_EXTERN zip_int8_t zip_fseek(zip_file_t *_Nonnull, zip_int64_t, int);
|
||||
ZIP_EXTERN zip_int64_t zip_ftell(zip_file_t *_Nonnull);
|
||||
ZIP_EXTERN const char *_Nullable zip_get_archive_comment(zip_t *_Nonnull, int *_Nullable, zip_flags_t);
|
||||
ZIP_EXTERN int zip_get_archive_flag(zip_t *_Nonnull, zip_flags_t, zip_flags_t);
|
||||
ZIP_EXTERN const char *_Nullable zip_get_name(zip_t *_Nonnull, zip_uint64_t, zip_flags_t);
|
||||
ZIP_EXTERN zip_int64_t zip_get_num_entries(zip_t *_Nonnull, zip_flags_t);
|
||||
ZIP_EXTERN const char *_Nonnull zip_libzip_version(void);
|
||||
ZIP_EXTERN zip_int64_t zip_name_locate(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t);
|
||||
ZIP_EXTERN zip_t *_Nullable zip_open(const char *_Nonnull, int, int *_Nullable);
|
||||
ZIP_EXTERN zip_t *_Nullable zip_open_from_source(zip_source_t *_Nonnull, int, zip_error_t *_Nullable);
|
||||
ZIP_EXTERN int zip_register_progress_callback_with_state(zip_t *_Nonnull, double, zip_progress_callback _Nullable, void (*_Nullable)(void *_Nullable), void *_Nullable);
|
||||
ZIP_EXTERN int zip_register_cancel_callback_with_state(zip_t *_Nonnull, zip_cancel_callback _Nullable, void (*_Nullable)(void *_Nullable), void *_Nullable);
|
||||
ZIP_EXTERN int zip_set_archive_comment(zip_t *_Nonnull, const char *_Nullable, zip_uint16_t);
|
||||
ZIP_EXTERN int zip_set_archive_flag(zip_t *_Nonnull, zip_flags_t, int);
|
||||
ZIP_EXTERN int zip_set_default_password(zip_t *_Nonnull, const char *_Nullable);
|
||||
ZIP_EXTERN int zip_set_file_compression(zip_t *_Nonnull, zip_uint64_t, zip_int32_t, zip_uint32_t);
|
||||
ZIP_EXTERN int zip_source_begin_write(zip_source_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_source_begin_write_cloning(zip_source_t *_Nonnull, zip_uint64_t);
|
||||
ZIP_EXTERN zip_source_t *_Nullable zip_source_buffer(zip_t *_Nonnull, const void *_Nullable, zip_uint64_t, int);
|
||||
ZIP_EXTERN zip_source_t *_Nullable zip_source_buffer_create(const void *_Nullable, zip_uint64_t, int, zip_error_t *_Nullable);
|
||||
ZIP_EXTERN zip_source_t *_Nullable zip_source_buffer_fragment(zip_t *_Nonnull, const zip_buffer_fragment_t *_Nonnull, zip_uint64_t, int);
|
||||
ZIP_EXTERN zip_source_t *_Nullable zip_source_buffer_fragment_create(const zip_buffer_fragment_t *_Nullable, zip_uint64_t, int, zip_error_t *_Nullable);
|
||||
ZIP_EXTERN int zip_source_close(zip_source_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_source_commit_write(zip_source_t *_Nonnull);
|
||||
ZIP_EXTERN zip_error_t *_Nonnull zip_source_error(zip_source_t *_Nonnull);
|
||||
ZIP_EXTERN zip_source_t *_Nullable zip_source_file(zip_t *_Nonnull, const char *_Nonnull, zip_uint64_t, zip_int64_t);
|
||||
ZIP_EXTERN zip_source_t *_Nullable zip_source_file_create(const char *_Nonnull, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable);
|
||||
ZIP_EXTERN zip_source_t *_Nullable zip_source_filep(zip_t *_Nonnull, FILE *_Nonnull, zip_uint64_t, zip_int64_t);
|
||||
ZIP_EXTERN zip_source_t *_Nullable zip_source_filep_create(FILE *_Nonnull, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable);
|
||||
ZIP_EXTERN void zip_source_free(zip_source_t *_Nullable);
|
||||
ZIP_EXTERN zip_source_t *_Nullable zip_source_function(zip_t *_Nonnull, zip_source_callback _Nonnull, void *_Nullable);
|
||||
ZIP_EXTERN zip_source_t *_Nullable zip_source_function_create(zip_source_callback _Nonnull, void *_Nullable, zip_error_t *_Nullable);
|
||||
ZIP_EXTERN int zip_source_get_file_attributes(zip_source_t *_Nonnull, zip_file_attributes_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_source_is_deleted(zip_source_t *_Nonnull);
|
||||
ZIP_EXTERN void zip_source_keep(zip_source_t *_Nonnull);
|
||||
ZIP_EXTERN zip_int64_t zip_source_make_command_bitmap(zip_source_cmd_t, ...);
|
||||
ZIP_EXTERN int zip_source_open(zip_source_t *);
|
||||
ZIP_EXTERN zip_int64_t zip_source_read(zip_source_t *, void *, zip_uint64_t);
|
||||
ZIP_EXTERN void zip_source_rollback_write(zip_source_t *);
|
||||
ZIP_EXTERN int zip_source_seek(zip_source_t *, zip_int64_t, int);
|
||||
ZIP_EXTERN zip_int64_t zip_source_seek_compute_offset(zip_uint64_t, zip_uint64_t, void *, zip_uint64_t, zip_error_t *);
|
||||
ZIP_EXTERN int zip_source_seek_write(zip_source_t *, zip_int64_t, int);
|
||||
ZIP_EXTERN int zip_source_stat(zip_source_t *, zip_stat_t *);
|
||||
ZIP_EXTERN zip_int64_t zip_source_tell(zip_source_t *);
|
||||
ZIP_EXTERN zip_int64_t zip_source_tell_write(zip_source_t *);
|
||||
ZIP_EXTERN int zip_source_open(zip_source_t *_Nonnull);
|
||||
ZIP_EXTERN zip_int64_t zip_source_read(zip_source_t *_Nonnull, void *_Nonnull, zip_uint64_t);
|
||||
ZIP_EXTERN void zip_source_rollback_write(zip_source_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_source_seek(zip_source_t *_Nonnull, zip_int64_t, int);
|
||||
ZIP_EXTERN zip_int64_t zip_source_seek_compute_offset(zip_uint64_t, zip_uint64_t, void *_Nonnull, zip_uint64_t, zip_error_t *_Nullable);
|
||||
ZIP_EXTERN int zip_source_seek_write(zip_source_t *_Nonnull, zip_int64_t, int);
|
||||
ZIP_EXTERN int zip_source_stat(zip_source_t *_Nonnull, zip_stat_t *_Nonnull);
|
||||
ZIP_EXTERN zip_int64_t zip_source_tell(zip_source_t *_Nonnull);
|
||||
ZIP_EXTERN zip_int64_t zip_source_tell_write(zip_source_t *_Nonnull);
|
||||
#ifdef _WIN32
|
||||
ZIP_EXTERN zip_source_t *zip_source_win32a(zip_t *, const char *, zip_uint64_t, zip_int64_t);
|
||||
ZIP_EXTERN zip_source_t *zip_source_win32a_create(const char *, zip_uint64_t, zip_int64_t, zip_error_t *);
|
||||
|
@ -439,15 +463,17 @@ ZIP_EXTERN zip_source_t *zip_source_win32handle_create(void *, zip_uint64_t, zip
|
|||
ZIP_EXTERN zip_source_t *zip_source_win32w(zip_t *, const wchar_t *, zip_uint64_t, zip_int64_t);
|
||||
ZIP_EXTERN zip_source_t *zip_source_win32w_create(const wchar_t *, zip_uint64_t, zip_int64_t, zip_error_t *);
|
||||
#endif
|
||||
ZIP_EXTERN zip_int64_t zip_source_write(zip_source_t *, const void *, zip_uint64_t);
|
||||
ZIP_EXTERN zip_source_t * zip_source_zip(zip_t *, zip_t *, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t);
|
||||
ZIP_EXTERN int zip_stat(zip_t *, const char *, zip_flags_t, zip_stat_t *);
|
||||
ZIP_EXTERN int zip_stat_index(zip_t *, zip_uint64_t, zip_flags_t, zip_stat_t *);
|
||||
ZIP_EXTERN void zip_stat_init( zip_stat_t *);
|
||||
ZIP_EXTERN const char * zip_strerror(zip_t *);
|
||||
ZIP_EXTERN int zip_unchange(zip_t *, zip_uint64_t);
|
||||
ZIP_EXTERN int zip_unchange_all(zip_t *);
|
||||
ZIP_EXTERN int zip_unchange_archive(zip_t *);
|
||||
ZIP_EXTERN zip_int64_t zip_source_write(zip_source_t *_Nonnull, const void *_Nullable, zip_uint64_t);
|
||||
ZIP_EXTERN zip_source_t *_Nullable zip_source_zip(zip_t *_Nonnull, zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t);
|
||||
ZIP_EXTERN int zip_stat(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t, zip_stat_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_stat_index(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_stat_t *_Nonnull);
|
||||
ZIP_EXTERN void zip_stat_init(zip_stat_t *_Nonnull);
|
||||
ZIP_EXTERN const char *_Nonnull zip_strerror(zip_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_unchange(zip_t *_Nonnull, zip_uint64_t);
|
||||
ZIP_EXTERN int zip_unchange_all(zip_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_unchange_archive(zip_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_compression_method_supported(zip_int32_t method, int compress);
|
||||
ZIP_EXTERN int zip_encryption_method_supported(zip_uint16_t method, int encode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -91,8 +91,8 @@ deallocate(void *ud) {
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
compression_flags(void *ud) {
|
||||
static zip_uint16_t
|
||||
general_purpose_bit_flags(void *ud) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
|
||||
if (!ctx->compress) {
|
||||
|
@ -100,10 +100,10 @@ compression_flags(void *ud) {
|
|||
}
|
||||
|
||||
if (ctx->compression_flags < 3) {
|
||||
return 2;
|
||||
return 2 << 1;
|
||||
}
|
||||
else if (ctx->compression_flags > 7) {
|
||||
return 1;
|
||||
return 1 << 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -220,12 +220,13 @@ process(void *ud, zip_uint8_t *data, zip_uint64_t *length) {
|
|||
}
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
/* clang-format off */
|
||||
|
||||
zip_compression_algorithm_t zip_algorithm_deflate_compress = {
|
||||
compress_allocate,
|
||||
deallocate,
|
||||
compression_flags,
|
||||
general_purpose_bit_flags,
|
||||
20,
|
||||
start,
|
||||
end,
|
||||
input,
|
||||
|
@ -237,7 +238,8 @@ zip_compression_algorithm_t zip_algorithm_deflate_compress = {
|
|||
zip_compression_algorithm_t zip_algorithm_deflate_decompress = {
|
||||
decompress_allocate,
|
||||
deallocate,
|
||||
compression_flags,
|
||||
general_purpose_bit_flags,
|
||||
20,
|
||||
start,
|
||||
end,
|
||||
input,
|
||||
|
@ -245,4 +247,4 @@ zip_compression_algorithm_t zip_algorithm_deflate_decompress = {
|
|||
process
|
||||
};
|
||||
|
||||
// clang-format on
|
||||
/* clang-format on */
|
||||
|
|
|
@ -36,25 +36,17 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_STRINGS_H
|
||||
#include <strings.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef _WIN32
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
|
||||
static int add_data(zip_t *, zip_source_t *, zip_dirent_t *);
|
||||
static int add_data(zip_t *, zip_source_t *, zip_dirent_t *, zip_uint32_t);
|
||||
static int copy_data(zip_t *, zip_uint64_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);
|
||||
static int write_data_descriptor(zip_t *za, const zip_dirent_t *dirent, int is_zip64);
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_close(zip_t *za) {
|
||||
|
@ -204,6 +196,7 @@ zip_close(zip_t *za) {
|
|||
}
|
||||
|
||||
if ((off = zip_source_tell_write(za->src)) < 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
|
@ -221,7 +214,7 @@ zip_close(zip_t *za) {
|
|||
}
|
||||
|
||||
/* add_data writes dirent */
|
||||
if (add_data(za, zs ? zs : entry->source, de) < 0) {
|
||||
if (add_data(za, zs ? zs : entry->source, de, entry->changes ? entry->changes->changed : 0) < 0) {
|
||||
error = 1;
|
||||
if (zs)
|
||||
zip_source_free(zs);
|
||||
|
@ -233,8 +226,11 @@ zip_close(zip_t *za) {
|
|||
else {
|
||||
zip_uint64_t offset;
|
||||
|
||||
/* when copying data, all sizes are known -> no data descriptor needed */
|
||||
de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
|
||||
if (de->encryption_method != ZIP_EM_TRAD_PKWARE) {
|
||||
/* when copying data, all sizes are known -> no data descriptor needed */
|
||||
/* except for PKWare encryption, where removing the data descriptor breaks password validation */
|
||||
de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
|
||||
}
|
||||
if (_zip_dirent_write(za, de, ZIP_FL_LOCAL) < 0) {
|
||||
error = 1;
|
||||
break;
|
||||
|
@ -245,13 +241,20 @@ zip_close(zip_t *za) {
|
|||
}
|
||||
if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
error = 1;
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
if (copy_data(za, de->comp_size) < 0) {
|
||||
error = 1;
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (de->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
|
||||
if (write_data_descriptor(za, de, _zip_dirent_needs_zip64(de, 0)) < 0) {
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -282,14 +285,14 @@ zip_close(zip_t *za) {
|
|||
|
||||
|
||||
static int
|
||||
add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) {
|
||||
add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
|
||||
zip_int64_t offstart, offdata, offend, data_length;
|
||||
struct zip_stat st;
|
||||
zip_stat_t st;
|
||||
zip_file_attributes_t attributes;
|
||||
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) {
|
||||
|
@ -453,6 +456,9 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) {
|
|||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
if (de->encryption_method == ZIP_EM_TRAD_PKWARE) {
|
||||
de->bitflags |= ZIP_GPBF_DATA_DESCRIPTOR;
|
||||
}
|
||||
|
||||
zip_source_free(src_final);
|
||||
src_final = src_tmp;
|
||||
|
@ -471,7 +477,7 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) {
|
|||
ret = -1;
|
||||
}
|
||||
|
||||
if ((compression_flags = zip_source_get_compression_flags(src_final)) < 0) {
|
||||
if (zip_source_get_file_attributes(src_final, &attributes) != 0) {
|
||||
_zip_error_set_from_source(&za->error, src_final);
|
||||
ret = -1;
|
||||
}
|
||||
|
@ -507,8 +513,7 @@ 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);
|
||||
_zip_dirent_apply_attributes(de, &attributes, (flags & ZIP_FL_FORCE_ZIP64) != 0, changed);
|
||||
|
||||
if ((ret = _zip_dirent_write(za, de, flags)) < 0)
|
||||
return -1;
|
||||
|
@ -524,6 +529,12 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (de->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
|
||||
if (write_data_descriptor(za, de, is_zip64) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -656,3 +667,37 @@ _zip_changed(const zip_t *za, zip_uint64_t *survivorsp) {
|
|||
|
||||
return changed;
|
||||
}
|
||||
|
||||
static int
|
||||
write_data_descriptor(zip_t *za, const zip_dirent_t *de, int is_zip64) {
|
||||
zip_buffer_t *buffer = _zip_buffer_new(NULL, MAX_DATA_DESCRIPTOR_LENGTH);
|
||||
int ret = 0;
|
||||
|
||||
if (buffer == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_zip_buffer_put(buffer, DATADES_MAGIC, 4);
|
||||
_zip_buffer_put_32(buffer, de->crc);
|
||||
if (is_zip64) {
|
||||
_zip_buffer_put_64(buffer, de->comp_size);
|
||||
_zip_buffer_put_64(buffer, de->uncomp_size);
|
||||
}
|
||||
else {
|
||||
_zip_buffer_put_32(buffer, (zip_uint32_t)de->comp_size);
|
||||
_zip_buffer_put_32(buffer, (zip_uint32_t)de->uncomp_size);
|
||||
}
|
||||
|
||||
if (!_zip_buffer_ok(buffer)) {
|
||||
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
|
||||
ret = -1;
|
||||
}
|
||||
else {
|
||||
ret = _zip_write(za, _zip_buffer_data(buffer), _zip_buffer_offset(buffer));
|
||||
}
|
||||
|
||||
_zip_buffer_free(buffer);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
|
||||
|
@ -522,29 +521,54 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (zde->uncomp_size == ZIP_UINT32_MAX)
|
||||
if (zde->uncomp_size == ZIP_UINT32_MAX) {
|
||||
zde->uncomp_size = _zip_buffer_get_64(ef_buffer);
|
||||
}
|
||||
else if (local) {
|
||||
/* From appnote.txt: This entry in the Local header MUST
|
||||
include BOTH original and compressed file size fields. */
|
||||
(void)_zip_buffer_skip(ef_buffer, 8); /* error is caught by _zip_buffer_eof() call */
|
||||
}
|
||||
if (zde->comp_size == ZIP_UINT32_MAX)
|
||||
if (zde->comp_size == ZIP_UINT32_MAX) {
|
||||
zde->comp_size = _zip_buffer_get_64(ef_buffer);
|
||||
}
|
||||
if (!local) {
|
||||
if (zde->offset == ZIP_UINT32_MAX)
|
||||
if (zde->offset == ZIP_UINT32_MAX) {
|
||||
zde->offset = _zip_buffer_get_64(ef_buffer);
|
||||
if (zde->disk_number == ZIP_UINT16_MAX)
|
||||
}
|
||||
if (zde->disk_number == ZIP_UINT16_MAX) {
|
||||
zde->disk_number = _zip_buffer_get_32(ef_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (!_zip_buffer_eof(ef_buffer)) {
|
||||
zip_error_set(error, ZIP_ER_INCONS, 0);
|
||||
_zip_buffer_free(ef_buffer);
|
||||
if (!from_buffer) {
|
||||
_zip_buffer_free(buffer);
|
||||
/* accept additional fields if values match */
|
||||
bool ok = true;
|
||||
switch (got_len) {
|
||||
case 28:
|
||||
_zip_buffer_set_offset(ef_buffer, 24);
|
||||
if (zde->disk_number != _zip_buffer_get_32(ef_buffer)) {
|
||||
ok = false;
|
||||
}
|
||||
/* fallthrough */
|
||||
case 24:
|
||||
_zip_buffer_set_offset(ef_buffer, 0);
|
||||
if ((zde->uncomp_size != _zip_buffer_get_64(ef_buffer)) || (zde->comp_size != _zip_buffer_get_64(ef_buffer)) || (zde->offset != _zip_buffer_get_64(ef_buffer))) {
|
||||
ok = false;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ok = false;
|
||||
}
|
||||
if (!ok) {
|
||||
zip_error_set(error, ZIP_ER_INCONS, 0);
|
||||
_zip_buffer_free(ef_buffer);
|
||||
if (!from_buffer) {
|
||||
_zip_buffer_free(buffer);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
_zip_buffer_free(ef_buffer);
|
||||
}
|
||||
|
@ -572,7 +596,7 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
|
|||
|
||||
zde->extra_fields = _zip_ef_remove_internal(zde->extra_fields);
|
||||
|
||||
return (zip_int64_t)(size + variable_size);
|
||||
return (zip_int64_t)size + (zip_int64_t)variable_size;
|
||||
}
|
||||
|
||||
|
||||
|
@ -867,9 +891,9 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) {
|
|||
_zip_buffer_put(buffer, (flags & ZIP_FL_LOCAL) ? LOCAL_MAGIC : CENTRAL_MAGIC, 4);
|
||||
|
||||
if ((flags & ZIP_FL_LOCAL) == 0) {
|
||||
_zip_buffer_put_16(buffer, (zip_uint16_t)(is_really_zip64 ? 45 : de->version_madeby));
|
||||
_zip_buffer_put_16(buffer, de->version_madeby);
|
||||
}
|
||||
_zip_buffer_put_16(buffer, (zip_uint16_t)(is_really_zip64 ? 45 : de->version_needed));
|
||||
_zip_buffer_put_16(buffer, ZIP_MAX(is_really_zip64 ? 45 : 0, de->version_needed));
|
||||
_zip_buffer_put_16(buffer, de->bitflags);
|
||||
if (is_winzip_aes) {
|
||||
_zip_buffer_put_16(buffer, ZIP_CM_WINZIP_AES);
|
||||
|
@ -1074,7 +1098,7 @@ _zip_u2d_time(time_t intime, zip_uint16_t *dtime, zip_uint16_t *ddate) {
|
|||
tpm = localtime(&intime);
|
||||
#endif
|
||||
if (tpm == NULL) {
|
||||
/* if localtime() fails, return an arbitrary date (1980-01-01 00:00:00) */
|
||||
/* if localtime() fails, return an arbitrary date (1980-01-01 00:00:00) */
|
||||
*ddate = (1 << 5) + 1;
|
||||
*dtime = 0;
|
||||
return;
|
||||
|
@ -1091,36 +1115,49 @@ _zip_u2d_time(time_t intime, zip_uint16_t *dtime, zip_uint16_t *ddate) {
|
|||
|
||||
|
||||
void
|
||||
_zip_dirent_set_version_needed(zip_dirent_t *de, bool force_zip64) {
|
||||
_zip_dirent_apply_attributes(zip_dirent_t *de, zip_file_attributes_t *attributes, bool force_zip64, zip_uint32_t changed) {
|
||||
zip_uint16_t length;
|
||||
|
||||
if (attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) {
|
||||
zip_uint16_t mask = attributes->general_purpose_bit_mask & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK;
|
||||
de->bitflags = (de->bitflags & ~mask) | (attributes->general_purpose_bit_flags & mask);
|
||||
}
|
||||
if (attributes->valid & ZIP_FILE_ATTRIBUTES_ASCII) {
|
||||
de->int_attrib = (de->int_attrib & ~0x1) | (attributes->ascii ? 1 : 0);
|
||||
}
|
||||
/* manually set attributes are preferred over attributes provided by source */
|
||||
if ((changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES)) {
|
||||
de->ext_attrib = attributes->external_file_attributes;
|
||||
}
|
||||
|
||||
if (de->comp_method == ZIP_CM_LZMA) {
|
||||
de->version_needed = 63;
|
||||
return;
|
||||
}
|
||||
|
||||
if (de->comp_method == ZIP_CM_BZIP2) {
|
||||
else if (de->encryption_method == ZIP_EM_AES_128 || de->encryption_method == ZIP_EM_AES_192 || de->encryption_method == ZIP_EM_AES_256) {
|
||||
de->version_needed = 51;
|
||||
}
|
||||
else if (de->comp_method == ZIP_CM_BZIP2) {
|
||||
de->version_needed = 46;
|
||||
return;
|
||||
}
|
||||
|
||||
if (force_zip64 || _zip_dirent_needs_zip64(de, 0)) {
|
||||
else 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) {
|
||||
else if (de->comp_method == ZIP_CM_DEFLATE || de->encryption_method == ZIP_EM_TRAD_PKWARE) {
|
||||
de->version_needed = 20;
|
||||
return;
|
||||
}
|
||||
else if ((length = _zip_string_length(de->filename)) > 0 && de->filename->raw[length - 1] == '/') {
|
||||
de->version_needed = 20;
|
||||
}
|
||||
else {
|
||||
de->version_needed = 10;
|
||||
}
|
||||
|
||||
/* directory */
|
||||
if ((length = _zip_string_length(de->filename)) > 0) {
|
||||
if (de->filename->raw[length - 1] == '/') {
|
||||
de->version_needed = 20;
|
||||
return;
|
||||
}
|
||||
if (attributes->valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED) {
|
||||
de->version_needed = ZIP_MAX(de->version_needed, attributes->version_needed);
|
||||
}
|
||||
|
||||
de->version_needed = 10;
|
||||
de->version_madeby = 63 | (de->version_madeby & 0xff00);
|
||||
if ((changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM)) {
|
||||
de->version_madeby = (de->version_madeby & 0xff) | (zip_uint16_t)(attributes->host_system << 8);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
|
|
|
@ -33,8 +33,8 @@
|
|||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#define _ZIP_COMPILING_DEPRECATED
|
||||
#include "zipint.h"
|
||||
|
|
|
@ -33,10 +33,7 @@
|
|||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
|
|
|
@ -32,9 +32,6 @@
|
|||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
|
||||
|
|
|
@ -39,10 +39,7 @@ zip_encryption_implementation
|
|||
_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;
|
||||
return operation == ZIP_CODEC_DECODE ? zip_source_pkware_decode : zip_source_pkware_encode;
|
||||
|
||||
#if defined(HAVE_CRYPTO)
|
||||
case ZIP_EM_AES_128:
|
||||
|
@ -55,3 +52,11 @@ _zip_get_encryption_implementation(zip_uint16_t em, int operation) {
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_encryption_method_supported(zip_uint16_t method, int encode) {
|
||||
if (method == ZIP_EM_NONE) {
|
||||
return 1;
|
||||
}
|
||||
return _zip_get_encryption_implementation(method, encode ? ZIP_CODEC_ENCODE : ZIP_CODEC_DECODE) != NULL;
|
||||
}
|
||||
|
|
|
@ -32,19 +32,13 @@
|
|||
*/
|
||||
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
typedef enum {
|
||||
EXISTS_ERROR = -1,
|
||||
EXISTS_NOT = 0,
|
||||
EXISTS_OK
|
||||
} exists_t;
|
||||
typedef enum { EXISTS_ERROR = -1, EXISTS_NOT = 0, EXISTS_OK } exists_t;
|
||||
static zip_t *_zip_allocate_new(zip_source_t *src, unsigned int flags, zip_error_t *error);
|
||||
static zip_int64_t _zip_checkcons(zip_t *za, zip_cdir_t *cdir, zip_error_t *error);
|
||||
static zip_cdir_t *_zip_find_central_dir(zip_t *za, zip_uint64_t len);
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
zip_pkware.c -- Traditional PKWARE de/encryption backend routines
|
||||
Copyright (C) 2009-2020 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
#define PKWARE_KEY0 305419896
|
||||
#define PKWARE_KEY1 591751049
|
||||
#define PKWARE_KEY2 878082192
|
||||
|
||||
|
||||
static void
|
||||
update_keys(zip_pkware_keys_t *keys, zip_uint8_t b) {
|
||||
keys->key[0] = (zip_uint32_t)crc32(keys->key[0] ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL;
|
||||
keys->key[1] = (keys->key[1] + (keys->key[0] & 0xff)) * 134775813 + 1;
|
||||
b = (zip_uint8_t)(keys->key[1] >> 24);
|
||||
keys->key[2] = (zip_uint32_t)crc32(keys->key[2] ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL;
|
||||
}
|
||||
|
||||
|
||||
static zip_uint8_t
|
||||
crypt_byte(zip_pkware_keys_t *keys) {
|
||||
zip_uint16_t tmp;
|
||||
tmp = (zip_uint16_t)(keys->key[2] | 2);
|
||||
tmp = (zip_uint16_t)(((zip_uint32_t)tmp * (tmp ^ 1)) >> 8);
|
||||
return (zip_uint8_t)tmp;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_zip_pkware_keys_reset(zip_pkware_keys_t *keys) {
|
||||
keys->key[0] = PKWARE_KEY0;
|
||||
keys->key[1] = PKWARE_KEY1;
|
||||
keys->key[2] = PKWARE_KEY2;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_zip_pkware_encrypt(zip_pkware_keys_t *keys, zip_uint8_t *out, const zip_uint8_t *in, zip_uint64_t len) {
|
||||
zip_uint64_t i;
|
||||
zip_uint8_t b;
|
||||
zip_uint8_t tmp;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
b = in[i];
|
||||
|
||||
if (out != NULL) {
|
||||
tmp = crypt_byte(keys);
|
||||
update_keys(keys, b);
|
||||
b ^= tmp;
|
||||
out[i] = b;
|
||||
}
|
||||
else {
|
||||
/* during initialization, we're only interested in key updates */
|
||||
update_keys(keys, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_zip_pkware_decrypt(zip_pkware_keys_t *keys, zip_uint8_t *out, const zip_uint8_t *in, zip_uint64_t len) {
|
||||
zip_uint64_t i;
|
||||
zip_uint8_t b;
|
||||
zip_uint8_t tmp;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
b = in[i];
|
||||
|
||||
/* during initialization, we're only interested in key updates */
|
||||
if (out != NULL) {
|
||||
tmp = crypt_byte(keys);
|
||||
b ^= tmp;
|
||||
out[i] = b;
|
||||
}
|
||||
|
||||
update_keys(keys, b);
|
||||
}
|
||||
}
|
|
@ -209,10 +209,8 @@ _zip_progress_update(zip_progress_t *progress, double sub_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 (za->progress == NULL) {
|
||||
if (za->progress == NULL) {
|
||||
if ((za->progress = _zip_progress_new(za)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -238,10 +236,8 @@ zip_register_progress_callback_with_state(zip_t *za, double precision, zip_progr
|
|||
|
||||
ZIP_EXTERN int
|
||||
zip_register_cancel_callback_with_state(zip_t *za, zip_cancel_callback callback, void (*ud_free)(void *), void *ud) {
|
||||
zip_progress_t *progress = NULL;
|
||||
|
||||
if (callback != NULL) {
|
||||
if (za->progress == NULL) {
|
||||
if (za->progress == NULL) {
|
||||
if ((za->progress = _zip_progress_new(za)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -32,8 +32,6 @@
|
|||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define _ZIP_COMPILING_DEPRECATED
|
||||
#include "zipint.h"
|
||||
|
||||
|
|
|
@ -32,8 +32,6 @@
|
|||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define _ZIP_COMPILING_DEPRECATED
|
||||
#include "zipint.h"
|
||||
|
||||
|
|
|
@ -61,6 +61,7 @@ typedef struct buffer buffer_t;
|
|||
struct read_data {
|
||||
zip_error_t error;
|
||||
time_t mtime;
|
||||
zip_file_attributes_t attributes;
|
||||
buffer_t *in;
|
||||
buffer_t *out;
|
||||
};
|
||||
|
@ -79,33 +80,42 @@ static zip_int64_t buffer_write(buffer_t *buffer, const zip_uint8_t *data, zip_u
|
|||
|
||||
static zip_int64_t read_data(void *, void *, zip_uint64_t, zip_source_cmd_t);
|
||||
|
||||
zip_source_t *zip_source_buffer_with_attributes_create(const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes, zip_error_t *error);
|
||||
zip_source_t *zip_source_buffer_fragment_with_attributes_create(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep, zip_file_attributes_t *attributes, zip_error_t *error);
|
||||
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_buffer(zip_t *za, const void *data, zip_uint64_t len, int freep) {
|
||||
if (za == NULL)
|
||||
return NULL;
|
||||
|
||||
return zip_source_buffer_create(data, len, freep, &za->error);
|
||||
return zip_source_buffer_with_attributes_create(data, len, freep, NULL, &za->error);
|
||||
}
|
||||
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_buffer_create(const void *data, zip_uint64_t len, int freep, zip_error_t *error) {
|
||||
return zip_source_buffer_with_attributes_create(data, len, freep, NULL, error);
|
||||
}
|
||||
|
||||
|
||||
zip_source_t *
|
||||
zip_source_buffer_with_attributes_create(const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes, zip_error_t *error) {
|
||||
zip_buffer_fragment_t fragment;
|
||||
|
||||
if (data == NULL) {
|
||||
if (len > 0) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
if (len > 0) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return zip_source_buffer_fragment_create(NULL, 0, freep, error);
|
||||
return zip_source_buffer_fragment_with_attributes_create(NULL, 0, freep, attributes, error);
|
||||
}
|
||||
|
||||
fragment.data = (zip_uint8_t *)data;
|
||||
fragment.length = len;
|
||||
|
||||
return zip_source_buffer_fragment_create(&fragment, 1, freep, error);
|
||||
return zip_source_buffer_fragment_with_attributes_create(&fragment, 1, freep, attributes, error);
|
||||
}
|
||||
|
||||
|
||||
|
@ -115,12 +125,17 @@ zip_source_buffer_fragment(zip_t *za, const zip_buffer_fragment_t *fragments, zi
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return zip_source_buffer_fragment_create(fragments, nfragments, freep, &za->error);
|
||||
return zip_source_buffer_fragment_with_attributes_create(fragments, nfragments, freep, NULL, &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) {
|
||||
return zip_source_buffer_fragment_with_attributes_create(fragments, nfragments, freep, NULL, error);
|
||||
}
|
||||
|
||||
zip_source_t *
|
||||
zip_source_buffer_fragment_with_attributes_create(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep, zip_file_attributes_t *attributes, zip_error_t *error) {
|
||||
struct read_data *ctx;
|
||||
zip_source_t *zs;
|
||||
buffer_t *buffer;
|
||||
|
@ -143,6 +158,12 @@ zip_source_buffer_fragment_create(const zip_buffer_fragment_t *fragments, zip_ui
|
|||
ctx->in = buffer;
|
||||
ctx->out = NULL;
|
||||
ctx->mtime = time(NULL);
|
||||
if (attributes) {
|
||||
memcpy(&ctx->attributes, attributes, sizeof(ctx->attributes));
|
||||
}
|
||||
else {
|
||||
zip_file_attributes_init(&ctx->attributes);
|
||||
}
|
||||
zip_error_init(&ctx->error);
|
||||
|
||||
if ((zs = zip_source_function_create(read_data, ctx, error)) == NULL) {
|
||||
|
@ -155,6 +176,11 @@ zip_source_buffer_fragment_create(const zip_buffer_fragment_t *fragments, zip_ui
|
|||
}
|
||||
|
||||
|
||||
zip_source_t *
|
||||
zip_source_buffer_with_attributes(zip_t *za, const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes) {
|
||||
return zip_source_buffer_with_attributes_create(data, len, freep, attributes, &za->error);
|
||||
}
|
||||
|
||||
static zip_int64_t
|
||||
read_data(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
|
||||
struct read_data *ctx = (struct read_data *)state;
|
||||
|
@ -194,6 +220,17 @@ read_data(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
|
|||
free(ctx);
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_GET_FILE_ATTRIBUTES: {
|
||||
if (len < sizeof(ctx->attributes)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(data, &ctx->attributes, sizeof(ctx->attributes));
|
||||
|
||||
return sizeof(ctx->attributes);
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_OPEN:
|
||||
ctx->in->offset = 0;
|
||||
ctx->in->current_fragment = 0;
|
||||
|
@ -250,7 +287,7 @@ read_data(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
|
|||
}
|
||||
|
||||
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_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);
|
||||
return zip_source_make_command_bitmap(ZIP_SOURCE_GET_FILE_ATTRIBUTES, 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) {
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
@ -68,12 +67,12 @@ static struct implementation implementations[] = {
|
|||
{ZIP_CM_BZIP2, &zip_algorithm_bzip2_compress, &zip_algorithm_bzip2_decompress},
|
||||
#endif
|
||||
#if defined(HAVE_LIBLZMA)
|
||||
/* Disabled - because 7z isn't able to unpack ZIP+LZMA ZIP+LZMA2
|
||||
archives made this way - and vice versa.
|
||||
/* Disabled - because 7z isn't able to unpack ZIP+LZMA ZIP+LZMA2
|
||||
archives made this way - and vice versa.
|
||||
|
||||
{ZIP_CM_LZMA, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress},
|
||||
{ZIP_CM_LZMA2, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress},
|
||||
*/
|
||||
{ZIP_CM_LZMA, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress},
|
||||
{ZIP_CM_LZMA2, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress},
|
||||
*/
|
||||
{ZIP_CM_XZ, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress},
|
||||
#endif
|
||||
|
||||
|
@ -106,10 +105,10 @@ get_algorithm(zip_int32_t method, bool compress) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
zip_compression_method_supported(zip_int32_t method, bool compress) {
|
||||
ZIP_EXTERN int
|
||||
zip_compression_method_supported(zip_int32_t method, int compress) {
|
||||
if (method == ZIP_CM_STORE) {
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
return get_algorithm(method, compress) != NULL;
|
||||
}
|
||||
|
@ -357,9 +356,6 @@ compress_callback(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip
|
|||
}
|
||||
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);
|
||||
|
||||
|
@ -367,8 +363,24 @@ compress_callback(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip
|
|||
context_free(ctx);
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_GET_FILE_ATTRIBUTES: {
|
||||
zip_file_attributes_t *attributes = (zip_file_attributes_t *)data;
|
||||
|
||||
if (len < sizeof(*attributes)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED | ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS;
|
||||
attributes->version_needed = ctx->algorithm->version_needed;
|
||||
attributes->general_purpose_bit_mask = ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK;
|
||||
attributes->general_purpose_bit_flags = (ctx->is_stored ? 0 : ctx->algorithm->general_purpose_bit_flags(ctx->ud));
|
||||
|
||||
return sizeof(*attributes);
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_SUPPORTS:
|
||||
return ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_GET_COMPRESSION_FLAGS, -1);
|
||||
return ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1);
|
||||
|
||||
default:
|
||||
zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
|
@ -167,7 +167,7 @@ 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, ZIP_SOURCE_GET_COMPRESSION_FLAGS, -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_FILE_ATTRIBUTES, -1);
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_SEEK: {
|
||||
|
|
|
@ -1,415 +0,0 @@
|
|||
/*
|
||||
zip_source_deflate.c -- deflate (de)compressoin routines
|
||||
Copyright (C) 2009-2015 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
struct deflate {
|
||||
zip_error_t error;
|
||||
|
||||
bool eof;
|
||||
bool can_store;
|
||||
bool is_stored;
|
||||
int mem_level;
|
||||
zip_uint64_t size;
|
||||
zip_uint8_t buffer[BUFSIZE];
|
||||
z_stream zstr;
|
||||
};
|
||||
|
||||
static zip_int64_t compress_read(zip_source_t *, struct deflate *, void *, zip_uint64_t);
|
||||
static zip_int64_t decompress_read(zip_source_t *, struct deflate *, void *, zip_uint64_t);
|
||||
static zip_int64_t deflate_compress(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t);
|
||||
static zip_int64_t deflate_decompress(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t);
|
||||
static void deflate_free(struct deflate *);
|
||||
|
||||
|
||||
zip_source_t *
|
||||
zip_source_deflate(zip_t *za, zip_source_t *src, zip_int32_t cm, int flags)
|
||||
{
|
||||
struct deflate *ctx;
|
||||
zip_source_t *s2;
|
||||
|
||||
if (src == NULL || (cm != ZIP_CM_DEFLATE && !ZIP_CM_IS_DEFAULT(cm))) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((ctx=(struct deflate *)malloc(sizeof(*ctx))) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
zip_error_init(&ctx->error);
|
||||
ctx->eof = false;
|
||||
ctx->is_stored = false;
|
||||
ctx->can_store = ZIP_CM_IS_DEFAULT(cm);
|
||||
if (flags & ZIP_CODEC_ENCODE) {
|
||||
ctx->mem_level = MAX_MEM_LEVEL;
|
||||
}
|
||||
|
||||
if ((s2=zip_source_layered(za, src,
|
||||
((flags & ZIP_CODEC_ENCODE)
|
||||
? deflate_compress : deflate_decompress),
|
||||
ctx)) == NULL) {
|
||||
deflate_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return s2;
|
||||
}
|
||||
|
||||
|
||||
static zip_int64_t
|
||||
compress_read(zip_source_t *src, struct deflate *ctx, void *data, zip_uint64_t len)
|
||||
{
|
||||
int end, ret;
|
||||
zip_int64_t n;
|
||||
zip_uint64_t out_offset;
|
||||
uInt out_len;
|
||||
|
||||
if (zip_error_code_zip(&ctx->error) != ZIP_ER_OK)
|
||||
return -1;
|
||||
|
||||
if (len == 0 || ctx->is_stored) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
out_offset = 0;
|
||||
out_len = (uInt)ZIP_MIN(UINT_MAX, len);
|
||||
ctx->zstr.next_out = (Bytef *)data;
|
||||
ctx->zstr.avail_out = out_len;
|
||||
|
||||
end = 0;
|
||||
while (!end) {
|
||||
ret = deflate(&ctx->zstr, ctx->eof ? Z_FINISH : 0);
|
||||
|
||||
switch (ret) {
|
||||
case Z_STREAM_END:
|
||||
if (ctx->can_store && ctx->zstr.total_in <= ctx->zstr.total_out) {
|
||||
ctx->is_stored = true;
|
||||
ctx->size = ctx->zstr.total_in;
|
||||
memcpy(data, ctx->buffer, ctx->size);
|
||||
return (zip_int64_t)ctx->size;
|
||||
}
|
||||
/* fallthrough */
|
||||
case Z_OK:
|
||||
/* all ok */
|
||||
|
||||
if (ctx->zstr.avail_out == 0) {
|
||||
out_offset += out_len;
|
||||
if (out_offset < len) {
|
||||
out_len = (uInt)ZIP_MIN(UINT_MAX, len-out_offset);
|
||||
ctx->zstr.next_out = (Bytef *)data+out_offset;
|
||||
ctx->zstr.avail_out = out_len;
|
||||
}
|
||||
else {
|
||||
ctx->can_store = false;
|
||||
end = 1;
|
||||
}
|
||||
}
|
||||
else if (ctx->eof && ctx->zstr.avail_in == 0)
|
||||
end = 1;
|
||||
break;
|
||||
|
||||
case Z_BUF_ERROR:
|
||||
if (ctx->zstr.avail_in == 0) {
|
||||
if (ctx->eof) {
|
||||
end = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
|
||||
_zip_error_set_from_source(&ctx->error, src);
|
||||
end = 1;
|
||||
break;
|
||||
}
|
||||
else if (n == 0) {
|
||||
ctx->eof = true;
|
||||
/* TODO: check against stat of src? */
|
||||
ctx->size = ctx->zstr.total_in;
|
||||
}
|
||||
else {
|
||||
if (ctx->zstr.total_in > 0) {
|
||||
/* we overwrote a previously filled ctx->buffer */
|
||||
ctx->can_store = false;
|
||||
}
|
||||
ctx->zstr.next_in = (Bytef *)ctx->buffer;
|
||||
ctx->zstr.avail_in = (uInt)n;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
/* fallthrough */
|
||||
case Z_NEED_DICT:
|
||||
case Z_DATA_ERROR:
|
||||
case Z_STREAM_ERROR:
|
||||
case Z_MEM_ERROR:
|
||||
zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret);
|
||||
|
||||
end = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->zstr.avail_out < len) {
|
||||
ctx->can_store = false;
|
||||
return (zip_int64_t)(len - ctx->zstr.avail_out);
|
||||
}
|
||||
|
||||
return (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) ? 0 : -1;
|
||||
}
|
||||
|
||||
|
||||
static zip_int64_t
|
||||
decompress_read(zip_source_t *src, struct deflate *ctx, void *data, zip_uint64_t len)
|
||||
{
|
||||
int end, ret;
|
||||
zip_int64_t n;
|
||||
zip_uint64_t out_offset;
|
||||
uInt out_len;
|
||||
|
||||
if (zip_error_code_zip(&ctx->error) != ZIP_ER_OK)
|
||||
return -1;
|
||||
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
out_offset = 0;
|
||||
out_len = (uInt)ZIP_MIN(UINT_MAX, len);
|
||||
ctx->zstr.next_out = (Bytef *)data;
|
||||
ctx->zstr.avail_out = out_len;
|
||||
|
||||
end = 0;
|
||||
while (!end) {
|
||||
ret = inflate(&ctx->zstr, Z_SYNC_FLUSH);
|
||||
|
||||
switch (ret) {
|
||||
case Z_OK:
|
||||
if (ctx->zstr.avail_out == 0) {
|
||||
out_offset += out_len;
|
||||
if (out_offset < len) {
|
||||
out_len = (uInt)ZIP_MIN(UINT_MAX, len-out_offset);
|
||||
ctx->zstr.next_out = (Bytef *)data+out_offset;
|
||||
ctx->zstr.avail_out = out_len;
|
||||
}
|
||||
else {
|
||||
end = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Z_STREAM_END:
|
||||
ctx->eof = 1;
|
||||
end = 1;
|
||||
break;
|
||||
|
||||
case Z_BUF_ERROR:
|
||||
if (ctx->zstr.avail_in == 0) {
|
||||
if (ctx->eof) {
|
||||
end = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
|
||||
_zip_error_set_from_source(&ctx->error, src);
|
||||
end = 1;
|
||||
break;
|
||||
}
|
||||
else if (n == 0) {
|
||||
ctx->eof = 1;
|
||||
}
|
||||
else {
|
||||
ctx->zstr.next_in = (Bytef *)ctx->buffer;
|
||||
ctx->zstr.avail_in = (uInt)n;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
/* fallthrough */
|
||||
case Z_NEED_DICT:
|
||||
case Z_DATA_ERROR:
|
||||
case Z_STREAM_ERROR:
|
||||
case Z_MEM_ERROR:
|
||||
zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret);
|
||||
end = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->zstr.avail_out < len)
|
||||
return (zip_int64_t)(len - ctx->zstr.avail_out);
|
||||
|
||||
return (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) ? 0 : -1;
|
||||
}
|
||||
|
||||
|
||||
static zip_int64_t
|
||||
deflate_compress(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
|
||||
{
|
||||
struct deflate *ctx;
|
||||
int ret;
|
||||
|
||||
ctx = (struct deflate *)ud;
|
||||
|
||||
switch (cmd) {
|
||||
case ZIP_SOURCE_OPEN:
|
||||
ctx->zstr.zalloc = Z_NULL;
|
||||
ctx->zstr.zfree = Z_NULL;
|
||||
ctx->zstr.opaque = NULL;
|
||||
ctx->zstr.avail_in = 0;
|
||||
ctx->zstr.next_in = NULL;
|
||||
ctx->zstr.avail_out = 0;
|
||||
ctx->zstr.next_out = NULL;
|
||||
|
||||
/* negative value to tell zlib not to write a header */
|
||||
if ((ret=deflateInit2(&ctx->zstr, Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS, ctx->mem_level, Z_DEFAULT_STRATEGY)) != Z_OK) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_READ:
|
||||
return compress_read(src, ctx, data, len);
|
||||
|
||||
case ZIP_SOURCE_CLOSE:
|
||||
deflateEnd(&ctx->zstr);
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_STAT:
|
||||
{
|
||||
zip_stat_t *st;
|
||||
|
||||
st = (zip_stat_t *)data;
|
||||
|
||||
st->comp_method = ctx->is_stored ? ZIP_CM_STORE : ZIP_CM_DEFLATE;
|
||||
st->valid |= ZIP_STAT_COMP_METHOD;
|
||||
if (ctx->eof) {
|
||||
st->comp_size = ctx->size;
|
||||
st->valid |= ZIP_STAT_COMP_SIZE;
|
||||
}
|
||||
else
|
||||
st->valid &= ~ZIP_STAT_COMP_SIZE;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_ERROR:
|
||||
return zip_error_to_data(&ctx->error, data, len);
|
||||
|
||||
case ZIP_SOURCE_FREE:
|
||||
deflate_free(ctx);
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_SUPPORTS:
|
||||
return ZIP_SOURCE_SUPPORTS_READABLE;
|
||||
|
||||
default:
|
||||
zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static zip_int64_t
|
||||
deflate_decompress(zip_source_t *src, void *ud, void *data,
|
||||
zip_uint64_t len, zip_source_cmd_t cmd)
|
||||
{
|
||||
struct deflate *ctx;
|
||||
zip_int64_t n;
|
||||
int ret;
|
||||
|
||||
ctx = (struct deflate *)ud;
|
||||
|
||||
switch (cmd) {
|
||||
case ZIP_SOURCE_OPEN:
|
||||
if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
|
||||
_zip_error_set_from_source(&ctx->error, src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->zstr.zalloc = Z_NULL;
|
||||
ctx->zstr.zfree = Z_NULL;
|
||||
ctx->zstr.opaque = NULL;
|
||||
ctx->zstr.next_in = (Bytef *)ctx->buffer;
|
||||
ctx->zstr.avail_in = (uInt)n;
|
||||
|
||||
/* negative value to tell zlib that there is no header */
|
||||
if ((ret=inflateInit2(&ctx->zstr, -MAX_WBITS)) != Z_OK) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_READ:
|
||||
return decompress_read(src, ctx, data, len);
|
||||
|
||||
case ZIP_SOURCE_CLOSE:
|
||||
inflateEnd(&ctx->zstr);
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_STAT:
|
||||
{
|
||||
zip_stat_t *st;
|
||||
|
||||
st = (zip_stat_t *)data;
|
||||
|
||||
st->comp_method = ZIP_CM_STORE;
|
||||
if (st->comp_size > 0 && st->size > 0)
|
||||
st->comp_size = st->size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_ERROR:
|
||||
return zip_error_to_data(&ctx->error, data, len);
|
||||
|
||||
case ZIP_SOURCE_FREE:
|
||||
free(ctx);
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_SUPPORTS:
|
||||
return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1);
|
||||
|
||||
default:
|
||||
zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
deflate_free(struct deflate *ctx)
|
||||
{
|
||||
free(ctx);
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
zip_source_file.c -- create data source from file
|
||||
Copyright (C) 1999-2019 Dieter Baron 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 <stdio.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#error This file is incompatible with Windows, use zip_source_win32utf8.c instead.
|
||||
#error Something probably went wrong with configure/cmake.
|
||||
#endif
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_file(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t len) {
|
||||
if (za == NULL)
|
||||
return NULL;
|
||||
|
||||
return zip_source_file_create(fname, start, len, &za->error);
|
||||
}
|
||||
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_file_create(const char *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error) {
|
||||
if (fname == NULL || length < -1) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return _zip_source_file_or_p(fname, NULL, start, length, NULL, error);
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
zip_source_file.h -- header for common file operations
|
||||
Copyright (C) 2020 Dieter Baron 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.
|
||||
*/
|
||||
|
||||
struct zip_source_file_stat {
|
||||
zip_uint64_t size; /* must be valid for regular files */
|
||||
time_t mtime; /* must always be valid, is initialized to current time */
|
||||
bool exists; /* must always be vaild */
|
||||
bool regular_file; /* must always be valid */
|
||||
};
|
||||
|
||||
typedef struct zip_source_file_context zip_source_file_context_t;
|
||||
typedef struct zip_source_file_operations zip_source_file_operations_t;
|
||||
typedef struct zip_source_file_stat zip_source_file_stat_t;
|
||||
|
||||
struct zip_source_file_context {
|
||||
zip_error_t error; /* last error information */
|
||||
zip_int64_t supports;
|
||||
|
||||
/* reading */
|
||||
char *fname; /* name of file to read from */
|
||||
void *f; /* file to read from */
|
||||
zip_stat_t st; /* stat information passed in */
|
||||
zip_file_attributes_t attributes; /* additional file attributes */
|
||||
zip_error_t stat_error; /* error returned for stat */
|
||||
zip_uint64_t start; /* start offset of data to read */
|
||||
zip_uint64_t len; /* length of the file, 0 for up to EOF */
|
||||
zip_uint64_t offset; /* current offset relative to start (0 is beginning of part we read) */
|
||||
|
||||
/* writing */
|
||||
char *tmpname;
|
||||
void *fout;
|
||||
|
||||
zip_source_file_operations_t *ops;
|
||||
void *ops_userdata;
|
||||
};
|
||||
|
||||
|
||||
/* The following methods must be implemented to support each feature:
|
||||
- close, read, seek, and stat must always be implemented.
|
||||
- To support specifying the file by name, open, and strdup must be implemented.
|
||||
- For write support, the file must be specified by name and close, commit_write, create_temp_output, remove, rollback_write, and tell must be implemented.
|
||||
- create_temp_output_cloning is always optional. */
|
||||
|
||||
struct zip_source_file_operations {
|
||||
void (*close)(zip_source_file_context_t *ctx);
|
||||
zip_int64_t (*commit_write)(zip_source_file_context_t *ctx);
|
||||
zip_int64_t (*create_temp_output)(zip_source_file_context_t *ctx);
|
||||
zip_int64_t (*create_temp_output_cloning)(zip_source_file_context_t *ctx, zip_uint64_t len);
|
||||
bool (*open)(zip_source_file_context_t *ctx);
|
||||
zip_int64_t (*read)(zip_source_file_context_t *ctx, void *buf, zip_uint64_t len);
|
||||
zip_int64_t (*remove)(zip_source_file_context_t *ctx);
|
||||
void (*rollback_write)(zip_source_file_context_t *ctx);
|
||||
bool (*seek)(zip_source_file_context_t *ctx, void *f, zip_int64_t offset, int whence);
|
||||
bool (*stat)(zip_source_file_context_t *ctx, zip_source_file_stat_t *st);
|
||||
char *(*string_duplicate)(zip_source_file_context_t *ctx, const char *);
|
||||
zip_int64_t (*tell)(zip_source_file_context_t *ctx, void *f);
|
||||
zip_int64_t (*write)(zip_source_file_context_t *ctx, const void *data, zip_uint64_t len);
|
||||
};
|
||||
|
||||
zip_source_t *zip_source_file_common_new(const char *fname, void *file, zip_uint64_t start, zip_int64_t len, const zip_stat_t *st, zip_source_file_operations_t *ops, void *ops_userdata, zip_error_t *error);
|
|
@ -0,0 +1,378 @@
|
|||
/*
|
||||
zip_source_file_common.c -- create data source from file
|
||||
Copyright (C) 1999-2019 Dieter Baron 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
#include "zip_source_file.h"
|
||||
|
||||
static zip_int64_t read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd);
|
||||
|
||||
static void
|
||||
zip_source_file_stat_init(zip_source_file_stat_t *st) {
|
||||
st->size = 0;
|
||||
st->mtime = time(NULL);
|
||||
st->exists = false;
|
||||
st->regular_file = false;
|
||||
}
|
||||
|
||||
zip_source_t *
|
||||
zip_source_file_common_new(const char *fname, void *file, zip_uint64_t start, zip_int64_t len, const zip_stat_t *st, zip_source_file_operations_t *ops, void *ops_userdata, zip_error_t *error) {
|
||||
zip_source_file_context_t *ctx;
|
||||
zip_source_t *zs;
|
||||
zip_source_file_stat_t sb;
|
||||
|
||||
if (ops == NULL) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ops->close == NULL || ops->read == NULL || ops->seek == NULL || ops->stat == NULL) {
|
||||
zip_error_set(error, ZIP_ER_INTERNAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ops->write != NULL && (ops->commit_write == NULL || ops->create_temp_output == NULL || ops->remove == NULL || ops->rollback_write == NULL || ops->tell == NULL)) {
|
||||
zip_error_set(error, ZIP_ER_INTERNAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fname != NULL) {
|
||||
if (ops->open == NULL || ops->string_duplicate == NULL) {
|
||||
zip_error_set(error, ZIP_ER_INTERNAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (file == NULL) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (len < 0) {
|
||||
len = 0;
|
||||
}
|
||||
|
||||
if (start > ZIP_INT64_MAX || start + (zip_uint64_t)len < start) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((ctx = (zip_source_file_context_t *)malloc(sizeof(zip_source_file_context_t))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->ops = ops;
|
||||
ctx->ops_userdata = ops_userdata;
|
||||
ctx->fname = NULL;
|
||||
if (fname) {
|
||||
if ((ctx->fname = ops->string_duplicate(ctx, fname)) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
ctx->f = file;
|
||||
ctx->start = start;
|
||||
ctx->len = (zip_uint64_t)len;
|
||||
if (st) {
|
||||
memcpy(&ctx->st, st, sizeof(ctx->st));
|
||||
ctx->st.name = NULL;
|
||||
ctx->st.valid &= ~ZIP_STAT_NAME;
|
||||
}
|
||||
else {
|
||||
zip_stat_init(&ctx->st);
|
||||
}
|
||||
|
||||
if (ctx->len > 0) {
|
||||
ctx->st.size = ctx->len;
|
||||
ctx->st.valid |= ZIP_STAT_SIZE;
|
||||
}
|
||||
|
||||
zip_error_init(&ctx->stat_error);
|
||||
|
||||
ctx->tmpname = NULL;
|
||||
ctx->fout = NULL;
|
||||
|
||||
zip_error_init(&ctx->error);
|
||||
zip_file_attributes_init(&ctx->attributes);
|
||||
|
||||
ctx->supports = ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1);
|
||||
|
||||
zip_source_file_stat_init(&sb);
|
||||
if (!ops->stat(ctx, &sb)) {
|
||||
_zip_error_copy(error, &ctx->error);
|
||||
free(ctx->fname);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!sb.exists) {
|
||||
if (ctx->fname && ctx->start == 0 && ctx->len == 0 && ops->write != NULL) {
|
||||
ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE;
|
||||
/* zip_open_from_source checks for this to detect non-existing files */
|
||||
zip_error_set(&ctx->stat_error, ZIP_ER_READ, ENOENT);
|
||||
}
|
||||
else {
|
||||
zip_error_set(&ctx->stat_error, ZIP_ER_READ, ENOENT);
|
||||
free(ctx->fname);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((ctx->st.valid & ZIP_STAT_MTIME) == 0) {
|
||||
ctx->st.mtime = sb.mtime;
|
||||
ctx->st.valid |= ZIP_STAT_MTIME;
|
||||
}
|
||||
if (sb.regular_file) {
|
||||
ctx->supports = ZIP_SOURCE_SUPPORTS_SEEKABLE;
|
||||
|
||||
if (ctx->start + ctx->len > sb.size) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
free(ctx->fname);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ctx->len == 0) {
|
||||
ctx->len = sb.size - ctx->start;
|
||||
ctx->st.size = ctx->len;
|
||||
ctx->st.valid |= ZIP_STAT_SIZE;
|
||||
|
||||
/* when using a partial file, don't allow writing */
|
||||
if (ctx->fname && start == 0 && ops->write != NULL) {
|
||||
ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_GET_FILE_ATTRIBUTES);
|
||||
}
|
||||
|
||||
ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ACCEPT_EMPTY);
|
||||
if (ops->create_temp_output_cloning != NULL) {
|
||||
if (ctx->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE)) {
|
||||
ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING);
|
||||
}
|
||||
}
|
||||
|
||||
if ((zs = zip_source_function_create(read_file, ctx, error)) == NULL) {
|
||||
free(ctx->fname);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return zs;
|
||||
}
|
||||
|
||||
|
||||
static zip_int64_t
|
||||
read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
|
||||
zip_source_file_context_t *ctx;
|
||||
char *buf;
|
||||
|
||||
ctx = (zip_source_file_context_t *)state;
|
||||
buf = (char *)data;
|
||||
|
||||
switch (cmd) {
|
||||
case ZIP_SOURCE_ACCEPT_EMPTY:
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_BEGIN_WRITE:
|
||||
/* write support should not be set if fname is NULL */
|
||||
if (ctx->fname == NULL) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
}
|
||||
return ctx->ops->create_temp_output(ctx);
|
||||
|
||||
case ZIP_SOURCE_BEGIN_WRITE_CLONING:
|
||||
/* write support should not be set if fname is NULL */
|
||||
if (ctx->fname == NULL) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
}
|
||||
return ctx->ops->create_temp_output_cloning(ctx, len);
|
||||
|
||||
case ZIP_SOURCE_CLOSE:
|
||||
if (ctx->fname) {
|
||||
ctx->ops->close(ctx);
|
||||
ctx->f = NULL;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_COMMIT_WRITE: {
|
||||
zip_int64_t ret = ctx->ops->commit_write(ctx);
|
||||
ctx->fout = NULL;
|
||||
if (ret == 0) {
|
||||
free(ctx->tmpname);
|
||||
ctx->tmpname = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_ERROR:
|
||||
return zip_error_to_data(&ctx->error, data, len);
|
||||
|
||||
case ZIP_SOURCE_FREE:
|
||||
free(ctx->fname);
|
||||
free(ctx->tmpname);
|
||||
if (ctx->f) {
|
||||
ctx->ops->close(ctx);
|
||||
}
|
||||
free(ctx);
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_GET_FILE_ATTRIBUTES:
|
||||
if (len < sizeof(ctx->attributes)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
memcpy(data, &ctx->attributes, sizeof(ctx->attributes));
|
||||
return sizeof(ctx->attributes);
|
||||
|
||||
case ZIP_SOURCE_OPEN:
|
||||
if (ctx->fname) {
|
||||
if (ctx->ops->open(ctx) == false) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->start > 0) { // TODO: rewind on re-open
|
||||
if (ctx->ops->seek(ctx, ctx->f, (zip_int64_t)ctx->start, SEEK_SET) == false) {
|
||||
/* TODO: skip by reading */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
ctx->offset = 0;
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_READ: {
|
||||
zip_int64_t i;
|
||||
zip_uint64_t n;
|
||||
|
||||
if (ctx->len > 0) {
|
||||
n = ZIP_MIN(ctx->len - ctx->offset, len);
|
||||
}
|
||||
else {
|
||||
n = len;
|
||||
}
|
||||
|
||||
if ((i = ctx->ops->read(ctx, buf, n)) < 0) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_READ, errno);
|
||||
return -1;
|
||||
}
|
||||
ctx->offset += (zip_uint64_t)i;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_REMOVE:
|
||||
return ctx->ops->remove(ctx);
|
||||
|
||||
case ZIP_SOURCE_ROLLBACK_WRITE:
|
||||
ctx->ops->rollback_write(ctx);
|
||||
ctx->fout = NULL;
|
||||
free(ctx->tmpname);
|
||||
ctx->tmpname = NULL;
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_SEEK: {
|
||||
zip_int64_t new_offset = zip_source_seek_compute_offset(ctx->offset, ctx->len, data, len, &ctx->error);
|
||||
|
||||
if (new_offset < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The actual offset inside the file must be representable as zip_int64_t. */
|
||||
if (new_offset > ZIP_INT64_MAX - (zip_int64_t)ctx->start) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_SEEK, EOVERFLOW);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->offset = (zip_uint64_t)new_offset;
|
||||
|
||||
if (ctx->ops->seek(ctx, ctx->f, (zip_int64_t)(ctx->offset + ctx->start), SEEK_SET) == false) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_SEEK_WRITE: {
|
||||
zip_source_args_seek_t *args;
|
||||
|
||||
args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);
|
||||
if (args == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ctx->ops->seek(ctx, ctx->fout, args->offset, args->whence) == false) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_STAT: {
|
||||
if (len < sizeof(ctx->st))
|
||||
return -1;
|
||||
|
||||
if (zip_error_code_zip(&ctx->stat_error) != 0) {
|
||||
zip_error_set(&ctx->error, zip_error_code_zip(&ctx->stat_error), zip_error_code_system(&ctx->stat_error));
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(data, &ctx->st, sizeof(ctx->st));
|
||||
return sizeof(ctx->st);
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_SUPPORTS:
|
||||
return ctx->supports;
|
||||
|
||||
case ZIP_SOURCE_TELL:
|
||||
return (zip_int64_t)ctx->offset;
|
||||
|
||||
case ZIP_SOURCE_TELL_WRITE:
|
||||
return ctx->ops->tell(ctx, ctx->fout);
|
||||
|
||||
case ZIP_SOURCE_WRITE:
|
||||
return ctx->ops->write(ctx, data, len);
|
||||
|
||||
default:
|
||||
zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
zip_source_file_stdio.c -- read-only stdio file source implementation
|
||||
Copyright (C) 2020 Dieter Baron 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 "zip_source_file.h"
|
||||
#include "zip_source_file_stdio.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef S_IWUSR
|
||||
#define S_IWUSR _S_IWRITE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* clang-format off */
|
||||
static zip_source_file_operations_t ops_stdio_read = {
|
||||
_zip_stdio_op_close,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
_zip_stdio_op_read,
|
||||
NULL,
|
||||
NULL,
|
||||
_zip_stdio_op_seek,
|
||||
_zip_stdio_op_stat,
|
||||
NULL,
|
||||
_zip_stdio_op_tell,
|
||||
NULL
|
||||
};
|
||||
/* clang-format on */
|
||||
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_filep(zip_t *za, FILE *file, zip_uint64_t start, zip_int64_t len) {
|
||||
if (za == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return zip_source_filep_create(file, start, len, &za->error);
|
||||
}
|
||||
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_filep_create(FILE *file, zip_uint64_t start, zip_int64_t length, zip_error_t *error) {
|
||||
if (file == NULL || length < -1) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return zip_source_file_common_new(NULL, file, start, length, NULL, &ops_stdio_read, NULL, error);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_zip_stdio_op_close(zip_source_file_context_t *ctx) {
|
||||
fclose((FILE *)ctx->f);
|
||||
}
|
||||
|
||||
|
||||
zip_int64_t
|
||||
_zip_stdio_op_read(zip_source_file_context_t *ctx, void *buf, zip_uint64_t len) {
|
||||
size_t i;
|
||||
if (len > SIZE_MAX) {
|
||||
len = SIZE_MAX;
|
||||
}
|
||||
|
||||
if ((i = fread(buf, 1, (size_t)len, ctx->f)) == 0) {
|
||||
if (ferror((FILE *)ctx->f)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_READ, errno);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return (zip_int64_t)i;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
_zip_stdio_op_seek(zip_source_file_context_t *ctx, void *f, zip_int64_t offset, int whence) {
|
||||
#if ZIP_FSEEK_MAX > ZIP_INT64_MAX
|
||||
if (offset > ZIP_FSEEK_MAX || offset < ZIP_FSEEK_MIN) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_SEEK, EOVERFLOW);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (fseeko((FILE *)f, (off_t)offset, whence) < 0) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_SEEK, errno);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
_zip_stdio_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st) {
|
||||
struct stat sb;
|
||||
|
||||
int ret;
|
||||
|
||||
if (ctx->fname) {
|
||||
ret = stat(ctx->fname, &sb);
|
||||
}
|
||||
else {
|
||||
ret = fstat(fileno((FILE *)ctx->f), &sb);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
if (errno == ENOENT) {
|
||||
st->exists = false;
|
||||
return true;
|
||||
}
|
||||
zip_error_set(&ctx->error, ZIP_ER_READ, errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
st->size = (zip_uint64_t)sb.st_size;
|
||||
st->mtime = sb.st_mtime;
|
||||
|
||||
st->regular_file = S_ISREG(sb.st_mode);
|
||||
st->exists = true;
|
||||
|
||||
/* We're using UNIX file API, even on Windows; thus, we supply external file attributes with Unix values. */
|
||||
/* TODO: This could be improved on Windows by providing Windows-specific file attributes */
|
||||
ctx->attributes.valid = ZIP_FILE_ATTRIBUTES_HOST_SYSTEM | ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES;
|
||||
ctx->attributes.host_system = ZIP_OPSYS_UNIX;
|
||||
ctx->attributes.external_file_attributes = (((zip_uint32_t)sb.st_mode) << 16) | ((sb.st_mode & S_IWUSR) ? 0 : 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
zip_int64_t
|
||||
_zip_stdio_op_tell(zip_source_file_context_t *ctx, void *f) {
|
||||
off_t offset = ftello((FILE *)f);
|
||||
|
||||
if (offset < 0) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_SEEK, errno);
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fopen replacement that sets the close-on-exec flag
|
||||
* some implementations support an fopen 'e' flag for that,
|
||||
* but e.g. macOS doesn't.
|
||||
*/
|
||||
FILE *
|
||||
_zip_fopen_close_on_exec(const char *name, bool writeable) {
|
||||
int fd;
|
||||
int flags;
|
||||
FILE *fp;
|
||||
|
||||
flags = O_CLOEXEC;
|
||||
if (writeable) {
|
||||
flags |= O_RDWR;
|
||||
}
|
||||
else {
|
||||
flags |= O_RDONLY;
|
||||
}
|
||||
|
||||
/* mode argument needed on Windows */
|
||||
if ((fd = open(name, flags, 0666)) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if ((fp = fdopen(fd, writeable ? "r+b" : "rb")) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return fp;
|
||||
}
|
|
@ -1,6 +1,9 @@
|
|||
#ifndef _HAD_ZIP_SOURCE_FILE_STDIO_H
|
||||
#define _HAD_ZIP_SOURCE_FILE_STDIO_H
|
||||
|
||||
/*
|
||||
zip_source_get_compression_flags.c -- get compression flags for entry
|
||||
Copyright (C) 2017-2019 Dieter Baron and Thomas Klausner
|
||||
zip_source_file_stdio.h -- common header for stdio file implementation
|
||||
Copyright (C) 2020 Dieter Baron 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,27 +34,14 @@
|
|||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "zipint.h"
|
||||
void _zip_stdio_op_close(zip_source_file_context_t *ctx);
|
||||
zip_int64_t _zip_stdio_op_read(zip_source_file_context_t *ctx, void *buf, zip_uint64_t len);
|
||||
bool _zip_stdio_op_seek(zip_source_file_context_t *ctx, void *f, zip_int64_t offset, int whence);
|
||||
bool _zip_stdio_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st);
|
||||
zip_int64_t _zip_stdio_op_tell(zip_source_file_context_t *ctx, void *f);
|
||||
|
||||
#define ZIP_COMPRESSION_BITFLAG_MAX 3
|
||||
FILE *_zip_fopen_close_on_exec(const char *name, bool writeable);
|
||||
|
||||
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;
|
||||
}
|
||||
#endif /* _HAD_ZIP_SOURCE_FILE_STDIO_H */
|
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
zip_source_file_win32.c -- read-only Windows file source implementation
|
||||
Copyright (C) 1999-2020 Dieter Baron 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 "zip_source_file_win32.h"
|
||||
|
||||
static bool _zip_win32_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st);
|
||||
|
||||
static bool _zip_stat_win32(zip_source_file_context_t *ctx, zip_source_file_stat_t *st, HANDLE h);
|
||||
|
||||
static zip_source_file_operations_t ops_win32_read = {
|
||||
_zip_win32_op_close,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
_zip_win32_op_read,
|
||||
NULL,
|
||||
NULL,
|
||||
_zip_win32_op_seek,
|
||||
_zip_win32_op_stat,
|
||||
NULL,
|
||||
_zip_win32_op_tell,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_win32handle(zip_t *za, HANDLE h, zip_uint64_t start, zip_int64_t len) {
|
||||
if (za == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return zip_source_win32handle_create(h, start, len, &za->error);
|
||||
}
|
||||
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_win32handle_create(HANDLE h, zip_uint64_t start, zip_int64_t length, zip_error_t *error) {
|
||||
if (h == INVALID_HANDLE_VALUE || length < -1) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return zip_source_file_common_new(NULL, h, start, length, NULL, &ops_win32_read, NULL, error);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_zip_win32_op_close(zip_source_file_context_t *ctx) {
|
||||
CloseHandle((HANDLE)ctx->f);
|
||||
}
|
||||
|
||||
|
||||
zip_int64_t
|
||||
_zip_win32_op_read(zip_source_file_context_t *ctx, void *buf, zip_uint64_t len) {
|
||||
DWORD i;
|
||||
|
||||
/* TODO: cap len to "DWORD_MAX" */
|
||||
if (!ReadFile((HANDLE)ctx->f, buf, (DWORD)len, &i, NULL)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (zip_int64_t)i;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
_zip_win32_op_seek(zip_source_file_context_t *ctx, void *f, zip_int64_t offset, int whence) {
|
||||
LARGE_INTEGER li;
|
||||
DWORD method;
|
||||
|
||||
switch (whence) {
|
||||
case SEEK_SET:
|
||||
method = FILE_BEGIN;
|
||||
break;
|
||||
case SEEK_END:
|
||||
method = FILE_END;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
method = FILE_CURRENT;
|
||||
break;
|
||||
default:
|
||||
zip_error_set(&ctx->error, ZIP_ER_SEEK, EINVAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
li.QuadPart = (LONGLONG)offset;
|
||||
if (!SetFilePointerEx((HANDLE)f, li, NULL, method)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_SEEK, _zip_win32_error_to_errno(GetLastError()));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
_zip_win32_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st) {
|
||||
return _zip_stat_win32(ctx, st, (HANDLE)ctx->f);
|
||||
}
|
||||
|
||||
|
||||
zip_int64_t
|
||||
_zip_win32_op_tell(zip_source_file_context_t *ctx, void *f) {
|
||||
LARGE_INTEGER zero;
|
||||
LARGE_INTEGER new_offset;
|
||||
|
||||
zero.QuadPart = 0;
|
||||
if (!SetFilePointerEx((HANDLE)f, zero, &new_offset, FILE_CURRENT)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_SEEK, _zip_win32_error_to_errno(GetLastError()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (zip_int64_t)new_offset.QuadPart;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
_zip_win32_error_to_errno(DWORD win32err) {
|
||||
/* Note: This list isn't exhaustive, but should cover common cases. */
|
||||
switch (win32err) {
|
||||
case ERROR_INVALID_PARAMETER:
|
||||
return EINVAL;
|
||||
case ERROR_FILE_NOT_FOUND:
|
||||
return ENOENT;
|
||||
case ERROR_INVALID_HANDLE:
|
||||
return EBADF;
|
||||
case ERROR_ACCESS_DENIED:
|
||||
return EACCES;
|
||||
case ERROR_FILE_EXISTS:
|
||||
return EEXIST;
|
||||
case ERROR_TOO_MANY_OPEN_FILES:
|
||||
return EMFILE;
|
||||
case ERROR_DISK_FULL:
|
||||
return ENOSPC;
|
||||
default:
|
||||
return 10000 + win32err;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
_zip_stat_win32(zip_source_file_context_t *ctx, zip_source_file_stat_t *st, HANDLE h) {
|
||||
FILETIME mtimeft;
|
||||
time_t mtime;
|
||||
LARGE_INTEGER size;
|
||||
|
||||
if (!GetFileTime(h, NULL, NULL, &mtimeft)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError()));
|
||||
return false;
|
||||
}
|
||||
if (_zip_filetime_to_time_t(mtimeft, &mtime) < 0) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_READ, ERANGE);
|
||||
return false;
|
||||
}
|
||||
|
||||
st->exists = true;
|
||||
st->mtime = mtime;
|
||||
|
||||
if (GetFileType(h) == FILE_TYPE_DISK) {
|
||||
st->regular_file = 1;
|
||||
|
||||
if (!GetFileSizeEx(h, &size)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError()));
|
||||
return false;
|
||||
}
|
||||
|
||||
st->size = (zip_uint64_t)size.QuadPart;
|
||||
}
|
||||
|
||||
/* TODO: fill in ctx->attributes */
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
_zip_filetime_to_time_t(FILETIME ft, time_t *t) {
|
||||
/*
|
||||
Inspired by http://stackoverflow.com/questions/6161776/convert-windows-filetime-to-second-in-unix-linux
|
||||
*/
|
||||
const zip_int64_t WINDOWS_TICK = 10000000LL;
|
||||
const zip_int64_t SEC_TO_UNIX_EPOCH = 11644473600LL;
|
||||
ULARGE_INTEGER li;
|
||||
zip_int64_t secs;
|
||||
time_t temp;
|
||||
|
||||
li.LowPart = ft.dwLowDateTime;
|
||||
li.HighPart = ft.dwHighDateTime;
|
||||
secs = (li.QuadPart / WINDOWS_TICK - SEC_TO_UNIX_EPOCH);
|
||||
|
||||
temp = (time_t)secs;
|
||||
if (secs != (zip_int64_t)temp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*t = temp;
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
#ifndef _HAD_ZIP_SOURCE_FILE_WIN32_H
|
||||
#define _HAD_ZIP_SOURCE_FILE_WIN32_H
|
||||
|
||||
/*
|
||||
zip_source_file_win32.h -- common header for Windows file implementation
|
||||
Copyright (C) 2020 Dieter Baron 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.
|
||||
*/
|
||||
|
||||
/* 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 <aclapi.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
#include "zip_source_file.h"
|
||||
|
||||
struct zip_win32_file_operations {
|
||||
char *(*allocate_tempname)(const char *name, size_t extra_chars, size_t *lengthp);
|
||||
HANDLE (__stdcall *create_file)(const void *name, DWORD access, DWORD share_mode, PSECURITY_ATTRIBUTES security_attributes, DWORD creation_disposition, DWORD file_attributes, HANDLE template_file);
|
||||
BOOL (__stdcall *delete_file)(const void *name);
|
||||
DWORD (__stdcall *get_file_attributes)(const void *name);
|
||||
BOOL (__stdcall *get_file_attributes_ex)(const void *name, GET_FILEEX_INFO_LEVELS info_level, void *information);
|
||||
void (*make_tempname)(char *buf, size_t len, const char *name, zip_uint32_t i);
|
||||
BOOL (__stdcall *move_file)(const void *from, const void *to, DWORD flags);
|
||||
BOOL (__stdcall *set_file_attributes)(const void *name, DWORD attributes);
|
||||
char *(*string_duplicate)(const char *string);
|
||||
};
|
||||
|
||||
typedef struct zip_win32_file_operations zip_win32_file_operations_t;
|
||||
|
||||
extern zip_source_file_operations_t _zip_source_file_win32_named_ops;
|
||||
|
||||
void _zip_win32_op_close(zip_source_file_context_t *ctx);
|
||||
zip_int64_t _zip_win32_op_read(zip_source_file_context_t *ctx, void *buf, zip_uint64_t len);
|
||||
bool _zip_win32_op_seek(zip_source_file_context_t *ctx, void *f, zip_int64_t offset, int whence);
|
||||
zip_int64_t _zip_win32_op_tell(zip_source_file_context_t *ctx, void *f);
|
||||
|
||||
bool _zip_filetime_to_time_t(FILETIME ft, time_t *t);
|
||||
int _zip_win32_error_to_errno(DWORD win32err);
|
||||
|
||||
#endif /* _HAD_ZIP_SOURCE_FILE_WIN32_H */
|
|
@ -0,0 +1,268 @@
|
|||
/*
|
||||
zip_source_file_win32_named.c -- source for Windows file opened by name
|
||||
Copyright (C) 1999-2020 Dieter Baron 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 "zip_source_file_win32.h"
|
||||
|
||||
static zip_int64_t _zip_win32_named_op_commit_write(zip_source_file_context_t *ctx);
|
||||
static zip_int64_t _zip_win32_named_op_create_temp_output(zip_source_file_context_t *ctx);
|
||||
static bool _zip_win32_named_op_open(zip_source_file_context_t *ctx);
|
||||
static zip_int64_t _zip_win32_named_op_remove(zip_source_file_context_t *ctx);
|
||||
static void _zip_win32_named_op_rollback_write(zip_source_file_context_t *ctx);
|
||||
static bool _zip_win32_named_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st);
|
||||
static char *_zip_win32_named_op_string_duplicate(zip_source_file_context_t *ctx, const char *string);
|
||||
static zip_int64_t _zip_win32_named_op_write(zip_source_file_context_t *ctx, const void *data, zip_uint64_t len);
|
||||
|
||||
static HANDLE win32_named_open(zip_source_file_context_t *ctx, const char *name, bool temporary, PSECURITY_ATTRIBUTES security_attributes);
|
||||
|
||||
/* clang-format off */
|
||||
zip_source_file_operations_t _zip_source_file_win32_named_ops = {
|
||||
_zip_win32_op_close,
|
||||
_zip_win32_named_op_commit_write,
|
||||
_zip_win32_named_op_create_temp_output,
|
||||
NULL,
|
||||
_zip_win32_named_op_open,
|
||||
_zip_win32_op_read,
|
||||
_zip_win32_named_op_remove,
|
||||
_zip_win32_named_op_rollback_write,
|
||||
_zip_win32_op_seek,
|
||||
_zip_win32_named_op_stat,
|
||||
_zip_win32_named_op_string_duplicate,
|
||||
_zip_win32_op_tell,
|
||||
_zip_win32_named_op_write
|
||||
};
|
||||
/* clang-format on */
|
||||
|
||||
static zip_int64_t
|
||||
_zip_win32_named_op_commit_write(zip_source_file_context_t *ctx) {
|
||||
zip_win32_file_operations_t *file_ops = (zip_win32_file_operations_t *)ctx->ops_userdata;
|
||||
DWORD attributes;
|
||||
|
||||
if (!CloseHandle((HANDLE)ctx->fout)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_WRITE, _zip_win32_error_to_errno(GetLastError()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
attributes = file_ops->get_file_attributes(ctx->tmpname);
|
||||
if (attributes == INVALID_FILE_ATTRIBUTES) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_RENAME, _zip_win32_error_to_errno(GetLastError()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (attributes & FILE_ATTRIBUTE_TEMPORARY) {
|
||||
if (!file_ops->set_file_attributes(ctx->tmpname, attributes & ~FILE_ATTRIBUTE_TEMPORARY)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_RENAME, _zip_win32_error_to_errno(GetLastError()));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!file_ops->move_file(ctx->tmpname, ctx->fname, MOVEFILE_REPLACE_EXISTING)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_RENAME, _zip_win32_error_to_errno(GetLastError()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static zip_int64_t
|
||||
_zip_win32_named_op_create_temp_output(zip_source_file_context_t *ctx) {
|
||||
zip_win32_file_operations_t *file_ops = (zip_win32_file_operations_t *)ctx->ops_userdata;
|
||||
|
||||
zip_uint32_t value, i;
|
||||
HANDLE th = INVALID_HANDLE_VALUE;
|
||||
void *temp = NULL;
|
||||
PSECURITY_DESCRIPTOR psd = NULL;
|
||||
PSECURITY_ATTRIBUTES psa = NULL;
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
SECURITY_INFORMATION si;
|
||||
DWORD success;
|
||||
PACL dacl = NULL;
|
||||
char *tempname = NULL;
|
||||
size_t tempname_size = 0;
|
||||
|
||||
if ((HANDLE)ctx->f != INVALID_HANDLE_VALUE && GetFileType((HANDLE)ctx->f) == FILE_TYPE_DISK) {
|
||||
si = DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION;
|
||||
success = GetSecurityInfo((HANDLE)ctx->f, SE_FILE_OBJECT, si, NULL, NULL, &dacl, NULL, &psd);
|
||||
if (success == ERROR_SUCCESS) {
|
||||
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
sa.bInheritHandle = FALSE;
|
||||
sa.lpSecurityDescriptor = psd;
|
||||
psa = &sa;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef MS_UWP
|
||||
value = GetTickCount();
|
||||
#else
|
||||
value = (zip_uint32_t)(GetTickCount64() & 0xffffffff);
|
||||
#endif
|
||||
|
||||
if ((tempname = file_ops->allocate_tempname(ctx->fname, 10, &tempname_size)) == NULL) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < 1024 && th == INVALID_HANDLE_VALUE; i++) {
|
||||
file_ops->make_tempname(tempname, tempname_size, ctx->fname, value + i);
|
||||
|
||||
th = win32_named_open(ctx, tempname, true, psa);
|
||||
if (th == INVALID_HANDLE_VALUE && GetLastError() != ERROR_FILE_EXISTS)
|
||||
break;
|
||||
}
|
||||
|
||||
if (th == INVALID_HANDLE_VALUE) {
|
||||
free(tempname);
|
||||
LocalFree(psd);
|
||||
zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, _zip_win32_error_to_errno(GetLastError()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
LocalFree(psd);
|
||||
ctx->fout = th;
|
||||
ctx->tmpname = tempname;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
_zip_win32_named_op_open(zip_source_file_context_t *ctx) {
|
||||
HANDLE h = win32_named_open(ctx, ctx->fname, false, NULL);
|
||||
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ctx->f = h;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static zip_int64_t
|
||||
_zip_win32_named_op_remove(zip_source_file_context_t *ctx) {
|
||||
zip_win32_file_operations_t *file_ops = (zip_win32_file_operations_t *)ctx->ops_userdata;
|
||||
|
||||
if (!file_ops->delete_file(ctx->fname)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_REMOVE, _zip_win32_error_to_errno(GetLastError()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_zip_win32_named_op_rollback_write(zip_source_file_context_t *ctx) {
|
||||
zip_win32_file_operations_t *file_ops = (zip_win32_file_operations_t *)ctx->ops_userdata;
|
||||
|
||||
if (ctx->fout) {
|
||||
CloseHandle((HANDLE)ctx->fout);
|
||||
}
|
||||
file_ops->delete_file(ctx->tmpname);
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
_zip_win32_named_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st) {
|
||||
zip_win32_file_operations_t *file_ops = (zip_win32_file_operations_t *)ctx->ops_userdata;
|
||||
|
||||
WIN32_FILE_ATTRIBUTE_DATA file_attributes;
|
||||
|
||||
if (!file_ops->get_file_attributes_ex(ctx->fname, GetFileExInfoStandard, &file_attributes)) {
|
||||
DWORD error = GetLastError();
|
||||
if (error == ERROR_FILE_NOT_FOUND) {
|
||||
st->exists = false;
|
||||
return true;
|
||||
}
|
||||
zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(error));
|
||||
return false;
|
||||
}
|
||||
|
||||
st->exists = true;
|
||||
st->regular_file = true; /* TODO: Is this always right? How to determine without a HANDLE? */
|
||||
if (!_zip_filetime_to_time_t(file_attributes.ftLastWriteTime, &st->mtime)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_READ, ERANGE);
|
||||
return false;
|
||||
}
|
||||
st->size = ((zip_uint64_t)file_attributes.nFileSizeHigh << 32) | file_attributes.nFileSizeLow;
|
||||
|
||||
/* TODO: fill in ctx->attributes */
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
_zip_win32_named_op_string_duplicate(zip_source_file_context_t *ctx, const char *string) {
|
||||
zip_win32_file_operations_t *file_ops = (zip_win32_file_operations_t *)ctx->ops_userdata;
|
||||
|
||||
return file_ops->string_duplicate(string);
|
||||
}
|
||||
|
||||
|
||||
static zip_int64_t
|
||||
_zip_win32_named_op_write(zip_source_file_context_t *ctx, const void *data, zip_uint64_t len) {
|
||||
DWORD ret;
|
||||
if (!WriteFile((HANDLE)ctx->fout, data, (DWORD)len, &ret, NULL) || ret != len) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_WRITE, _zip_win32_error_to_errno(GetLastError()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (zip_int64_t)ret;
|
||||
}
|
||||
|
||||
|
||||
static HANDLE
|
||||
win32_named_open(zip_source_file_context_t *ctx, const char *name, bool temporary, PSECURITY_ATTRIBUTES security_attributes) {
|
||||
zip_win32_file_operations_t *file_ops = (zip_win32_file_operations_t *)ctx->ops_userdata;
|
||||
|
||||
DWORD access = GENERIC_READ;
|
||||
DWORD share_mode = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
||||
DWORD creation_disposition = OPEN_EXISTING;
|
||||
DWORD file_attributes = FILE_ATTRIBUTE_NORMAL;
|
||||
HANDLE h;
|
||||
|
||||
if (temporary) {
|
||||
access = GENERIC_READ | GENERIC_WRITE;
|
||||
share_mode = FILE_SHARE_READ;
|
||||
creation_disposition = CREATE_NEW;
|
||||
file_attributes = FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_TEMPORARY;
|
||||
}
|
||||
|
||||
h = file_ops->create_file(name, access, share_mode, security_attributes, creation_disposition, file_attributes, NULL);
|
||||
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_OPEN, _zip_win32_error_to_errno(GetLastError()));
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
zip_source_file_win32_utf16.c -- source for Windows file opened by UTF-16 name
|
||||
Copyright (C) 1999-2020 Dieter Baron 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 "zip_source_file_win32.h"
|
||||
|
||||
#define RtlGenRandom SystemFunction036
|
||||
BOOLEAN NTAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength);
|
||||
|
||||
bool zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length)
|
||||
{
|
||||
return RtlGenRandom (buffer, (ULONG) length);
|
||||
}
|
||||
|
||||
|
||||
static char *utf16_allocate_tempname(const char *name, size_t extra_chars, size_t *lengthp);
|
||||
static HANDLE __stdcall utf16_create_file(const char *name, DWORD access, DWORD share_mode, PSECURITY_ATTRIBUTES security_attributes, DWORD creation_disposition, DWORD file_attributes, HANDLE template_file);
|
||||
static void utf16_make_tempname(char *buf, size_t len, const char *name, zip_uint32_t i);
|
||||
static char *utf16_strdup(const char *string);
|
||||
|
||||
zip_win32_file_operations_t ops_utf16 = {
|
||||
utf16_allocate_tempname,
|
||||
utf16_create_file,
|
||||
DeleteFileW,
|
||||
GetFileAttributesW,
|
||||
GetFileAttributesExW,
|
||||
utf16_make_tempname,
|
||||
MoveFileExW,
|
||||
SetFileAttributesW,
|
||||
utf16_strdup
|
||||
};
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_win32w(zip_t *za, const wchar_t *fname, zip_uint64_t start, zip_int64_t len) {
|
||||
if (za == NULL)
|
||||
return NULL;
|
||||
|
||||
return zip_source_win32w_create(fname, start, len, &za->error);
|
||||
}
|
||||
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_win32w_create(const wchar_t *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error) {
|
||||
if (fname == NULL || length < -1) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
return zip_source_file_common_new((const char *)fname, NULL, start, length, NULL, &_zip_source_file_win32_named_ops, &ops_utf16, error);
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
utf16_allocate_tempname(const char *name, size_t extra_chars, size_t *lengthp) {
|
||||
*lengthp = wcslen((const wchar_t *)name) + extra_chars;
|
||||
return (char *)malloc(*lengthp * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
|
||||
static HANDLE __stdcall
|
||||
utf16_create_file(const char *name, DWORD access, DWORD share_mode, PSECURITY_ATTRIBUTES security_attributes, DWORD creation_disposition, DWORD file_attributes, HANDLE template_file) {
|
||||
#ifdef MS_UWP
|
||||
CREATEFILE2_EXTENDED_PARAMETERS extParams = {0};
|
||||
extParams.dwFileAttributes = file_attributes;
|
||||
extParams.dwFileFlags = FILE_FLAG_RANDOM_ACCESS;
|
||||
extParams.dwSecurityQosFlags = SECURITY_ANONYMOUS;
|
||||
extParams.dwSize = sizeof(extParams);
|
||||
extParams.hTemplateFile = template_file;
|
||||
extParams.lpSecurityAttributes = security_attributes;
|
||||
|
||||
return CreateFile2((const wchar_t *)name, access, share_mode, creation_disposition, &extParams);
|
||||
#else
|
||||
return CreateFileW((const wchar_t *)name, access, share_mode, security_attributes, creation_disposition, file_attributes, template_file);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
utf16_make_tempname(char *buf, size_t len, const char *name, zip_uint32_t i) {
|
||||
_snwprintf((wchar_t *)buf, len, L"%s.%08x", (const wchar_t *)name, i);
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
utf16_strdup(const char *string) {
|
||||
return (char *)_wcsdup((const wchar_t *)string);
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
zip_source_win32utf8.c -- create data source from Windows file (UTF-8)
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
zip_source_file_win32_ansi.c -- source for Windows file opened by UTF-8 name
|
||||
Copyright (C) 1999-2020 Dieter Baron 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,23 +31,14 @@
|
|||
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 <stdlib.h>
|
||||
|
||||
#include "zipint.h"
|
||||
#include "zipwin32.h"
|
||||
|
||||
#include "zip_source_file_win32.h"
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_file(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t len) {
|
||||
if (za == NULL)
|
||||
return NULL;
|
||||
|
||||
if (za == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return zip_source_file_create(fname, start, len, &za->error);
|
||||
}
|
||||
|
||||
|
@ -59,24 +50,24 @@ zip_source_file_create(const char *fname, zip_uint64_t start, zip_int64_t length
|
|||
zip_source_t *source;
|
||||
|
||||
if (fname == NULL || length < -1) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Convert fname from UTF-8 to Windows-friendly UTF-16. */
|
||||
size = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, fname, -1, NULL, 0);
|
||||
if (size == 0) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
if ((wfname = (wchar_t *)malloc(sizeof(wchar_t) * size)) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, fname, -1, wfname, size);
|
||||
|
||||
source = zip_source_win32w_create(wfname, start, length, error);
|
||||
|
||||
|
||||
free(wfname);
|
||||
return source;
|
||||
}
|
|
@ -1,663 +0,0 @@
|
|||
/*
|
||||
zip_source_filep.c -- create data source from FILE *
|
||||
Copyright (C) 1999-2019 Dieter Baron 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 <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#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
|
||||
|
||||
struct read_file {
|
||||
zip_error_t error; /* last error information */
|
||||
zip_int64_t supports;
|
||||
|
||||
/* reading */
|
||||
char *fname; /* name of file to read from */
|
||||
FILE *f; /* file to read from */
|
||||
struct zip_stat st; /* stat information passed in */
|
||||
zip_error_t stat_error; /* error returned for stat */
|
||||
zip_uint64_t start; /* start offset of data to read */
|
||||
zip_uint64_t end; /* end offset of data to read relative to start, 0 for up to EOF */
|
||||
zip_uint64_t current; /* current offset relative to start (0 is beginning of part we read) */
|
||||
|
||||
/* writing */
|
||||
char *tmpname;
|
||||
FILE *fout;
|
||||
};
|
||||
|
||||
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 FILE *_zip_fopen(const char *name, bool writeable);
|
||||
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) {
|
||||
if (za == NULL)
|
||||
return NULL;
|
||||
|
||||
return zip_source_filep_create(file, start, len, &za->error);
|
||||
}
|
||||
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_filep_create(FILE *file, zip_uint64_t start, zip_int64_t length, zip_error_t *error) {
|
||||
if (file == NULL || length < -1) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return _zip_source_file_or_p(NULL, file, start, length, NULL, error);
|
||||
}
|
||||
|
||||
|
||||
zip_source_t *
|
||||
_zip_source_file_or_p(const char *fname, FILE *file, zip_uint64_t start, zip_int64_t len, const zip_stat_t *st, zip_error_t *error) {
|
||||
struct read_file *ctx;
|
||||
zip_source_t *zs;
|
||||
struct stat sb;
|
||||
bool stat_valid;
|
||||
|
||||
if (file == NULL && fname == NULL) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (len < 0) {
|
||||
len = 0;
|
||||
}
|
||||
|
||||
if (start > ZIP_INT64_MAX || start + (zip_uint64_t)len < start) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((ctx = (struct read_file *)malloc(sizeof(struct read_file))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->fname = NULL;
|
||||
if (fname) {
|
||||
if ((ctx->fname = strdup(fname)) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
ctx->f = file;
|
||||
ctx->start = start;
|
||||
ctx->end = (zip_uint64_t)len;
|
||||
if (st) {
|
||||
memcpy(&ctx->st, st, sizeof(ctx->st));
|
||||
ctx->st.name = NULL;
|
||||
ctx->st.valid &= ~ZIP_STAT_NAME;
|
||||
}
|
||||
else {
|
||||
zip_stat_init(&ctx->st);
|
||||
}
|
||||
|
||||
if (ctx->end > 0) {
|
||||
ctx->st.size = ctx->end;
|
||||
ctx->st.valid |= ZIP_STAT_SIZE;
|
||||
}
|
||||
|
||||
zip_error_init(&ctx->stat_error);
|
||||
|
||||
ctx->tmpname = NULL;
|
||||
ctx->fout = NULL;
|
||||
|
||||
zip_error_init(&ctx->error);
|
||||
|
||||
ctx->supports = ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1);
|
||||
|
||||
if (ctx->fname) {
|
||||
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;
|
||||
ctx->st.valid |= ZIP_STAT_MTIME;
|
||||
}
|
||||
if (S_ISREG(sb.st_mode)) {
|
||||
ctx->supports = ZIP_SOURCE_SUPPORTS_SEEKABLE;
|
||||
|
||||
if (ctx->start + ctx->end > (zip_uint64_t)sb.st_size) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
free(ctx->fname);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ctx->end == 0) {
|
||||
ctx->st.size = (zip_uint64_t)sb.st_size - ctx->start;
|
||||
ctx->st.valid |= ZIP_STAT_SIZE;
|
||||
|
||||
if (ctx->fname && start == 0) {
|
||||
ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ACCEPT_EMPTY);
|
||||
#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;
|
||||
}
|
||||
|
||||
return zs;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
create_temp_output(struct read_file *ctx) {
|
||||
char *temp;
|
||||
int tfd;
|
||||
int mode;
|
||||
FILE *tfp;
|
||||
struct stat st;
|
||||
|
||||
if ((temp = (char *)malloc(strlen(ctx->fname) + 8)) == NULL) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (stat(ctx->fname, &st) == 0) {
|
||||
mode = st.st_mode;
|
||||
}
|
||||
else {
|
||||
mode = -1;
|
||||
}
|
||||
|
||||
sprintf(temp, "%s.XXXXXX", ctx->fname);
|
||||
|
||||
if ((tfd = _zip_mkstempm(temp, mode)) == -1) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
|
||||
free(temp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((tfp = fdopen(tfd, "r+b")) == NULL) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
|
||||
close(tfd);
|
||||
(void)remove(temp);
|
||||
free(temp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->fout = tfp;
|
||||
ctx->tmpname = temp;
|
||||
|
||||
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 = _zip_fopen(temp, true)) == 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) {
|
||||
struct read_file *ctx;
|
||||
char *buf;
|
||||
zip_uint64_t n;
|
||||
size_t i;
|
||||
|
||||
ctx = (struct read_file *)state;
|
||||
buf = (char *)data;
|
||||
|
||||
switch (cmd) {
|
||||
case ZIP_SOURCE_ACCEPT_EMPTY:
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_BEGIN_WRITE:
|
||||
#ifdef _WIN32
|
||||
return -1;
|
||||
#else
|
||||
if (ctx->fname == NULL) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
|
||||
return -1;
|
||||
}
|
||||
return create_temp_output(ctx);
|
||||
#endif
|
||||
|
||||
#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_CLOSE:
|
||||
if (ctx->fname) {
|
||||
fclose(ctx->f);
|
||||
ctx->f = NULL;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_COMMIT_WRITE: {
|
||||
if (fclose(ctx->fout) < 0) {
|
||||
ctx->fout = NULL;
|
||||
zip_error_set(&ctx->error, ZIP_ER_WRITE, errno);
|
||||
}
|
||||
ctx->fout = NULL;
|
||||
if (rename(ctx->tmpname, ctx->fname) < 0) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_RENAME, errno);
|
||||
return -1;
|
||||
}
|
||||
free(ctx->tmpname);
|
||||
ctx->tmpname = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_ERROR:
|
||||
return zip_error_to_data(&ctx->error, data, len);
|
||||
|
||||
case ZIP_SOURCE_FREE:
|
||||
free(ctx->fname);
|
||||
free(ctx->tmpname);
|
||||
if (ctx->f)
|
||||
fclose(ctx->f);
|
||||
free(ctx);
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_OPEN:
|
||||
if (ctx->fname) {
|
||||
if ((ctx->f = _zip_fopen(ctx->fname, false)) == NULL) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_OPEN, errno);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->start > 0) {
|
||||
if (_zip_fseek_u(ctx->f, ctx->start, SEEK_SET, &ctx->error) < 0) {
|
||||
/* TODO: skip by reading */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
ctx->current = 0;
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_READ:
|
||||
if (ctx->end > 0) {
|
||||
n = ctx->end - ctx->current;
|
||||
if (n > len) {
|
||||
n = len;
|
||||
}
|
||||
}
|
||||
else {
|
||||
n = len;
|
||||
}
|
||||
|
||||
if (n > SIZE_MAX)
|
||||
n = SIZE_MAX;
|
||||
|
||||
if ((i = fread(buf, 1, (size_t)n, ctx->f)) == 0) {
|
||||
if (ferror(ctx->f)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_READ, errno);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
ctx->current += i;
|
||||
|
||||
return (zip_int64_t)i;
|
||||
|
||||
case ZIP_SOURCE_REMOVE:
|
||||
if (remove(ctx->fname) < 0) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_REMOVE, errno);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_ROLLBACK_WRITE:
|
||||
if (ctx->fout) {
|
||||
fclose(ctx->fout);
|
||||
ctx->fout = NULL;
|
||||
}
|
||||
(void)remove(ctx->tmpname);
|
||||
free(ctx->tmpname);
|
||||
ctx->tmpname = NULL;
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_SEEK: {
|
||||
zip_int64_t new_current;
|
||||
int need_seek;
|
||||
zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);
|
||||
|
||||
if (args == NULL)
|
||||
return -1;
|
||||
|
||||
need_seek = 1;
|
||||
|
||||
switch (args->whence) {
|
||||
case SEEK_SET:
|
||||
new_current = args->offset;
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
if (ctx->end == 0) {
|
||||
if (_zip_fseek(ctx->f, args->offset, SEEK_END, &ctx->error) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if ((new_current = ftello(ctx->f)) < 0) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_SEEK, errno);
|
||||
return -1;
|
||||
}
|
||||
new_current -= (zip_int64_t)ctx->start;
|
||||
need_seek = 0;
|
||||
}
|
||||
else {
|
||||
new_current = (zip_int64_t)ctx->end + args->offset;
|
||||
}
|
||||
break;
|
||||
|
||||
case SEEK_CUR:
|
||||
new_current = (zip_int64_t)ctx->current + args->offset;
|
||||
break;
|
||||
|
||||
default:
|
||||
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (new_current < 0 || (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;
|
||||
}
|
||||
|
||||
ctx->current = (zip_uint64_t)new_current;
|
||||
|
||||
if (need_seek) {
|
||||
if (_zip_fseek_u(ctx->f, ctx->current + ctx->start, SEEK_SET, &ctx->error) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_SEEK_WRITE: {
|
||||
zip_source_args_seek_t *args;
|
||||
|
||||
args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);
|
||||
if (args == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_zip_fseek(ctx->fout, args->offset, args->whence, &ctx->error) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_STAT: {
|
||||
if (len < sizeof(ctx->st))
|
||||
return -1;
|
||||
|
||||
if (zip_error_code_zip(&ctx->stat_error) != 0) {
|
||||
zip_error_set(&ctx->error, zip_error_code_zip(&ctx->stat_error), zip_error_code_system(&ctx->stat_error));
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(data, &ctx->st, sizeof(ctx->st));
|
||||
return sizeof(ctx->st);
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_SUPPORTS:
|
||||
return ctx->supports;
|
||||
|
||||
case ZIP_SOURCE_TELL:
|
||||
return (zip_int64_t)ctx->current;
|
||||
|
||||
case ZIP_SOURCE_TELL_WRITE: {
|
||||
off_t ret = ftello(ctx->fout);
|
||||
|
||||
if (ret < 0) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_TELL, errno);
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_WRITE: {
|
||||
size_t ret;
|
||||
|
||||
clearerr(ctx->fout);
|
||||
ret = fwrite(data, 1, len, ctx->fout);
|
||||
if (ret != len || ferror(ctx->fout)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_WRITE, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (zip_int64_t)ret;
|
||||
}
|
||||
|
||||
default:
|
||||
zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
_zip_fseek_u(FILE *f, zip_uint64_t offset, int whence, zip_error_t *error) {
|
||||
if (offset > ZIP_INT64_MAX) {
|
||||
zip_error_set(error, ZIP_ER_SEEK, EOVERFLOW);
|
||||
return -1;
|
||||
}
|
||||
return _zip_fseek(f, (zip_int64_t)offset, whence, error);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
_zip_fseek(FILE *f, zip_int64_t offset, int whence, zip_error_t *error) {
|
||||
if (offset > ZIP_FSEEK_MAX || offset < ZIP_FSEEK_MIN) {
|
||||
zip_error_set(error, ZIP_ER_SEEK, EOVERFLOW);
|
||||
return -1;
|
||||
}
|
||||
if (fseeko(f, (off_t)offset, whence) < 0) {
|
||||
zip_error_set(error, ZIP_ER_SEEK, errno);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fopen replacement that sets the close-on-exec flag
|
||||
* some implementations support an fopen 'e' flag for that,
|
||||
* but e.g. macOS doesn't.
|
||||
*/
|
||||
static FILE *
|
||||
_zip_fopen(const char *name, bool writeable)
|
||||
{
|
||||
int fd;
|
||||
int flags;
|
||||
FILE *fp;
|
||||
|
||||
flags = O_CLOEXEC;
|
||||
if (writeable) {
|
||||
flags |= O_RDWR;
|
||||
}
|
||||
else {
|
||||
flags |= O_RDONLY;
|
||||
}
|
||||
|
||||
/* mode argument needed on Windows */
|
||||
if ((fd = open(name, flags, 0666)) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if ((fp = fdopen(fd, writeable ? "r+b" : "rb")) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return fp;
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
zip_source_get_file_attributes.c -- get attributes for file from source
|
||||
Copyright (C) 2020 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
ZIP_EXTERN void
|
||||
zip_file_attributes_init(zip_file_attributes_t *attributes) {
|
||||
attributes->valid = 0;
|
||||
attributes->version = 1;
|
||||
}
|
||||
|
||||
int
|
||||
zip_source_get_file_attributes(zip_source_t *src, zip_file_attributes_t *attributes) {
|
||||
if (src->source_closed) {
|
||||
return -1;
|
||||
}
|
||||
if (attributes == NULL) {
|
||||
zip_error_set(&src->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
zip_file_attributes_init(attributes);
|
||||
|
||||
if (src->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_GET_FILE_ATTRIBUTES)) {
|
||||
if (_zip_source_call(src, attributes, sizeof(*attributes), ZIP_SOURCE_GET_FILE_ATTRIBUTES) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ZIP_SOURCE_IS_LAYERED(src)) {
|
||||
zip_file_attributes_t lower_attributes;
|
||||
|
||||
if (zip_source_get_file_attributes(src->src, &lower_attributes) < 0) {
|
||||
_zip_error_set_from_source(&src->error, src->src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM) && (attributes->valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM) == 0) {
|
||||
attributes->host_system = lower_attributes.host_system;
|
||||
attributes->valid |= ZIP_FILE_ATTRIBUTES_HOST_SYSTEM;
|
||||
}
|
||||
if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_ASCII) && (attributes->valid & ZIP_FILE_ATTRIBUTES_ASCII) == 0) {
|
||||
attributes->ascii = lower_attributes.ascii;
|
||||
attributes->valid |= ZIP_FILE_ATTRIBUTES_ASCII;
|
||||
}
|
||||
if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED)) {
|
||||
if (attributes->valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED) {
|
||||
attributes->version_needed = ZIP_MAX(lower_attributes.version_needed, attributes->version_needed);
|
||||
}
|
||||
else {
|
||||
attributes->version_needed = lower_attributes.version_needed;
|
||||
attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED;
|
||||
}
|
||||
}
|
||||
if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES) && (attributes->valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES) == 0) {
|
||||
attributes->external_file_attributes = lower_attributes.external_file_attributes;
|
||||
attributes->valid |= ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES;
|
||||
}
|
||||
if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS)) {
|
||||
if (attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) {
|
||||
attributes->general_purpose_bit_flags &= ~lower_attributes.general_purpose_bit_mask;
|
||||
attributes->general_purpose_bit_flags |= lower_attributes.general_purpose_bit_flags & lower_attributes.general_purpose_bit_mask;
|
||||
attributes->general_purpose_bit_mask |= lower_attributes.general_purpose_bit_mask;
|
||||
}
|
||||
else {
|
||||
attributes->valid |= ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS;
|
||||
attributes->general_purpose_bit_flags = lower_attributes.general_purpose_bit_flags;
|
||||
attributes->general_purpose_bit_mask = lower_attributes.general_purpose_bit_mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
zip_source_pkware.c -- Traditional PKWARE de/encryption routines
|
||||
Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
|
||||
zip_source_pkware_decode.c -- Traditional PKWARE decryption routines
|
||||
Copyright (C) 2009-2020 Dieter Baron 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,24 +38,20 @@
|
|||
#include "zipint.h"
|
||||
|
||||
struct trad_pkware {
|
||||
char *password;
|
||||
zip_pkware_keys_t keys;
|
||||
zip_error_t error;
|
||||
zip_uint32_t key[3];
|
||||
};
|
||||
|
||||
#define HEADERLEN 12
|
||||
#define KEY0 305419896
|
||||
#define KEY1 591751049
|
||||
#define KEY2 878082192
|
||||
|
||||
|
||||
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 void pkware_free(struct trad_pkware *);
|
||||
static struct trad_pkware *trad_pkware_new(const char *password, zip_error_t *error);
|
||||
static void trad_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_decode(zip_t *za, zip_source_t *src, zip_uint16_t em, int flags, const char *password) {
|
||||
struct trad_pkware *ctx;
|
||||
zip_source_t *s2;
|
||||
|
||||
|
@ -68,20 +64,12 @@ zip_source_pkware(zip_t *za, zip_source_t *src, zip_uint16_t em, int flags, cons
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if ((ctx = (struct trad_pkware *)malloc(sizeof(*ctx))) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
if ((ctx = trad_pkware_new(password, &za->error)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
zip_error_init(&ctx->error);
|
||||
|
||||
ctx->key[0] = KEY0;
|
||||
ctx->key[1] = KEY1;
|
||||
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) {
|
||||
pkware_free(ctx);
|
||||
trad_pkware_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -89,62 +77,52 @@ zip_source_pkware(zip_t *za, zip_source_t *src, zip_uint16_t em, int flags, cons
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
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++) {
|
||||
b = in[i];
|
||||
|
||||
if (!update_only) {
|
||||
/* decrypt next byte */
|
||||
tmp = (zip_uint16_t)(ctx->key[2] | 2);
|
||||
tmp = (zip_uint16_t)(((zip_uint32_t)tmp * (tmp ^ 1)) >> 8);
|
||||
b ^= (Bytef)tmp;
|
||||
}
|
||||
|
||||
/* store cleartext */
|
||||
if (out)
|
||||
out[i] = b;
|
||||
|
||||
/* update keys */
|
||||
ctx->key[0] = (zip_uint32_t)crc32(ctx->key[0] ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL;
|
||||
ctx->key[1] = (ctx->key[1] + (ctx->key[0] & 0xff)) * 134775813 + 1;
|
||||
b = (Bytef)(ctx->key[1] >> 24);
|
||||
ctx->key[2] = (zip_uint32_t)crc32(ctx->key[2] ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
decrypt_header(zip_source_t *src, struct trad_pkware *ctx) {
|
||||
zip_uint8_t header[HEADERLEN];
|
||||
zip_uint8_t header[ZIP_CRYPTO_PKWARE_HEADERLEN];
|
||||
struct zip_stat st;
|
||||
zip_int64_t n;
|
||||
unsigned short dostime, dosdate;
|
||||
bool ok;
|
||||
|
||||
if ((n = zip_source_read(src, header, HEADERLEN)) < 0) {
|
||||
if ((n = zip_source_read(src, header, ZIP_CRYPTO_PKWARE_HEADERLEN)) < 0) {
|
||||
_zip_error_set_from_source(&ctx->error, src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (n != HEADERLEN) {
|
||||
if (n != ZIP_CRYPTO_PKWARE_HEADERLEN) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_EOF, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
decrypt(ctx, header, header, HEADERLEN, 0);
|
||||
_zip_pkware_decrypt(&ctx->keys, header, header, ZIP_CRYPTO_PKWARE_HEADERLEN);
|
||||
|
||||
if (zip_source_stat(src, &st) < 0) {
|
||||
if (zip_source_stat(src, &st)) {
|
||||
/* stat failed, skip password validation */
|
||||
return 0;
|
||||
}
|
||||
|
||||
_zip_u2d_time(st.mtime, &dostime, &dosdate);
|
||||
/* password verification - two ways:
|
||||
* mtime - InfoZIP way, to avoid computing complete CRC before encrypting data
|
||||
* CRC - old PKWare way
|
||||
*/
|
||||
|
||||
if (header[HEADERLEN - 1] != st.crc >> 24 && header[HEADERLEN - 1] != dostime >> 8) {
|
||||
ok = false;
|
||||
|
||||
if (st.valid & ZIP_STAT_MTIME) {
|
||||
unsigned short dostime, dosdate;
|
||||
_zip_u2d_time(st.mtime, &dostime, &dosdate);
|
||||
if (header[ZIP_CRYPTO_PKWARE_HEADERLEN - 1] == dostime >> 8) {
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (st.valid & ZIP_STAT_CRC) {
|
||||
if (header[ZIP_CRYPTO_PKWARE_HEADERLEN - 1] == st.crc >> 24) {
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ok && ((st.valid & (ZIP_STAT_MTIME | ZIP_STAT_CRC)) != 0)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_WRONGPASSWD, 0);
|
||||
return -1;
|
||||
}
|
||||
|
@ -162,8 +140,11 @@ pkware_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_so
|
|||
|
||||
switch (cmd) {
|
||||
case ZIP_SOURCE_OPEN:
|
||||
if (decrypt_header(src, ctx) < 0)
|
||||
_zip_pkware_keys_reset(&ctx->keys);
|
||||
_zip_pkware_decrypt(&ctx->keys, NULL, (const zip_uint8_t *)ctx->password, strlen(ctx->password));
|
||||
if (decrypt_header(src, ctx) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_READ:
|
||||
|
@ -172,7 +153,7 @@ pkware_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_so
|
|||
return -1;
|
||||
}
|
||||
|
||||
decrypt((struct trad_pkware *)ud, (zip_uint8_t *)data, (zip_uint8_t *)data, (zip_uint64_t)n, 0);
|
||||
_zip_pkware_decrypt(&ctx->keys, (zip_uint8_t *)data, (zip_uint8_t *)data, (zip_uint64_t)n);
|
||||
return n;
|
||||
|
||||
case ZIP_SOURCE_CLOSE:
|
||||
|
@ -185,9 +166,9 @@ pkware_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_so
|
|||
|
||||
st->encryption_method = ZIP_EM_NONE;
|
||||
st->valid |= ZIP_STAT_ENCRYPTION_METHOD;
|
||||
/* TODO: deduce HEADERLEN from size for uncompressed */
|
||||
if (st->valid & ZIP_STAT_COMP_SIZE)
|
||||
st->comp_size -= HEADERLEN;
|
||||
if (st->valid & ZIP_STAT_COMP_SIZE) {
|
||||
st->comp_size -= ZIP_CRYPTO_PKWARE_HEADERLEN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -199,7 +180,7 @@ pkware_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_so
|
|||
return zip_error_to_data(&ctx->error, data, len);
|
||||
|
||||
case ZIP_SOURCE_FREE:
|
||||
pkware_free(ctx);
|
||||
trad_pkware_free(ctx);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
|
@ -209,7 +190,33 @@ pkware_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_so
|
|||
}
|
||||
|
||||
|
||||
static struct trad_pkware *
|
||||
trad_pkware_new(const char *password, zip_error_t *error) {
|
||||
struct trad_pkware *ctx;
|
||||
|
||||
if ((ctx = (struct trad_pkware *)malloc(sizeof(*ctx))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((ctx->password = strdup(password)) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
zip_error_init(&ctx->error);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pkware_free(struct trad_pkware *ctx) {
|
||||
trad_pkware_free(struct trad_pkware *ctx) {
|
||||
if (ctx == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
free(ctx->password);
|
||||
free(ctx);
|
||||
}
|
|
@ -0,0 +1,249 @@
|
|||
/*
|
||||
zip_source_pkware_encode.c -- Traditional PKWARE encryption routines
|
||||
Copyright (C) 2009-2020 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
struct trad_pkware {
|
||||
char *password;
|
||||
zip_pkware_keys_t keys;
|
||||
zip_buffer_t *buffer;
|
||||
bool eof;
|
||||
zip_error_t error;
|
||||
};
|
||||
|
||||
|
||||
static int encrypt_header(zip_source_t *, struct trad_pkware *);
|
||||
static zip_int64_t pkware_encrypt(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t);
|
||||
static void trad_pkware_free(struct trad_pkware *);
|
||||
static struct trad_pkware *trad_pkware_new(const char *password, zip_error_t *error);
|
||||
|
||||
|
||||
zip_source_t *
|
||||
zip_source_pkware_encode(zip_t *za, zip_source_t *src, zip_uint16_t em, int flags, const char *password) {
|
||||
struct trad_pkware *ctx;
|
||||
zip_source_t *s2;
|
||||
|
||||
if (password == NULL || src == NULL || em != ZIP_EM_TRAD_PKWARE) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
if (!(flags & ZIP_CODEC_ENCODE)) {
|
||||
zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((ctx = trad_pkware_new(password, &za->error)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((s2 = zip_source_layered(za, src, pkware_encrypt, ctx)) == NULL) {
|
||||
trad_pkware_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return s2;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
encrypt_header(zip_source_t *src, struct trad_pkware *ctx) {
|
||||
struct zip_stat st;
|
||||
unsigned short dostime, dosdate;
|
||||
zip_uint8_t *header;
|
||||
|
||||
if (zip_source_stat(src, &st) != 0) {
|
||||
_zip_error_set_from_source(&ctx->error, src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_zip_u2d_time(st.mtime, &dostime, &dosdate);
|
||||
|
||||
if ((ctx->buffer = _zip_buffer_new(NULL, ZIP_CRYPTO_PKWARE_HEADERLEN)) == NULL) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
header = _zip_buffer_data(ctx->buffer);
|
||||
|
||||
/* generate header from random bytes and mtime
|
||||
see appnote.iz, XIII. Decryption, Step 2, last paragraph */
|
||||
if (!zip_secure_random(header, ZIP_CRYPTO_PKWARE_HEADERLEN - 1)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
|
||||
_zip_buffer_free(ctx->buffer);
|
||||
ctx->buffer = NULL;
|
||||
return -1;
|
||||
}
|
||||
header[ZIP_CRYPTO_PKWARE_HEADERLEN - 1] = (zip_uint8_t)((dostime >> 8) & 0xff);
|
||||
|
||||
_zip_pkware_encrypt(&ctx->keys, header, header, ZIP_CRYPTO_PKWARE_HEADERLEN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static zip_int64_t
|
||||
pkware_encrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t length, zip_source_cmd_t cmd) {
|
||||
struct trad_pkware *ctx;
|
||||
zip_int64_t n;
|
||||
zip_uint64_t buffer_n;
|
||||
|
||||
ctx = (struct trad_pkware *)ud;
|
||||
|
||||
switch (cmd) {
|
||||
case ZIP_SOURCE_OPEN:
|
||||
ctx->eof = false;
|
||||
|
||||
/* initialize keys */
|
||||
_zip_pkware_keys_reset(&ctx->keys);
|
||||
_zip_pkware_encrypt(&ctx->keys, NULL, (const zip_uint8_t *)ctx->password, strlen(ctx->password));
|
||||
|
||||
if (encrypt_header(src, ctx) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_READ:
|
||||
buffer_n = 0;
|
||||
|
||||
if (ctx->buffer) {
|
||||
/* write header values to data */
|
||||
buffer_n = _zip_buffer_read(ctx->buffer, data, length);
|
||||
data = (zip_uint8_t *)data + buffer_n;
|
||||
length -= buffer_n;
|
||||
|
||||
if (_zip_buffer_eof(ctx->buffer)) {
|
||||
_zip_buffer_free(ctx->buffer);
|
||||
ctx->buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->eof) {
|
||||
return (zip_int64_t)buffer_n;
|
||||
}
|
||||
|
||||
if ((n = zip_source_read(src, data, length)) < 0) {
|
||||
_zip_error_set_from_source(&ctx->error, src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_zip_pkware_encrypt(&ctx->keys, (zip_uint8_t *)data, (zip_uint8_t *)data, (zip_uint64_t)n);
|
||||
|
||||
if ((zip_uint64_t)n < length) {
|
||||
ctx->eof = true;
|
||||
}
|
||||
|
||||
return (zip_int64_t)buffer_n + n;
|
||||
|
||||
case ZIP_SOURCE_CLOSE:
|
||||
_zip_buffer_free(ctx->buffer);
|
||||
ctx->buffer = NULL;
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_STAT: {
|
||||
zip_stat_t *st;
|
||||
|
||||
st = (zip_stat_t *)data;
|
||||
st->encryption_method = ZIP_EM_TRAD_PKWARE;
|
||||
st->valid |= ZIP_STAT_ENCRYPTION_METHOD;
|
||||
if (st->valid & ZIP_STAT_COMP_SIZE) {
|
||||
st->comp_size += ZIP_CRYPTO_PKWARE_HEADERLEN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_GET_FILE_ATTRIBUTES: {
|
||||
zip_file_attributes_t *attributes = (zip_file_attributes_t *)data;
|
||||
if (length < sizeof(*attributes)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED;
|
||||
attributes->version_needed = 20;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_SUPPORTS:
|
||||
return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1);
|
||||
|
||||
case ZIP_SOURCE_ERROR:
|
||||
return zip_error_to_data(&ctx->error, data, length);
|
||||
|
||||
case ZIP_SOURCE_FREE:
|
||||
trad_pkware_free(ctx);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct trad_pkware *
|
||||
trad_pkware_new(const char *password, zip_error_t *error) {
|
||||
struct trad_pkware *ctx;
|
||||
|
||||
if ((ctx = (struct trad_pkware *)malloc(sizeof(*ctx))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((ctx->password = strdup(password)) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
ctx->buffer = NULL;
|
||||
zip_error_init(&ctx->error);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
trad_pkware_free(struct trad_pkware *ctx) {
|
||||
if (ctx == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
free(ctx->password);
|
||||
_zip_buffer_free(ctx->buffer);
|
||||
zip_error_fini(&ctx->error);
|
||||
free(ctx);
|
||||
}
|
|
@ -1,135 +0,0 @@
|
|||
/*
|
||||
zip_source_win32a.c -- create data source from Windows file (ANSI)
|
||||
Copyright (C) 1999-2019 Dieter Baron 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.
|
||||
*/
|
||||
|
||||
/* 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 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,
|
||||
_win32_create_temp_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) {
|
||||
if (za == NULL)
|
||||
return NULL;
|
||||
|
||||
return zip_source_win32a_create(fname, start, len, &za->error);
|
||||
}
|
||||
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_win32a_create(const char *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error) {
|
||||
if (fname == NULL || length < -1) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return _zip_source_win32_handle_or_name(fname, INVALID_HANDLE_VALUE, start, length, 1, NULL, &win32_ops_a, error);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
_win32_strdup_a(const void *str) {
|
||||
return strdup((const char *)str);
|
||||
}
|
||||
|
||||
|
||||
static HANDLE
|
||||
_win32_open_a(_zip_source_win32_read_file_t *ctx) {
|
||||
return CreateFileA(ctx->fname, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
}
|
||||
|
||||
|
||||
static HANDLE
|
||||
_win32_create_temp_a(_zip_source_win32_read_file_t *ctx, void **temp, zip_uint32_t value, PSECURITY_ATTRIBUTES sa) {
|
||||
size_t len;
|
||||
|
||||
len = strlen((const char *)ctx->fname) + 10;
|
||||
if (*temp == NULL) {
|
||||
if ((*temp = malloc(sizeof(char) * len)) == NULL) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
if (sprintf((char *)*temp, "%s.%08x", (const char *)ctx->fname, value) != len - 1) {
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
return CreateFileA((const char *)*temp, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, sa, CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_TEMPORARY, NULL);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
_win32_rename_temp_a(_zip_source_win32_read_file_t *ctx) {
|
||||
DWORD attributes = GetFileAttributesA(ctx->tmpname);
|
||||
if (INVALID_FILE_ATTRIBUTES == attributes)
|
||||
return -1;
|
||||
|
||||
if (FILE_ATTRIBUTE_TEMPORARY & attributes) {
|
||||
if (!SetFileAttributesA(ctx->tmpname, attributes & ~FILE_ATTRIBUTE_TEMPORARY))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!MoveFileExA(ctx->tmpname, ctx->fname, MOVEFILE_REPLACE_EXISTING))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
_win32_remove_a(const void *fname) {
|
||||
DeleteFileA((const char *)fname);
|
||||
return 0;
|
||||
}
|
|
@ -1,602 +0,0 @@
|
|||
/*
|
||||
zip_source_win32file.c -- create data source from HANDLE (Win32)
|
||||
Copyright (C) 1999-2019 Dieter Baron 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 <aclapi.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "zipint.h"
|
||||
#include "zipwin32.h"
|
||||
|
||||
static zip_int64_t _win32_read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd);
|
||||
static int _win32_create_temp_file(_zip_source_win32_read_file_t *ctx);
|
||||
static int _zip_filetime_to_time_t(FILETIME ft, time_t *t);
|
||||
static int _zip_seek_win32_u(void *h, zip_uint64_t offset, int whence, zip_error_t *error);
|
||||
static int _zip_seek_win32(void *h, zip_int64_t offset, int whence, zip_error_t *error);
|
||||
static int _zip_win32_error_to_errno(unsigned long win32err);
|
||||
static int _zip_stat_win32(void *h, zip_stat_t *st, _zip_source_win32_read_file_t *ctx);
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_win32handle(zip_t *za, HANDLE h, zip_uint64_t start, zip_int64_t len) {
|
||||
if (za == NULL)
|
||||
return NULL;
|
||||
|
||||
return zip_source_win32handle_create(h, start, len, &za->error);
|
||||
}
|
||||
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_win32handle_create(HANDLE h, zip_uint64_t start, zip_int64_t length, zip_error_t *error) {
|
||||
if (h == INVALID_HANDLE_VALUE || length < -1) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return _zip_source_win32_handle_or_name(NULL, h, start, length, 1, NULL, NULL, error);
|
||||
}
|
||||
|
||||
|
||||
zip_source_t *
|
||||
_zip_source_win32_handle_or_name(const void *fname, HANDLE h, zip_uint64_t start, zip_int64_t len, int closep, const zip_stat_t *st, _zip_source_win32_file_ops_t *ops, zip_error_t *error) {
|
||||
_zip_source_win32_read_file_t *ctx;
|
||||
zip_source_t *zs;
|
||||
|
||||
if (h == INVALID_HANDLE_VALUE && fname == NULL) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((ctx = (_zip_source_win32_read_file_t *)malloc(sizeof(_zip_source_win32_read_file_t))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->fname = NULL;
|
||||
if (fname) {
|
||||
if ((ctx->fname = ops->op_strdup(fname)) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->ops = ops;
|
||||
ctx->h = h;
|
||||
ctx->start = start;
|
||||
ctx->end = (len < 0 ? 0 : start + (zip_uint64_t)len);
|
||||
ctx->closep = ctx->fname ? 1 : closep;
|
||||
if (st) {
|
||||
memcpy(&ctx->st, st, sizeof(ctx->st));
|
||||
ctx->st.name = NULL;
|
||||
ctx->st.valid &= ~ZIP_STAT_NAME;
|
||||
}
|
||||
else {
|
||||
zip_stat_init(&ctx->st);
|
||||
}
|
||||
|
||||
ctx->tmpname = NULL;
|
||||
ctx->hout = INVALID_HANDLE_VALUE;
|
||||
|
||||
zip_error_init(&ctx->error);
|
||||
|
||||
ctx->supports = ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1);
|
||||
if (ctx->fname) {
|
||||
HANDLE th;
|
||||
|
||||
th = ops->op_open(ctx);
|
||||
if (th == INVALID_HANDLE_VALUE || GetFileType(th) == FILE_TYPE_DISK) {
|
||||
ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE;
|
||||
}
|
||||
if (th != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(th);
|
||||
}
|
||||
}
|
||||
else if (GetFileType(ctx->h) == FILE_TYPE_DISK) {
|
||||
ctx->supports = ZIP_SOURCE_SUPPORTS_SEEKABLE;
|
||||
}
|
||||
|
||||
ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ACCEPT_EMPTY);
|
||||
|
||||
if ((zs = zip_source_function_create(_win32_read_file, ctx, error)) == NULL) {
|
||||
free(ctx->fname);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return zs;
|
||||
}
|
||||
|
||||
|
||||
static zip_int64_t
|
||||
_win32_read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
|
||||
_zip_source_win32_read_file_t *ctx;
|
||||
char *buf;
|
||||
zip_uint64_t n;
|
||||
DWORD i;
|
||||
|
||||
ctx = (_zip_source_win32_read_file_t *)state;
|
||||
buf = (char *)data;
|
||||
|
||||
switch (cmd) {
|
||||
case ZIP_SOURCE_ACCEPT_EMPTY:
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_BEGIN_WRITE:
|
||||
if (ctx->fname == NULL) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
|
||||
return -1;
|
||||
}
|
||||
return _win32_create_temp_file(ctx);
|
||||
|
||||
case ZIP_SOURCE_COMMIT_WRITE: {
|
||||
if (!CloseHandle(ctx->hout)) {
|
||||
ctx->hout = INVALID_HANDLE_VALUE;
|
||||
zip_error_set(&ctx->error, ZIP_ER_WRITE, _zip_win32_error_to_errno(GetLastError()));
|
||||
}
|
||||
ctx->hout = INVALID_HANDLE_VALUE;
|
||||
if (ctx->ops->op_rename_temp(ctx) < 0) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_RENAME, _zip_win32_error_to_errno(GetLastError()));
|
||||
return -1;
|
||||
}
|
||||
free(ctx->tmpname);
|
||||
ctx->tmpname = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_CLOSE:
|
||||
if (ctx->fname) {
|
||||
CloseHandle(ctx->h);
|
||||
ctx->h = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_ERROR:
|
||||
return zip_error_to_data(&ctx->error, data, len);
|
||||
|
||||
case ZIP_SOURCE_FREE:
|
||||
free(ctx->fname);
|
||||
free(ctx->tmpname);
|
||||
if (ctx->closep && ctx->h != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(ctx->h);
|
||||
free(ctx);
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_OPEN:
|
||||
if (ctx->fname) {
|
||||
if ((ctx->h = ctx->ops->op_open(ctx)) == INVALID_HANDLE_VALUE) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_OPEN, _zip_win32_error_to_errno(GetLastError()));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->closep && ctx->start > 0) {
|
||||
if (_zip_seek_win32_u(ctx->h, ctx->start, SEEK_SET, &ctx->error) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
ctx->current = ctx->start;
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_READ:
|
||||
if (ctx->end > 0) {
|
||||
n = ctx->end - ctx->current;
|
||||
if (n > len) {
|
||||
n = len;
|
||||
}
|
||||
}
|
||||
else {
|
||||
n = len;
|
||||
}
|
||||
|
||||
if (n > SIZE_MAX)
|
||||
n = SIZE_MAX;
|
||||
|
||||
if (!ctx->closep) {
|
||||
if (_zip_seek_win32_u(ctx->h, ctx->current, SEEK_SET, &ctx->error) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ReadFile(ctx->h, buf, (DWORD)n, &i, NULL)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError()));
|
||||
return -1;
|
||||
}
|
||||
ctx->current += i;
|
||||
|
||||
return (zip_int64_t)i;
|
||||
|
||||
case ZIP_SOURCE_REMOVE:
|
||||
if (ctx->ops->op_remove(ctx->fname) < 0) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_REMOVE, _zip_win32_error_to_errno(GetLastError()));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_ROLLBACK_WRITE:
|
||||
if (ctx->hout) {
|
||||
CloseHandle(ctx->hout);
|
||||
ctx->hout = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
ctx->ops->op_remove(ctx->tmpname);
|
||||
free(ctx->tmpname);
|
||||
ctx->tmpname = NULL;
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_SEEK: {
|
||||
zip_int64_t new_current;
|
||||
int need_seek;
|
||||
zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);
|
||||
|
||||
if (args == NULL)
|
||||
return -1;
|
||||
|
||||
need_seek = ctx->closep;
|
||||
|
||||
switch (args->whence) {
|
||||
case SEEK_SET:
|
||||
new_current = args->offset + ctx->start;
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
if (ctx->end == 0) {
|
||||
LARGE_INTEGER zero;
|
||||
LARGE_INTEGER new_offset;
|
||||
|
||||
if (_zip_seek_win32(ctx->h, args->offset, SEEK_END, &ctx->error) < 0) {
|
||||
return -1;
|
||||
}
|
||||
zero.QuadPart = 0;
|
||||
if (!SetFilePointerEx(ctx->h, zero, &new_offset, FILE_CURRENT)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_SEEK, _zip_win32_error_to_errno(GetLastError()));
|
||||
return -1;
|
||||
}
|
||||
new_current = new_offset.QuadPart;
|
||||
need_seek = 0;
|
||||
}
|
||||
else {
|
||||
new_current = (zip_int64_t)ctx->end + args->offset;
|
||||
}
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
new_current = (zip_int64_t)ctx->current + args->offset;
|
||||
break;
|
||||
|
||||
default:
|
||||
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (new_current < 0 || (zip_uint64_t)new_current < ctx->start || (ctx->end != 0 && (zip_uint64_t)new_current > ctx->end)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->current = (zip_uint64_t)new_current;
|
||||
|
||||
if (need_seek) {
|
||||
if (_zip_seek_win32_u(ctx->h, ctx->current, SEEK_SET, &ctx->error) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_SEEK_WRITE: {
|
||||
zip_source_args_seek_t *args;
|
||||
|
||||
args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);
|
||||
if (args == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_zip_seek_win32(ctx->hout, args->offset, args->whence, &ctx->error) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_STAT: {
|
||||
if (len < sizeof(ctx->st))
|
||||
return -1;
|
||||
|
||||
if (ctx->st.valid != 0)
|
||||
memcpy(data, &ctx->st, sizeof(ctx->st));
|
||||
else {
|
||||
DWORD win32err;
|
||||
zip_stat_t *st;
|
||||
HANDLE h;
|
||||
int success;
|
||||
|
||||
st = (zip_stat_t *)data;
|
||||
|
||||
if (ctx->h != INVALID_HANDLE_VALUE) {
|
||||
h = ctx->h;
|
||||
}
|
||||
else {
|
||||
h = ctx->ops->op_open(ctx);
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
win32err = GetLastError();
|
||||
if (win32err == ERROR_FILE_NOT_FOUND || win32err == ERROR_PATH_NOT_FOUND) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_READ, ENOENT);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
success = _zip_stat_win32(h, st, ctx);
|
||||
win32err = GetLastError();
|
||||
|
||||
/* We're done with the handle, so close it if we just opened it. */
|
||||
if (h != ctx->h) {
|
||||
CloseHandle(h);
|
||||
}
|
||||
|
||||
if (success < 0) {
|
||||
/* TODO: Is this the correct error to return in all cases? */
|
||||
zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(win32err));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return sizeof(ctx->st);
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_SUPPORTS:
|
||||
return ctx->supports;
|
||||
|
||||
case ZIP_SOURCE_TELL:
|
||||
return (zip_int64_t)ctx->current;
|
||||
|
||||
case ZIP_SOURCE_TELL_WRITE: {
|
||||
LARGE_INTEGER zero;
|
||||
LARGE_INTEGER offset;
|
||||
|
||||
zero.QuadPart = 0;
|
||||
if (!SetFilePointerEx(ctx->hout, zero, &offset, FILE_CURRENT)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_TELL, _zip_win32_error_to_errno(GetLastError()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return offset.QuadPart;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_WRITE: {
|
||||
DWORD ret;
|
||||
if (!WriteFile(ctx->hout, data, (DWORD)len, &ret, NULL) || ret != len) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_WRITE, _zip_win32_error_to_errno(GetLastError()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (zip_int64_t)ret;
|
||||
}
|
||||
|
||||
default:
|
||||
zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
_win32_create_temp_file(_zip_source_win32_read_file_t *ctx) {
|
||||
zip_uint32_t value;
|
||||
/*
|
||||
Windows has GetTempFileName(), but it closes the file after
|
||||
creation, leaving it open to a horrible race condition. So
|
||||
we reinvent the wheel.
|
||||
*/
|
||||
int i;
|
||||
HANDLE th = INVALID_HANDLE_VALUE;
|
||||
void *temp = NULL;
|
||||
PSECURITY_DESCRIPTOR psd = NULL;
|
||||
PSECURITY_ATTRIBUTES psa = NULL;
|
||||
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.
|
||||
If there is no original file, or if we can't read the DACL, we'll use the
|
||||
default security descriptor.
|
||||
*/
|
||||
if (ctx->h != INVALID_HANDLE_VALUE && GetFileType(ctx->h) == FILE_TYPE_DISK) {
|
||||
si = DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION;
|
||||
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;
|
||||
psa = &sa;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#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)
|
||||
break;
|
||||
}
|
||||
|
||||
if (th == INVALID_HANDLE_VALUE) {
|
||||
free(temp);
|
||||
LocalFree(psd);
|
||||
zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, _zip_win32_error_to_errno(GetLastError()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
LocalFree(psd);
|
||||
ctx->hout = th;
|
||||
ctx->tmpname = temp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
_zip_seek_win32_u(HANDLE h, zip_uint64_t offset, int whence, zip_error_t *error) {
|
||||
if (offset > ZIP_INT64_MAX) {
|
||||
zip_error_set(error, ZIP_ER_SEEK, EOVERFLOW);
|
||||
return -1;
|
||||
}
|
||||
return _zip_seek_win32(h, (zip_int64_t)offset, whence, error);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
_zip_seek_win32(HANDLE h, zip_int64_t offset, int whence, zip_error_t *error) {
|
||||
LARGE_INTEGER li;
|
||||
DWORD method;
|
||||
|
||||
switch (whence) {
|
||||
case SEEK_SET:
|
||||
method = FILE_BEGIN;
|
||||
break;
|
||||
case SEEK_END:
|
||||
method = FILE_END;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
method = FILE_CURRENT;
|
||||
break;
|
||||
default:
|
||||
zip_error_set(error, ZIP_ER_SEEK, EINVAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
li.QuadPart = (LONGLONG)offset;
|
||||
if (!SetFilePointerEx(h, li, NULL, method)) {
|
||||
zip_error_set(error, ZIP_ER_SEEK, _zip_win32_error_to_errno(GetLastError()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
_zip_win32_error_to_errno(DWORD win32err) {
|
||||
/*
|
||||
Note: This list isn't exhaustive, but should cover common cases.
|
||||
*/
|
||||
switch (win32err) {
|
||||
case ERROR_INVALID_PARAMETER:
|
||||
return EINVAL;
|
||||
case ERROR_FILE_NOT_FOUND:
|
||||
return ENOENT;
|
||||
case ERROR_INVALID_HANDLE:
|
||||
return EBADF;
|
||||
case ERROR_ACCESS_DENIED:
|
||||
return EACCES;
|
||||
case ERROR_FILE_EXISTS:
|
||||
return EEXIST;
|
||||
case ERROR_TOO_MANY_OPEN_FILES:
|
||||
return EMFILE;
|
||||
case ERROR_DISK_FULL:
|
||||
return ENOSPC;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
_zip_stat_win32(HANDLE h, zip_stat_t *st, _zip_source_win32_read_file_t *ctx) {
|
||||
FILETIME mtimeft;
|
||||
time_t mtime;
|
||||
LARGE_INTEGER size;
|
||||
int regularp;
|
||||
|
||||
if (!GetFileTime(h, NULL, NULL, &mtimeft)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError()));
|
||||
return -1;
|
||||
}
|
||||
if (_zip_filetime_to_time_t(mtimeft, &mtime) < 0) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_READ, ERANGE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
regularp = 0;
|
||||
if (GetFileType(h) == FILE_TYPE_DISK) {
|
||||
regularp = 1;
|
||||
}
|
||||
|
||||
if (!GetFileSizeEx(h, &size)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
zip_stat_init(st);
|
||||
st->mtime = mtime;
|
||||
st->valid |= ZIP_STAT_MTIME;
|
||||
if (ctx->end != 0) {
|
||||
st->size = ctx->end - ctx->start;
|
||||
st->valid |= ZIP_STAT_SIZE;
|
||||
}
|
||||
else if (regularp) {
|
||||
st->size = (zip_uint64_t)size.QuadPart;
|
||||
st->valid |= ZIP_STAT_SIZE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
_zip_filetime_to_time_t(FILETIME ft, time_t *t) {
|
||||
/*
|
||||
Inspired by http://stackoverflow.com/questions/6161776/convert-windows-filetime-to-second-in-unix-linux
|
||||
*/
|
||||
const zip_int64_t WINDOWS_TICK = 10000000LL;
|
||||
const zip_int64_t SEC_TO_UNIX_EPOCH = 11644473600LL;
|
||||
ULARGE_INTEGER li;
|
||||
zip_int64_t secs;
|
||||
time_t temp;
|
||||
|
||||
li.LowPart = ft.dwLowDateTime;
|
||||
li.HighPart = ft.dwHighDateTime;
|
||||
secs = (li.QuadPart / WINDOWS_TICK - SEC_TO_UNIX_EPOCH);
|
||||
|
||||
temp = (time_t)secs;
|
||||
if (secs != (zip_int64_t)temp)
|
||||
return -1;
|
||||
|
||||
*t = temp;
|
||||
return 0;
|
||||
}
|
|
@ -1,159 +0,0 @@
|
|||
/*
|
||||
zip_source_win32w.c -- create data source from Windows file (UTF-16)
|
||||
Copyright (C) 1999-2019 Dieter Baron 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.
|
||||
*/
|
||||
|
||||
/* 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_w(const void *str);
|
||||
static HANDLE _win32_open_w(_zip_source_win32_read_file_t *ctx);
|
||||
static HANDLE _win32_create_temp_w(_zip_source_win32_read_file_t *ctx, void **temp, zip_uint32_t value, PSECURITY_ATTRIBUTES sa);
|
||||
static int _win32_rename_temp_w(_zip_source_win32_read_file_t *ctx);
|
||||
static int _win32_remove_w(const void *fname);
|
||||
|
||||
// clang-format off
|
||||
static _zip_source_win32_file_ops_t win32_ops_w = {
|
||||
_win32_strdup_w,
|
||||
_win32_open_w,
|
||||
_win32_create_temp_w,
|
||||
_win32_rename_temp_w,
|
||||
_win32_remove_w
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_win32w(zip_t *za, const wchar_t *fname, zip_uint64_t start, zip_int64_t len) {
|
||||
if (za == NULL)
|
||||
return NULL;
|
||||
|
||||
return zip_source_win32w_create(fname, start, len, &za->error);
|
||||
}
|
||||
|
||||
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_win32w_create(const wchar_t *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error) {
|
||||
if (fname == NULL || length < -1) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return _zip_source_win32_handle_or_name(fname, INVALID_HANDLE_VALUE, start, length, 1, NULL, &win32_ops_w, error);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
_win32_strdup_w(const void *str) {
|
||||
return _wcsdup((const wchar_t *)str);
|
||||
}
|
||||
|
||||
|
||||
static HANDLE
|
||||
_win32_open_w(_zip_source_win32_read_file_t *ctx) {
|
||||
#ifdef MS_UWP
|
||||
CREATEFILE2_EXTENDED_PARAMETERS extParams = {0};
|
||||
extParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
|
||||
extParams.dwFileFlags = FILE_FLAG_RANDOM_ACCESS;
|
||||
extParams.dwSecurityQosFlags = SECURITY_ANONYMOUS;
|
||||
extParams.dwSize = sizeof(extParams);
|
||||
extParams.hTemplateFile = NULL;
|
||||
extParams.lpSecurityAttributes = NULL;
|
||||
|
||||
return CreateFile2(ctx->fname, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING, &extParams);
|
||||
#else
|
||||
return CreateFileW(ctx->fname, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static HANDLE
|
||||
_win32_create_temp_w(_zip_source_win32_read_file_t *ctx, void **temp, zip_uint32_t value, PSECURITY_ATTRIBUTES sa) {
|
||||
size_t len;
|
||||
|
||||
len = wcslen((const wchar_t *)ctx->fname) + 10;
|
||||
if (*temp == NULL) {
|
||||
if ((*temp = malloc(sizeof(wchar_t) * len)) == NULL) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
if (_snwprintf((wchar_t *)*temp, len, L"%s.%08x", (const wchar_t *)ctx->fname, value) != len - 1) {
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
#ifdef MS_UWP
|
||||
CREATEFILE2_EXTENDED_PARAMETERS extParams = {0};
|
||||
extParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_TEMPORARY;
|
||||
extParams.dwFileFlags = FILE_FLAG_RANDOM_ACCESS;
|
||||
extParams.dwSecurityQosFlags = SECURITY_ANONYMOUS;
|
||||
extParams.dwSize = sizeof(extParams);
|
||||
extParams.hTemplateFile = NULL;
|
||||
extParams.lpSecurityAttributes = NULL;
|
||||
|
||||
return CreateFile2((const wchar_t *)*temp, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, CREATE_NEW, &extParams);
|
||||
#else
|
||||
return CreateFileW((const wchar_t *)*temp, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, sa, CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_TEMPORARY, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
_win32_rename_temp_w(_zip_source_win32_read_file_t *ctx) {
|
||||
DWORD attributes = GetFileAttributesW(ctx->tmpname);
|
||||
if (INVALID_FILE_ATTRIBUTES == attributes)
|
||||
return -1;
|
||||
|
||||
if (FILE_ATTRIBUTE_TEMPORARY & attributes) {
|
||||
if (!SetFileAttributesW(ctx->tmpname, attributes & ~FILE_ATTRIBUTE_TEMPORARY))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!MoveFileExW(ctx->tmpname, ctx->fname, MOVEFILE_REPLACE_EXISTING))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
_win32_remove_w(const void *fname) {
|
||||
DeleteFileW((const wchar_t *)fname);
|
||||
return 0;
|
||||
}
|
|
@ -48,7 +48,7 @@ struct window {
|
|||
zip_uint64_t offset; /* offset in src for next read */
|
||||
|
||||
zip_stat_t stat;
|
||||
zip_int8_t compression_flags;
|
||||
zip_file_attributes_t attributes;
|
||||
zip_error_t error;
|
||||
zip_int64_t supports;
|
||||
bool needs_seek;
|
||||
|
@ -64,7 +64,7 @@ zip_source_window(zip_t *za, zip_source_t *src, zip_uint64_t start, zip_uint64_t
|
|||
|
||||
|
||||
zip_source_t *
|
||||
_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_int8_t compression_flags, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error) {
|
||||
_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_file_attributes_t *attributes, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error) {
|
||||
struct window *ctx;
|
||||
|
||||
if (src == NULL || start + length < start || (source_archive == NULL && source_index != 0)) {
|
||||
|
@ -80,11 +80,16 @@ _zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t lengt
|
|||
ctx->start = start;
|
||||
ctx->end = start + length;
|
||||
zip_stat_init(&ctx->stat);
|
||||
ctx->compression_flags = compression_flags;
|
||||
if (attributes != NULL) {
|
||||
memcpy(&ctx->attributes, attributes, sizeof(ctx->attributes));
|
||||
}
|
||||
else {
|
||||
zip_file_attributes_init(&ctx->attributes);
|
||||
}
|
||||
ctx->source_archive = source_archive;
|
||||
ctx->source_index = source_index;
|
||||
zip_error_init(&ctx->error);
|
||||
ctx->supports = (zip_source_supports(src) & ZIP_SOURCE_SUPPORTS_SEEKABLE) | (zip_source_make_command_bitmap(ZIP_SOURCE_GET_COMPRESSION_FLAGS, ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1));
|
||||
ctx->supports = (zip_source_supports(src) & ZIP_SOURCE_SUPPORTS_SEEKABLE) | (zip_source_make_command_bitmap(ZIP_SOURCE_GET_FILE_ATTRIBUTES, ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1));
|
||||
ctx->needs_seek = (ctx->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK)) ? true : false;
|
||||
|
||||
if (st) {
|
||||
|
@ -173,7 +178,7 @@ window_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_sou
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
byte_array_fini(b);
|
||||
}
|
||||
|
||||
|
@ -231,8 +236,14 @@ window_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_sou
|
|||
return 0;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_GET_COMPRESSION_FLAGS:
|
||||
return ctx->compression_flags;
|
||||
case ZIP_SOURCE_GET_FILE_ATTRIBUTES:
|
||||
if (len < sizeof(ctx->attributes)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(data, &ctx->attributes, sizeof(ctx->attributes));
|
||||
return sizeof(ctx->attributes);
|
||||
|
||||
case ZIP_SOURCE_SUPPORTS:
|
||||
return ctx->supports;
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
|
|
|
@ -36,15 +36,19 @@
|
|||
|
||||
#include "zipint.h"
|
||||
|
||||
static void _zip_file_attributes_from_dirent(zip_file_attributes_t *attributes, zip_dirent_t *de);
|
||||
|
||||
zip_source_t *
|
||||
_zip_source_zip_new(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_uint64_t len, const char *password) {
|
||||
zip_source_t *src, *s2;
|
||||
struct zip_stat st;
|
||||
zip_stat_t st;
|
||||
zip_file_attributes_t attributes;
|
||||
zip_dirent_t *de;
|
||||
bool partial_data, needs_crc, needs_decrypt, needs_decompress;
|
||||
|
||||
if (za == NULL)
|
||||
if (za == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (srcza == NULL || srcidx >= srcza->nentry) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
|
@ -61,8 +65,9 @@ _zip_source_zip_new(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t fl
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (flags & ZIP_FL_ENCRYPTED)
|
||||
if (flags & ZIP_FL_ENCRYPTED) {
|
||||
flags |= ZIP_FL_COMPRESSED;
|
||||
}
|
||||
|
||||
if ((start > 0 || len > 0) && (flags & ZIP_FL_COMPRESSED)) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
|
@ -95,8 +100,13 @@ _zip_source_zip_new(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t fl
|
|||
}
|
||||
}
|
||||
|
||||
if ((de = _zip_get_dirent(srcza, srcidx, flags, &za->error)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
_zip_file_attributes_from_dirent(&attributes, de);
|
||||
|
||||
if (st.comp_size == 0) {
|
||||
return zip_source_buffer(za, NULL, 0, 0);
|
||||
return zip_source_buffer_with_attributes(za, NULL, 0, 0, &attributes);
|
||||
}
|
||||
|
||||
if (partial_data && !needs_decrypt && !needs_decompress) {
|
||||
|
@ -108,17 +118,12 @@ _zip_source_zip_new(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t fl
|
|||
st2.mtime = st.mtime;
|
||||
st2.valid = ZIP_STAT_SIZE | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_MTIME;
|
||||
|
||||
if ((src = _zip_source_window_new(srcza->src, start, len, &st2, 0, srcza, srcidx, &za->error)) == NULL) {
|
||||
if ((src = _zip_source_window_new(srcza->src, start, len, &st2, &attributes, srcza, srcidx, &za->error)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
zip_dirent_t *de;
|
||||
|
||||
if ((de = _zip_get_dirent(srcza, srcidx, flags, &za->error)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if ((src = _zip_source_window_new(srcza->src, 0, st.comp_size, &st, (de->bitflags >> 1) & 3, srcza, srcidx, &za->error)) == NULL) {
|
||||
if ((src = _zip_source_window_new(srcza->src, 0, st.comp_size, &st, &attributes, srcza, srcidx, &za->error)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -173,3 +178,14 @@ _zip_source_zip_new(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t fl
|
|||
|
||||
return src;
|
||||
}
|
||||
|
||||
static void
|
||||
_zip_file_attributes_from_dirent(zip_file_attributes_t *attributes, zip_dirent_t *de) {
|
||||
zip_file_attributes_init(attributes);
|
||||
attributes->valid = ZIP_FILE_ATTRIBUTES_ASCII | ZIP_FILE_ATTRIBUTES_HOST_SYSTEM | ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES | ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS;
|
||||
attributes->ascii = de->int_attrib & 1;
|
||||
attributes->host_system = de->version_madeby >> 8;
|
||||
attributes->external_file_attributes = de->ext_attrib;
|
||||
attributes->general_purpose_bit_flags = de->bitflags;
|
||||
attributes->general_purpose_bit_mask = ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK;
|
||||
}
|
||||
|
|
|
@ -34,10 +34,10 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
|
||||
zip_uint32_t
|
||||
_zip_string_crc32(const zip_string_t *s) {
|
||||
zip_uint32_t crc;
|
||||
|
@ -145,7 +145,7 @@ _zip_string_new(const zip_uint8_t *raw, zip_uint16_t length, zip_flags_t flags,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if ((s->raw = (zip_uint8_t *)malloc((size_t)(length + 1))) == NULL) {
|
||||
if ((s->raw = (zip_uint8_t *)malloc((size_t)length + 1)) == NULL) {
|
||||
free(s);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -32,8 +32,6 @@
|
|||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
|
||||
|
|
|
@ -34,10 +34,7 @@
|
|||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
#ifdef ZIP_ALLOCATE_BUFFER
|
||||
|
@ -69,6 +66,9 @@
|
|||
#define BUFSIZE 8192
|
||||
#define EFZIP64SIZE 28
|
||||
#define EF_WINZIP_AES_SIZE 7
|
||||
#define MAX_DATA_DESCRIPTOR_LENGTH 24
|
||||
|
||||
#define ZIP_CRYPTO_PKWARE_HEADERLEN 12
|
||||
|
||||
#define ZIP_CM_REPLACED_DEFAULT (-2)
|
||||
#define ZIP_CM_WINZIP_AES 99 /* Winzip AES encrypted */
|
||||
|
@ -95,6 +95,7 @@
|
|||
/* according to unzip-6.0's zipinfo.c, this corresponds to a directory with rwx permissions for everyone */
|
||||
#define ZIP_EXT_ATTRIB_DEFAULT_DIR (0040777u << 16)
|
||||
|
||||
#define ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK 0x0836
|
||||
|
||||
#define ZIP_MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define ZIP_MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
@ -111,14 +112,14 @@ typedef zip_source_t *(*zip_encryption_implementation)(zip_t *, zip_source_t *,
|
|||
|
||||
zip_encryption_implementation _zip_get_encryption_implementation(zip_uint16_t method, int operation);
|
||||
|
||||
// clang-format off
|
||||
/* clang-format off */
|
||||
enum zip_compression_status {
|
||||
ZIP_COMPRESSION_OK,
|
||||
ZIP_COMPRESSION_END,
|
||||
ZIP_COMPRESSION_ERROR,
|
||||
ZIP_COMPRESSION_NEED_DATA
|
||||
};
|
||||
// clang-format on
|
||||
/* clang-format on */
|
||||
typedef enum zip_compression_status zip_compression_status_t;
|
||||
|
||||
struct zip_compression_algorithm {
|
||||
|
@ -128,7 +129,9 @@ struct zip_compression_algorithm {
|
|||
void (*deallocate)(void *ctx);
|
||||
|
||||
/* get compression specific general purpose bitflags */
|
||||
int (*compression_flags)(void *ctx);
|
||||
zip_uint16_t (*general_purpose_bit_flags)(void *ctx);
|
||||
/* minimum version needed when using this algorithm */
|
||||
zip_uint8_t version_needed;
|
||||
|
||||
/* start processing */
|
||||
bool (*start)(void *ctx);
|
||||
|
@ -154,8 +157,6 @@ extern zip_compression_algorithm_t zip_algorithm_xz_compress;
|
|||
extern zip_compression_algorithm_t zip_algorithm_xz_decompress;
|
||||
|
||||
|
||||
bool zip_compression_method_supported(zip_int32_t method, bool compress);
|
||||
|
||||
/* This API is not final yet, but we need it internally, so it's private for now. */
|
||||
|
||||
const zip_uint8_t *zip_get_extra_field_by_id(zip_t *, int, int, zip_uint16_t, int, zip_uint16_t *);
|
||||
|
@ -170,13 +171,14 @@ zip_source_t *zip_source_crc(zip_t *, zip_source_t *, int);
|
|||
zip_source_t *zip_source_decompress(zip_t *za, zip_source_t *src, zip_int32_t cm);
|
||||
zip_source_t *zip_source_layered(zip_t *, zip_source_t *, zip_source_layered_callback, void *);
|
||||
zip_source_t *zip_source_layered_create(zip_source_t *src, zip_source_layered_callback cb, void *ud, zip_error_t *error);
|
||||
zip_source_t *zip_source_pkware(zip_t *, zip_source_t *, zip_uint16_t, int, const char *);
|
||||
zip_source_t *zip_source_pkware_decode(zip_t *, zip_source_t *, zip_uint16_t, int, const char *);
|
||||
zip_source_t *zip_source_pkware_encode(zip_t *, zip_source_t *, zip_uint16_t, int, const char *);
|
||||
int zip_source_remove(zip_source_t *);
|
||||
zip_int64_t zip_source_supports(zip_source_t *src);
|
||||
zip_source_t *zip_source_window(zip_t *, zip_source_t *, zip_uint64_t, zip_uint64_t);
|
||||
zip_source_t *zip_source_winzip_aes_decode(zip_t *, zip_source_t *, zip_uint16_t, int, const char *);
|
||||
zip_source_t *zip_source_winzip_aes_encode(zip_t *, zip_source_t *, zip_uint16_t, int, const char *);
|
||||
|
||||
zip_source_t *zip_source_buffer_with_attributes(zip_t *za, const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes);
|
||||
|
||||
/* error source for layered sources */
|
||||
|
||||
|
@ -381,13 +383,13 @@ struct zip_string {
|
|||
for those, use malloc()/free() */
|
||||
|
||||
#ifdef ZIP_ALLOCATE_BUFFER
|
||||
#define DEFINE_BYTE_ARRAY(buf, size) zip_uint8_t *buf
|
||||
#define byte_array_init(buf, size) (((buf) = (zip_uint8_t *)malloc(size)) != NULL)
|
||||
#define byte_array_fini(buf) (free(buf))
|
||||
#define DEFINE_BYTE_ARRAY(buf, size) zip_uint8_t *buf
|
||||
#define byte_array_init(buf, size) (((buf) = (zip_uint8_t *)malloc(size)) != NULL)
|
||||
#define byte_array_fini(buf) (free(buf))
|
||||
#else
|
||||
#define DEFINE_BYTE_ARRAY(buf, size) zip_uint8_t buf[size]
|
||||
#define byte_array_init(buf, size) (1)
|
||||
#define byte_array_fini(buf) ((void)0)
|
||||
#define DEFINE_BYTE_ARRAY(buf, size) zip_uint8_t buf[size]
|
||||
#define byte_array_init(buf, size) (1)
|
||||
#define byte_array_fini(buf) ((void)0)
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -414,6 +416,11 @@ typedef struct zip_filelist zip_filelist_t;
|
|||
struct _zip_winzip_aes;
|
||||
typedef struct _zip_winzip_aes zip_winzip_aes_t;
|
||||
|
||||
struct _zip_pkware_keys {
|
||||
zip_uint32_t key[3];
|
||||
};
|
||||
typedef struct _zip_pkware_keys zip_pkware_keys_t;
|
||||
|
||||
extern const char *const _zip_err_str[];
|
||||
extern const int _zip_nerr_str;
|
||||
extern const int _zip_err_type[];
|
||||
|
@ -466,7 +473,6 @@ int _zip_buffer_skip(zip_buffer_t *buffer, zip_uint64_t length);
|
|||
int _zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset);
|
||||
zip_uint64_t _zip_buffer_size(zip_buffer_t *buffer);
|
||||
|
||||
int _zip_cdir_compute_crc(zip_t *, uLong *);
|
||||
void _zip_cdir_free(zip_cdir_t *);
|
||||
bool _zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *error);
|
||||
zip_cdir_t *_zip_cdir_new(zip_uint64_t, zip_error_t *);
|
||||
|
@ -474,6 +480,7 @@ zip_int64_t _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint6
|
|||
time_t _zip_d2u_time(zip_uint16_t, zip_uint16_t);
|
||||
void _zip_deregister_source(zip_t *za, zip_source_t *src);
|
||||
|
||||
void _zip_dirent_apply_attributes(zip_dirent_t *, zip_file_attributes_t *, bool, zip_uint32_t);
|
||||
zip_dirent_t *_zip_dirent_clone(const zip_dirent_t *);
|
||||
void _zip_dirent_free(zip_dirent_t *);
|
||||
void _zip_dirent_finalize(zip_dirent_t *);
|
||||
|
@ -512,8 +519,6 @@ int _zip_file_fillbuf(void *, size_t, zip_file_t *);
|
|||
zip_uint64_t _zip_file_get_end(const zip_t *za, zip_uint64_t index, zip_error_t *error);
|
||||
zip_uint64_t _zip_file_get_offset(const zip_t *, zip_uint64_t, zip_error_t *);
|
||||
|
||||
int _zip_filerange_crc(zip_source_t *src, zip_uint64_t offset, zip_uint64_t length, uLong *crcp, zip_error_t *error);
|
||||
|
||||
zip_dirent_t *_zip_get_dirent(zip_t *, zip_uint64_t, zip_flags_t, zip_error_t *);
|
||||
|
||||
enum zip_encoding_type _zip_guess_encoding(zip_string_t *, enum zip_encoding_type);
|
||||
|
@ -545,7 +550,7 @@ int _zip_read(zip_source_t *src, zip_uint8_t *data, zip_uint64_t length, zip_err
|
|||
int _zip_read_at_offset(zip_source_t *src, zip_uint64_t offset, unsigned char *b, size_t length, zip_error_t *error);
|
||||
zip_uint8_t *_zip_read_data(zip_buffer_t *buffer, zip_source_t *src, size_t length, bool nulp, zip_error_t *error);
|
||||
int _zip_read_local_ef(zip_t *, zip_uint64_t);
|
||||
zip_string_t *_zip_read_string(zip_buffer_t *buffer, zip_source_t *src, zip_uint16_t lenght, bool nulp, zip_error_t *error);
|
||||
zip_string_t *_zip_read_string(zip_buffer_t *buffer, zip_source_t *src, zip_uint16_t length, bool nulp, zip_error_t *error);
|
||||
int _zip_register_source(zip_t *za, zip_source_t *src);
|
||||
|
||||
void _zip_set_open_error(int *zep, const zip_error_t *err, int ze);
|
||||
|
@ -554,12 +559,11 @@ bool zip_source_accept_empty(zip_source_t *src);
|
|||
zip_int64_t _zip_source_call(zip_source_t *src, void *data, zip_uint64_t length, zip_source_cmd_t command);
|
||||
bool _zip_source_eof(zip_source_t *);
|
||||
zip_source_t *_zip_source_file_or_p(const char *, FILE *, zip_uint64_t, zip_int64_t, const zip_stat_t *, zip_error_t *error);
|
||||
zip_int8_t zip_source_get_compression_flags(zip_source_t *);
|
||||
bool _zip_source_had_error(zip_source_t *);
|
||||
void _zip_source_invalidate(zip_source_t *src);
|
||||
zip_source_t *_zip_source_new(zip_error_t *error);
|
||||
int _zip_source_set_source_archive(zip_source_t *, zip_t *);
|
||||
zip_source_t *_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_int8_t compression_flags, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error);
|
||||
zip_source_t *_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_file_attributes_t *attributes, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error);
|
||||
zip_source_t *_zip_source_zip_new(zip_t *, zip_t *, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_uint64_t, const char *);
|
||||
|
||||
int _zip_stat_merge(zip_stat_t *dst, const zip_stat_t *src, zip_error_t *error);
|
||||
|
@ -576,6 +580,12 @@ bool _zip_winzip_aes_finish(zip_winzip_aes_t *ctx, zip_uint8_t *hmac);
|
|||
void _zip_winzip_aes_free(zip_winzip_aes_t *ctx);
|
||||
zip_winzip_aes_t *_zip_winzip_aes_new(const zip_uint8_t *password, zip_uint64_t password_length, const zip_uint8_t *salt, zip_uint16_t key_size, zip_uint8_t *password_verify, zip_error_t *error);
|
||||
|
||||
void _zip_pkware_encrypt(zip_pkware_keys_t *keys, zip_uint8_t *out, const zip_uint8_t *in, zip_uint64_t len);
|
||||
void _zip_pkware_decrypt(zip_pkware_keys_t *keys, zip_uint8_t *out, const zip_uint8_t *in, zip_uint64_t len);
|
||||
zip_pkware_keys_t *_zip_pkware_keys_new(zip_error_t *error);
|
||||
void _zip_pkware_keys_free(zip_pkware_keys_t *keys);
|
||||
void _zip_pkware_keys_reset(zip_pkware_keys_t *keys);
|
||||
|
||||
int _zip_changed(const zip_t *, zip_uint64_t *);
|
||||
const char *_zip_get_name(zip_t *, zip_uint64_t, zip_flags_t, zip_error_t *);
|
||||
int _zip_local_header_read(zip_t *, int);
|
||||
|
|
|
@ -1,85 +0,0 @@
|
|||
#ifndef _HAD_ZIPWIN32_H
|
||||
#define _HAD_ZIPWIN32_H
|
||||
|
||||
/*
|
||||
zipwin32.h -- internal declarations for Windows.
|
||||
Copyright (C) 1999-2019 Dieter Baron 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.
|
||||
*/
|
||||
|
||||
/* 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>
|
||||
|
||||
/* context for Win32 source */
|
||||
|
||||
struct _zip_source_win32_file_ops;
|
||||
|
||||
struct _zip_source_win32_read_file {
|
||||
zip_error_t error; /* last error information */
|
||||
zip_int64_t supports;
|
||||
|
||||
/* operations */
|
||||
struct _zip_source_win32_file_ops *ops;
|
||||
|
||||
/* reading */
|
||||
void *fname; /* name of file to read from - ANSI (char *) or Unicode (wchar_t *) */
|
||||
void *h; /* HANDLE for file to read from */
|
||||
int closep; /* whether to close f on ZIP_CMD_FREE */
|
||||
struct zip_stat st; /* stat information passed in */
|
||||
zip_uint64_t start; /* start offset of data to read */
|
||||
zip_uint64_t end; /* end offset of data to read, 0 for up to EOF */
|
||||
zip_uint64_t current; /* current offset */
|
||||
|
||||
/* writing */
|
||||
void *tmpname; /* name of temp file - ANSI (char *) or Unicode (wchar_t *) */
|
||||
void *hout; /* HANDLE for output file */
|
||||
};
|
||||
|
||||
typedef struct _zip_source_win32_read_file _zip_source_win32_read_file_t;
|
||||
|
||||
/* internal operations for Win32 source */
|
||||
|
||||
struct _zip_source_win32_file_ops {
|
||||
void *(*op_strdup)(const void *);
|
||||
void *(*op_open)(_zip_source_win32_read_file_t *);
|
||||
void *(*op_create_temp)(_zip_source_win32_read_file_t *, void **, zip_uint32_t, PSECURITY_ATTRIBUTES);
|
||||
int (*op_rename_temp)(_zip_source_win32_read_file_t *);
|
||||
int (*op_remove)(const void *);
|
||||
};
|
||||
|
||||
typedef struct _zip_source_win32_file_ops _zip_source_win32_file_ops_t;
|
||||
|
||||
zip_source_t *_zip_source_win32_handle_or_name(const void *, void *, zip_uint64_t, zip_int64_t, int, const zip_stat_t *, _zip_source_win32_file_ops_t *, zip_error_t *);
|
||||
|
||||
#endif /* zipwin32.h */
|
Loading…
Reference in New Issue