libarchive: merge from vendor branch
libarchive 3.8.1 New features: #2088 7-zip reader: improve self-extracting archive detection #2137 zip writer: added XZ, LZMA, ZSTD and BZIP2 support #2403 zip writer: added LZMA + RISCV BCJ filter #2601 bsdtar: support --mtime and --clamp-mtime #2602 libarchive: mbedtls 3.x compatibility Security fixes: #2422 tar reader: Handle truncation in the middle of a GNU long linkname CVE-2024-57970 #2532 tar reader: fix unchecked return value in list_item_verbose() CVE-2025-25724 #2532 unzip: fix null pointer dereference CVE-2025-1632 #2568 warc: prevent signed integer overflow #2584 rar: do not skip past EOF while reading #2588 tar: fix overflow in build_ustar_entry #2598 rar: fix double free with over 4 billion nodes #2599 rar: fix heap-buffer-overflow Important bugfixes: #2399 7-zip reader: add SPARC filter support for non-LZMA compressors #2405 tar reader: ignore ustar size when pax size is present #2435 tar writer: fix bug when -s/a/b/ used more than once with b flag #2459 7-zip reader: add POWERPC filter support for non-LZMA compressors #2519 libarchive: handle ARCHIVE_FILTER_LZOP in archive_read_append_filter #2539 libarchive: add missing seeker function to archive_read_open_FILE() #2544 gzip: allow setting the original filename for gzip compressed files #2564 libarchive: improve lseek handling #2582 rar: support large headers on 32 bit systems #2587 bsdtar: don't hardlink negative inode files together #2596 rar: support large headers on 32 bit systems #2606 libarchive: support @-prefixed Unix epoch timestamps as date strings #2634 tar: Support negative time values with pax #2637 tar: Keep block alignment after pax error #2642 libarchive: fix FILE_skip regression #2643 tar: Handle extra bytes after sparse entries #2649 compress: Prevent call stack overflow #2651 iso9660: always check archive_string_ensure return value CVE: CVE-2024-57970, CVE-2025-1632, CVE-2025-25724 PR: 286944 (exp-run, 3.8.0) MFC after: 2 weeks
This commit is contained in:
@@ -20,7 +20,7 @@ the actual statements in the files are controlling.
|
||||
libarchive/mtree.5
|
||||
|
||||
* The following source files are in the public domain:
|
||||
libarchive/archive_getdate.c
|
||||
libarchive/archive_parse_date.c
|
||||
|
||||
* The following source files are triple-licensed with the ability to choose
|
||||
from CC0 1.0 Universal, OpenSSL or Apache 2.0 licenses:
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
Jun 01, 2026: libarchive 3.8.1 released
|
||||
|
||||
May 20, 2025: libarchive 3.8.0 released
|
||||
|
||||
Mar 30, 2025: libarchive 3.7.9 released
|
||||
|
||||
Mar 20, 2025: libarchive 3.7.8 released
|
||||
|
||||
Oct 13, 2024: libarchive 3.7.7 released
|
||||
|
||||
Sep 23, 2024: libarchive 3.7.6 released
|
||||
|
||||
@@ -85,13 +85,14 @@ Currently, the library automatically detects and reads the following formats:
|
||||
* PWB binary cpio
|
||||
* ISO9660 CD-ROM images (with optional Rockridge or Joliet extensions)
|
||||
* ZIP archives (with uncompressed or "deflate" compressed entries, including support for encrypted Zip archives)
|
||||
* ZIPX archives (with support for bzip2, ppmd8, lzma and xz compressed entries)
|
||||
* ZIPX archives (with support for bzip2, zstd, ppmd8, lzma and xz compressed entries)
|
||||
* GNU and BSD 'ar' archives
|
||||
* 'mtree' format
|
||||
* 7-Zip archives (including archives that use zstandard compression)
|
||||
* Microsoft CAB format
|
||||
* LHA and LZH archives
|
||||
* RAR and RAR 5.0 archives (with some limitations due to RAR's proprietary status)
|
||||
* WARC archives
|
||||
* XAR archives
|
||||
|
||||
The library also detects and handles any of the following before evaluating the archive:
|
||||
@@ -120,15 +121,18 @@ The library can create archives in any of the following formats:
|
||||
* PWB binary cpio
|
||||
* shar archives
|
||||
* ZIP archives (with uncompressed or "deflate" compressed entries)
|
||||
* ZIPX archives (with bzip2, zstd, lzma or xz compressed entries)
|
||||
* GNU and BSD 'ar' archives
|
||||
* 'mtree' format
|
||||
* ISO9660 format
|
||||
* 7-Zip archives
|
||||
* 7-Zip archives (including archives that use zstandard compression)
|
||||
* WARC archives
|
||||
* XAR archives
|
||||
|
||||
When creating archives, the result can be filtered with any of the following:
|
||||
|
||||
* uuencode
|
||||
* base64
|
||||
* gzip compression
|
||||
* bzip2 compression
|
||||
* compress/LZW compression
|
||||
@@ -241,4 +245,3 @@ questions we are asked about libarchive:
|
||||
appropriate. It has many advantages over other tar formats
|
||||
(including the legacy GNU tar format) and is widely supported by
|
||||
current tar implementations.
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#!/bin/sh
|
||||
set -eux
|
||||
|
||||
# Uncommenting these adds a full minute to the CI time
|
||||
#brew update > /dev/null
|
||||
#brew upgrade > /dev/null
|
||||
|
||||
# This does an upgrade if the package is already installed
|
||||
brew install \
|
||||
autoconf \
|
||||
automake \
|
||||
libtool \
|
||||
pkg-config \
|
||||
cmake \
|
||||
xz \
|
||||
lz4 \
|
||||
zstd \
|
||||
libxml2 \
|
||||
openssl
|
||||
@@ -1206,7 +1206,7 @@ list_item_verbose(struct cpio *cpio, struct archive_entry *entry)
|
||||
else
|
||||
strcpy(date, "invalid mtime");
|
||||
|
||||
fprintf(out, "%s%3d %-8s %-8s %8s %12s %s",
|
||||
fprintf(out, "%s%3u %-8s %-8s %8s %12s %s",
|
||||
archive_entry_strmode(entry),
|
||||
archive_entry_nlink(entry),
|
||||
uname, gname, size, date,
|
||||
|
||||
@@ -189,10 +189,10 @@ DEFINE_TEST(test_format_newc)
|
||||
gid = from_hex(e + 30, 8); /* gid */
|
||||
assertEqualMem(e + 38, "00000003", 8); /* nlink */
|
||||
t = from_hex(e + 46, 8); /* mtime */
|
||||
failure("t=%#08jx now=%#08jx=%jd", (intmax_t)t, (intmax_t)now,
|
||||
failure("t=%#08jx now=%#08jx=%jd", (uintmax_t)t, (uintmax_t)now,
|
||||
(intmax_t)now);
|
||||
assert(t <= now); /* File wasn't created in future. */
|
||||
failure("t=%#08jx now - 2=%#08jx=%jd", (intmax_t)t, (intmax_t)now - 2,
|
||||
failure("t=%#08jx now - 2=%#08jx=%jd", (uintmax_t)t, (uintmax_t)now - 2,
|
||||
(intmax_t)now - 2);
|
||||
assert(t >= now - 2); /* File was created w/in last 2 secs. */
|
||||
failure("newc format stores body only with last appearance of a link\n"
|
||||
@@ -219,7 +219,7 @@ DEFINE_TEST(test_format_newc)
|
||||
assert(is_hex(e, 110));
|
||||
assertEqualMem(e + 0, "070701", 6); /* Magic */
|
||||
assert(is_hex(e + 6, 8)); /* ino */
|
||||
#if defined(_WIN32) && !defined(CYGWIN)
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* Mode: Group members bits and others bits do not work. */
|
||||
assertEqualInt(0xa180, from_hex(e + 14, 8) & 0xffc0);
|
||||
#else
|
||||
@@ -230,7 +230,7 @@ DEFINE_TEST(test_format_newc)
|
||||
assertEqualMem(e + 38, "00000001", 8); /* nlink */
|
||||
t2 = from_hex(e + 46, 8); /* mtime */
|
||||
failure("First entry created at t=%#08jx this entry created"
|
||||
" at t2=%#08jx", (intmax_t)t, (intmax_t)t2);
|
||||
" at t2=%#08jx", (uintmax_t)t, (uintmax_t)t2);
|
||||
assert(t2 == t || t2 == t + 1); /* Almost same as first entry. */
|
||||
assertEqualMem(e + 54, "00000005", 8); /* File size */
|
||||
fs = (uint64_t)from_hex(e + 54, 8);
|
||||
@@ -266,7 +266,7 @@ DEFINE_TEST(test_format_newc)
|
||||
#endif
|
||||
t2 = from_hex(e + 46, 8); /* mtime */
|
||||
failure("First entry created at t=%#08jx this entry created at"
|
||||
"t2=%#08jx", (intmax_t)t, (intmax_t)t2);
|
||||
"t2=%#08jx", (uintmax_t)t, (uintmax_t)t2);
|
||||
assert(t2 == t || t2 == t + 1); /* Almost same as first entry. */
|
||||
assertEqualMem(e + 54, "00000000", 8); /* File size */
|
||||
fs = (uint64_t)from_hex(e + 54, 8);
|
||||
@@ -300,7 +300,7 @@ DEFINE_TEST(test_format_newc)
|
||||
assertEqualMem(e + 38, "00000003", 8); /* nlink */
|
||||
t2 = from_hex(e + 46, 8); /* mtime */
|
||||
failure("First entry created at t=%#08jx this entry created at"
|
||||
"t2=%#08jx", (intmax_t)t, (intmax_t)t2);
|
||||
"t2=%#08jx", (uintmax_t)t, (uintmax_t)t2);
|
||||
assert(t2 == t || t2 == t + 1); /* Almost same as first entry. */
|
||||
assertEqualInt(10, from_hex(e + 54, 8)); /* File size */
|
||||
fs = (uint64_t)from_hex(e + 54, 8);
|
||||
|
||||
@@ -52,7 +52,7 @@ test_create(void)
|
||||
* #ifdef this section out. Most of the test below is
|
||||
* still valid. */
|
||||
memset(×, 0, sizeof(times));
|
||||
#if defined(_WIN32) && !defined(CYGWIN)
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
times.actime = 86400;
|
||||
times.modtime = 86400;
|
||||
#else
|
||||
|
||||
@@ -18,7 +18,7 @@ is_octal(const char *p, size_t l)
|
||||
return (1);
|
||||
}
|
||||
|
||||
static long long int
|
||||
static unsigned long long int
|
||||
from_octal(const char *p, size_t l)
|
||||
{
|
||||
long long int r = 0;
|
||||
@@ -117,7 +117,7 @@ DEFINE_TEST(test_option_c)
|
||||
gid = (int)from_octal(e + 30, 6);
|
||||
assertEqualMem(e + 36, "000001", 6); /* nlink */
|
||||
failure("file entries should not have rdev set (dev field was 0%o)",
|
||||
dev);
|
||||
(unsigned int)dev);
|
||||
assertEqualMem(e + 42, "000000", 6); /* rdev */
|
||||
t = from_octal(e + 48, 11); /* mtime */
|
||||
assert(t <= now); /* File wasn't created in future. */
|
||||
@@ -133,7 +133,7 @@ DEFINE_TEST(test_option_c)
|
||||
assert(is_octal(e, 76)); /* Entire header is octal digits. */
|
||||
assertEqualMem(e + 0, "070707", 6); /* Magic */
|
||||
assertEqualInt(dev, from_octal(e + 6, 6)); /* dev */
|
||||
assert(ino != from_octal(e + 12, 6)); /* ino */
|
||||
assert(ino != (int)from_octal(e + 12, 6)); /* ino */
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
/* On Windows, symbolic link and group members bits and
|
||||
* others bits do not work. */
|
||||
@@ -163,7 +163,7 @@ DEFINE_TEST(test_option_c)
|
||||
assertEqualInt(dev, from_octal(e + 6, 6));
|
||||
/* Ino must be different from first entry. */
|
||||
assert(is_octal(e + 12, 6)); /* ino */
|
||||
assert(ino != from_octal(e + 12, 6));
|
||||
assert(ino != (int)from_octal(e + 12, 6));
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* Group members bits and others bits do not work. */
|
||||
assertEqualMem(e + 18, "040777", 6); /* Mode */
|
||||
|
||||
@@ -34,12 +34,15 @@
|
||||
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
|
||||
*/
|
||||
/* Note: Compiler will complain if this does not match archive_entry.h! */
|
||||
#define ARCHIVE_VERSION_NUMBER 3007007
|
||||
#define ARCHIVE_VERSION_NUMBER 3008001
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stddef.h> /* for wchar_t */
|
||||
#include <stdio.h> /* For FILE * */
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* time_t is slated to be removed from public includes in 4.0 */
|
||||
#include <time.h> /* For time_t */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Note: archive.h is for use outside of libarchive; the configuration
|
||||
@@ -63,12 +66,15 @@
|
||||
#define __LA_INT64_T_DEFINED
|
||||
# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
|
||||
typedef __int64 la_int64_t;
|
||||
typedef unsigned __int64 la_uint64_t;
|
||||
# else
|
||||
# include <unistd.h> /* ssize_t */
|
||||
# if defined(_SCO_DS) || defined(__osf__)
|
||||
typedef long long la_int64_t;
|
||||
typedef unsigned long long la_uint64_t;
|
||||
# else
|
||||
typedef int64_t la_int64_t;
|
||||
typedef uint64_t la_uint64_t;
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
@@ -94,6 +100,22 @@ typedef ssize_t la_ssize_t;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* Use the platform types for time_t */
|
||||
#define __LA_TIME_T time_t
|
||||
#else
|
||||
/* Use 64-bits integer types for time_t */
|
||||
#define __LA_TIME_T la_int64_t
|
||||
#endif
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* Use the platform types for dev_t */
|
||||
#define __LA_DEV_T dev_t
|
||||
#else
|
||||
/* Use 64-bits integer types for dev_t */
|
||||
#define __LA_DEV_T la_int64_t
|
||||
#endif
|
||||
|
||||
/* Large file support for Android */
|
||||
#if defined(__LIBARCHIVE_BUILD) && defined(__ANDROID__)
|
||||
#include "android_lf.h"
|
||||
@@ -132,7 +154,7 @@ typedef ssize_t la_ssize_t;
|
||||
#define __LA_PRINTF(fmtarg, firstvararg) /* nothing */
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ >= 3 && __GNUC_MINOR__ >= 1
|
||||
#if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
|
||||
# define __LA_DEPRECATED __attribute__((deprecated))
|
||||
#else
|
||||
# define __LA_DEPRECATED
|
||||
@@ -155,7 +177,7 @@ __LA_DECL int archive_version_number(void);
|
||||
/*
|
||||
* Textual name/version of the library, useful for version displays.
|
||||
*/
|
||||
#define ARCHIVE_VERSION_ONLY_STRING "3.7.7"
|
||||
#define ARCHIVE_VERSION_ONLY_STRING "3.8.1"
|
||||
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
|
||||
__LA_DECL const char * archive_version_string(void);
|
||||
|
||||
@@ -178,6 +200,23 @@ __LA_DECL const char * archive_liblzma_version(void);
|
||||
__LA_DECL const char * archive_bzlib_version(void);
|
||||
__LA_DECL const char * archive_liblz4_version(void);
|
||||
__LA_DECL const char * archive_libzstd_version(void);
|
||||
__LA_DECL const char * archive_liblzo2_version(void);
|
||||
__LA_DECL const char * archive_libexpat_version(void);
|
||||
__LA_DECL const char * archive_libbsdxml_version(void);
|
||||
__LA_DECL const char * archive_libxml2_version(void);
|
||||
__LA_DECL const char * archive_mbedtls_version(void);
|
||||
__LA_DECL const char * archive_nettle_version(void);
|
||||
__LA_DECL const char * archive_openssl_version(void);
|
||||
__LA_DECL const char * archive_libmd_version(void);
|
||||
__LA_DECL const char * archive_commoncrypto_version(void);
|
||||
__LA_DECL const char * archive_cng_version(void);
|
||||
__LA_DECL const char * archive_wincrypt_version(void);
|
||||
__LA_DECL const char * archive_librichacl_version(void);
|
||||
__LA_DECL const char * archive_libacl_version(void);
|
||||
__LA_DECL const char * archive_libattr_version(void);
|
||||
__LA_DECL const char * archive_libiconv_version(void);
|
||||
__LA_DECL const char * archive_libpcre_version(void);
|
||||
__LA_DECL const char * archive_libpcre2_version(void);
|
||||
|
||||
/* Declare our basic types. */
|
||||
struct archive;
|
||||
@@ -449,6 +488,8 @@ __LA_DECL int archive_read_support_format_by_code(struct archive *, int);
|
||||
__LA_DECL int archive_read_support_format_cab(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_cpio(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_empty(struct archive *);
|
||||
/* archive_read_support_format_gnutar() is an alias for historical reasons
|
||||
* of archive_read_support_format_tar(). */
|
||||
__LA_DECL int archive_read_support_format_gnutar(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_iso9660(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_lha(struct archive *);
|
||||
@@ -828,6 +869,10 @@ __LA_DECL int archive_write_set_format_filter_by_ext(struct archive *a, const ch
|
||||
__LA_DECL int archive_write_set_format_filter_by_ext_def(struct archive *a, const char *filename, const char * def_ext);
|
||||
__LA_DECL int archive_write_zip_set_compression_deflate(struct archive *);
|
||||
__LA_DECL int archive_write_zip_set_compression_store(struct archive *);
|
||||
__LA_DECL int archive_write_zip_set_compression_lzma(struct archive *);
|
||||
__LA_DECL int archive_write_zip_set_compression_xz(struct archive *);
|
||||
__LA_DECL int archive_write_zip_set_compression_bzip2(struct archive *);
|
||||
__LA_DECL int archive_write_zip_set_compression_zstd(struct archive *);
|
||||
/* Deprecated; use archive_write_open2 instead */
|
||||
__LA_DECL int archive_write_open(struct archive *, void *,
|
||||
archive_open_callback *, archive_write_callback *,
|
||||
@@ -1083,6 +1128,10 @@ __LA_DECL int archive_compression(struct archive *)
|
||||
__LA_DEPRECATED;
|
||||
#endif
|
||||
|
||||
/* Parses a date string relative to the current time.
|
||||
* NOTE: This is not intended for general date parsing, and the resulting timestamp should only be used for libarchive. */
|
||||
__LA_DECL time_t archive_parse_date(time_t now, const char *datestr);
|
||||
|
||||
__LA_DECL int archive_errno(struct archive *);
|
||||
__LA_DECL const char *archive_error_string(struct archive *);
|
||||
__LA_DECL const char *archive_format_name(struct archive *);
|
||||
@@ -1201,8 +1250,10 @@ __LA_DECL int archive_match_include_gname_w(struct archive *,
|
||||
const wchar_t *);
|
||||
|
||||
/* Utility functions */
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* Convenience function to sort a NULL terminated list of strings */
|
||||
__LA_DECL int archive_utility_string_sort(char **);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -1185,8 +1185,13 @@ archive_acl_from_text_w(struct archive_acl *acl, const wchar_t *text,
|
||||
/* Set remaining fields to blank. */
|
||||
for (n = fields; n < numfields; ++n)
|
||||
field[n].start = field[n].end = NULL;
|
||||
|
||||
if (field[0].start == NULL || field[0].end == NULL) {
|
||||
/* This should never happen */
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
if (field[0].start != NULL && *(field[0].start) == L'#') {
|
||||
if (*(field[0].start) == L'#') {
|
||||
/* Comment, skip entry */
|
||||
continue;
|
||||
}
|
||||
@@ -1676,7 +1681,12 @@ archive_acl_from_text_nl(struct archive_acl *acl, const char *text,
|
||||
for (n = fields; n < numfields; ++n)
|
||||
field[n].start = field[n].end = NULL;
|
||||
|
||||
if (field[0].start != NULL && *(field[0].start) == '#') {
|
||||
if (field[0].start == NULL || field[0].end == NULL) {
|
||||
/* This should never happen */
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
if (*(field[0].start) == '#') {
|
||||
/* Comment, skip entry */
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -80,4 +80,4 @@ int archive_acl_from_text_l(struct archive_acl *, const char * /* text */,
|
||||
int archive_acl_from_text_nl(struct archive_acl *, const char * /* text */,
|
||||
size_t /* size of text */, int /* type */, struct archive_string_conv *);
|
||||
|
||||
#endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */
|
||||
#endif /* !ARCHIVE_ACL_PRIVATE_H_INCLUDED */
|
||||
|
||||
@@ -71,7 +71,7 @@ get_argument(struct archive_string *as, const char *p)
|
||||
archive_string_empty(as);
|
||||
|
||||
/* Skip beginning space characters. */
|
||||
while (*s != '\0' && *s == ' ')
|
||||
while (*s == ' ')
|
||||
s++;
|
||||
/* Copy non-space characters. */
|
||||
while (*s != '\0' && *s != ' ') {
|
||||
|
||||
@@ -64,6 +64,7 @@ typedef struct {
|
||||
|
||||
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
#include <bcrypt.h>
|
||||
#define ARCHIVE_CRYPTOR_USE_CNG 1
|
||||
|
||||
/* Common in other bcrypt implementations, but missing from VS2008. */
|
||||
#ifndef BCRYPT_SUCCESS
|
||||
@@ -86,6 +87,7 @@ typedef struct {
|
||||
#include <mbedtls/aes.h>
|
||||
#include <mbedtls/md.h>
|
||||
#include <mbedtls/pkcs5.h>
|
||||
#define ARCHIVE_CRYPTOR_USE_MBED 1
|
||||
|
||||
#define AES_MAX_KEY_SIZE 32
|
||||
#define AES_BLOCK_SIZE 16
|
||||
@@ -105,6 +107,7 @@ typedef struct {
|
||||
#endif
|
||||
#include <nettle/aes.h>
|
||||
#include <nettle/version.h>
|
||||
#define ARCHIVE_CRYPTOR_USE_NETTLE 1
|
||||
|
||||
typedef struct {
|
||||
#if NETTLE_VERSION_MAJOR < 3
|
||||
@@ -125,6 +128,7 @@ typedef struct {
|
||||
|
||||
#elif defined(HAVE_LIBCRYPTO)
|
||||
#include "archive_openssl_evp_private.h"
|
||||
#define ARCHIVE_CRYPTOR_USE_OPENSSL 1
|
||||
#define AES_BLOCK_SIZE 16
|
||||
#define AES_MAX_KEY_SIZE 32
|
||||
|
||||
@@ -140,6 +144,10 @@ typedef struct {
|
||||
|
||||
#else
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__) && !(defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA)
|
||||
#define ARCHIVE_CRYPTOR_USE_WINCRYPT 1
|
||||
#endif
|
||||
|
||||
#define AES_BLOCK_SIZE 16
|
||||
#define AES_MAX_KEY_SIZE 32
|
||||
typedef int archive_crypto_ctx;
|
||||
|
||||
@@ -196,6 +196,13 @@ __archive_md5final(archive_md5_ctx *ctx, void *md)
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM)
|
||||
|
||||
// These functions are available in macOS 10.4 and later, but deprecated from 10.15 onwards.
|
||||
// We need to continue supporting this feature regardless, so suppress the warnings.
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
static int
|
||||
__archive_md5init(archive_md5_ctx *ctx)
|
||||
{
|
||||
@@ -218,13 +225,46 @@ __archive_md5final(archive_md5_ctx *ctx, void *md)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_MD5_WIN)
|
||||
|
||||
static int
|
||||
__archive_md5init(archive_md5_ctx *ctx)
|
||||
{
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
return (win_crypto_init(ctx, BCRYPT_MD5_ALGORITHM));
|
||||
#else
|
||||
return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_MD5));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_md5update(archive_md5_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
return (win_crypto_Update(ctx, indata, insize));
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_md5final(archive_md5_ctx *ctx, void *md)
|
||||
{
|
||||
return (win_crypto_Final(md, 16, ctx));
|
||||
}
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_MD5_MBEDTLS)
|
||||
|
||||
static int
|
||||
__archive_md5init(archive_md5_ctx *ctx)
|
||||
{
|
||||
mbedtls_md5_init(ctx);
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_md5_starts(ctx) == 0)
|
||||
#else
|
||||
if (mbedtls_md5_starts_ret(ctx) == 0)
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
else
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -234,7 +274,11 @@ static int
|
||||
__archive_md5update(archive_md5_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_md5_update(ctx, indata, insize) == 0)
|
||||
#else
|
||||
if (mbedtls_md5_update_ret(ctx, indata, insize) == 0)
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
else
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -243,7 +287,11 @@ __archive_md5update(archive_md5_ctx *ctx, const void *indata,
|
||||
static int
|
||||
__archive_md5final(archive_md5_ctx *ctx, void *md)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_md5_finish(ctx, md) == 0) {
|
||||
#else
|
||||
if (mbedtls_md5_finish_ret(ctx, md) == 0) {
|
||||
#endif
|
||||
mbedtls_md5_free(ctx);
|
||||
return (ARCHIVE_OK);
|
||||
} else {
|
||||
@@ -311,31 +359,6 @@ __archive_md5final(archive_md5_ctx *ctx, void *md)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_MD5_WIN)
|
||||
|
||||
static int
|
||||
__archive_md5init(archive_md5_ctx *ctx)
|
||||
{
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
return (win_crypto_init(ctx, BCRYPT_MD5_ALGORITHM));
|
||||
#else
|
||||
return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_MD5));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_md5update(archive_md5_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
return (win_crypto_Update(ctx, indata, insize));
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_md5final(archive_md5_ctx *ctx, void *md)
|
||||
{
|
||||
return (win_crypto_Final(md, 16, ctx));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int
|
||||
@@ -420,7 +443,11 @@ static int
|
||||
__archive_ripemd160init(archive_rmd160_ctx *ctx)
|
||||
{
|
||||
mbedtls_ripemd160_init(ctx);
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_ripemd160_starts(ctx) == 0)
|
||||
#else
|
||||
if (mbedtls_ripemd160_starts_ret(ctx) == 0)
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
else
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -430,7 +457,11 @@ static int
|
||||
__archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_ripemd160_update(ctx, indata, insize) == 0)
|
||||
#else
|
||||
if (mbedtls_ripemd160_update_ret(ctx, indata, insize) == 0)
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
else
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -439,7 +470,11 @@ __archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
|
||||
static int
|
||||
__archive_ripemd160final(archive_rmd160_ctx *ctx, void *md)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_ripemd160_finish(ctx, md) == 0) {
|
||||
#else
|
||||
if (mbedtls_ripemd160_finish_ret(ctx, md) == 0) {
|
||||
#endif
|
||||
mbedtls_ripemd160_free(ctx);
|
||||
return (ARCHIVE_OK);
|
||||
} else {
|
||||
@@ -605,13 +640,42 @@ __archive_sha1final(archive_sha1_ctx *ctx, void *md)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA1_WIN)
|
||||
|
||||
static int
|
||||
__archive_sha1init(archive_sha1_ctx *ctx)
|
||||
{
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
return (win_crypto_init(ctx, BCRYPT_SHA1_ALGORITHM));
|
||||
#else
|
||||
return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_SHA1));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
return (win_crypto_Update(ctx, indata, insize));
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha1final(archive_sha1_ctx *ctx, void *md)
|
||||
{
|
||||
return (win_crypto_Final(md, 20, ctx));
|
||||
}
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA1_MBEDTLS)
|
||||
|
||||
static int
|
||||
__archive_sha1init(archive_sha1_ctx *ctx)
|
||||
{
|
||||
mbedtls_sha1_init(ctx);
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_sha1_starts(ctx) == 0)
|
||||
#else
|
||||
if (mbedtls_sha1_starts_ret(ctx) == 0)
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
else
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -621,7 +685,11 @@ static int
|
||||
__archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_sha1_update(ctx, indata, insize) == 0)
|
||||
#else
|
||||
if (mbedtls_sha1_update_ret(ctx, indata, insize) == 0)
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
else
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -630,7 +698,11 @@ __archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
|
||||
static int
|
||||
__archive_sha1final(archive_sha1_ctx *ctx, void *md)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_sha1_finish(ctx, md) == 0) {
|
||||
#else
|
||||
if (mbedtls_sha1_finish_ret(ctx, md) == 0) {
|
||||
#endif
|
||||
mbedtls_sha1_free(ctx);
|
||||
return (ARCHIVE_OK);
|
||||
} else {
|
||||
@@ -698,31 +770,6 @@ __archive_sha1final(archive_sha1_ctx *ctx, void *md)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA1_WIN)
|
||||
|
||||
static int
|
||||
__archive_sha1init(archive_sha1_ctx *ctx)
|
||||
{
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
return (win_crypto_init(ctx, BCRYPT_SHA1_ALGORITHM));
|
||||
#else
|
||||
return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_SHA1));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
return (win_crypto_Update(ctx, indata, insize));
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha1final(archive_sha1_ctx *ctx, void *md)
|
||||
{
|
||||
return (win_crypto_Final(md, 20, ctx));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int
|
||||
@@ -873,13 +920,42 @@ __archive_sha256final(archive_sha256_ctx *ctx, void *md)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA256_WIN)
|
||||
|
||||
static int
|
||||
__archive_sha256init(archive_sha256_ctx *ctx)
|
||||
{
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
return (win_crypto_init(ctx, BCRYPT_SHA256_ALGORITHM));
|
||||
#else
|
||||
return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_256));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
return (win_crypto_Update(ctx, indata, insize));
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha256final(archive_sha256_ctx *ctx, void *md)
|
||||
{
|
||||
return (win_crypto_Final(md, 32, ctx));
|
||||
}
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA256_MBEDTLS)
|
||||
|
||||
static int
|
||||
__archive_sha256init(archive_sha256_ctx *ctx)
|
||||
{
|
||||
mbedtls_sha256_init(ctx);
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_sha256_starts(ctx, 0) == 0)
|
||||
#else
|
||||
if (mbedtls_sha256_starts_ret(ctx, 0) == 0)
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
else
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -889,7 +965,11 @@ static int
|
||||
__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_sha256_update(ctx, indata, insize) == 0)
|
||||
#else
|
||||
if (mbedtls_sha256_update_ret(ctx, indata, insize) == 0)
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
else
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -898,7 +978,11 @@ __archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
|
||||
static int
|
||||
__archive_sha256final(archive_sha256_ctx *ctx, void *md)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_sha256_finish(ctx, md) == 0) {
|
||||
#else
|
||||
if (mbedtls_sha256_finish_ret(ctx, md) == 0) {
|
||||
#endif
|
||||
mbedtls_sha256_free(ctx);
|
||||
return (ARCHIVE_OK);
|
||||
} else {
|
||||
@@ -962,31 +1046,6 @@ __archive_sha256final(archive_sha256_ctx *ctx, void *md)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA256_WIN)
|
||||
|
||||
static int
|
||||
__archive_sha256init(archive_sha256_ctx *ctx)
|
||||
{
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
return (win_crypto_init(ctx, BCRYPT_SHA256_ALGORITHM));
|
||||
#else
|
||||
return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_256));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
return (win_crypto_Update(ctx, indata, insize));
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha256final(archive_sha256_ctx *ctx, void *md)
|
||||
{
|
||||
return (win_crypto_Final(md, 32, ctx));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int
|
||||
@@ -1113,13 +1172,42 @@ __archive_sha384final(archive_sha384_ctx *ctx, void *md)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA384_WIN)
|
||||
|
||||
static int
|
||||
__archive_sha384init(archive_sha384_ctx *ctx)
|
||||
{
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
return (win_crypto_init(ctx, BCRYPT_SHA384_ALGORITHM));
|
||||
#else
|
||||
return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_384));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
return (win_crypto_Update(ctx, indata, insize));
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha384final(archive_sha384_ctx *ctx, void *md)
|
||||
{
|
||||
return (win_crypto_Final(md, 48, ctx));
|
||||
}
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA384_MBEDTLS)
|
||||
|
||||
static int
|
||||
__archive_sha384init(archive_sha384_ctx *ctx)
|
||||
{
|
||||
mbedtls_sha512_init(ctx);
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_sha512_starts(ctx, 1) == 0)
|
||||
#else
|
||||
if (mbedtls_sha512_starts_ret(ctx, 1) == 0)
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
else
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -1129,7 +1217,11 @@ static int
|
||||
__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_sha512_update(ctx, indata, insize) == 0)
|
||||
#else
|
||||
if (mbedtls_sha512_update_ret(ctx, indata, insize) == 0)
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
else
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -1138,7 +1230,11 @@ __archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
|
||||
static int
|
||||
__archive_sha384final(archive_sha384_ctx *ctx, void *md)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_sha512_finish(ctx, md) == 0) {
|
||||
#else
|
||||
if (mbedtls_sha512_finish_ret(ctx, md) == 0) {
|
||||
#endif
|
||||
mbedtls_sha512_free(ctx);
|
||||
return (ARCHIVE_OK);
|
||||
} else {
|
||||
@@ -1202,31 +1298,6 @@ __archive_sha384final(archive_sha384_ctx *ctx, void *md)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA384_WIN)
|
||||
|
||||
static int
|
||||
__archive_sha384init(archive_sha384_ctx *ctx)
|
||||
{
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
return (win_crypto_init(ctx, BCRYPT_SHA384_ALGORITHM));
|
||||
#else
|
||||
return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_384));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
return (win_crypto_Update(ctx, indata, insize));
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha384final(archive_sha384_ctx *ctx, void *md)
|
||||
{
|
||||
return (win_crypto_Final(md, 48, ctx));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int
|
||||
@@ -1377,13 +1448,42 @@ __archive_sha512final(archive_sha512_ctx *ctx, void *md)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA512_WIN)
|
||||
|
||||
static int
|
||||
__archive_sha512init(archive_sha512_ctx *ctx)
|
||||
{
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
return (win_crypto_init(ctx, BCRYPT_SHA512_ALGORITHM));
|
||||
#else
|
||||
return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_512));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
return (win_crypto_Update(ctx, indata, insize));
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha512final(archive_sha512_ctx *ctx, void *md)
|
||||
{
|
||||
return (win_crypto_Final(md, 64, ctx));
|
||||
}
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA512_MBEDTLS)
|
||||
|
||||
static int
|
||||
__archive_sha512init(archive_sha512_ctx *ctx)
|
||||
{
|
||||
mbedtls_sha512_init(ctx);
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_sha512_starts(ctx, 0) == 0)
|
||||
#else
|
||||
if (mbedtls_sha512_starts_ret(ctx, 0) == 0)
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
else
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -1393,7 +1493,11 @@ static int
|
||||
__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_sha512_update(ctx, indata, insize) == 0)
|
||||
#else
|
||||
if (mbedtls_sha512_update_ret(ctx, indata, insize) == 0)
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
else
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -1402,7 +1506,11 @@ __archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
|
||||
static int
|
||||
__archive_sha512final(archive_sha512_ctx *ctx, void *md)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_sha512_finish(ctx, md) == 0) {
|
||||
#else
|
||||
if (mbedtls_sha512_finish_ret(ctx, md) == 0) {
|
||||
#endif
|
||||
mbedtls_sha512_free(ctx);
|
||||
return (ARCHIVE_OK);
|
||||
} else {
|
||||
@@ -1466,31 +1574,6 @@ __archive_sha512final(archive_sha512_ctx *ctx, void *md)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA512_WIN)
|
||||
|
||||
static int
|
||||
__archive_sha512init(archive_sha512_ctx *ctx)
|
||||
{
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
return (win_crypto_init(ctx, BCRYPT_SHA512_ALGORITHM));
|
||||
#else
|
||||
return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_512));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
return (win_crypto_Update(ctx, indata, insize));
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha512final(archive_sha512_ctx *ctx, void *md)
|
||||
{
|
||||
return (win_crypto_Final(md, 64, ctx));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int
|
||||
@@ -1525,11 +1608,12 @@ __archive_sha512final(archive_sha512_ctx *ctx, void *md)
|
||||
* 1. libc
|
||||
* 2. libc2
|
||||
* 3. libc3
|
||||
* 4. libSystem
|
||||
* 5. Nettle
|
||||
* 6. OpenSSL
|
||||
* 7. libmd
|
||||
* 8. Windows API
|
||||
* 4. libmd
|
||||
* 5. libSystem
|
||||
* 6. Windows API
|
||||
* 7. mbedTLS
|
||||
* 8. Nettle
|
||||
* 9. OpenSSL
|
||||
*/
|
||||
const struct archive_digest __archive_digest =
|
||||
{
|
||||
|
||||
@@ -113,6 +113,7 @@
|
||||
defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM)
|
||||
#include <CommonCrypto/CommonDigest.h>
|
||||
#define ARCHIVE_CRYPTO_CommonCrypto 1
|
||||
#endif
|
||||
|
||||
/* mbed TLS crypto headers */
|
||||
@@ -167,6 +168,7 @@
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
/* don't use bcrypt when XP needs to be supported */
|
||||
#include <bcrypt.h>
|
||||
#define ARCHIVE_CRYPTO_CNG 1
|
||||
typedef struct {
|
||||
int valid;
|
||||
BCRYPT_ALG_HANDLE hAlg;
|
||||
@@ -175,6 +177,7 @@ typedef struct {
|
||||
#else
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
#define ARCHIVE_CRYPTO_WINCRYPT 1
|
||||
typedef struct {
|
||||
int valid;
|
||||
HCRYPTPROV cryptProv;
|
||||
@@ -190,14 +193,16 @@ typedef MD5_CTX archive_md5_ctx;
|
||||
typedef MD5_CTX archive_md5_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM)
|
||||
typedef CC_MD5_CTX archive_md5_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_MD5_WIN)
|
||||
typedef Digest_CTX archive_md5_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_MD5_MBEDTLS)
|
||||
#define ARCHIVE_CRYPTO_MBED 1
|
||||
typedef mbedtls_md5_context archive_md5_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_MD5_NETTLE)
|
||||
#define ARCHIVE_CRYPTO_NETTLE 1
|
||||
typedef struct md5_ctx archive_md5_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_MD5_OPENSSL)
|
||||
typedef EVP_MD_CTX *archive_md5_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_MD5_WIN)
|
||||
typedef Digest_CTX archive_md5_ctx;
|
||||
#else
|
||||
typedef unsigned char archive_md5_ctx;
|
||||
#endif
|
||||
@@ -207,8 +212,10 @@ typedef RMD160_CTX archive_rmd160_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_RMD160_LIBMD)
|
||||
typedef RIPEMD160_CTX archive_rmd160_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_RMD160_MBEDTLS)
|
||||
#define ARCHIVE_CRYPTO_MBED 1
|
||||
typedef mbedtls_ripemd160_context archive_rmd160_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_RMD160_NETTLE)
|
||||
#define ARCHIVE_CRYPTO_NETTLE 1
|
||||
typedef struct ripemd160_ctx archive_rmd160_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_RMD160_OPENSSL)
|
||||
typedef EVP_MD_CTX *archive_rmd160_ctx;
|
||||
@@ -222,14 +229,16 @@ typedef SHA1_CTX archive_sha1_ctx;
|
||||
typedef SHA1_CTX archive_sha1_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA1_LIBSYSTEM)
|
||||
typedef CC_SHA1_CTX archive_sha1_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA1_WIN)
|
||||
typedef Digest_CTX archive_sha1_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA1_MBEDTLS)
|
||||
#define ARCHIVE_CRYPTO_MBED 1
|
||||
typedef mbedtls_sha1_context archive_sha1_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA1_NETTLE)
|
||||
#define ARCHIVE_CRYPTO_NETTLE 1
|
||||
typedef struct sha1_ctx archive_sha1_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA1_OPENSSL)
|
||||
typedef EVP_MD_CTX *archive_sha1_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA1_WIN)
|
||||
typedef Digest_CTX archive_sha1_ctx;
|
||||
#else
|
||||
typedef unsigned char archive_sha1_ctx;
|
||||
#endif
|
||||
@@ -244,14 +253,16 @@ typedef SHA2_CTX archive_sha256_ctx;
|
||||
typedef SHA256_CTX archive_sha256_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM)
|
||||
typedef CC_SHA256_CTX archive_sha256_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA256_WIN)
|
||||
typedef Digest_CTX archive_sha256_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA256_MBEDTLS)
|
||||
#define ARCHIVE_CRYPTO_MBED 1
|
||||
typedef mbedtls_sha256_context archive_sha256_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA256_NETTLE)
|
||||
#define ARCHIVE_CRYPTO_NETTLE 1
|
||||
typedef struct sha256_ctx archive_sha256_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA256_OPENSSL)
|
||||
typedef EVP_MD_CTX *archive_sha256_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA256_WIN)
|
||||
typedef Digest_CTX archive_sha256_ctx;
|
||||
#else
|
||||
typedef unsigned char archive_sha256_ctx;
|
||||
#endif
|
||||
@@ -264,14 +275,16 @@ typedef SHA384_CTX archive_sha384_ctx;
|
||||
typedef SHA2_CTX archive_sha384_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM)
|
||||
typedef CC_SHA512_CTX archive_sha384_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA384_WIN)
|
||||
typedef Digest_CTX archive_sha384_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA384_MBEDTLS)
|
||||
#define ARCHIVE_CRYPTO_MBED 1
|
||||
typedef mbedtls_sha512_context archive_sha384_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA384_NETTLE)
|
||||
#define ARCHIVE_CRYPTO_NETTLE 1
|
||||
typedef struct sha384_ctx archive_sha384_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA384_OPENSSL)
|
||||
typedef EVP_MD_CTX *archive_sha384_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA384_WIN)
|
||||
typedef Digest_CTX archive_sha384_ctx;
|
||||
#else
|
||||
typedef unsigned char archive_sha384_ctx;
|
||||
#endif
|
||||
@@ -286,14 +299,16 @@ typedef SHA2_CTX archive_sha512_ctx;
|
||||
typedef SHA512_CTX archive_sha512_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM)
|
||||
typedef CC_SHA512_CTX archive_sha512_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA512_WIN)
|
||||
typedef Digest_CTX archive_sha512_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA512_MBEDTLS)
|
||||
#define ARCHIVE_CRYPTO_MBED 1
|
||||
typedef mbedtls_sha512_context archive_sha512_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA512_NETTLE)
|
||||
#define ARCHIVE_CRYPTO_NETTLE 1
|
||||
typedef struct sha512_ctx archive_sha512_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA512_OPENSSL)
|
||||
typedef EVP_MD_CTX *archive_sha512_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA512_WIN)
|
||||
typedef Digest_CTX archive_sha512_ctx;
|
||||
#else
|
||||
typedef unsigned char archive_sha512_ctx;
|
||||
#endif
|
||||
|
||||
@@ -262,7 +262,7 @@ translate_acl(struct archive_read_disk *a,
|
||||
}
|
||||
for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
|
||||
r = acl_get_flag_np(acl_flagset,
|
||||
acl_nfs4_flag_map[i].p_perm);
|
||||
(acl_flag_t)acl_nfs4_flag_map[i].p_perm);
|
||||
if (r == -1) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Failed to check flag in a NFSv4 "
|
||||
@@ -517,7 +517,7 @@ set_acl(struct archive *a, int fd, const char *name,
|
||||
for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
|
||||
if (ae_permset & acl_nfs4_flag_map[i].a_perm) {
|
||||
if (acl_add_flag_np(acl_flagset,
|
||||
acl_nfs4_flag_map[i].p_perm) != 0) {
|
||||
(acl_flag_t)acl_nfs4_flag_map[i].p_perm) != 0) {
|
||||
archive_set_error(a, errno,
|
||||
"Failed to add flag to "
|
||||
"NFSv4 ACL flagset");
|
||||
|
||||
@@ -275,7 +275,7 @@ archive_entry_new2(struct archive *a)
|
||||
* Functions for reading fields from an archive_entry.
|
||||
*/
|
||||
|
||||
time_t
|
||||
__LA_TIME_T
|
||||
archive_entry_atime(struct archive_entry *entry)
|
||||
{
|
||||
return (entry->ae_stat.aest_atime);
|
||||
@@ -293,7 +293,7 @@ archive_entry_atime_is_set(struct archive_entry *entry)
|
||||
return (entry->ae_set & AE_SET_ATIME);
|
||||
}
|
||||
|
||||
time_t
|
||||
__LA_TIME_T
|
||||
archive_entry_birthtime(struct archive_entry *entry)
|
||||
{
|
||||
return (entry->ae_stat.aest_birthtime);
|
||||
@@ -311,7 +311,7 @@ archive_entry_birthtime_is_set(struct archive_entry *entry)
|
||||
return (entry->ae_set & AE_SET_BIRTHTIME);
|
||||
}
|
||||
|
||||
time_t
|
||||
__LA_TIME_T
|
||||
archive_entry_ctime(struct archive_entry *entry)
|
||||
{
|
||||
return (entry->ae_stat.aest_ctime);
|
||||
@@ -329,7 +329,7 @@ archive_entry_ctime_nsec(struct archive_entry *entry)
|
||||
return (entry->ae_stat.aest_ctime_nsec);
|
||||
}
|
||||
|
||||
dev_t
|
||||
__LA_DEV_T
|
||||
archive_entry_dev(struct archive_entry *entry)
|
||||
{
|
||||
if (entry->ae_stat.aest_dev_is_broken_down)
|
||||
@@ -345,7 +345,7 @@ archive_entry_dev_is_set(struct archive_entry *entry)
|
||||
return (entry->ae_set & AE_SET_DEV);
|
||||
}
|
||||
|
||||
dev_t
|
||||
__LA_DEV_T
|
||||
archive_entry_devmajor(struct archive_entry *entry)
|
||||
{
|
||||
if (entry->ae_stat.aest_dev_is_broken_down)
|
||||
@@ -354,7 +354,7 @@ archive_entry_devmajor(struct archive_entry *entry)
|
||||
return major(entry->ae_stat.aest_dev);
|
||||
}
|
||||
|
||||
dev_t
|
||||
__LA_DEV_T
|
||||
archive_entry_devminor(struct archive_entry *entry)
|
||||
{
|
||||
if (entry->ae_stat.aest_dev_is_broken_down)
|
||||
@@ -568,7 +568,7 @@ archive_entry_mode(struct archive_entry *entry)
|
||||
return (entry->acl.mode);
|
||||
}
|
||||
|
||||
time_t
|
||||
__LA_TIME_T
|
||||
archive_entry_mtime(struct archive_entry *entry)
|
||||
{
|
||||
return (entry->ae_stat.aest_mtime);
|
||||
@@ -667,7 +667,7 @@ archive_entry_rdev_is_set(struct archive_entry *entry)
|
||||
return (entry->ae_set & AE_SET_RDEV);
|
||||
}
|
||||
|
||||
dev_t
|
||||
__LA_DEV_T
|
||||
archive_entry_rdev(struct archive_entry *entry)
|
||||
{
|
||||
if (archive_entry_rdev_is_set(entry)) {
|
||||
@@ -681,7 +681,7 @@ archive_entry_rdev(struct archive_entry *entry)
|
||||
}
|
||||
}
|
||||
|
||||
dev_t
|
||||
__LA_DEV_T
|
||||
archive_entry_rdevmajor(struct archive_entry *entry)
|
||||
{
|
||||
if (archive_entry_rdev_is_set(entry)) {
|
||||
@@ -694,7 +694,7 @@ archive_entry_rdevmajor(struct archive_entry *entry)
|
||||
}
|
||||
}
|
||||
|
||||
dev_t
|
||||
__LA_DEV_T
|
||||
archive_entry_rdevminor(struct archive_entry *entry)
|
||||
{
|
||||
if (archive_entry_rdev_is_set(entry)) {
|
||||
@@ -984,7 +984,9 @@ void
|
||||
archive_entry_set_ino(struct archive_entry *entry, la_int64_t ino)
|
||||
{
|
||||
if (ino < 0) {
|
||||
ino = 0;
|
||||
entry->stat_valid = 0;
|
||||
entry->ae_set &= ~AE_SET_INO;
|
||||
return;
|
||||
}
|
||||
entry->stat_valid = 0;
|
||||
entry->ae_set |= AE_SET_INO;
|
||||
@@ -995,7 +997,9 @@ void
|
||||
archive_entry_set_ino64(struct archive_entry *entry, la_int64_t ino)
|
||||
{
|
||||
if (ino < 0) {
|
||||
ino = 0;
|
||||
entry->stat_valid = 0;
|
||||
entry->ae_set &= ~AE_SET_INO;
|
||||
return;
|
||||
}
|
||||
entry->stat_valid = 0;
|
||||
entry->ae_set |= AE_SET_INO;
|
||||
@@ -1088,7 +1092,7 @@ _archive_entry_copy_hardlink_l(struct archive_entry *entry,
|
||||
}
|
||||
|
||||
void
|
||||
archive_entry_set_atime(struct archive_entry *entry, time_t t, long ns)
|
||||
archive_entry_set_atime(struct archive_entry *entry, __LA_TIME_T t, long ns)
|
||||
{
|
||||
FIX_NS(t, ns);
|
||||
entry->stat_valid = 0;
|
||||
@@ -1105,7 +1109,7 @@ archive_entry_unset_atime(struct archive_entry *entry)
|
||||
}
|
||||
|
||||
void
|
||||
archive_entry_set_birthtime(struct archive_entry *entry, time_t t, long ns)
|
||||
archive_entry_set_birthtime(struct archive_entry *entry, __LA_TIME_T t, long ns)
|
||||
{
|
||||
FIX_NS(t, ns);
|
||||
entry->stat_valid = 0;
|
||||
@@ -1122,7 +1126,7 @@ archive_entry_unset_birthtime(struct archive_entry *entry)
|
||||
}
|
||||
|
||||
void
|
||||
archive_entry_set_ctime(struct archive_entry *entry, time_t t, long ns)
|
||||
archive_entry_set_ctime(struct archive_entry *entry, __LA_TIME_T t, long ns)
|
||||
{
|
||||
FIX_NS(t, ns);
|
||||
entry->stat_valid = 0;
|
||||
@@ -1139,7 +1143,7 @@ archive_entry_unset_ctime(struct archive_entry *entry)
|
||||
}
|
||||
|
||||
void
|
||||
archive_entry_set_dev(struct archive_entry *entry, dev_t d)
|
||||
archive_entry_set_dev(struct archive_entry *entry, __LA_DEV_T d)
|
||||
{
|
||||
entry->stat_valid = 0;
|
||||
entry->ae_set |= AE_SET_DEV;
|
||||
@@ -1148,7 +1152,7 @@ archive_entry_set_dev(struct archive_entry *entry, dev_t d)
|
||||
}
|
||||
|
||||
void
|
||||
archive_entry_set_devmajor(struct archive_entry *entry, dev_t m)
|
||||
archive_entry_set_devmajor(struct archive_entry *entry, __LA_DEV_T m)
|
||||
{
|
||||
entry->stat_valid = 0;
|
||||
entry->ae_set |= AE_SET_DEV;
|
||||
@@ -1157,7 +1161,7 @@ archive_entry_set_devmajor(struct archive_entry *entry, dev_t m)
|
||||
}
|
||||
|
||||
void
|
||||
archive_entry_set_devminor(struct archive_entry *entry, dev_t m)
|
||||
archive_entry_set_devminor(struct archive_entry *entry, __LA_DEV_T m)
|
||||
{
|
||||
entry->stat_valid = 0;
|
||||
entry->ae_set |= AE_SET_DEV;
|
||||
@@ -1243,7 +1247,7 @@ archive_entry_set_mode(struct archive_entry *entry, mode_t m)
|
||||
}
|
||||
|
||||
void
|
||||
archive_entry_set_mtime(struct archive_entry *entry, time_t t, long ns)
|
||||
archive_entry_set_mtime(struct archive_entry *entry, __LA_TIME_T t, long ns)
|
||||
{
|
||||
FIX_NS(t, ns);
|
||||
entry->stat_valid = 0;
|
||||
@@ -1319,7 +1323,7 @@ archive_entry_set_perm(struct archive_entry *entry, mode_t p)
|
||||
}
|
||||
|
||||
void
|
||||
archive_entry_set_rdev(struct archive_entry *entry, dev_t m)
|
||||
archive_entry_set_rdev(struct archive_entry *entry, __LA_DEV_T m)
|
||||
{
|
||||
entry->stat_valid = 0;
|
||||
entry->ae_stat.aest_rdev = m;
|
||||
@@ -1330,7 +1334,7 @@ archive_entry_set_rdev(struct archive_entry *entry, dev_t m)
|
||||
}
|
||||
|
||||
void
|
||||
archive_entry_set_rdevmajor(struct archive_entry *entry, dev_t m)
|
||||
archive_entry_set_rdevmajor(struct archive_entry *entry, __LA_DEV_T m)
|
||||
{
|
||||
entry->stat_valid = 0;
|
||||
entry->ae_stat.aest_rdev_is_broken_down = 1;
|
||||
@@ -1340,7 +1344,7 @@ archive_entry_set_rdevmajor(struct archive_entry *entry, dev_t m)
|
||||
}
|
||||
|
||||
void
|
||||
archive_entry_set_rdevminor(struct archive_entry *entry, dev_t m)
|
||||
archive_entry_set_rdevminor(struct archive_entry *entry, __LA_DEV_T m)
|
||||
{
|
||||
entry->stat_valid = 0;
|
||||
entry->ae_stat.aest_rdev_is_broken_down = 1;
|
||||
@@ -1603,21 +1607,27 @@ archive_entry_set_digest(struct archive_entry *entry, int type,
|
||||
switch (type) {
|
||||
case ARCHIVE_ENTRY_DIGEST_MD5:
|
||||
copy_digest(entry, md5, digest);
|
||||
entry->mset_digest |= AE_MSET_DIGEST_MD5;
|
||||
break;
|
||||
case ARCHIVE_ENTRY_DIGEST_RMD160:
|
||||
copy_digest(entry, rmd160, digest);
|
||||
entry->mset_digest |= AE_MSET_DIGEST_RMD160;
|
||||
break;
|
||||
case ARCHIVE_ENTRY_DIGEST_SHA1:
|
||||
copy_digest(entry, sha1, digest);
|
||||
entry->mset_digest |= AE_MSET_DIGEST_SHA1;
|
||||
break;
|
||||
case ARCHIVE_ENTRY_DIGEST_SHA256:
|
||||
copy_digest(entry, sha256, digest);
|
||||
entry->mset_digest |= AE_MSET_DIGEST_SHA256;
|
||||
break;
|
||||
case ARCHIVE_ENTRY_DIGEST_SHA384:
|
||||
copy_digest(entry, sha384, digest);
|
||||
entry->mset_digest |= AE_MSET_DIGEST_SHA384;
|
||||
break;
|
||||
case ARCHIVE_ENTRY_DIGEST_SHA512:
|
||||
copy_digest(entry, sha512, digest);
|
||||
entry->mset_digest |= AE_MSET_DIGEST_SHA512;
|
||||
break;
|
||||
default:
|
||||
return ARCHIVE_WARN;
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#define ARCHIVE_ENTRY_H_INCLUDED
|
||||
|
||||
/* Note: Compiler will complain if this does not match archive.h! */
|
||||
#define ARCHIVE_VERSION_NUMBER 3007007
|
||||
#define ARCHIVE_VERSION_NUMBER 3008001
|
||||
|
||||
/*
|
||||
* Note: archive_entry.h is for use outside of libarchive; the
|
||||
@@ -40,8 +40,11 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stddef.h> /* for wchar_t */
|
||||
#include <stdint.h>
|
||||
#include <stdint.h> /* for C99 int64_t, etc. */
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* time_t is slated to be removed from public includes in 4.0 */
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#include <windows.h>
|
||||
@@ -55,12 +58,15 @@
|
||||
#define __LA_INT64_T_DEFINED
|
||||
# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
|
||||
typedef __int64 la_int64_t;
|
||||
typedef unsigned __int64 la_uint64_t;
|
||||
# else
|
||||
#include <unistd.h>
|
||||
# if defined(_SCO_DS) || defined(__osf__)
|
||||
typedef long long la_int64_t;
|
||||
typedef unsigned long long la_uint64_t;
|
||||
# else
|
||||
typedef int64_t la_int64_t;
|
||||
typedef uint64_t la_uint64_t;
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
@@ -96,6 +102,30 @@ typedef ssize_t la_ssize_t;
|
||||
# define __LA_MODE_T mode_t
|
||||
#endif
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* Use the platform types for time_t */
|
||||
#define __LA_TIME_T time_t
|
||||
#else
|
||||
/* Use 64-bits integer types for time_t */
|
||||
#define __LA_TIME_T la_int64_t
|
||||
#endif
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* Use the platform types for dev_t */
|
||||
#define __LA_DEV_T dev_t
|
||||
#else
|
||||
/* Use 64-bits integer types for dev_t */
|
||||
#define __LA_DEV_T la_int64_t
|
||||
#endif
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* Libarchive 3.x used signed int64 for inode numbers */
|
||||
#define __LA_INO_T la_int64_t
|
||||
#else
|
||||
/* Switch to unsigned for libarchive 4.0 */
|
||||
#define __LA_INO_T la_uint64_t
|
||||
#endif
|
||||
|
||||
/* Large file support for Android */
|
||||
#if defined(__LIBARCHIVE_BUILD) && defined(__ANDROID__)
|
||||
#include "android_lf.h"
|
||||
@@ -127,7 +157,8 @@ typedef ssize_t la_ssize_t;
|
||||
# define __LA_DECL
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ >= 3 && __GNUC_MINOR__ >= 1
|
||||
#if defined(__GNUC__) && (__GNUC__ > 3 || \
|
||||
(__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
|
||||
# define __LA_DEPRECATED __attribute__((deprecated))
|
||||
#else
|
||||
# define __LA_DEPRECATED
|
||||
@@ -235,19 +266,19 @@ __LA_DECL struct archive_entry *archive_entry_new2(struct archive *);
|
||||
* also return NULL when implicit character set conversions fail.
|
||||
* This is usually what you want.
|
||||
*/
|
||||
__LA_DECL time_t archive_entry_atime(struct archive_entry *);
|
||||
__LA_DECL __LA_TIME_T archive_entry_atime(struct archive_entry *);
|
||||
__LA_DECL long archive_entry_atime_nsec(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_atime_is_set(struct archive_entry *);
|
||||
__LA_DECL time_t archive_entry_birthtime(struct archive_entry *);
|
||||
__LA_DECL __LA_TIME_T archive_entry_birthtime(struct archive_entry *);
|
||||
__LA_DECL long archive_entry_birthtime_nsec(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_birthtime_is_set(struct archive_entry *);
|
||||
__LA_DECL time_t archive_entry_ctime(struct archive_entry *);
|
||||
__LA_DECL __LA_TIME_T archive_entry_ctime(struct archive_entry *);
|
||||
__LA_DECL long archive_entry_ctime_nsec(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_ctime_is_set(struct archive_entry *);
|
||||
__LA_DECL dev_t archive_entry_dev(struct archive_entry *);
|
||||
__LA_DECL __LA_DEV_T archive_entry_dev(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_dev_is_set(struct archive_entry *);
|
||||
__LA_DECL dev_t archive_entry_devmajor(struct archive_entry *);
|
||||
__LA_DECL dev_t archive_entry_devminor(struct archive_entry *);
|
||||
__LA_DECL __LA_DEV_T archive_entry_devmajor(struct archive_entry *);
|
||||
__LA_DECL __LA_DEV_T archive_entry_devminor(struct archive_entry *);
|
||||
__LA_DECL __LA_MODE_T archive_entry_filetype(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_filetype_is_set(struct archive_entry *);
|
||||
__LA_DECL void archive_entry_fflags(struct archive_entry *,
|
||||
@@ -264,8 +295,8 @@ __LA_DECL const char *archive_entry_hardlink(struct archive_entry *);
|
||||
__LA_DECL const char *archive_entry_hardlink_utf8(struct archive_entry *);
|
||||
__LA_DECL const wchar_t *archive_entry_hardlink_w(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_hardlink_is_set(struct archive_entry *);
|
||||
__LA_DECL la_int64_t archive_entry_ino(struct archive_entry *);
|
||||
__LA_DECL la_int64_t archive_entry_ino64(struct archive_entry *);
|
||||
__LA_DECL __LA_INO_T archive_entry_ino(struct archive_entry *);
|
||||
__LA_DECL __LA_INO_T archive_entry_ino64(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_ino_is_set(struct archive_entry *);
|
||||
__LA_DECL __LA_MODE_T archive_entry_mode(struct archive_entry *);
|
||||
__LA_DECL time_t archive_entry_mtime(struct archive_entry *);
|
||||
@@ -278,9 +309,9 @@ __LA_DECL const wchar_t *archive_entry_pathname_w(struct archive_entry *);
|
||||
__LA_DECL __LA_MODE_T archive_entry_perm(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_perm_is_set(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_rdev_is_set(struct archive_entry *);
|
||||
__LA_DECL dev_t archive_entry_rdev(struct archive_entry *);
|
||||
__LA_DECL dev_t archive_entry_rdevmajor(struct archive_entry *);
|
||||
__LA_DECL dev_t archive_entry_rdevminor(struct archive_entry *);
|
||||
__LA_DECL __LA_DEV_T archive_entry_rdev(struct archive_entry *);
|
||||
__LA_DECL __LA_DEV_T archive_entry_rdevmajor(struct archive_entry *);
|
||||
__LA_DECL __LA_DEV_T archive_entry_rdevminor(struct archive_entry *);
|
||||
__LA_DECL const char *archive_entry_sourcepath(struct archive_entry *);
|
||||
__LA_DECL const wchar_t *archive_entry_sourcepath_w(struct archive_entry *);
|
||||
__LA_DECL la_int64_t archive_entry_size(struct archive_entry *);
|
||||
@@ -309,18 +340,18 @@ __LA_DECL int archive_entry_is_encrypted(struct archive_entry *);
|
||||
* always copied.
|
||||
*/
|
||||
|
||||
__LA_DECL void archive_entry_set_atime(struct archive_entry *, time_t, long);
|
||||
__LA_DECL void archive_entry_set_atime(struct archive_entry *, __LA_TIME_T, long);
|
||||
__LA_DECL void archive_entry_unset_atime(struct archive_entry *);
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
__LA_DECL void archive_entry_copy_bhfi(struct archive_entry *, BY_HANDLE_FILE_INFORMATION *);
|
||||
#endif
|
||||
__LA_DECL void archive_entry_set_birthtime(struct archive_entry *, time_t, long);
|
||||
__LA_DECL void archive_entry_set_birthtime(struct archive_entry *, __LA_TIME_T, long);
|
||||
__LA_DECL void archive_entry_unset_birthtime(struct archive_entry *);
|
||||
__LA_DECL void archive_entry_set_ctime(struct archive_entry *, time_t, long);
|
||||
__LA_DECL void archive_entry_set_ctime(struct archive_entry *, __LA_TIME_T, long);
|
||||
__LA_DECL void archive_entry_unset_ctime(struct archive_entry *);
|
||||
__LA_DECL void archive_entry_set_dev(struct archive_entry *, dev_t);
|
||||
__LA_DECL void archive_entry_set_devmajor(struct archive_entry *, dev_t);
|
||||
__LA_DECL void archive_entry_set_devminor(struct archive_entry *, dev_t);
|
||||
__LA_DECL void archive_entry_set_dev(struct archive_entry *, __LA_DEV_T);
|
||||
__LA_DECL void archive_entry_set_devmajor(struct archive_entry *, __LA_DEV_T);
|
||||
__LA_DECL void archive_entry_set_devminor(struct archive_entry *, __LA_DEV_T);
|
||||
__LA_DECL void archive_entry_set_filetype(struct archive_entry *, unsigned int);
|
||||
__LA_DECL void archive_entry_set_fflags(struct archive_entry *,
|
||||
unsigned long /* set */, unsigned long /* clear */);
|
||||
@@ -343,15 +374,15 @@ __LA_DECL void archive_entry_set_hardlink_utf8(struct archive_entry *, const cha
|
||||
__LA_DECL void archive_entry_copy_hardlink(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_hardlink_w(struct archive_entry *, const wchar_t *);
|
||||
__LA_DECL int archive_entry_update_hardlink_utf8(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_set_ino(struct archive_entry *, la_int64_t);
|
||||
__LA_DECL void archive_entry_set_ino64(struct archive_entry *, la_int64_t);
|
||||
__LA_DECL void archive_entry_set_ino(struct archive_entry *, __LA_INO_T);
|
||||
__LA_DECL void archive_entry_set_ino64(struct archive_entry *, __LA_INO_T);
|
||||
__LA_DECL void archive_entry_set_link(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_set_link_utf8(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_link(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_link_w(struct archive_entry *, const wchar_t *);
|
||||
__LA_DECL int archive_entry_update_link_utf8(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_set_mode(struct archive_entry *, __LA_MODE_T);
|
||||
__LA_DECL void archive_entry_set_mtime(struct archive_entry *, time_t, long);
|
||||
__LA_DECL void archive_entry_set_mtime(struct archive_entry *, __LA_TIME_T, long);
|
||||
__LA_DECL void archive_entry_unset_mtime(struct archive_entry *);
|
||||
__LA_DECL void archive_entry_set_nlink(struct archive_entry *, unsigned int);
|
||||
__LA_DECL void archive_entry_set_pathname(struct archive_entry *, const char *);
|
||||
@@ -360,9 +391,9 @@ __LA_DECL void archive_entry_copy_pathname(struct archive_entry *, const char *)
|
||||
__LA_DECL void archive_entry_copy_pathname_w(struct archive_entry *, const wchar_t *);
|
||||
__LA_DECL int archive_entry_update_pathname_utf8(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_set_perm(struct archive_entry *, __LA_MODE_T);
|
||||
__LA_DECL void archive_entry_set_rdev(struct archive_entry *, dev_t);
|
||||
__LA_DECL void archive_entry_set_rdevmajor(struct archive_entry *, dev_t);
|
||||
__LA_DECL void archive_entry_set_rdevminor(struct archive_entry *, dev_t);
|
||||
__LA_DECL void archive_entry_set_rdev(struct archive_entry *, __LA_DEV_T);
|
||||
__LA_DECL void archive_entry_set_rdevmajor(struct archive_entry *, __LA_DEV_T);
|
||||
__LA_DECL void archive_entry_set_rdevminor(struct archive_entry *, __LA_DEV_T);
|
||||
__LA_DECL void archive_entry_set_size(struct archive_entry *, la_int64_t);
|
||||
__LA_DECL void archive_entry_unset_size(struct archive_entry *);
|
||||
__LA_DECL void archive_entry_copy_sourcepath(struct archive_entry *, const char *);
|
||||
@@ -418,6 +449,7 @@ __LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const voi
|
||||
#define ARCHIVE_ENTRY_DIGEST_SHA512 0x00000006
|
||||
|
||||
__LA_DECL const unsigned char * archive_entry_digest(struct archive_entry *, int /* type */);
|
||||
__LA_DECL int archive_entry_set_digest(struct archive_entry *, int, const unsigned char *);
|
||||
|
||||
/*
|
||||
* ACL routines. This used to simply store and return text-format ACL
|
||||
|
||||
@@ -280,6 +280,10 @@ find_entry(struct archive_entry_linkresolver *res,
|
||||
dev_t dev;
|
||||
int64_t ino;
|
||||
|
||||
if (!archive_entry_ino_is_set(entry) || !archive_entry_dev_is_set(entry)) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Free a held entry. */
|
||||
if (res->spare != NULL) {
|
||||
archive_entry_free(res->spare->canonical);
|
||||
@@ -369,6 +373,10 @@ insert_entry(struct archive_entry_linkresolver *res,
|
||||
struct links_entry *le;
|
||||
size_t hash, bucket;
|
||||
|
||||
if (!archive_entry_ino_is_set(entry) || !archive_entry_dev_is_set(entry)) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Add this entry to the links cache. */
|
||||
le = calloc(1, sizeof(struct links_entry));
|
||||
if (le == NULL)
|
||||
|
||||
@@ -87,4 +87,4 @@ int _archive_entry_copy_symlink_l(struct archive_entry *,
|
||||
int _archive_entry_copy_uname_l(struct archive_entry *,
|
||||
const char *, size_t, struct archive_string_conv *);
|
||||
|
||||
#endif /* ARCHIVE_ENTRY_LOCALE_H_INCLUDED */
|
||||
#endif /* !ARCHIVE_ENTRY_LOCALE_H_INCLUDED */
|
||||
|
||||
@@ -174,6 +174,13 @@ struct archive_entry {
|
||||
size_t mac_metadata_size;
|
||||
|
||||
/* Digest support. */
|
||||
#define AE_MSET_DIGEST_MD5 1
|
||||
#define AE_MSET_DIGEST_RMD160 2
|
||||
#define AE_MSET_DIGEST_SHA1 4
|
||||
#define AE_MSET_DIGEST_SHA256 8
|
||||
#define AE_MSET_DIGEST_SHA384 16
|
||||
#define AE_MSET_DIGEST_SHA512 32
|
||||
uint_least32_t mset_digest;
|
||||
struct ae_digest digest;
|
||||
|
||||
/* ACL support. */
|
||||
@@ -195,8 +202,4 @@ struct archive_entry {
|
||||
int ae_symlink_type;
|
||||
};
|
||||
|
||||
int
|
||||
archive_entry_set_digest(struct archive_entry *entry, int type,
|
||||
const unsigned char *digest);
|
||||
|
||||
#endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */
|
||||
#endif /* !ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */
|
||||
|
||||
@@ -116,4 +116,4 @@ struct archive_hmac {
|
||||
};
|
||||
|
||||
extern const struct archive_hmac __archive_hmac;
|
||||
#endif /* ARCHIVE_HMAC_PRIVATE_H_INCLUDED */
|
||||
#endif /* !ARCHIVE_HMAC_PRIVATE_H_INCLUDED */
|
||||
|
||||
@@ -35,14 +35,17 @@
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_getdate.h"
|
||||
#include "archive_pathmatch.h"
|
||||
#include "archive_rb.h"
|
||||
#include "archive_string.h"
|
||||
#include "archive_time_private.h"
|
||||
|
||||
struct match {
|
||||
struct match *next;
|
||||
@@ -53,8 +56,7 @@ struct match {
|
||||
struct match_list {
|
||||
struct match *first;
|
||||
struct match **last;
|
||||
int count;
|
||||
int unmatched_count;
|
||||
size_t unmatched_count;
|
||||
struct match *unmatched_next;
|
||||
int unmatched_eof;
|
||||
};
|
||||
@@ -73,7 +75,6 @@ struct match_file {
|
||||
struct entry_list {
|
||||
struct match_file *first;
|
||||
struct match_file **last;
|
||||
int count;
|
||||
};
|
||||
|
||||
struct id_array {
|
||||
@@ -144,12 +145,15 @@ static int add_pattern_mbs(struct archive_match *, struct match_list *,
|
||||
const char *);
|
||||
static int add_pattern_wcs(struct archive_match *, struct match_list *,
|
||||
const wchar_t *);
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
static int cmp_key_mbs(const struct archive_rb_node *, const void *);
|
||||
static int cmp_key_wcs(const struct archive_rb_node *, const void *);
|
||||
static int cmp_node_mbs(const struct archive_rb_node *,
|
||||
const struct archive_rb_node *);
|
||||
#else
|
||||
static int cmp_key_wcs(const struct archive_rb_node *, const void *);
|
||||
static int cmp_node_wcs(const struct archive_rb_node *,
|
||||
const struct archive_rb_node *);
|
||||
#endif
|
||||
static void entry_list_add(struct entry_list *, struct match_file *);
|
||||
static void entry_list_free(struct entry_list *);
|
||||
static void entry_list_init(struct entry_list *);
|
||||
@@ -187,14 +191,14 @@ static int time_excluded(struct archive_match *,
|
||||
struct archive_entry *);
|
||||
static int validate_time_flag(struct archive *, int, const char *);
|
||||
|
||||
#define get_date __archive_get_date
|
||||
#define get_date archive_parse_date
|
||||
|
||||
static const struct archive_rb_tree_ops rb_ops_mbs = {
|
||||
static const struct archive_rb_tree_ops rb_ops = {
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
cmp_node_mbs, cmp_key_mbs
|
||||
};
|
||||
|
||||
static const struct archive_rb_tree_ops rb_ops_wcs = {
|
||||
#else
|
||||
cmp_node_wcs, cmp_key_wcs
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -228,7 +232,7 @@ archive_match_new(void)
|
||||
a->recursive_include = 1;
|
||||
match_list_init(&(a->inclusions));
|
||||
match_list_init(&(a->exclusions));
|
||||
__archive_rb_tree_init(&(a->exclusion_tree), &rb_ops_mbs);
|
||||
__archive_rb_tree_init(&(a->exclusion_tree), &rb_ops);
|
||||
entry_list_init(&(a->exclusion_entry_list));
|
||||
match_list_init(&(a->inclusion_unames));
|
||||
match_list_init(&(a->inclusion_gnames));
|
||||
@@ -507,7 +511,9 @@ archive_match_path_unmatched_inclusions(struct archive *_a)
|
||||
ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions");
|
||||
a = (struct archive_match *)_a;
|
||||
|
||||
return (a->inclusions.unmatched_count);
|
||||
if (a->inclusions.unmatched_count > (size_t)INT_MAX)
|
||||
return INT_MAX;
|
||||
return (int)(a->inclusions.unmatched_count);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -650,7 +656,7 @@ add_pattern_from_file(struct archive_match *a, struct match_list *mlist,
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (*b == 0x0d || *b == 0x0a) {
|
||||
if (*b == 0x0d || *b == 0x0a) {
|
||||
found_separator = 1;
|
||||
break;
|
||||
}
|
||||
@@ -735,7 +741,7 @@ path_excluded(struct archive_match *a, int mbs, const void *pathname)
|
||||
}
|
||||
}
|
||||
|
||||
/* Exclusions take priority */
|
||||
/* Exclusions take priority. */
|
||||
for (match = a->exclusions.first; match != NULL;
|
||||
match = match->next){
|
||||
r = match_path_exclusion(a, match, mbs, pathname);
|
||||
@@ -834,7 +840,6 @@ match_list_init(struct match_list *list)
|
||||
{
|
||||
list->first = NULL;
|
||||
list->last = &(list->first);
|
||||
list->count = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -855,7 +860,6 @@ match_list_add(struct match_list *list, struct match *m)
|
||||
{
|
||||
*list->last = m;
|
||||
list->last = &(m->next);
|
||||
list->count++;
|
||||
list->unmatched_count++;
|
||||
}
|
||||
|
||||
@@ -1145,36 +1149,15 @@ set_timefilter_date_w(struct archive_match *a, int timetype,
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
|
||||
static int
|
||||
set_timefilter_find_data(struct archive_match *a, int timetype,
|
||||
DWORD ftLastWriteTime_dwHighDateTime, DWORD ftLastWriteTime_dwLowDateTime,
|
||||
DWORD ftCreationTime_dwHighDateTime, DWORD ftCreationTime_dwLowDateTime)
|
||||
const FILETIME* ftLastWriteTime, const FILETIME* ftCreationTime)
|
||||
{
|
||||
ULARGE_INTEGER utc;
|
||||
time_t ctime_sec, mtime_sec;
|
||||
long ctime_ns, mtime_ns;
|
||||
uint32_t ctime_ns, mtime_ns;
|
||||
|
||||
utc.HighPart = ftCreationTime_dwHighDateTime;
|
||||
utc.LowPart = ftCreationTime_dwLowDateTime;
|
||||
if (utc.QuadPart >= EPOC_TIME) {
|
||||
utc.QuadPart -= EPOC_TIME;
|
||||
ctime_sec = (time_t)(utc.QuadPart / 10000000);
|
||||
ctime_ns = (long)(utc.QuadPart % 10000000) * 100;
|
||||
} else {
|
||||
ctime_sec = 0;
|
||||
ctime_ns = 0;
|
||||
}
|
||||
utc.HighPart = ftLastWriteTime_dwHighDateTime;
|
||||
utc.LowPart = ftLastWriteTime_dwLowDateTime;
|
||||
if (utc.QuadPart >= EPOC_TIME) {
|
||||
utc.QuadPart -= EPOC_TIME;
|
||||
mtime_sec = (time_t)(utc.QuadPart / 10000000);
|
||||
mtime_ns = (long)(utc.QuadPart % 10000000) * 100;
|
||||
} else {
|
||||
mtime_sec = 0;
|
||||
mtime_ns = 0;
|
||||
}
|
||||
ntfs_to_unix(FILETIME_to_ntfs(ftLastWriteTime), &mtime_sec, &mtime_ns);
|
||||
ntfs_to_unix(FILETIME_to_ntfs(ftCreationTime), &ctime_sec, &ctime_ns);
|
||||
return set_timefilter(a, timetype,
|
||||
mtime_sec, mtime_ns, ctime_sec, ctime_ns);
|
||||
}
|
||||
@@ -1199,9 +1182,7 @@ set_timefilter_pathname_mbs(struct archive_match *a, int timetype,
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
FindClose(h);
|
||||
return set_timefilter_find_data(a, timetype,
|
||||
d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime,
|
||||
d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime);
|
||||
return set_timefilter_find_data(a, timetype, &d.ftLastWriteTime, &d.ftCreationTime);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1223,9 +1204,7 @@ set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
FindClose(h);
|
||||
return set_timefilter_find_data(a, timetype,
|
||||
d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime,
|
||||
d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime);
|
||||
return set_timefilter_find_data(a, timetype, &d.ftLastWriteTime, &d.ftCreationTime);
|
||||
}
|
||||
|
||||
#else /* _WIN32 && !__CYGWIN__ */
|
||||
@@ -1300,6 +1279,7 @@ set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
|
||||
/*
|
||||
* Call back functions for archive_rb.
|
||||
*/
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
static int
|
||||
cmp_node_mbs(const struct archive_rb_node *n1,
|
||||
const struct archive_rb_node *n2)
|
||||
@@ -1316,7 +1296,7 @@ cmp_node_mbs(const struct archive_rb_node *n1,
|
||||
return (-1);
|
||||
return (strcmp(p1, p2));
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cmp_key_mbs(const struct archive_rb_node *n, const void *key)
|
||||
{
|
||||
@@ -1328,7 +1308,7 @@ cmp_key_mbs(const struct archive_rb_node *n, const void *key)
|
||||
return (-1);
|
||||
return (strcmp(p, (const char *)key));
|
||||
}
|
||||
|
||||
#else
|
||||
static int
|
||||
cmp_node_wcs(const struct archive_rb_node *n1,
|
||||
const struct archive_rb_node *n2)
|
||||
@@ -1345,7 +1325,7 @@ cmp_node_wcs(const struct archive_rb_node *n1,
|
||||
return (-1);
|
||||
return (wcscmp(p1, p2));
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cmp_key_wcs(const struct archive_rb_node *n, const void *key)
|
||||
{
|
||||
@@ -1357,13 +1337,13 @@ cmp_key_wcs(const struct archive_rb_node *n, const void *key)
|
||||
return (-1);
|
||||
return (wcscmp(p, (const wchar_t *)key));
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
entry_list_init(struct entry_list *list)
|
||||
{
|
||||
list->first = NULL;
|
||||
list->last = &(list->first);
|
||||
list->count = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1384,7 +1364,6 @@ entry_list_add(struct entry_list *list, struct match_file *file)
|
||||
{
|
||||
*list->last = file;
|
||||
list->last = &(file->next);
|
||||
list->count++;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1407,9 +1386,7 @@ add_entry(struct archive_match *a, int flag,
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
archive_mstring_copy_wcs(&(f->pathname), pathname);
|
||||
a->exclusion_tree.rbt_ops = &rb_ops_wcs;
|
||||
#else
|
||||
(void)rb_ops_wcs;
|
||||
pathname = archive_entry_pathname(entry);
|
||||
if (pathname == NULL) {
|
||||
free(f);
|
||||
@@ -1417,7 +1394,6 @@ add_entry(struct archive_match *a, int flag,
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
archive_mstring_copy_mbs(&(f->pathname), pathname);
|
||||
a->exclusion_tree.rbt_ops = &rb_ops_mbs;
|
||||
#endif
|
||||
f->flag = flag;
|
||||
f->mtime_sec = archive_entry_mtime(entry);
|
||||
@@ -1542,16 +1518,13 @@ time_excluded(struct archive_match *a, struct archive_entry *entry)
|
||||
}
|
||||
|
||||
/* If there is no exclusion list, include the file. */
|
||||
if (a->exclusion_entry_list.count == 0)
|
||||
if (a->exclusion_entry_list.first == NULL)
|
||||
return (0);
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
pathname = archive_entry_pathname_w(entry);
|
||||
a->exclusion_tree.rbt_ops = &rb_ops_wcs;
|
||||
#else
|
||||
(void)rb_ops_wcs;
|
||||
pathname = archive_entry_pathname(entry);
|
||||
a->exclusion_tree.rbt_ops = &rb_ops_mbs;
|
||||
#endif
|
||||
if (pathname == NULL)
|
||||
return (0);
|
||||
@@ -1707,7 +1680,7 @@ archive_match_owner_excluded(struct archive *_a,
|
||||
static int
|
||||
add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id)
|
||||
{
|
||||
unsigned i;
|
||||
size_t i;
|
||||
|
||||
if (ids->count + 1 >= ids->size) {
|
||||
void *p;
|
||||
@@ -1744,10 +1717,10 @@ add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id)
|
||||
static int
|
||||
match_owner_id(struct id_array *ids, int64_t id)
|
||||
{
|
||||
unsigned b, m, t;
|
||||
size_t b, m, t;
|
||||
|
||||
t = 0;
|
||||
b = (unsigned)ids->count;
|
||||
b = ids->count;
|
||||
while (t < b) {
|
||||
m = (t + b)>>1;
|
||||
if (ids->ids[m] == id)
|
||||
@@ -1842,7 +1815,7 @@ owner_excluded(struct archive_match *a, struct archive_entry *entry)
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (a->inclusion_unames.count) {
|
||||
if (a->inclusion_unames.first != NULL) {
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
r = match_owner_name_wcs(a, &(a->inclusion_unames),
|
||||
archive_entry_uname_w(entry));
|
||||
@@ -1856,7 +1829,7 @@ owner_excluded(struct archive_match *a, struct archive_entry *entry)
|
||||
return (r);
|
||||
}
|
||||
|
||||
if (a->inclusion_gnames.count) {
|
||||
if (a->inclusion_gnames.first != NULL) {
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
r = match_owner_name_wcs(a, &(a->inclusion_gnames),
|
||||
archive_entry_gname_w(entry));
|
||||
@@ -1871,4 +1844,3 @@ owner_excluded(struct archive_match *a, struct archive_entry *entry)
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ parse_option(const char **str,
|
||||
int
|
||||
_archive_set_option(struct archive *a,
|
||||
const char *m, const char *o, const char *v,
|
||||
int magic, const char *fn, option_handler use_option)
|
||||
unsigned int magic, const char *fn, option_handler use_option)
|
||||
{
|
||||
const char *mp, *op, *vp;
|
||||
int r;
|
||||
@@ -97,7 +97,7 @@ _archive_set_either_option(struct archive *a, const char *m, const char *o, cons
|
||||
|
||||
int
|
||||
_archive_set_options(struct archive *a, const char *options,
|
||||
int magic, const char *fn, option_handler use_option)
|
||||
unsigned int magic, const char *fn, option_handler use_option)
|
||||
{
|
||||
int allok = 1, anyok = 0, ignore_mod_err = 0, r;
|
||||
char *data;
|
||||
|
||||
@@ -35,11 +35,11 @@ typedef int (*option_handler)(struct archive *a,
|
||||
int
|
||||
_archive_set_option(struct archive *a,
|
||||
const char *mod, const char *opt, const char *val,
|
||||
int magic, const char *fn, option_handler use_option);
|
||||
unsigned int magic, const char *fn, option_handler use_option);
|
||||
|
||||
int
|
||||
_archive_set_options(struct archive *a, const char *options,
|
||||
int magic, const char *fn, option_handler use_option);
|
||||
unsigned int magic, const char *fn, option_handler use_option);
|
||||
|
||||
int
|
||||
_archive_set_either_option(struct archive *a,
|
||||
|
||||
@@ -46,4 +46,4 @@ pack_t pack_native;
|
||||
(((y) << 12) & 0xfff00000) | \
|
||||
(((y) << 0) & 0x000000ff)))
|
||||
|
||||
#endif /* ARCHIVE_PACK_DEV_H */
|
||||
#endif /* !ARCHIVE_PACK_DEV_H */
|
||||
|
||||
+56
-9
@@ -35,8 +35,7 @@
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#define __LIBARCHIVE_BUILD 1
|
||||
#include "archive_getdate.h"
|
||||
#include "archive.h"
|
||||
|
||||
/* Basic time units. */
|
||||
#define EPOCH 1970
|
||||
@@ -820,6 +819,23 @@ RelativeMonth(time_t Start, time_t Timezone, time_t RelMonth)
|
||||
Timezone, DSTmaybe));
|
||||
}
|
||||
|
||||
/*
|
||||
* Parses and consumes an unsigned number.
|
||||
* Returns 1 if any number is parsed. Otherwise, *value is unchanged.
|
||||
*/
|
||||
static char
|
||||
consume_unsigned_number(const char **in, time_t *value)
|
||||
{
|
||||
char c;
|
||||
if (isdigit((unsigned char)(c = **in))) {
|
||||
for (*value = 0; isdigit((unsigned char)(c = *(*in)++)); )
|
||||
*value = 10 * *value + c - '0';
|
||||
(*in)--;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tokenizer.
|
||||
*/
|
||||
@@ -861,7 +877,8 @@ nexttoken(const char **in, time_t *value)
|
||||
&& i < sizeof(buff)-1) {
|
||||
if (*src != '.') {
|
||||
if (isupper((unsigned char)*src))
|
||||
buff[i++] = tolower((unsigned char)*src);
|
||||
buff[i++] = (char)tolower(
|
||||
(unsigned char)*src);
|
||||
else
|
||||
buff[i++] = *src;
|
||||
}
|
||||
@@ -895,10 +912,7 @@ nexttoken(const char **in, time_t *value)
|
||||
* Because '-' and '+' have other special meanings, I
|
||||
* don't deal with signed numbers here.
|
||||
*/
|
||||
if (isdigit((unsigned char)(c = **in))) {
|
||||
for (*value = 0; isdigit((unsigned char)(c = *(*in)++)); )
|
||||
*value = 10 * *value + c - '0';
|
||||
(*in)--;
|
||||
if (consume_unsigned_number(in, value)) {
|
||||
return (tUNUMBER);
|
||||
}
|
||||
|
||||
@@ -914,7 +928,7 @@ difftm (struct tm *a, struct tm *b)
|
||||
{
|
||||
int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
|
||||
int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
|
||||
int days = (
|
||||
long days = (
|
||||
/* difference in day of year */
|
||||
a->tm_yday - b->tm_yday
|
||||
/* + intervening leap days */
|
||||
@@ -929,6 +943,32 @@ difftm (struct tm *a, struct tm *b)
|
||||
+ (a->tm_sec - b->tm_sec));
|
||||
}
|
||||
|
||||
/*
|
||||
* Parses a Unix epoch timestamp (seconds).
|
||||
* This supports a subset of what GNU tar accepts from black box testing,
|
||||
* but covers common use cases.
|
||||
*/
|
||||
static time_t
|
||||
parse_unix_epoch(const char *p)
|
||||
{
|
||||
time_t epoch;
|
||||
|
||||
/* may begin with + */
|
||||
if (*p == '+') {
|
||||
p++;
|
||||
}
|
||||
|
||||
/* followed by some number */
|
||||
if (!consume_unsigned_number(&p, &epoch))
|
||||
return (time_t)-1;
|
||||
|
||||
/* ...and nothing else */
|
||||
if (*p != '\0')
|
||||
return (time_t)-1;
|
||||
|
||||
return epoch;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* The public function.
|
||||
@@ -936,7 +976,7 @@ difftm (struct tm *a, struct tm *b)
|
||||
* TODO: tokens[] array should be dynamically sized.
|
||||
*/
|
||||
time_t
|
||||
__archive_get_date(time_t now, const char *p)
|
||||
archive_parse_date(time_t now, const char *p)
|
||||
{
|
||||
struct token tokens[256];
|
||||
struct gdstate _gds;
|
||||
@@ -948,6 +988,13 @@ __archive_get_date(time_t now, const char *p)
|
||||
time_t tod;
|
||||
long tzone;
|
||||
|
||||
/*
|
||||
* @-prefixed Unix epoch timestamps (seconds)
|
||||
* Skip the complex tokenizer - We do not want to accept strings like "@tenth"
|
||||
*/
|
||||
if (*p == '@')
|
||||
return parse_unix_epoch(p + 1);
|
||||
|
||||
/* Clear out the parsed token array. */
|
||||
memset(tokens, 0, sizeof(tokens));
|
||||
/* Initialize the parser state. */
|
||||
@@ -61,6 +61,11 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* For cygwin, to avoid missing LONG, ULONG, PUCHAR, ... definitions */
|
||||
#ifdef __CYGWIN__
|
||||
#include <windef.h>
|
||||
#endif
|
||||
|
||||
/* It should be possible to get rid of this by extending the feature-test
|
||||
* macros to cover Windows API functions, probably along with non-trivial
|
||||
* refactoring of code to find structures that sit more cleanly on top of
|
||||
|
||||
@@ -50,4 +50,4 @@
|
||||
#define ARCHIVE_ACL_SUPPORT 1
|
||||
#endif
|
||||
|
||||
#endif /* ARCHIVE_PLATFORM_ACL_H_INCLUDED */
|
||||
#endif /* !ARCHIVE_PLATFORM_ACL_H_INCLUDED */
|
||||
|
||||
@@ -42,4 +42,4 @@
|
||||
#define ARCHIVE_XATTR_SUPPORT 1
|
||||
#endif
|
||||
|
||||
#endif /* ARCHIVE_PLATFORM_XATTR_H_INCLUDED */
|
||||
#endif /* !ARCHIVE_PLATFORM_XATTR_H_INCLUDED */
|
||||
|
||||
@@ -287,9 +287,14 @@ static void *AllocUnits(CPpmd7 *p, unsigned indx)
|
||||
return AllocUnitsRare(p, indx);
|
||||
}
|
||||
|
||||
#define MyMem12Cpy(dest, src, num) \
|
||||
{ UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \
|
||||
do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while(--n); }
|
||||
#define MyMem12Cpy(dest, src, num) do { \
|
||||
UInt32 *d = (UInt32 *)dest; \
|
||||
const UInt32 *s = (const UInt32 *)src; \
|
||||
UInt32 n = num; \
|
||||
do { \
|
||||
d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; \
|
||||
} while(--n); \
|
||||
} while (0)
|
||||
|
||||
static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU)
|
||||
{
|
||||
|
||||
@@ -242,9 +242,14 @@ static void *AllocUnits(CPpmd8 *p, unsigned indx)
|
||||
return AllocUnitsRare(p, indx);
|
||||
}
|
||||
|
||||
#define MyMem12Cpy(dest, src, num) \
|
||||
{ UInt32 *d = (UInt32 *)dest; const UInt32 *z = (const UInt32 *)src; UInt32 n = num; \
|
||||
do { d[0] = z[0]; d[1] = z[1]; d[2] = z[2]; z += 3; d += 3; } while (--n); }
|
||||
#define MyMem12Cpy(dest, src, num) do { \
|
||||
UInt32 *d = (UInt32 *)dest; \
|
||||
const UInt32 *z = (const UInt32 *)src; \
|
||||
UInt32 n = num; \
|
||||
do { \
|
||||
d[0] = z[0]; d[1] = z[1]; d[2] = z[2]; z += 3; d += 3; \
|
||||
} while (--n); \
|
||||
} while (0)
|
||||
|
||||
static void *ShrinkUnits(CPpmd8 *p, void *oldPtr, unsigned oldNU, unsigned newNU)
|
||||
{
|
||||
@@ -341,7 +346,9 @@ static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)
|
||||
(p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF);
|
||||
}
|
||||
|
||||
#define RESET_TEXT(offs) { p->Text = p->Base + p->AlignOffset + (offs); }
|
||||
#define RESET_TEXT(offs) do { \
|
||||
p->Text = p->Base + p->AlignOffset + (offs); \
|
||||
} while (0)
|
||||
|
||||
static void RestartModel(CPpmd8 *p)
|
||||
{
|
||||
|
||||
@@ -109,8 +109,12 @@ typedef struct
|
||||
Byte Count; /* Count to next change of Shift */
|
||||
} CPpmd_See;
|
||||
|
||||
#define Ppmd_See_Update(p) if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \
|
||||
{ (p)->Summ <<= 1; (p)->Count = (Byte)(3 << (p)->Shift++); }
|
||||
#define Ppmd_See_Update(p) do { \
|
||||
if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) { \
|
||||
(p)->Summ <<= 1; \
|
||||
(p)->Count = (Byte)(3 << (p)->Shift++); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -144,8 +148,12 @@ typedef
|
||||
#endif
|
||||
CPpmd_Byte_Ref;
|
||||
|
||||
#define PPMD_SetAllBitsIn256Bytes(p) \
|
||||
{ unsigned j; for (j = 0; j < 256 / sizeof(p[0]); j += 8) { \
|
||||
p[j+7] = p[j+6] = p[j+5] = p[j+4] = p[j+3] = p[j+2] = p[j+1] = p[j+0] = ~(size_t)0; }}
|
||||
#define PPMD_SetAllBitsIn256Bytes(p) do { \
|
||||
unsigned j; \
|
||||
for (j = 0; j < 256 / sizeof(p[0]); j += 8) { \
|
||||
p[j+7] = p[j+6] = p[j+5] = p[j+4] = \
|
||||
p[j+3] = p[j+2] = p[j+1] = p[j+0] = ~(size_t)0; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -33,4 +33,4 @@
|
||||
/* Random number generator. */
|
||||
int archive_random(void *buf, size_t nbytes);
|
||||
|
||||
#endif /* ARCHIVE_RANDOM_PRIVATE_H_INCLUDED */
|
||||
#endif /* !ARCHIVE_RANDOM_PRIVATE_H_INCLUDED */
|
||||
|
||||
@@ -110,4 +110,4 @@ struct archive_rb_node *
|
||||
__archive_rb_tree_iterate(struct archive_rb_tree *,
|
||||
struct archive_rb_node *, const unsigned int);
|
||||
|
||||
#endif /* ARCHIVE_RB_H_*/
|
||||
#endif /* !ARCHIVE_RB_H_INCLUDED */
|
||||
|
||||
@@ -176,15 +176,9 @@ client_skip_proxy(struct archive_read_filter *self, int64_t request)
|
||||
return 0;
|
||||
|
||||
if (self->archive->client.skipper != NULL) {
|
||||
/* Seek requests over 1GiB are broken down into
|
||||
* multiple seeks. This avoids overflows when the
|
||||
* requests get passed through 32-bit arguments. */
|
||||
int64_t skip_limit = (int64_t)1 << 30;
|
||||
int64_t total = 0;
|
||||
for (;;) {
|
||||
int64_t get, ask = request;
|
||||
if (ask > skip_limit)
|
||||
ask = skip_limit;
|
||||
get = (self->archive->client.skipper)
|
||||
(&self->archive->archive, self->data, ask);
|
||||
total += get;
|
||||
|
||||
@@ -96,6 +96,10 @@ archive_read_append_filter(struct archive *_a, int code)
|
||||
strcpy(str, "lzip");
|
||||
r1 = archive_read_support_filter_lzip(_a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_LZOP:
|
||||
strcpy(str, "lzop");
|
||||
r1 = archive_read_support_filter_lzop(_a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_LRZIP:
|
||||
strcpy(str, "lrzip");
|
||||
r1 = archive_read_support_filter_lrzip(_a);
|
||||
|
||||
@@ -888,7 +888,7 @@ setup_sparse_fiemap(struct archive_read_disk *a,
|
||||
count = (sizeof(buff) - sizeof(*fm))/sizeof(*fe);
|
||||
fm = (struct fiemap *)buff;
|
||||
fm->fm_start = 0;
|
||||
fm->fm_length = ~0ULL;;
|
||||
fm->fm_length = ~0ULL;
|
||||
fm->fm_flags = FIEMAP_FLAG_SYNC;
|
||||
fm->fm_extent_count = count;
|
||||
do_fiemap = 1;
|
||||
|
||||
@@ -276,7 +276,7 @@ tree_dir_next_posix(struct tree *t);
|
||||
#endif
|
||||
|
||||
/* Initiate/terminate a tree traversal. */
|
||||
static struct tree *tree_open(const char *, int, int);
|
||||
static struct tree *tree_open(const char *, char, int);
|
||||
static struct tree *tree_reopen(struct tree *, const char *, int);
|
||||
static void tree_close(struct tree *);
|
||||
static void tree_free(struct tree *);
|
||||
@@ -514,7 +514,7 @@ _archive_read_close(struct archive *_a)
|
||||
|
||||
static void
|
||||
setup_symlink_mode(struct archive_read_disk *a, char symlink_mode,
|
||||
int follow_symlinks)
|
||||
char follow_symlinks)
|
||||
{
|
||||
a->symlink_mode = symlink_mode;
|
||||
a->follow_symlinks = follow_symlinks;
|
||||
@@ -778,7 +778,8 @@ _archive_read_data_block(struct archive *_a, const void **buff,
|
||||
*/
|
||||
if (t->current_sparse->offset > t->entry_total) {
|
||||
if (lseek(t->entry_fd,
|
||||
(off_t)t->current_sparse->offset, SEEK_SET) < 0) {
|
||||
(off_t)t->current_sparse->offset, SEEK_SET) !=
|
||||
t->current_sparse->offset) {
|
||||
archive_set_error(&a->archive, errno, "Seek error");
|
||||
r = ARCHIVE_FATAL;
|
||||
a->archive.state = ARCHIVE_STATE_FATAL;
|
||||
@@ -2180,7 +2181,7 @@ tree_append(struct tree *t, const char *name, size_t name_length)
|
||||
* Open a directory tree for traversal.
|
||||
*/
|
||||
static struct tree *
|
||||
tree_open(const char *path, int symlink_mode, int restore_time)
|
||||
tree_open(const char *path, char symlink_mode, int restore_time)
|
||||
{
|
||||
struct tree *t;
|
||||
|
||||
|
||||
@@ -52,10 +52,11 @@ struct archive_read_disk {
|
||||
|
||||
/*
|
||||
* Since symlink interaction changes, we need to track whether
|
||||
* we're following symlinks for the current item. 'L' mode above
|
||||
* sets this true, 'P' sets it false, 'H' changes it as we traverse.
|
||||
* we're following symlinks for the current item, governed by the above
|
||||
* symlink_mode. 'L' sets this true, 'P' sets it false, 'H' changes it
|
||||
* as we traverse.
|
||||
*/
|
||||
char follow_symlinks; /* Either 'L' or 'P'. */
|
||||
char follow_symlinks; /* Either 0 or 1. */
|
||||
|
||||
/* Directory traversals. */
|
||||
struct tree *tree;
|
||||
|
||||
@@ -37,8 +37,10 @@
|
||||
.Nm archive_read_support_format_lha ,
|
||||
.Nm archive_read_support_format_mtree ,
|
||||
.Nm archive_read_support_format_rar ,
|
||||
.Nm archive_read_support_format_rar5 ,
|
||||
.Nm archive_read_support_format_raw ,
|
||||
.Nm archive_read_support_format_tar ,
|
||||
.Nm archive_read_support_format_warc ,
|
||||
.Nm archive_read_support_format_xar ,
|
||||
.Nm archive_read_support_format_zip
|
||||
.Nd functions for reading streaming archives
|
||||
@@ -70,10 +72,14 @@ Streaming Archive Library (libarchive, -larchive)
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_rar "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_rar5 "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_raw "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_tar "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_warc "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_xar "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_zip "struct archive *"
|
||||
@@ -89,8 +95,10 @@ Streaming Archive Library (libarchive, -larchive)
|
||||
.Fn archive_read_support_format_lha ,
|
||||
.Fn archive_read_support_format_mtree ,
|
||||
.Fn archive_read_support_format_rar ,
|
||||
.Fn archive_read_support_format_rar5 ,
|
||||
.Fn archive_read_support_format_raw ,
|
||||
.Fn archive_read_support_format_tar ,
|
||||
.Fn archive_read_support_format_warc ,
|
||||
.Fn archive_read_support_format_xar ,
|
||||
.Fn archive_read_support_format_zip
|
||||
.Xc
|
||||
@@ -100,6 +108,13 @@ For example,
|
||||
.Fn archive_read_support_format_tar
|
||||
enables support for a variety of standard tar formats, old-style tar,
|
||||
ustar, pax interchange format, and many common variants.
|
||||
.Fn archive_read_support_format_zip
|
||||
enables support for both the streaming and the seeking zip readers,
|
||||
which can separately be enabled by respectively
|
||||
.Fn archive_read_support_format_zip_streamable
|
||||
and
|
||||
.Fn archive_read_support_format_zip_seekable
|
||||
.
|
||||
.It Fn archive_read_support_format_all
|
||||
Enables support for all available formats except the
|
||||
.Dq raw
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
struct read_fd_data {
|
||||
int fd;
|
||||
size_t block_size;
|
||||
int64_t size;
|
||||
char use_lseek;
|
||||
void *buffer;
|
||||
};
|
||||
@@ -95,6 +96,7 @@ archive_read_open_fd(struct archive *a, int fd, size_t block_size)
|
||||
if (S_ISREG(st.st_mode)) {
|
||||
archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
|
||||
mine->use_lseek = 1;
|
||||
mine->size = st.st_size;
|
||||
}
|
||||
#if defined(__CYGWIN__) || defined(_WIN32)
|
||||
setmode(mine->fd, O_BINARY);
|
||||
@@ -131,7 +133,7 @@ static int64_t
|
||||
file_skip(struct archive *a, void *client_data, int64_t request)
|
||||
{
|
||||
struct read_fd_data *mine = (struct read_fd_data *)client_data;
|
||||
int64_t skip = request;
|
||||
off_t skip = (off_t)request;
|
||||
int64_t old_offset, new_offset;
|
||||
int skip_bits = sizeof(skip) * 8 - 1; /* off_t is a signed type. */
|
||||
|
||||
@@ -140,20 +142,25 @@ file_skip(struct archive *a, void *client_data, int64_t request)
|
||||
|
||||
/* Reduce a request that would overflow the 'skip' variable. */
|
||||
if (sizeof(request) > sizeof(skip)) {
|
||||
int64_t max_skip =
|
||||
const int64_t max_skip =
|
||||
(((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
|
||||
if (request > max_skip)
|
||||
skip = max_skip;
|
||||
skip = (off_t)max_skip;
|
||||
}
|
||||
|
||||
/* Reduce request to the next smallest multiple of block_size */
|
||||
request = (request / mine->block_size) * mine->block_size;
|
||||
if (request == 0)
|
||||
/* Reduce 'skip' to the next smallest multiple of block_size */
|
||||
skip = (off_t)(((int64_t)skip / mine->block_size) * mine->block_size);
|
||||
if (skip == 0)
|
||||
return (0);
|
||||
|
||||
if (((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0) &&
|
||||
((new_offset = lseek(mine->fd, skip, SEEK_CUR)) >= 0))
|
||||
return (new_offset - old_offset);
|
||||
if ((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0) {
|
||||
if (old_offset >= mine->size ||
|
||||
skip > mine->size - old_offset) {
|
||||
/* Do not seek past end of file. */
|
||||
errno = ESPIPE;
|
||||
} else if ((new_offset = lseek(mine->fd, skip, SEEK_CUR)) >= 0)
|
||||
return (new_offset - old_offset);
|
||||
}
|
||||
|
||||
/* If seek failed once, it will probably fail again. */
|
||||
mine->use_lseek = 0;
|
||||
@@ -178,11 +185,24 @@ static int64_t
|
||||
file_seek(struct archive *a, void *client_data, int64_t request, int whence)
|
||||
{
|
||||
struct read_fd_data *mine = (struct read_fd_data *)client_data;
|
||||
off_t seek = (off_t)request;
|
||||
int64_t r;
|
||||
int seek_bits = sizeof(seek) * 8 - 1; /* off_t is a signed type. */
|
||||
|
||||
/* We use off_t here because lseek() is declared that way. */
|
||||
/* See above for notes about when off_t is less than 64 bits. */
|
||||
r = lseek(mine->fd, request, whence);
|
||||
|
||||
/* Reduce a request that would overflow the 'seek' variable. */
|
||||
if (sizeof(request) > sizeof(seek)) {
|
||||
const int64_t max_seek =
|
||||
(((int64_t)1 << (seek_bits - 1)) - 1) * 2 + 1;
|
||||
const int64_t min_seek = ~max_seek;
|
||||
if (request > max_seek)
|
||||
seek = (off_t)max_seek;
|
||||
else if (request < min_seek)
|
||||
seek = (off_t)min_seek;
|
||||
}
|
||||
|
||||
r = lseek(mine->fd, seek, whence);
|
||||
if (r >= 0)
|
||||
return r;
|
||||
|
||||
|
||||
@@ -52,13 +52,15 @@
|
||||
struct read_FILE_data {
|
||||
FILE *f;
|
||||
size_t block_size;
|
||||
int64_t size;
|
||||
void *buffer;
|
||||
char can_skip;
|
||||
};
|
||||
|
||||
static int file_close(struct archive *, void *);
|
||||
static ssize_t file_read(struct archive *, void *, const void **buff);
|
||||
static int64_t file_skip(struct archive *, void *, int64_t request);
|
||||
static int FILE_close(struct archive *, void *);
|
||||
static ssize_t FILE_read(struct archive *, void *, const void **buff);
|
||||
static int64_t FILE_seek(struct archive *, void *, int64_t, int);
|
||||
static int64_t FILE_skip(struct archive *, void *, int64_t);
|
||||
|
||||
int
|
||||
archive_read_open_FILE(struct archive *a, FILE *f)
|
||||
@@ -69,7 +71,7 @@ archive_read_open_FILE(struct archive *a, FILE *f)
|
||||
void *b;
|
||||
|
||||
archive_clear_error(a);
|
||||
mine = malloc(sizeof(*mine));
|
||||
mine = calloc(1, sizeof(*mine));
|
||||
b = malloc(block_size);
|
||||
if (mine == NULL || b == NULL) {
|
||||
archive_set_error(a, ENOMEM, "No memory");
|
||||
@@ -90,22 +92,23 @@ archive_read_open_FILE(struct archive *a, FILE *f)
|
||||
archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
|
||||
/* Enable the seek optimization only for regular files. */
|
||||
mine->can_skip = 1;
|
||||
} else
|
||||
mine->can_skip = 0;
|
||||
mine->size = st.st_size;
|
||||
}
|
||||
|
||||
#if defined(__CYGWIN__) || defined(_WIN32)
|
||||
setmode(fileno(mine->f), O_BINARY);
|
||||
#endif
|
||||
|
||||
archive_read_set_read_callback(a, file_read);
|
||||
archive_read_set_skip_callback(a, file_skip);
|
||||
archive_read_set_close_callback(a, file_close);
|
||||
archive_read_set_read_callback(a, FILE_read);
|
||||
archive_read_set_skip_callback(a, FILE_skip);
|
||||
archive_read_set_seek_callback(a, FILE_seek);
|
||||
archive_read_set_close_callback(a, FILE_close);
|
||||
archive_read_set_callback_data(a, mine);
|
||||
return (archive_read_open1(a));
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
file_read(struct archive *a, void *client_data, const void **buff)
|
||||
FILE_read(struct archive *a, void *client_data, const void **buff)
|
||||
{
|
||||
struct read_FILE_data *mine = (struct read_FILE_data *)client_data;
|
||||
size_t bytes_read;
|
||||
@@ -119,16 +122,17 @@ file_read(struct archive *a, void *client_data, const void **buff)
|
||||
}
|
||||
|
||||
static int64_t
|
||||
file_skip(struct archive *a, void *client_data, int64_t request)
|
||||
FILE_skip(struct archive *a, void *client_data, int64_t request)
|
||||
{
|
||||
struct read_FILE_data *mine = (struct read_FILE_data *)client_data;
|
||||
#if HAVE_FSEEKO
|
||||
off_t skip = (off_t)request;
|
||||
#elif HAVE__FSEEKI64
|
||||
#if HAVE__FSEEKI64
|
||||
int64_t skip = request;
|
||||
#elif HAVE_FSEEKO
|
||||
off_t skip = (off_t)request;
|
||||
#else
|
||||
long skip = (long)request;
|
||||
#endif
|
||||
int64_t old_offset, new_offset = -1;
|
||||
int skip_bits = sizeof(skip) * 8 - 1;
|
||||
|
||||
(void)a; /* UNUSED */
|
||||
@@ -144,7 +148,7 @@ file_skip(struct archive *a, void *client_data, int64_t request)
|
||||
|
||||
/* If request is too big for a long or an off_t, reduce it. */
|
||||
if (sizeof(request) > sizeof(skip)) {
|
||||
int64_t max_skip =
|
||||
const int64_t max_skip =
|
||||
(((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
|
||||
if (request > max_skip)
|
||||
skip = max_skip;
|
||||
@@ -152,23 +156,92 @@ file_skip(struct archive *a, void *client_data, int64_t request)
|
||||
|
||||
#ifdef __ANDROID__
|
||||
/* fileno() isn't safe on all platforms ... see above. */
|
||||
if (lseek(fileno(mine->f), skip, SEEK_CUR) < 0)
|
||||
old_offset = lseek(fileno(mine->f), 0, SEEK_CUR);
|
||||
#elif HAVE__FSEEKI64
|
||||
if (_fseeki64(mine->f, skip, SEEK_CUR) != 0)
|
||||
old_offset = _ftelli64(mine->f);
|
||||
#elif HAVE_FSEEKO
|
||||
if (fseeko(mine->f, skip, SEEK_CUR) != 0)
|
||||
old_offset = ftello(mine->f);
|
||||
#else
|
||||
if (fseek(mine->f, skip, SEEK_CUR) != 0)
|
||||
old_offset = ftell(mine->f);
|
||||
#endif
|
||||
{
|
||||
mine->can_skip = 0;
|
||||
return (0);
|
||||
if (old_offset >= 0) {
|
||||
if (old_offset < mine->size &&
|
||||
skip <= mine->size - old_offset) {
|
||||
#ifdef __ANDROID__
|
||||
new_offset = lseek(fileno(mine->f), skip, SEEK_CUR);
|
||||
#elif HAVE__FSEEKI64
|
||||
if (_fseeki64(mine->f, skip, SEEK_CUR) == 0)
|
||||
new_offset = _ftelli64(mine->f);
|
||||
#elif HAVE_FSEEKO
|
||||
if (fseeko(mine->f, skip, SEEK_CUR) == 0)
|
||||
new_offset = ftello(mine->f);
|
||||
#else
|
||||
if (fseek(mine->f, skip, SEEK_CUR) == 0)
|
||||
new_offset = ftell(mine->f);
|
||||
#endif
|
||||
if (new_offset >= 0)
|
||||
return (new_offset - old_offset);
|
||||
}
|
||||
}
|
||||
return (request);
|
||||
|
||||
mine->can_skip = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: Store the offset and use it in the read callback.
|
||||
*/
|
||||
static int64_t
|
||||
FILE_seek(struct archive *a, void *client_data, int64_t request, int whence)
|
||||
{
|
||||
struct read_FILE_data *mine = (struct read_FILE_data *)client_data;
|
||||
#if HAVE__FSEEKI64
|
||||
int64_t seek = request;
|
||||
#elif HAVE_FSEEKO
|
||||
off_t seek = (off_t)request;
|
||||
#else
|
||||
long seek = (long)request;
|
||||
#endif
|
||||
int seek_bits = sizeof(seek) * 8 - 1;
|
||||
(void)a; /* UNUSED */
|
||||
|
||||
/* Reduce a request that would overflow the 'seek' variable. */
|
||||
if (sizeof(request) > sizeof(seek)) {
|
||||
const int64_t max_seek =
|
||||
(((int64_t)1 << (seek_bits - 1)) - 1) * 2 + 1;
|
||||
const int64_t min_seek = ~max_seek;
|
||||
if (request > max_seek)
|
||||
seek = max_seek;
|
||||
else if (request < min_seek)
|
||||
seek = min_seek;
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
/* Newer Android versions have fseeko...to meditate. */
|
||||
int64_t ret = lseek(fileno(mine->f), seek, whence);
|
||||
if (ret >= 0) {
|
||||
return ret;
|
||||
}
|
||||
#elif HAVE__FSEEKI64
|
||||
if (_fseeki64(mine->f, seek, whence) == 0) {
|
||||
return _ftelli64(mine->f);
|
||||
}
|
||||
#elif HAVE_FSEEKO
|
||||
if (fseeko(mine->f, seek, whence) == 0) {
|
||||
return ftello(mine->f);
|
||||
}
|
||||
#else
|
||||
if (fseek(mine->f, seek, whence) == 0) {
|
||||
return ftell(mine->f);
|
||||
}
|
||||
#endif
|
||||
/* If we arrive here, the input is corrupted or truncated so fail. */
|
||||
archive_set_error(a, errno, "Error seeking in FILE* pointer");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
static int
|
||||
file_close(struct archive *a, void *client_data)
|
||||
FILE_close(struct archive *a, void *client_data)
|
||||
{
|
||||
struct read_FILE_data *mine = (struct read_FILE_data *)client_data;
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ struct read_file_data {
|
||||
size_t block_size;
|
||||
void *buffer;
|
||||
mode_t st_mode; /* Mode bits for opened file. */
|
||||
int64_t size;
|
||||
char use_lseek;
|
||||
enum fnt_e { FNT_STDIN, FNT_MBS, FNT_WCS } filename_type;
|
||||
union {
|
||||
@@ -303,7 +304,7 @@ file_open(struct archive *a, void *client_data)
|
||||
}
|
||||
if (fd < 0) {
|
||||
archive_set_error(a, errno,
|
||||
"Failed to open '%S'", wfilename);
|
||||
"Failed to open '%ls'", wfilename);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
#else
|
||||
@@ -315,7 +316,7 @@ file_open(struct archive *a, void *client_data)
|
||||
if (fstat(fd, &st) != 0) {
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
if (mine->filename_type == FNT_WCS)
|
||||
archive_set_error(a, errno, "Can't stat '%S'",
|
||||
archive_set_error(a, errno, "Can't stat '%ls'",
|
||||
wfilename);
|
||||
else
|
||||
#endif
|
||||
@@ -400,8 +401,10 @@ file_open(struct archive *a, void *client_data)
|
||||
mine->st_mode = st.st_mode;
|
||||
|
||||
/* Disk-like inputs can use lseek(). */
|
||||
if (is_disk_like)
|
||||
if (is_disk_like) {
|
||||
mine->use_lseek = 1;
|
||||
mine->size = st.st_size;
|
||||
}
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
fail:
|
||||
@@ -447,7 +450,7 @@ file_read(struct archive *a, void *client_data, const void **buff)
|
||||
"Error reading '%s'", mine->filename.m);
|
||||
else
|
||||
archive_set_error(a, errno,
|
||||
"Error reading '%S'", mine->filename.w);
|
||||
"Error reading '%ls'", mine->filename.w);
|
||||
}
|
||||
return (bytes_read);
|
||||
}
|
||||
@@ -479,21 +482,30 @@ file_skip_lseek(struct archive *a, void *client_data, int64_t request)
|
||||
struct read_file_data *mine = (struct read_file_data *)client_data;
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* We use _lseeki64() on Windows. */
|
||||
int64_t old_offset, new_offset;
|
||||
int64_t old_offset, new_offset, skip = request;
|
||||
#else
|
||||
off_t old_offset, new_offset;
|
||||
off_t old_offset, new_offset, skip = (off_t)request;
|
||||
#endif
|
||||
int skip_bits = sizeof(skip) * 8 - 1;
|
||||
|
||||
/* We use off_t here because lseek() is declared that way. */
|
||||
|
||||
/* TODO: Deal with case where off_t isn't 64 bits.
|
||||
* This shouldn't be a problem on Linux or other POSIX
|
||||
* systems, since the configuration logic for libarchive
|
||||
* tries to obtain a 64-bit off_t.
|
||||
*/
|
||||
if ((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0 &&
|
||||
(new_offset = lseek(mine->fd, request, SEEK_CUR)) >= 0)
|
||||
return (new_offset - old_offset);
|
||||
/* Reduce a request that would overflow the 'skip' variable. */
|
||||
if (sizeof(request) > sizeof(skip)) {
|
||||
const int64_t max_skip =
|
||||
(((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
|
||||
if (request > max_skip)
|
||||
skip = max_skip;
|
||||
}
|
||||
|
||||
if ((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0) {
|
||||
if (old_offset >= mine->size ||
|
||||
skip > mine->size - old_offset) {
|
||||
/* Do not seek past end of file. */
|
||||
errno = ESPIPE;
|
||||
} else if ((new_offset = lseek(mine->fd, skip, SEEK_CUR)) >= 0)
|
||||
return (new_offset - old_offset);
|
||||
}
|
||||
|
||||
/* If lseek() fails, don't bother trying again. */
|
||||
mine->use_lseek = 0;
|
||||
@@ -509,7 +521,7 @@ file_skip_lseek(struct archive *a, void *client_data, int64_t request)
|
||||
archive_set_error(a, errno, "Error seeking in '%s'",
|
||||
mine->filename.m);
|
||||
else
|
||||
archive_set_error(a, errno, "Error seeking in '%S'",
|
||||
archive_set_error(a, errno, "Error seeking in '%ls'",
|
||||
mine->filename.w);
|
||||
return (-1);
|
||||
}
|
||||
@@ -540,11 +552,24 @@ static int64_t
|
||||
file_seek(struct archive *a, void *client_data, int64_t request, int whence)
|
||||
{
|
||||
struct read_file_data *mine = (struct read_file_data *)client_data;
|
||||
off_t seek = (off_t)request;
|
||||
int64_t r;
|
||||
int seek_bits = sizeof(seek) * 8 - 1;
|
||||
|
||||
/* We use off_t here because lseek() is declared that way. */
|
||||
/* See above for notes about when off_t is less than 64 bits. */
|
||||
r = lseek(mine->fd, request, whence);
|
||||
|
||||
/* Reduce a request that would overflow the 'seek' variable. */
|
||||
if (sizeof(request) > sizeof(seek)) {
|
||||
const int64_t max_seek =
|
||||
(((int64_t)1 << (seek_bits - 1)) - 1) * 2 + 1;
|
||||
const int64_t min_seek = ~max_seek;
|
||||
if (request > max_seek)
|
||||
seek = (off_t)max_seek;
|
||||
else if (request < min_seek)
|
||||
seek = (off_t)min_seek;
|
||||
}
|
||||
|
||||
r = lseek(mine->fd, seek, whence);
|
||||
if (r >= 0)
|
||||
return r;
|
||||
|
||||
@@ -555,7 +580,7 @@ file_seek(struct archive *a, void *client_data, int64_t request, int whence)
|
||||
archive_set_error(a, errno, "Error seeking in '%s'",
|
||||
mine->filename.m);
|
||||
else
|
||||
archive_set_error(a, errno, "Error seeking in '%S'",
|
||||
archive_set_error(a, errno, "Error seeking in '%ls'",
|
||||
mine->filename.w);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
@@ -37,46 +37,32 @@ archive_read_support_filter_by_code(struct archive *a, int filter_code)
|
||||
switch (filter_code) {
|
||||
case ARCHIVE_FILTER_NONE:
|
||||
return archive_read_support_filter_none(a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_GZIP:
|
||||
return archive_read_support_filter_gzip(a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_BZIP2:
|
||||
return archive_read_support_filter_bzip2(a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_COMPRESS:
|
||||
return archive_read_support_filter_compress(a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_LZMA:
|
||||
return archive_read_support_filter_lzma(a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_XZ:
|
||||
return archive_read_support_filter_xz(a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_UU:
|
||||
return archive_read_support_filter_uu(a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_RPM:
|
||||
return archive_read_support_filter_rpm(a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_LZIP:
|
||||
return archive_read_support_filter_lzip(a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_LRZIP:
|
||||
return archive_read_support_filter_lrzip(a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_LZOP:
|
||||
return archive_read_support_filter_lzop(a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_GRZIP:
|
||||
return archive_read_support_filter_grzip(a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_LZ4:
|
||||
return archive_read_support_filter_lz4(a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_ZSTD:
|
||||
return archive_read_support_filter_zstd(a);
|
||||
break;
|
||||
}
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
@@ -328,6 +328,7 @@ next_code(struct archive_read_filter *self)
|
||||
static int debug_buff[1024];
|
||||
static unsigned debug_index;
|
||||
|
||||
again:
|
||||
code = newcode = getbits(self, state->bits);
|
||||
if (code < 0)
|
||||
return (code);
|
||||
@@ -360,7 +361,7 @@ next_code(struct archive_read_filter *self)
|
||||
state->section_end_code = (1 << state->bits) - 1;
|
||||
state->free_ent = 257;
|
||||
state->oldcode = -1;
|
||||
return (next_code(self));
|
||||
goto again;
|
||||
}
|
||||
|
||||
if (code > state->free_ent
|
||||
|
||||
@@ -323,7 +323,6 @@ lz4_filter_read(struct archive_read_filter *self, const void **p)
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC, "Program error.");
|
||||
return (ARCHIVE_FATAL);
|
||||
break;
|
||||
}
|
||||
|
||||
while (state->stage == SELECT_STREAM) {
|
||||
|
||||
@@ -28,6 +28,9 @@
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#if HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
@@ -50,6 +53,7 @@
|
||||
#include "archive_ppmd7_private.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
#include "archive_time_private.h"
|
||||
#include "archive_endian.h"
|
||||
|
||||
#ifndef HAVE_ZLIB_H
|
||||
@@ -59,7 +63,26 @@
|
||||
#define _7ZIP_SIGNATURE "7z\xBC\xAF\x27\x1C"
|
||||
#define SFX_MIN_ADDR 0x27000
|
||||
#define SFX_MAX_ADDR 0x60000
|
||||
#define SFX_MAX_OFFSET (SFX_MAX_ADDR - SFX_MIN_ADDR)
|
||||
|
||||
/*
|
||||
* PE format
|
||||
*/
|
||||
#define PE_DOS_HDR_LEN 0x40
|
||||
#define PE_DOS_HDR_ELFANEW_OFFSET 0x3c
|
||||
#define PE_COFF_HDR_LEN 0x18
|
||||
#define PE_COFF_HDR_SEC_CNT_OFFSET 0x6
|
||||
#define PE_COFF_HDR_OPT_SZ_OFFSET 0x14
|
||||
#define PE_SEC_HDR_LEN 0x28
|
||||
#define PE_SEC_HDR_RAW_ADDR_OFFSET 0x14
|
||||
#define PE_SEC_HDR_RAW_SZ_OFFSET 0x10
|
||||
|
||||
/*
|
||||
* ELF format
|
||||
*/
|
||||
#define ELF_HDR_MIN_LEN 0x34
|
||||
#define ELF_HDR_EI_CLASS_OFFSET 0x04
|
||||
#define ELF_HDR_EI_DATA_OFFSET 0x05
|
||||
|
||||
/*
|
||||
* Codec ID
|
||||
@@ -83,6 +106,7 @@
|
||||
#define _7Z_ARM 0x03030501
|
||||
#define _7Z_ARMTHUMB 0x03030701
|
||||
#define _7Z_ARM64 0xa
|
||||
#define _7Z_RISCV 0xb
|
||||
#define _7Z_SPARC 0x03030805
|
||||
|
||||
#define _7Z_ZSTD 0x4F71101 /* Copied from https://github.com/mcmilk/7-Zip-zstd.git */
|
||||
@@ -144,7 +168,6 @@ struct _7z_digests {
|
||||
uint32_t *digests;
|
||||
};
|
||||
|
||||
|
||||
struct _7z_folder {
|
||||
uint64_t numCoders;
|
||||
struct _7z_coder {
|
||||
@@ -224,13 +247,13 @@ struct _7zip_entry {
|
||||
#define CRC32_IS_SET (1<<3)
|
||||
#define HAS_STREAM (1<<4)
|
||||
|
||||
time_t mtime;
|
||||
time_t atime;
|
||||
time_t ctime;
|
||||
long mtime_ns;
|
||||
long atime_ns;
|
||||
long ctime_ns;
|
||||
uint32_t mode;
|
||||
int64_t mtime;
|
||||
int64_t atime;
|
||||
int64_t ctime;
|
||||
uint32_t mtime_ns;
|
||||
uint32_t atime_ns;
|
||||
uint32_t ctime_ns;
|
||||
__LA_MODE_T mode;
|
||||
uint32_t attr;
|
||||
};
|
||||
|
||||
@@ -388,7 +411,6 @@ static int decode_encoded_header_info(struct archive_read *,
|
||||
static int decompress(struct archive_read *, struct _7zip *,
|
||||
void *, size_t *, const void *, size_t *);
|
||||
static ssize_t extract_pack_stream(struct archive_read *, size_t);
|
||||
static void fileTimeToUtc(uint64_t, time_t *, long *);
|
||||
static uint64_t folder_uncompressed_size(struct _7z_folder *);
|
||||
static void free_CodersInfo(struct _7z_coders_info *);
|
||||
static void free_Digest(struct _7z_digests *);
|
||||
@@ -424,7 +446,9 @@ static ssize_t read_stream(struct archive_read *, const void **, size_t,
|
||||
size_t);
|
||||
static int seek_pack(struct archive_read *);
|
||||
static int64_t skip_stream(struct archive_read *, size_t);
|
||||
static int skip_sfx(struct archive_read *, ssize_t);
|
||||
static int skip_sfx(struct archive_read *, const ssize_t);
|
||||
static ssize_t find_pe_overlay(struct archive_read *);
|
||||
static ssize_t find_elf_data_sec(struct archive_read *);
|
||||
static int slurp_central_directory(struct archive_read *, struct _7zip *,
|
||||
struct _7z_header_info *);
|
||||
static int setup_decode_folder(struct archive_read *, struct _7z_folder *,
|
||||
@@ -435,6 +459,8 @@ static void arm_Init(struct _7zip *);
|
||||
static size_t arm_Convert(struct _7zip *, uint8_t *, size_t);
|
||||
static size_t arm64_Convert(struct _7zip *, uint8_t *, size_t);
|
||||
static ssize_t Bcj2_Decode(struct _7zip *, uint8_t *, size_t);
|
||||
static size_t sparc_Convert(struct _7zip *, uint8_t *, size_t);
|
||||
static size_t powerpc_Convert(struct _7zip *, uint8_t *, size_t);
|
||||
|
||||
|
||||
int
|
||||
@@ -522,15 +548,17 @@ archive_read_format_7zip_bid(struct archive_read *a, int best_bid)
|
||||
* It may a 7-Zip SFX archive file. If first two bytes are
|
||||
* 'M' and 'Z' available on Windows or first four bytes are
|
||||
* "\x7F\x45LF" available on posix like system, seek the 7-Zip
|
||||
* signature. Although we will perform a seek when reading
|
||||
* a header, what we do not use __archive_read_seek() here is
|
||||
* due to a bidding performance.
|
||||
* signature. While find_pe_overlay can be performed without
|
||||
* performing a seek, find_elf_data_sec requires one,
|
||||
* thus a performance difference between the two is expected.
|
||||
*/
|
||||
if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0) {
|
||||
ssize_t offset = SFX_MIN_ADDR;
|
||||
const ssize_t min_addr = p[0] == 'M' ? find_pe_overlay(a) :
|
||||
find_elf_data_sec(a);
|
||||
ssize_t offset = min_addr;
|
||||
ssize_t window = 4096;
|
||||
ssize_t bytes_avail;
|
||||
while (offset + window <= (SFX_MAX_ADDR)) {
|
||||
while (offset + window <= (min_addr + SFX_MAX_OFFSET)) {
|
||||
const char *buff = __archive_read_ahead(a,
|
||||
offset + window, &bytes_avail);
|
||||
if (buff == NULL) {
|
||||
@@ -580,21 +608,14 @@ check_7zip_header_in_sfx(const char *p)
|
||||
}
|
||||
|
||||
static int
|
||||
skip_sfx(struct archive_read *a, ssize_t bytes_avail)
|
||||
skip_sfx(struct archive_read *a, const ssize_t min_addr)
|
||||
{
|
||||
const void *h;
|
||||
const char *p, *q;
|
||||
size_t skip, offset;
|
||||
ssize_t bytes, window;
|
||||
|
||||
/*
|
||||
* If bytes_avail > SFX_MIN_ADDR we do not have to call
|
||||
* __archive_read_seek() at this time since we have
|
||||
* already had enough data.
|
||||
*/
|
||||
if (bytes_avail > SFX_MIN_ADDR)
|
||||
__archive_read_consume(a, SFX_MIN_ADDR);
|
||||
else if (__archive_read_seek(a, SFX_MIN_ADDR, SEEK_SET) < 0)
|
||||
if (__archive_read_seek(a, min_addr, SEEK_SET) < 0)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
offset = 0;
|
||||
@@ -627,7 +648,7 @@ skip_sfx(struct archive_read *a, ssize_t bytes_avail)
|
||||
(struct _7zip *)a->format->data;
|
||||
skip = p - (const char *)h;
|
||||
__archive_read_consume(a, skip);
|
||||
zip->seek_base = SFX_MIN_ADDR + offset + skip;
|
||||
zip->seek_base = min_addr + offset + skip;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
p += step;
|
||||
@@ -644,6 +665,207 @@ skip_sfx(struct archive_read *a, ssize_t bytes_avail)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
find_pe_overlay(struct archive_read *a)
|
||||
{
|
||||
const char *h;
|
||||
ssize_t bytes, max_offset, offset, sec_end;
|
||||
ssize_t opt_hdr_sz, sec_cnt;
|
||||
|
||||
for (;;) {
|
||||
/*
|
||||
* Read Dos header to find e_lfanew
|
||||
*/
|
||||
h = __archive_read_ahead(a, PE_DOS_HDR_LEN, &bytes);
|
||||
if (h == NULL || h[0] != 'M' || h[1] != 'Z') {
|
||||
break;
|
||||
}
|
||||
offset = archive_le32dec(h + PE_DOS_HDR_ELFANEW_OFFSET);
|
||||
|
||||
/*
|
||||
* Read COFF header to find opt header size and sec cnt
|
||||
*/
|
||||
if (bytes < offset + PE_COFF_HDR_LEN) {
|
||||
h = __archive_read_ahead(a, offset + PE_COFF_HDR_LEN,
|
||||
&bytes);
|
||||
if (h == NULL || h[offset] != 'P' ||
|
||||
h[offset + 1] != 'E') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
sec_cnt = archive_le16dec(
|
||||
h + offset + PE_COFF_HDR_SEC_CNT_OFFSET);
|
||||
opt_hdr_sz = archive_le16dec(
|
||||
h + offset + PE_COFF_HDR_OPT_SZ_OFFSET);
|
||||
|
||||
/*
|
||||
* Skip optional header
|
||||
*/
|
||||
if (opt_hdr_sz != 0) {
|
||||
offset += PE_COFF_HDR_LEN + opt_hdr_sz;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Traverse sec table to find max raw offset (i.e., overlay)
|
||||
*/
|
||||
if (bytes < offset + sec_cnt * PE_SEC_HDR_LEN) {
|
||||
h = __archive_read_ahead(a,
|
||||
offset + sec_cnt * PE_SEC_HDR_LEN, NULL);
|
||||
if (h == NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
max_offset = offset;
|
||||
while (sec_cnt > 0) {
|
||||
sec_end = archive_le32dec(
|
||||
h + offset + PE_SEC_HDR_RAW_SZ_OFFSET) +
|
||||
archive_le32dec(
|
||||
h + offset + PE_SEC_HDR_RAW_ADDR_OFFSET);
|
||||
if (sec_end > max_offset) {
|
||||
max_offset = sec_end;
|
||||
}
|
||||
offset += PE_SEC_HDR_LEN;
|
||||
sec_cnt--;
|
||||
}
|
||||
return (max_offset);
|
||||
}
|
||||
|
||||
/*
|
||||
* If encounter any weirdness, revert to old brute-force style search
|
||||
*/
|
||||
return (SFX_MIN_ADDR);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
find_elf_data_sec(struct archive_read *a)
|
||||
{
|
||||
const char *h;
|
||||
char big_endian, format_64;
|
||||
ssize_t bytes, min_addr = SFX_MIN_ADDR;
|
||||
uint64_t e_shoff, strtab_offset, strtab_size;
|
||||
uint16_t e_shentsize, e_shnum, e_shstrndx;
|
||||
uint16_t (*dec16)(const void *);
|
||||
uint32_t (*dec32)(const void *);
|
||||
uint64_t (*dec64)(const void *);
|
||||
|
||||
for (;;) {
|
||||
/*
|
||||
* Read Elf header to find bitness & endianness
|
||||
*/
|
||||
h = __archive_read_ahead(a, ELF_HDR_MIN_LEN, &bytes);
|
||||
if (h == NULL || memcmp(h, "\x7F\x45LF", 4) != 0) {
|
||||
break;
|
||||
}
|
||||
format_64 = h[ELF_HDR_EI_CLASS_OFFSET] == 0x2;
|
||||
big_endian = h[ELF_HDR_EI_DATA_OFFSET] == 0x2;
|
||||
if (big_endian) {
|
||||
dec16 = &archive_be16dec;
|
||||
dec32 = &archive_be32dec;
|
||||
dec64 = &archive_be64dec;
|
||||
} else {
|
||||
dec16 = &archive_le16dec;
|
||||
dec32 = &archive_le32dec;
|
||||
dec64 = &archive_le64dec;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read section header table info
|
||||
*/
|
||||
if (format_64) {
|
||||
e_shoff = (*dec64)(h + 0x28);
|
||||
e_shentsize = (*dec16)(h + 0x3A);
|
||||
e_shnum = (*dec16)(h + 0x3C);
|
||||
e_shstrndx = (*dec16)(h + 0x3E);
|
||||
if (e_shnum < e_shstrndx || e_shentsize < 0x28)
|
||||
break;
|
||||
|
||||
} else {
|
||||
e_shoff = (*dec32)(h + 0x20);
|
||||
e_shentsize = (*dec16)(h + 0x2E);
|
||||
e_shnum = (*dec16)(h + 0x30);
|
||||
e_shstrndx = (*dec16)(h + 0x32);
|
||||
if (e_shnum < e_shstrndx || e_shentsize < 0x18)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reading the section table to find strtab section
|
||||
*/
|
||||
if (__archive_read_seek(a, e_shoff, SEEK_SET) < 0) {
|
||||
break;
|
||||
}
|
||||
h = __archive_read_ahead(a, (size_t)e_shnum * (size_t)e_shentsize, NULL);
|
||||
if (h == NULL) {
|
||||
break;
|
||||
}
|
||||
if (format_64) {
|
||||
strtab_offset = (*dec64)(
|
||||
h + e_shstrndx * e_shentsize + 0x18);
|
||||
strtab_size = (*dec64)(
|
||||
h + e_shstrndx * e_shentsize + 0x20);
|
||||
} else {
|
||||
strtab_offset = (*dec32)(
|
||||
h + e_shstrndx * e_shentsize + 0x10);
|
||||
strtab_size = (*dec32)(
|
||||
h + e_shstrndx * e_shentsize + 0x14);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the STRTAB section to find the .data offset
|
||||
*/
|
||||
if (__archive_read_seek(a, strtab_offset, SEEK_SET) < 0) {
|
||||
break;
|
||||
}
|
||||
h = __archive_read_ahead(a, strtab_size, NULL);
|
||||
if (h == NULL) {
|
||||
break;
|
||||
}
|
||||
ssize_t data_sym_offset = -1;
|
||||
for (size_t offset = 0; offset < strtab_size - 6; offset++) {
|
||||
if (memcmp(h + offset, ".data\00", 6) == 0) {
|
||||
data_sym_offset = offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (data_sym_offset == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the section with the .data name
|
||||
*/
|
||||
if (__archive_read_seek(a, e_shoff, SEEK_SET) < 0) {
|
||||
break;
|
||||
}
|
||||
h = __archive_read_ahead(a, (size_t)e_shnum * (size_t)e_shentsize, NULL);
|
||||
if (h == NULL) {
|
||||
break;
|
||||
}
|
||||
ssize_t sec_tbl_offset = 0, name_offset;
|
||||
while (e_shnum > 0) {
|
||||
name_offset = (*dec32)(h + sec_tbl_offset);
|
||||
if (name_offset == data_sym_offset) {
|
||||
if (format_64) {
|
||||
min_addr = (*dec64)(
|
||||
h + sec_tbl_offset + 0x18);
|
||||
} else {
|
||||
min_addr = (*dec32)(
|
||||
h + sec_tbl_offset + 0x10);
|
||||
}
|
||||
break;
|
||||
}
|
||||
sec_tbl_offset += e_shentsize;
|
||||
e_shnum--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
__archive_read_seek(a, 0, SEEK_SET);
|
||||
return (min_addr);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_7zip_read_header(struct archive_read *a,
|
||||
struct archive_entry *entry)
|
||||
@@ -770,7 +992,7 @@ archive_read_format_7zip_read_header(struct archive_read *a,
|
||||
/* allocate for ",rdonly,hidden,system" */
|
||||
fflags_text = malloc(22 * sizeof(*fflags_text));
|
||||
if (fflags_text != NULL) {
|
||||
ptr = fflags_text;
|
||||
ptr = fflags_text;
|
||||
if (zip_entry->attr & FILE_ATTRIBUTE_READONLY) {
|
||||
strcpy(ptr, ",rdonly");
|
||||
ptr = ptr + 7;
|
||||
@@ -1109,7 +1331,9 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
|
||||
if (coder2->codec != _7Z_X86 &&
|
||||
coder2->codec != _7Z_X86_BCJ2 &&
|
||||
coder2->codec != _7Z_ARM &&
|
||||
coder2->codec != _7Z_ARM64) {
|
||||
coder2->codec != _7Z_ARM64 &&
|
||||
coder2->codec != _7Z_POWERPC &&
|
||||
coder2->codec != _7Z_SPARC) {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Unsupported filter %lx for %lx",
|
||||
@@ -1223,6 +1447,12 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
|
||||
filters[fi].id = LZMA_FILTER_ARM64;
|
||||
fi++;
|
||||
break;
|
||||
#endif
|
||||
#ifdef LZMA_FILTER_RISCV
|
||||
case _7Z_RISCV:
|
||||
filters[fi].id = LZMA_FILTER_RISCV;
|
||||
fi++;
|
||||
break;
|
||||
#endif
|
||||
case _7Z_SPARC:
|
||||
filters[fi].id = LZMA_FILTER_SPARC;
|
||||
@@ -1396,6 +1626,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
|
||||
case _7Z_ARM:
|
||||
case _7Z_ARMTHUMB:
|
||||
case _7Z_ARM64:
|
||||
case _7Z_RISCV:
|
||||
case _7Z_SPARC:
|
||||
case _7Z_DELTA:
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
@@ -1708,6 +1939,10 @@ decompress(struct archive_read *a, struct _7zip *zip,
|
||||
*outbytes = arm_Convert(zip, buff, *outbytes);
|
||||
} else if (zip->codec2 == _7Z_ARM64) {
|
||||
*outbytes = arm64_Convert(zip, buff, *outbytes);
|
||||
} else if (zip->codec2 == _7Z_SPARC) {
|
||||
*outbytes = sparc_Convert(zip, buff, *outbytes);
|
||||
} else if (zip->codec2 == _7Z_POWERPC) {
|
||||
*outbytes = powerpc_Convert(zip, buff, *outbytes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2841,23 +3076,6 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
|
||||
return (0);
|
||||
}
|
||||
|
||||
#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
|
||||
static void
|
||||
fileTimeToUtc(uint64_t fileTime, time_t *timep, long *ns)
|
||||
{
|
||||
|
||||
if (fileTime >= EPOC_TIME) {
|
||||
fileTime -= EPOC_TIME;
|
||||
/* milli seconds base */
|
||||
*timep = (time_t)(fileTime / 10000000);
|
||||
/* nano seconds base */
|
||||
*ns = (long)(fileTime % 10000000) * 100;
|
||||
} else {
|
||||
*timep = 0;
|
||||
*ns = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
read_Times(struct archive_read *a, struct _7z_header_info *h, int type)
|
||||
{
|
||||
@@ -2900,19 +3118,19 @@ read_Times(struct archive_read *a, struct _7z_header_info *h, int type)
|
||||
goto failed;
|
||||
switch (type) {
|
||||
case kCTime:
|
||||
fileTimeToUtc(archive_le64dec(p),
|
||||
ntfs_to_unix(archive_le64dec(p),
|
||||
&(entries[i].ctime),
|
||||
&(entries[i].ctime_ns));
|
||||
entries[i].flg |= CTIME_IS_SET;
|
||||
break;
|
||||
case kATime:
|
||||
fileTimeToUtc(archive_le64dec(p),
|
||||
ntfs_to_unix(archive_le64dec(p),
|
||||
&(entries[i].atime),
|
||||
&(entries[i].atime_ns));
|
||||
entries[i].flg |= ATIME_IS_SET;
|
||||
break;
|
||||
case kMTime:
|
||||
fileTimeToUtc(archive_le64dec(p),
|
||||
ntfs_to_unix(archive_le64dec(p),
|
||||
&(entries[i].mtime),
|
||||
&(entries[i].mtime_ns));
|
||||
entries[i].flg |= MTIME_IS_SET;
|
||||
@@ -3007,7 +3225,9 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip,
|
||||
|
||||
if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0) {
|
||||
/* This is an executable ? Must be self-extracting... */
|
||||
r = skip_sfx(a, bytes_avail);
|
||||
const ssize_t min_addr = p[0] == 'M' ? find_pe_overlay(a) :
|
||||
find_elf_data_sec(a);
|
||||
r = skip_sfx(a, min_addr);
|
||||
if (r < ARCHIVE_WARN)
|
||||
return (r);
|
||||
if ((p = __archive_read_ahead(a, 32, &bytes_avail)) == NULL)
|
||||
@@ -4007,6 +4227,121 @@ arm64_Convert(struct _7zip *zip, uint8_t *buf, size_t size)
|
||||
return i;
|
||||
}
|
||||
|
||||
static size_t
|
||||
sparc_Convert(struct _7zip *zip, uint8_t *buf, size_t size)
|
||||
{
|
||||
// This function was adapted from
|
||||
// static size_t bcj_sparc(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
|
||||
// in https://git.tukaani.org/xz-embedded.git
|
||||
|
||||
/*
|
||||
* Branch/Call/Jump (BCJ) filter decoders
|
||||
*
|
||||
* Authors: Lasse Collin <lasse.collin@tukaani.org>
|
||||
* Igor Pavlov <https://7-zip.org/>
|
||||
*
|
||||
* Copyright (C) The XZ Embedded authors and contributors
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this
|
||||
* software for any purpose with or without fee is hereby granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
size_t i;
|
||||
uint32_t instr;
|
||||
|
||||
size &= ~(size_t)3;
|
||||
|
||||
for (i = 0; i < size; i += 4) {
|
||||
instr = (uint32_t)(buf[i] << 24)
|
||||
| ((uint32_t)buf[i+1] << 16)
|
||||
| ((uint32_t)buf[i+2] << 8)
|
||||
| (uint32_t)buf[i+3];
|
||||
|
||||
if ((instr >> 22) == 0x100 || (instr >> 22) == 0x1FF) {
|
||||
instr <<= 2;
|
||||
instr -= zip->bcj_ip + (uint32_t)i;
|
||||
instr >>= 2;
|
||||
instr = ((uint32_t)0x40000000 - (instr & 0x400000))
|
||||
| 0x40000000 | (instr & 0x3FFFFF);
|
||||
|
||||
buf[i] = (uint8_t)(instr >> 24);
|
||||
buf[i+1] = (uint8_t)(instr >> 16);
|
||||
buf[i+2] = (uint8_t)(instr >> 8);
|
||||
buf[i+3] = (uint8_t)instr;
|
||||
}
|
||||
}
|
||||
|
||||
zip->bcj_ip += (uint32_t)i;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static size_t
|
||||
powerpc_Convert(struct _7zip *zip, uint8_t *buf, size_t size)
|
||||
{
|
||||
// This function was adapted from
|
||||
// static size_t powerpc_code(void *simple, uint32_t now_pos, bool is_encoder, uint8_t *buffer, size_t size)
|
||||
// in https://git.tukaani.org/xz.git
|
||||
|
||||
/*
|
||||
* Filter for PowerPC (big endian) binaries
|
||||
*
|
||||
* Authors: Igor Pavlov
|
||||
* Lasse Collin
|
||||
*
|
||||
* Copyright (C) The XZ Utils authors and contributors
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this
|
||||
* software for any purpose with or without fee is hereby granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
size &= ~(size_t)3;
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < size; i += 4) {
|
||||
// PowerPC branch 6(48) 24(Offset) 1(Abs) 1(Link)
|
||||
if ((buf[i] >> 2) == 0x12
|
||||
&& ((buf[i + 3] & 3) == 1)) {
|
||||
|
||||
const uint32_t src
|
||||
= (((uint32_t)(buf[i + 0]) & 3) << 24)
|
||||
| ((uint32_t)(buf[i + 1]) << 16)
|
||||
| ((uint32_t)(buf[i + 2]) << 8)
|
||||
| ((uint32_t)(buf[i + 3]) & ~UINT32_C(3));
|
||||
|
||||
uint32_t dest = src - (zip->bcj_ip + (uint32_t)(i));
|
||||
|
||||
buf[i + 0] = 0x48 | ((dest >> 24) & 0x03);
|
||||
buf[i + 1] = (dest >> 16);
|
||||
buf[i + 2] = (dest >> 8);
|
||||
buf[i + 3] &= 0x03;
|
||||
buf[i + 3] |= dest;
|
||||
}
|
||||
}
|
||||
|
||||
zip->bcj_ip += (uint32_t)i;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Brought from LZMA SDK.
|
||||
*
|
||||
@@ -4029,8 +4364,17 @@ arm64_Convert(struct _7zip *zip, uint8_t *buf, size_t size)
|
||||
|
||||
#define RC_READ_BYTE (*buffer++)
|
||||
#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; }
|
||||
#define RC_INIT2 zip->bcj2_code = 0; zip->bcj2_range = 0xFFFFFFFF; \
|
||||
{ int ii; for (ii = 0; ii < 5; ii++) { RC_TEST; zip->bcj2_code = (zip->bcj2_code << 8) | RC_READ_BYTE; }}
|
||||
#define RC_INIT2 do { \
|
||||
zip->bcj2_code = 0; \
|
||||
zip->bcj2_range = 0xFFFFFFFF; \
|
||||
{ \
|
||||
int ii; \
|
||||
for (ii = 0; ii < 5; ii++) { \
|
||||
RC_TEST; \
|
||||
zip->bcj2_code = (zip->bcj2_code << 8) | RC_READ_BYTE; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define NORMALIZE if (zip->bcj2_range < kTopValue) { RC_TEST; zip->bcj2_range <<= 8; zip->bcj2_code = (zip->bcj2_code << 8) | RC_READ_BYTE; }
|
||||
|
||||
@@ -4177,4 +4521,3 @@ Bcj2_Decode(struct _7zip *zip, uint8_t *outBuf, size_t outSize)
|
||||
|
||||
return ((ssize_t)outPos);
|
||||
}
|
||||
|
||||
|
||||
@@ -41,49 +41,34 @@ archive_read_support_format_by_code(struct archive *a, int format_code)
|
||||
switch (format_code & ARCHIVE_FORMAT_BASE_MASK) {
|
||||
case ARCHIVE_FORMAT_7ZIP:
|
||||
return archive_read_support_format_7zip(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_AR:
|
||||
return archive_read_support_format_ar(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_CAB:
|
||||
return archive_read_support_format_cab(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_CPIO:
|
||||
return archive_read_support_format_cpio(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_EMPTY:
|
||||
return archive_read_support_format_empty(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_ISO9660:
|
||||
return archive_read_support_format_iso9660(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_LHA:
|
||||
return archive_read_support_format_lha(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_MTREE:
|
||||
return archive_read_support_format_mtree(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_RAR:
|
||||
return archive_read_support_format_rar(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_RAR_V5:
|
||||
return archive_read_support_format_rar5(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_RAW:
|
||||
return archive_read_support_format_raw(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_TAR:
|
||||
return archive_read_support_format_tar(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_WARC:
|
||||
return archive_read_support_format_warc(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_XAR:
|
||||
return archive_read_support_format_xar(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_ZIP:
|
||||
return archive_read_support_format_zip(a);
|
||||
break;
|
||||
}
|
||||
archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
"Invalid format code specified");
|
||||
|
||||
@@ -363,7 +363,12 @@ archive_read_support_format_cab(struct archive *_a)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
archive_string_init(&cab->ws);
|
||||
archive_wstring_ensure(&cab->ws, 256);
|
||||
if (archive_wstring_ensure(&cab->ws, 256) == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate memory");
|
||||
free(cab);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
r = __archive_read_register_format(a,
|
||||
cab,
|
||||
|
||||
@@ -189,6 +189,7 @@ struct cpio {
|
||||
};
|
||||
|
||||
static int64_t atol16(const char *, unsigned);
|
||||
static uint64_t atol16u(const char *, unsigned);
|
||||
static int64_t atol8(const char *, unsigned);
|
||||
static int archive_read_format_cpio_bid(struct archive_read *, int);
|
||||
static int archive_read_format_cpio_options(struct archive_read *,
|
||||
@@ -835,6 +836,7 @@ header_afiol(struct archive_read *a, struct cpio *cpio,
|
||||
struct archive_entry *entry, size_t *namelength, size_t *name_pad)
|
||||
{
|
||||
int64_t t;
|
||||
uint64_t u;
|
||||
const void *h;
|
||||
const char *header;
|
||||
|
||||
@@ -851,12 +853,12 @@ header_afiol(struct archive_read *a, struct cpio *cpio,
|
||||
|
||||
archive_entry_set_dev(entry,
|
||||
(dev_t)atol16(header + afiol_dev_offset, afiol_dev_size));
|
||||
t = atol16(header + afiol_ino_offset, afiol_ino_size);
|
||||
if (t < 0) {
|
||||
archive_set_error(&a->archive, 0, "Nonsensical ino value");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
archive_entry_set_ino(entry, t);
|
||||
u = atol16u(header + afiol_ino_offset, afiol_ino_size);
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
archive_entry_set_ino(entry, (int64_t)(u & INT64_MAX));
|
||||
#else
|
||||
archive_entry_set_ino(entry, u);
|
||||
#endif
|
||||
archive_entry_set_mode(entry,
|
||||
(mode_t)atol8(header + afiol_mode_offset, afiol_mode_size));
|
||||
archive_entry_set_uid(entry, atol16(header + afiol_uid_offset, afiol_uid_size));
|
||||
@@ -1030,6 +1032,12 @@ atol8(const char *p, unsigned char_cnt)
|
||||
|
||||
static int64_t
|
||||
atol16(const char *p, unsigned char_cnt)
|
||||
{
|
||||
return ((int64_t)atol16u(p, char_cnt));
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
atol16u(const char *p, unsigned char_cnt)
|
||||
{
|
||||
uint64_t l;
|
||||
int digit;
|
||||
@@ -1048,7 +1056,7 @@ atol16(const char *p, unsigned char_cnt)
|
||||
l <<= 4;
|
||||
l |= digit;
|
||||
}
|
||||
return ((int64_t)l);
|
||||
return (l);
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
@@ -1429,7 +1429,7 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
|
||||
* information first, then store all file bodies. */
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Ignoring out-of-order file @%jx (%s) %jd < %jd",
|
||||
(intmax_t)file->number,
|
||||
(uintmax_t)file->number,
|
||||
iso9660->pathname.s,
|
||||
(intmax_t)file->offset,
|
||||
(intmax_t)iso9660->current_position);
|
||||
@@ -2273,7 +2273,7 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
|
||||
if (version == 1) {
|
||||
if (data_length >= 8)
|
||||
file->mode
|
||||
= toi(data, 4);
|
||||
= (__LA_MODE_T)toi(data, 4);
|
||||
if (data_length >= 16)
|
||||
file->nlinks
|
||||
= toi(data + 8, 4);
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "archive_entry_locale.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
#include "archive_time_private.h"
|
||||
#include "archive_endian.h"
|
||||
|
||||
|
||||
@@ -162,12 +163,12 @@ struct lha {
|
||||
#define ATIME_IS_SET 2
|
||||
#define UNIX_MODE_IS_SET 4
|
||||
#define CRC_IS_SET 8
|
||||
time_t birthtime;
|
||||
long birthtime_tv_nsec;
|
||||
time_t mtime;
|
||||
long mtime_tv_nsec;
|
||||
time_t atime;
|
||||
long atime_tv_nsec;
|
||||
int64_t birthtime;
|
||||
uint32_t birthtime_tv_nsec;
|
||||
int64_t mtime;
|
||||
uint32_t mtime_tv_nsec;
|
||||
int64_t atime;
|
||||
uint32_t atime_tv_nsec;
|
||||
mode_t mode;
|
||||
int64_t uid;
|
||||
int64_t gid;
|
||||
@@ -230,8 +231,6 @@ static int lha_read_file_extended_header(struct archive_read *,
|
||||
struct lha *, uint16_t *, int, uint64_t, size_t *);
|
||||
static size_t lha_check_header_format(const void *);
|
||||
static int lha_skip_sfx(struct archive_read *);
|
||||
static time_t lha_dos_time(const unsigned char *);
|
||||
static time_t lha_win_time(uint64_t, long *);
|
||||
static unsigned char lha_calcsum(unsigned char, const void *,
|
||||
int, size_t);
|
||||
static int lha_parse_linkname(struct archive_wstring *,
|
||||
@@ -819,7 +818,7 @@ lha_read_file_header_0(struct archive_read *a, struct lha *lha)
|
||||
headersum = p[H0_HEADER_SUM_OFFSET];
|
||||
lha->compsize = archive_le32dec(p + H0_COMP_SIZE_OFFSET);
|
||||
lha->origsize = archive_le32dec(p + H0_ORIG_SIZE_OFFSET);
|
||||
lha->mtime = lha_dos_time(p + H0_DOS_TIME_OFFSET);
|
||||
lha->mtime = dos_to_unix(archive_le32dec(p + H0_DOS_TIME_OFFSET));
|
||||
namelen = p[H0_NAME_LEN_OFFSET];
|
||||
extdsize = (int)lha->header_size - H0_FIXED_SIZE - namelen;
|
||||
if ((namelen > 221 || extdsize < 0) && extdsize != -2) {
|
||||
@@ -919,7 +918,7 @@ lha_read_file_header_1(struct archive_read *a, struct lha *lha)
|
||||
/* Note: An extended header size is included in a compsize. */
|
||||
lha->compsize = archive_le32dec(p + H1_COMP_SIZE_OFFSET);
|
||||
lha->origsize = archive_le32dec(p + H1_ORIG_SIZE_OFFSET);
|
||||
lha->mtime = lha_dos_time(p + H1_DOS_TIME_OFFSET);
|
||||
lha->mtime = dos_to_unix(archive_le32dec(p + H1_DOS_TIME_OFFSET));
|
||||
namelen = p[H1_NAME_LEN_OFFSET];
|
||||
/* Calculate a padding size. The result will be normally 0 only(?) */
|
||||
padding = ((int)lha->header_size) - H1_FIXED_SIZE - namelen;
|
||||
@@ -1090,7 +1089,7 @@ lha_read_file_header_3(struct archive_read *a, struct lha *lha)
|
||||
|
||||
if (archive_le16dec(p + H3_FIELD_LEN_OFFSET) != 4)
|
||||
goto invalid;
|
||||
lha->header_size =archive_le32dec(p + H3_HEADER_SIZE_OFFSET);
|
||||
lha->header_size = archive_le32dec(p + H3_HEADER_SIZE_OFFSET);
|
||||
lha->compsize = archive_le32dec(p + H3_COMP_SIZE_OFFSET);
|
||||
lha->origsize = archive_le32dec(p + H3_ORIG_SIZE_OFFSET);
|
||||
lha->mtime = archive_le32dec(p + H3_TIME_OFFSET);
|
||||
@@ -1326,16 +1325,16 @@ lha_read_file_extended_header(struct archive_read *a, struct lha *lha,
|
||||
break;
|
||||
case EXT_TIMESTAMP:
|
||||
if (datasize == (sizeof(uint64_t) * 3)) {
|
||||
lha->birthtime = lha_win_time(
|
||||
archive_le64dec(extdheader),
|
||||
ntfs_to_unix(archive_le64dec(extdheader),
|
||||
&lha->birthtime,
|
||||
&lha->birthtime_tv_nsec);
|
||||
extdheader += sizeof(uint64_t);
|
||||
lha->mtime = lha_win_time(
|
||||
archive_le64dec(extdheader),
|
||||
ntfs_to_unix(archive_le64dec(extdheader),
|
||||
&lha->mtime,
|
||||
&lha->mtime_tv_nsec);
|
||||
extdheader += sizeof(uint64_t);
|
||||
lha->atime = lha_win_time(
|
||||
archive_le64dec(extdheader),
|
||||
ntfs_to_unix(archive_le64dec(extdheader),
|
||||
&lha->atime,
|
||||
&lha->atime_tv_nsec);
|
||||
lha->setflag |= BIRTHTIME_IS_SET |
|
||||
ATIME_IS_SET;
|
||||
@@ -1716,45 +1715,6 @@ lha_parse_linkname(struct archive_wstring *linkname,
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Convert an MSDOS-style date/time into Unix-style time. */
|
||||
static time_t
|
||||
lha_dos_time(const unsigned char *p)
|
||||
{
|
||||
int msTime, msDate;
|
||||
struct tm ts;
|
||||
|
||||
msTime = archive_le16dec(p);
|
||||
msDate = archive_le16dec(p+2);
|
||||
|
||||
memset(&ts, 0, sizeof(ts));
|
||||
ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */
|
||||
ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */
|
||||
ts.tm_mday = msDate & 0x1f; /* Day of month. */
|
||||
ts.tm_hour = (msTime >> 11) & 0x1f;
|
||||
ts.tm_min = (msTime >> 5) & 0x3f;
|
||||
ts.tm_sec = (msTime << 1) & 0x3e;
|
||||
ts.tm_isdst = -1;
|
||||
return (mktime(&ts));
|
||||
}
|
||||
|
||||
/* Convert an MS-Windows-style date/time into Unix-style time. */
|
||||
static time_t
|
||||
lha_win_time(uint64_t wintime, long *ns)
|
||||
{
|
||||
#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
|
||||
|
||||
if (wintime >= EPOC_TIME) {
|
||||
wintime -= EPOC_TIME; /* 1970-01-01 00:00:00 (UTC) */
|
||||
if (ns != NULL)
|
||||
*ns = (long)(wintime % 10000000) * 100;
|
||||
return (wintime / 10000000);
|
||||
} else {
|
||||
if (ns != NULL)
|
||||
*ns = 0;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned char
|
||||
lha_calcsum(unsigned char sum, const void *pp, int offset, size_t size)
|
||||
{
|
||||
@@ -2917,4 +2877,3 @@ lzh_decode_huffman(struct huffman *hf, unsigned rbits)
|
||||
/* This bit pattern needs to be found out at a huffman tree. */
|
||||
return (lzh_decode_huffman_tree(hf, rbits, c));
|
||||
}
|
||||
|
||||
|
||||
@@ -335,8 +335,8 @@ struct rar
|
||||
int found_first_header;
|
||||
char has_endarc_header;
|
||||
struct data_block_offsets *dbo;
|
||||
unsigned int cursor;
|
||||
unsigned int nodes;
|
||||
size_t cursor;
|
||||
size_t nodes;
|
||||
char filename_must_match;
|
||||
|
||||
/* LZSS members */
|
||||
@@ -451,7 +451,7 @@ static int read_filter(struct archive_read *, int64_t *);
|
||||
static int rar_decode_byte(struct archive_read*, uint8_t *);
|
||||
static int execute_filter(struct archive_read*, struct rar_filter *,
|
||||
struct rar_virtual_machine *, size_t);
|
||||
static int copy_from_lzss_window(struct archive_read *, void *, int64_t, int);
|
||||
static int copy_from_lzss_window(struct archive_read *, uint8_t *, int64_t, int);
|
||||
static inline void vm_write_32(struct rar_virtual_machine*, size_t, uint32_t);
|
||||
static inline uint32_t vm_read_32(struct rar_virtual_machine*, size_t);
|
||||
|
||||
@@ -475,7 +475,7 @@ static inline uint32_t vm_read_32(struct rar_virtual_machine*, size_t);
|
||||
((rar_br_has(br, (n)) || rar_br_fillup(a, br)) || rar_br_has(br, (n)))
|
||||
/* Notify how many bits we consumed. */
|
||||
#define rar_br_consume(br, n) ((br)->cache_avail -= (n))
|
||||
#define rar_br_consume_unalined_bits(br) ((br)->cache_avail &= ~7)
|
||||
#define rar_br_consume_unaligned_bits(br) ((br)->cache_avail &= ~7)
|
||||
|
||||
static const uint32_t cache_masks[] = {
|
||||
0x00000000, 0x00000001, 0x00000003, 0x00000007,
|
||||
@@ -741,11 +741,11 @@ archive_read_support_format_rar(struct archive *_a)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Until enough data has been read, we cannot tell about
|
||||
* any encrypted entries yet.
|
||||
*/
|
||||
rar->has_encrypted_entries = ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
|
||||
/*
|
||||
* Until enough data has been read, we cannot tell about
|
||||
* any encrypted entries yet.
|
||||
*/
|
||||
rar->has_encrypted_entries = ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
|
||||
|
||||
r = __archive_read_register_format(a,
|
||||
rar,
|
||||
@@ -768,21 +768,21 @@ archive_read_support_format_rar(struct archive *_a)
|
||||
static int
|
||||
archive_read_support_format_rar_capabilities(struct archive_read * a)
|
||||
{
|
||||
(void)a; /* UNUSED */
|
||||
return (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA
|
||||
| ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA);
|
||||
(void)a; /* UNUSED */
|
||||
return (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA
|
||||
| ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_rar_has_encrypted_entries(struct archive_read *_a)
|
||||
{
|
||||
if (_a && _a->format) {
|
||||
struct rar * rar = (struct rar *)_a->format->data;
|
||||
if (rar) {
|
||||
return rar->has_encrypted_entries;
|
||||
}
|
||||
}
|
||||
return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
|
||||
if (_a && _a->format) {
|
||||
struct rar * rar = (struct rar *)_a->format->data;
|
||||
if (rar) {
|
||||
return rar->has_encrypted_entries;
|
||||
}
|
||||
}
|
||||
return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
|
||||
}
|
||||
|
||||
|
||||
@@ -793,7 +793,7 @@ archive_read_format_rar_bid(struct archive_read *a, int best_bid)
|
||||
|
||||
/* If there's already a bid > 30, we'll never win. */
|
||||
if (best_bid > 30)
|
||||
return (-1);
|
||||
return (-1);
|
||||
|
||||
if ((p = __archive_read_ahead(a, 7, NULL)) == NULL)
|
||||
return (-1);
|
||||
@@ -865,7 +865,7 @@ skip_sfx(struct archive_read *a)
|
||||
}
|
||||
skip = p - (const char *)h;
|
||||
__archive_read_consume(a, skip);
|
||||
total += skip;
|
||||
total += skip;
|
||||
}
|
||||
fatal:
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
@@ -910,7 +910,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
|
||||
const void *h;
|
||||
const char *p;
|
||||
struct rar *rar;
|
||||
size_t skip;
|
||||
int64_t skip;
|
||||
char head_type;
|
||||
int ret;
|
||||
unsigned flags;
|
||||
@@ -930,7 +930,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
|
||||
* as well.
|
||||
*/
|
||||
if (rar->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
|
||||
rar->has_encrypted_entries = 0;
|
||||
rar->has_encrypted_entries = 0;
|
||||
}
|
||||
|
||||
/* RAR files can be generated without EOF headers, so return ARCHIVE_EOF if
|
||||
@@ -953,8 +953,11 @@ archive_read_format_rar_read_header(struct archive_read *a,
|
||||
{
|
||||
unsigned long crc32_val;
|
||||
|
||||
if ((h = __archive_read_ahead(a, 7, NULL)) == NULL)
|
||||
if ((h = __archive_read_ahead(a, 7, NULL)) == NULL) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Failed to read next header.");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
p = h;
|
||||
|
||||
head_type = p[2];
|
||||
@@ -972,7 +975,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
|
||||
case MAIN_HEAD:
|
||||
rar->main_flags = archive_le16dec(p + 3);
|
||||
skip = archive_le16dec(p + 5);
|
||||
if (skip < 7 + sizeof(rar->reserved1) + sizeof(rar->reserved2)) {
|
||||
if ((size_t)skip < 7 + sizeof(rar->reserved1) + sizeof(rar->reserved2)) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Invalid header size");
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -984,7 +987,8 @@ archive_read_format_rar_read_header(struct archive_read *a,
|
||||
memcpy(rar->reserved2, p + 7 + sizeof(rar->reserved1),
|
||||
sizeof(rar->reserved2));
|
||||
if (rar->main_flags & MHD_ENCRYPTVER) {
|
||||
if (skip < 7 + sizeof(rar->reserved1) + sizeof(rar->reserved2)+1) {
|
||||
if ((size_t)skip <
|
||||
7 + sizeof(rar->reserved1) + sizeof(rar->reserved2) + 1) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Invalid header size");
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -1053,28 +1057,30 @@ archive_read_format_rar_read_header(struct archive_read *a,
|
||||
/* Skim the entire header and compute the CRC. */
|
||||
crc32_val = 0;
|
||||
while (skip > 0) {
|
||||
size_t to_read = skip;
|
||||
if (to_read > 32 * 1024)
|
||||
to_read = 32 * 1024;
|
||||
if ((h = __archive_read_ahead(a, to_read, NULL)) == NULL) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Bad RAR file");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
p = h;
|
||||
crc32_val = crc32(crc32_val, (const unsigned char *)p, (unsigned int)to_read);
|
||||
__archive_read_consume(a, to_read);
|
||||
skip -= to_read;
|
||||
unsigned to_read;
|
||||
if (skip > 32 * 1024)
|
||||
to_read = 32 * 1024;
|
||||
else
|
||||
to_read = (unsigned)skip;
|
||||
if ((h = __archive_read_ahead(a, to_read, NULL)) == NULL) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Bad RAR file");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
p = h;
|
||||
crc32_val = crc32(crc32_val, (const unsigned char *)p, to_read);
|
||||
__archive_read_consume(a, to_read);
|
||||
skip -= to_read;
|
||||
}
|
||||
if ((crc32_val & 0xffff) != crc32_expected) {
|
||||
#ifndef DONT_FAIL_ON_CRC_ERROR
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Header CRC error");
|
||||
return (ARCHIVE_FATAL);
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Header CRC error");
|
||||
return (ARCHIVE_FATAL);
|
||||
#endif
|
||||
}
|
||||
if (head_type == ENDARC_HEAD)
|
||||
return (ARCHIVE_EOF);
|
||||
return (ARCHIVE_EOF);
|
||||
break;
|
||||
|
||||
case NEWSUB_HEAD:
|
||||
@@ -1083,7 +1089,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
|
||||
break;
|
||||
|
||||
default:
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Bad RAR file");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@@ -1098,7 +1104,7 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff,
|
||||
int ret;
|
||||
|
||||
if (rar->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
|
||||
rar->has_encrypted_entries = 0;
|
||||
rar->has_encrypted_entries = 0;
|
||||
}
|
||||
|
||||
if (rar->bytes_unconsumed > 0) {
|
||||
@@ -1186,7 +1192,7 @@ archive_read_format_rar_seek_data(struct archive_read *a, int64_t offset,
|
||||
int whence)
|
||||
{
|
||||
int64_t client_offset, ret;
|
||||
unsigned int i;
|
||||
size_t i;
|
||||
struct rar *rar = (struct rar *)(a->format->data);
|
||||
|
||||
if (rar->compression_method == COMPRESS_METHOD_STORE)
|
||||
@@ -1433,7 +1439,11 @@ read_header(struct archive_read *a, struct archive_entry *entry,
|
||||
}
|
||||
|
||||
if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL)
|
||||
{
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Failed to read full header content.");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
/* File Header CRC check. */
|
||||
crc32_computed = crc32(crc32_computed, h, (unsigned)(header_size - 7));
|
||||
@@ -1460,8 +1470,8 @@ read_header(struct archive_read *a, struct archive_entry *entry,
|
||||
|
||||
if (rar->file_flags & FHD_PASSWORD)
|
||||
{
|
||||
archive_entry_set_is_data_encrypted(entry, 1);
|
||||
rar->has_encrypted_entries = 1;
|
||||
archive_entry_set_is_data_encrypted(entry, 1);
|
||||
rar->has_encrypted_entries = 1;
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"RAR encryption support unavailable.");
|
||||
/* Since it is only the data part itself that is encrypted we can at least
|
||||
@@ -1506,10 +1516,23 @@ read_header(struct archive_read *a, struct archive_entry *entry,
|
||||
*/
|
||||
if (head_type == NEWSUB_HEAD) {
|
||||
size_t distance = p - (const char *)h;
|
||||
if (rar->packed_size > INT64_MAX - header_size) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Extended header size too large.");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
header_size += rar->packed_size;
|
||||
if ((uintmax_t)header_size > SIZE_MAX) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Unable to read extended header data.");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
/* Make sure we have the extended data. */
|
||||
if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Failed to read extended header data.");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
p = h;
|
||||
endp = p + header_size - 7;
|
||||
p += distance;
|
||||
@@ -1670,6 +1693,8 @@ read_header(struct archive_read *a, struct archive_entry *entry,
|
||||
!memcmp(rar->filename, rar->filename_save, filename_size + 1))
|
||||
{
|
||||
__archive_read_consume(a, header_size - 7);
|
||||
rar->br.avail_in = 0;
|
||||
rar->br.next_in = NULL;
|
||||
rar->cursor++;
|
||||
if (rar->cursor >= rar->nodes)
|
||||
{
|
||||
@@ -1689,6 +1714,12 @@ read_header(struct archive_read *a, struct archive_entry *entry,
|
||||
}
|
||||
if (rar->dbo[rar->cursor].start_offset < 0)
|
||||
{
|
||||
if (rar->packed_size > INT64_MAX - a->filter->position)
|
||||
{
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Unable to store offsets.");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
rar->dbo[rar->cursor].start_offset = a->filter->position;
|
||||
rar->dbo[rar->cursor].end_offset = rar->dbo[rar->cursor].start_offset +
|
||||
rar->packed_size;
|
||||
@@ -1745,6 +1776,11 @@ read_header(struct archive_read *a, struct archive_entry *entry,
|
||||
}
|
||||
|
||||
__archive_read_consume(a, header_size - 7);
|
||||
if (rar->packed_size > INT64_MAX - a->filter->position) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Unable to store offsets.");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
rar->dbo[0].start_offset = a->filter->position;
|
||||
rar->dbo[0].end_offset = rar->dbo[0].start_offset + rar->packed_size;
|
||||
|
||||
@@ -1753,7 +1789,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
|
||||
case OS_MSDOS:
|
||||
case OS_OS2:
|
||||
case OS_WIN32:
|
||||
rar->mode = archive_le32dec(file_header.file_attr);
|
||||
rar->mode = (__LA_MODE_T)archive_le32dec(file_header.file_attr);
|
||||
if (rar->mode & FILE_ATTRIBUTE_DIRECTORY)
|
||||
rar->mode = AE_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
|
||||
else
|
||||
@@ -1764,7 +1800,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
|
||||
case OS_UNIX:
|
||||
case OS_MAC_OS:
|
||||
case OS_BEOS:
|
||||
rar->mode = archive_le32dec(file_header.file_attr);
|
||||
rar->mode = (__LA_MODE_T)archive_le32dec(file_header.file_attr);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1780,6 +1816,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
|
||||
rar->offset_outgoing = 0;
|
||||
rar->br.cache_avail = 0;
|
||||
rar->br.avail_in = 0;
|
||||
rar->br.next_in = NULL;
|
||||
rar->crc_calculated = 0;
|
||||
rar->entry_eof = 0;
|
||||
rar->valid = 1;
|
||||
@@ -1941,8 +1978,18 @@ read_symlink_stored(struct archive_read *a, struct archive_entry *entry,
|
||||
int ret = (ARCHIVE_OK);
|
||||
|
||||
rar = (struct rar *)(a->format->data);
|
||||
if ((h = rar_read_ahead(a, (size_t)rar->packed_size, NULL)) == NULL)
|
||||
if ((uintmax_t)rar->packed_size > SIZE_MAX)
|
||||
{
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Unable to read link.");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if ((h = rar_read_ahead(a, (size_t)rar->packed_size, NULL)) == NULL)
|
||||
{
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Failed to read link.");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
p = h;
|
||||
|
||||
if (archive_entry_copy_symlink_l(entry,
|
||||
@@ -2224,7 +2271,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
|
||||
|
||||
ret = expand(a, &end);
|
||||
if (ret != ARCHIVE_OK)
|
||||
return (ret);
|
||||
return (ret);
|
||||
|
||||
rar->bytes_uncopied = end - start;
|
||||
rar->filters.lastend = end;
|
||||
@@ -2276,7 +2323,7 @@ parse_codes(struct archive_read *a)
|
||||
free_codes(a);
|
||||
|
||||
/* Skip to the next byte */
|
||||
rar_br_consume_unalined_bits(br);
|
||||
rar_br_consume_unaligned_bits(br);
|
||||
|
||||
/* PPMd block flag */
|
||||
if (!rar_br_read_ahead(a, br, 1))
|
||||
@@ -2332,9 +2379,9 @@ parse_codes(struct archive_read *a)
|
||||
__archive_ppmd7_functions.Ppmd7_Construct(&rar->ppmd7_context);
|
||||
|
||||
if (rar->dictionary_size == 0) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Invalid zero dictionary size");
|
||||
return (ARCHIVE_FATAL);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
if (!__archive_ppmd7_functions.Ppmd7_Alloc(&rar->ppmd7_context,
|
||||
@@ -2803,7 +2850,7 @@ make_table(struct archive_read *a, struct huffman_code *code)
|
||||
else
|
||||
code->tablesize = code->maxlength;
|
||||
|
||||
code->table = calloc(1U << code->tablesize, sizeof(*code->table));
|
||||
code->table = calloc(((size_t)1U) << code->tablesize, sizeof(*code->table));
|
||||
|
||||
return make_table_recurse(a, code, 0, code->table, 0, code->tablesize);
|
||||
}
|
||||
@@ -2929,11 +2976,11 @@ expand(struct archive_read *a, int64_t *end)
|
||||
}
|
||||
|
||||
if ((symbol = read_next_symbol(a, &rar->maincode)) < 0)
|
||||
return (ARCHIVE_FATAL);
|
||||
goto bad_data;
|
||||
|
||||
if (symbol < 256)
|
||||
{
|
||||
lzss_emit_literal(rar, symbol);
|
||||
lzss_emit_literal(rar, (uint8_t)symbol);
|
||||
continue;
|
||||
}
|
||||
else if (symbol == 256)
|
||||
@@ -2956,14 +3003,14 @@ expand(struct archive_read *a, int64_t *end)
|
||||
else
|
||||
{
|
||||
if (parse_codes(a) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
goto bad_data;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if(symbol==257)
|
||||
{
|
||||
if (!read_filter(a, end))
|
||||
return (ARCHIVE_FATAL);
|
||||
goto bad_data;
|
||||
continue;
|
||||
}
|
||||
else if(symbol==258)
|
||||
@@ -3048,7 +3095,7 @@ expand(struct archive_read *a, int64_t *end)
|
||||
{
|
||||
if ((lowoffsetsymbol =
|
||||
read_next_symbol(a, &rar->lowoffsetcode)) < 0)
|
||||
return (ARCHIVE_FATAL);
|
||||
goto bad_data;
|
||||
if(lowoffsetsymbol == 16)
|
||||
{
|
||||
rar->numlowoffsetrepeats = 15;
|
||||
@@ -3096,7 +3143,7 @@ expand(struct archive_read *a, int64_t *end)
|
||||
}
|
||||
|
||||
static int
|
||||
copy_from_lzss_window(struct archive_read *a, void *buffer,
|
||||
copy_from_lzss_window(struct archive_read *a, uint8_t *buffer,
|
||||
int64_t startpos, int length)
|
||||
{
|
||||
int windowoffs, firstpart;
|
||||
@@ -3111,7 +3158,7 @@ copy_from_lzss_window(struct archive_read *a, void *buffer,
|
||||
}
|
||||
if (firstpart < length) {
|
||||
memcpy(buffer, &rar->lzss.window[windowoffs], firstpart);
|
||||
memcpy(buffer, &rar->lzss.window[0], length - firstpart);
|
||||
memcpy(buffer + firstpart, &rar->lzss.window[0], length - firstpart);
|
||||
} else {
|
||||
memcpy(buffer, &rar->lzss.window[windowoffs], length);
|
||||
}
|
||||
@@ -3180,8 +3227,12 @@ static const void *
|
||||
rar_read_ahead(struct archive_read *a, size_t min, ssize_t *avail)
|
||||
{
|
||||
struct rar *rar = (struct rar *)(a->format->data);
|
||||
const void *h = __archive_read_ahead(a, min, avail);
|
||||
const void *h;
|
||||
int ret;
|
||||
|
||||
again:
|
||||
h = __archive_read_ahead(a, min, avail);
|
||||
|
||||
if (avail)
|
||||
{
|
||||
if (a->archive.read_data_is_posix_read && *avail > (ssize_t)a->archive.read_data_requested)
|
||||
@@ -3203,7 +3254,7 @@ rar_read_ahead(struct archive_read *a, size_t min, ssize_t *avail)
|
||||
rar->filename_must_match = 0;
|
||||
if (ret != (ARCHIVE_OK))
|
||||
return NULL;
|
||||
return rar_read_ahead(a, min, avail);
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
return h;
|
||||
@@ -3266,6 +3317,9 @@ parse_filter(struct archive_read *a, const uint8_t *bytes, uint16_t length, uint
|
||||
else
|
||||
blocklength = prog ? prog->oldfilterlength : 0;
|
||||
|
||||
if (blocklength > rar->dictionary_size)
|
||||
return 0;
|
||||
|
||||
registers[3] = PROGRAM_SYSTEM_GLOBAL_ADDRESS;
|
||||
registers[4] = blocklength;
|
||||
registers[5] = prog ? prog->usagecount : 0;
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include "archive_entry_locale.h"
|
||||
#include "archive_ppmd7_private.h"
|
||||
#include "archive_entry_private.h"
|
||||
#include "archive_time_private.h"
|
||||
|
||||
#ifdef HAVE_BLAKE2_H
|
||||
#include <blake2.h>
|
||||
@@ -100,10 +101,12 @@ struct file_header {
|
||||
uint8_t dir : 1; /* Is this file entry a directory? */
|
||||
|
||||
/* Optional time fields. */
|
||||
uint64_t e_mtime;
|
||||
uint64_t e_ctime;
|
||||
uint64_t e_atime;
|
||||
uint32_t e_unix_ns;
|
||||
int64_t e_mtime;
|
||||
int64_t e_ctime;
|
||||
int64_t e_atime;
|
||||
uint32_t e_mtime_ns;
|
||||
uint32_t e_ctime_ns;
|
||||
uint32_t e_atime_ns;
|
||||
|
||||
/* Optional hash fields. */
|
||||
uint32_t stored_crc32;
|
||||
@@ -691,7 +694,8 @@ static int run_filter(struct archive_read* a, struct filter_info* flt) {
|
||||
default:
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Unsupported filter type: 0x%x", flt->type);
|
||||
"Unsupported filter type: 0x%x",
|
||||
(unsigned int)flt->type);
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
@@ -1100,22 +1104,22 @@ static int read_consume_bits(struct archive_read* a, struct rar5* rar,
|
||||
return ARCHIVE_OK;
|
||||
}
|
||||
|
||||
static int read_u32(struct archive_read* a, uint32_t* pvalue) {
|
||||
static char read_u32(struct archive_read* a, uint32_t* pvalue) {
|
||||
const uint8_t* p;
|
||||
if(!read_ahead(a, 4, &p))
|
||||
return 0;
|
||||
|
||||
*pvalue = archive_le32dec(p);
|
||||
return ARCHIVE_OK == consume(a, 4) ? 1 : 0;
|
||||
return ARCHIVE_OK == consume(a, 4);
|
||||
}
|
||||
|
||||
static int read_u64(struct archive_read* a, uint64_t* pvalue) {
|
||||
static char read_u64(struct archive_read* a, uint64_t* pvalue) {
|
||||
const uint8_t* p;
|
||||
if(!read_ahead(a, 8, &p))
|
||||
return 0;
|
||||
|
||||
*pvalue = archive_le64dec(p);
|
||||
return ARCHIVE_OK == consume(a, 8) ? 1 : 0;
|
||||
return ARCHIVE_OK == consume(a, 8);
|
||||
}
|
||||
|
||||
static int bid_standard(struct archive_read* a) {
|
||||
@@ -1293,21 +1297,15 @@ static int parse_file_extra_hash(struct archive_read* a, struct rar5* rar,
|
||||
*extra_data_size -= hash_size;
|
||||
} else {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Unsupported hash type (0x%x)", (int) hash_type);
|
||||
"Unsupported hash type (0x%jx)", (uintmax_t)hash_type);
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
return ARCHIVE_OK;
|
||||
}
|
||||
|
||||
static uint64_t time_win_to_unix(uint64_t win_time) {
|
||||
const size_t ns_in_sec = 10000000;
|
||||
const uint64_t sec_to_unix = 11644473600LL;
|
||||
return win_time / ns_in_sec - sec_to_unix;
|
||||
}
|
||||
|
||||
static int parse_htime_item(struct archive_read* a, char unix_time,
|
||||
uint64_t* where, int64_t* extra_data_size)
|
||||
int64_t* sec, uint32_t* nsec, int64_t* extra_data_size)
|
||||
{
|
||||
if(unix_time) {
|
||||
uint32_t time_val;
|
||||
@@ -1315,13 +1313,13 @@ static int parse_htime_item(struct archive_read* a, char unix_time,
|
||||
return ARCHIVE_EOF;
|
||||
|
||||
*extra_data_size -= 4;
|
||||
*where = (uint64_t) time_val;
|
||||
*sec = (int64_t) time_val;
|
||||
} else {
|
||||
uint64_t windows_time;
|
||||
if(!read_u64(a, &windows_time))
|
||||
return ARCHIVE_EOF;
|
||||
|
||||
*where = time_win_to_unix(windows_time);
|
||||
ntfs_to_unix(windows_time, sec, nsec);
|
||||
*extra_data_size -= 8;
|
||||
}
|
||||
|
||||
@@ -1385,7 +1383,7 @@ static int parse_file_extra_version(struct archive_read* a,
|
||||
static int parse_file_extra_htime(struct archive_read* a,
|
||||
struct archive_entry* e, struct rar5* rar, int64_t* extra_data_size)
|
||||
{
|
||||
char unix_time = 0;
|
||||
char unix_time, has_unix_ns, has_mtime, has_ctime, has_atime;
|
||||
size_t flags = 0;
|
||||
size_t value_len;
|
||||
|
||||
@@ -1406,32 +1404,62 @@ static int parse_file_extra_htime(struct archive_read* a,
|
||||
}
|
||||
|
||||
unix_time = flags & IS_UNIX;
|
||||
has_unix_ns = unix_time && (flags & HAS_UNIX_NS);
|
||||
has_mtime = flags & HAS_MTIME;
|
||||
has_atime = flags & HAS_ATIME;
|
||||
has_ctime = flags & HAS_CTIME;
|
||||
rar->file.e_atime_ns = rar->file.e_ctime_ns = rar->file.e_mtime_ns = 0;
|
||||
|
||||
if(flags & HAS_MTIME) {
|
||||
if(has_mtime) {
|
||||
parse_htime_item(a, unix_time, &rar->file.e_mtime,
|
||||
extra_data_size);
|
||||
archive_entry_set_mtime(e, rar->file.e_mtime, 0);
|
||||
&rar->file.e_mtime_ns, extra_data_size);
|
||||
}
|
||||
|
||||
if(flags & HAS_CTIME) {
|
||||
if(has_ctime) {
|
||||
parse_htime_item(a, unix_time, &rar->file.e_ctime,
|
||||
extra_data_size);
|
||||
archive_entry_set_ctime(e, rar->file.e_ctime, 0);
|
||||
&rar->file.e_ctime_ns, extra_data_size);
|
||||
}
|
||||
|
||||
if(flags & HAS_ATIME) {
|
||||
if(has_atime) {
|
||||
parse_htime_item(a, unix_time, &rar->file.e_atime,
|
||||
extra_data_size);
|
||||
archive_entry_set_atime(e, rar->file.e_atime, 0);
|
||||
&rar->file.e_atime_ns, extra_data_size);
|
||||
}
|
||||
|
||||
if(flags & HAS_UNIX_NS) {
|
||||
if(!read_u32(a, &rar->file.e_unix_ns))
|
||||
if(has_mtime && has_unix_ns) {
|
||||
if(!read_u32(a, &rar->file.e_mtime_ns))
|
||||
return ARCHIVE_EOF;
|
||||
|
||||
*extra_data_size -= 4;
|
||||
}
|
||||
|
||||
if(has_ctime && has_unix_ns) {
|
||||
if(!read_u32(a, &rar->file.e_ctime_ns))
|
||||
return ARCHIVE_EOF;
|
||||
|
||||
*extra_data_size -= 4;
|
||||
}
|
||||
|
||||
if(has_atime && has_unix_ns) {
|
||||
if(!read_u32(a, &rar->file.e_atime_ns))
|
||||
return ARCHIVE_EOF;
|
||||
|
||||
*extra_data_size -= 4;
|
||||
}
|
||||
|
||||
/* The seconds and nanoseconds are either together, or separated in two
|
||||
* fields so we parse them, then set the archive_entry's times. */
|
||||
if(has_mtime) {
|
||||
archive_entry_set_mtime(e, rar->file.e_mtime, rar->file.e_mtime_ns);
|
||||
}
|
||||
|
||||
if(has_ctime) {
|
||||
archive_entry_set_ctime(e, rar->file.e_ctime, rar->file.e_ctime_ns);
|
||||
}
|
||||
|
||||
if(has_atime) {
|
||||
archive_entry_set_atime(e, rar->file.e_atime, rar->file.e_atime_ns);
|
||||
}
|
||||
|
||||
return ARCHIVE_OK;
|
||||
}
|
||||
|
||||
@@ -1896,7 +1924,8 @@ static int process_head_file(struct archive_read* a, struct rar5* rar,
|
||||
} else {
|
||||
/* Unknown host OS */
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Unsupported Host OS: 0x%x", (int) host_os);
|
||||
"Unsupported Host OS: 0x%jx",
|
||||
(uintmax_t)host_os);
|
||||
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
@@ -2104,8 +2133,8 @@ static int process_head_main(struct archive_read* a, struct rar5* rar,
|
||||
default:
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Unsupported extra type (0x%x)",
|
||||
(int) extra_field_id);
|
||||
"Unsupported extra type (0x%jx)",
|
||||
(uintmax_t)extra_field_id);
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
@@ -3093,7 +3122,7 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
|
||||
* can be stored in the output buffer directly.
|
||||
*
|
||||
* - Code 256 defines a new filter, which is later used to
|
||||
* ransform the data block accordingly to the filter type.
|
||||
* transform the data block accordingly to the filter type.
|
||||
* The data block needs to be fully uncompressed first.
|
||||
*
|
||||
* - Code bigger than 257 and smaller than 262 define
|
||||
@@ -3983,7 +4012,7 @@ static int do_unpack(struct archive_read* a, struct rar5* rar,
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Compression method not supported: 0x%x",
|
||||
rar->cstate.method);
|
||||
(unsigned int)rar->cstate.method);
|
||||
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
@@ -129,7 +129,11 @@ struct tar {
|
||||
int64_t entry_offset;
|
||||
int64_t entry_padding;
|
||||
int64_t entry_bytes_unconsumed;
|
||||
int64_t realsize;
|
||||
int64_t disk_size;
|
||||
int64_t GNU_sparse_realsize;
|
||||
int64_t GNU_sparse_size;
|
||||
int64_t SCHILY_sparse_realsize;
|
||||
int64_t pax_size;
|
||||
struct sparse_block *sparse_list;
|
||||
struct sparse_block *sparse_last;
|
||||
int64_t sparse_offset;
|
||||
@@ -138,6 +142,7 @@ struct tar {
|
||||
int sparse_gnu_minor;
|
||||
char sparse_gnu_attributes_seen;
|
||||
char filetype;
|
||||
char size_fields; /* Bits defined below */
|
||||
|
||||
struct archive_string localname;
|
||||
struct archive_string_conv *opt_sconv;
|
||||
@@ -148,9 +153,15 @@ struct tar {
|
||||
int compat_2x;
|
||||
int process_mac_extensions;
|
||||
int read_concatenated_archives;
|
||||
int realsize_override;
|
||||
};
|
||||
|
||||
/* Track which size fields were present in the headers */
|
||||
#define TAR_SIZE_PAX_SIZE 1
|
||||
#define TAR_SIZE_GNU_SPARSE_REALSIZE 2
|
||||
#define TAR_SIZE_GNU_SPARSE_SIZE 4
|
||||
#define TAR_SIZE_SCHILY_SPARSE_REALSIZE 8
|
||||
|
||||
|
||||
static int archive_block_is_null(const char *p);
|
||||
static char *base64_decode(const char *, size_t, size_t *);
|
||||
static int gnu_add_sparse_entry(struct archive_read *, struct tar *,
|
||||
@@ -158,36 +169,36 @@ static int gnu_add_sparse_entry(struct archive_read *, struct tar *,
|
||||
|
||||
static void gnu_clear_sparse_list(struct tar *);
|
||||
static int gnu_sparse_old_read(struct archive_read *, struct tar *,
|
||||
const struct archive_entry_header_gnutar *header, size_t *);
|
||||
const struct archive_entry_header_gnutar *header, int64_t *);
|
||||
static int gnu_sparse_old_parse(struct archive_read *, struct tar *,
|
||||
const struct gnu_sparse *sparse, int length);
|
||||
static int gnu_sparse_01_parse(struct archive_read *, struct tar *,
|
||||
const char *, size_t);
|
||||
static ssize_t gnu_sparse_10_read(struct archive_read *, struct tar *,
|
||||
size_t *);
|
||||
static int64_t gnu_sparse_10_read(struct archive_read *, struct tar *,
|
||||
int64_t *);
|
||||
static int header_Solaris_ACL(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, const void *, size_t *);
|
||||
struct archive_entry *, const void *, int64_t *);
|
||||
static int header_common(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, const void *);
|
||||
static int header_old_tar(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, const void *);
|
||||
static int header_pax_extension(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, const void *, size_t *);
|
||||
struct archive_entry *, const void *, int64_t *);
|
||||
static int header_pax_global(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, const void *h, size_t *);
|
||||
struct archive_entry *, const void *h, int64_t *);
|
||||
static int header_gnu_longlink(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, const void *h, size_t *);
|
||||
struct archive_entry *, const void *h, int64_t *);
|
||||
static int header_gnu_longname(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, const void *h, size_t *);
|
||||
struct archive_entry *, const void *h, int64_t *);
|
||||
static int is_mac_metadata_entry(struct archive_entry *entry);
|
||||
static int read_mac_metadata_blob(struct archive_read *,
|
||||
struct archive_entry *, size_t *);
|
||||
struct archive_entry *, int64_t *);
|
||||
static int header_volume(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, const void *h, size_t *);
|
||||
struct archive_entry *, const void *h, int64_t *);
|
||||
static int header_ustar(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, const void *h);
|
||||
static int header_gnutar(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, const void *h, size_t *);
|
||||
struct archive_entry *, const void *h, int64_t *);
|
||||
static int archive_read_format_tar_bid(struct archive_read *, int);
|
||||
static int archive_read_format_tar_options(struct archive_read *,
|
||||
const char *, const char *);
|
||||
@@ -200,7 +211,7 @@ static int archive_read_format_tar_read_header(struct archive_read *,
|
||||
static int checksum(struct archive_read *, const void *);
|
||||
static int pax_attribute(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, const char *key, size_t key_length,
|
||||
size_t value_length, size_t *unconsumed);
|
||||
size_t value_length, int64_t *unconsumed);
|
||||
static int pax_attribute_LIBARCHIVE_xattr(struct archive_entry *,
|
||||
const char *, size_t, const char *, size_t);
|
||||
static int pax_attribute_SCHILY_acl(struct archive_read *, struct tar *,
|
||||
@@ -209,20 +220,20 @@ static int pax_attribute_SUN_holesdata(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, const char *, size_t);
|
||||
static void pax_time(const char *, size_t, int64_t *sec, long *nanos);
|
||||
static ssize_t readline(struct archive_read *, struct tar *, const char **,
|
||||
ssize_t limit, size_t *);
|
||||
ssize_t limit, int64_t *);
|
||||
static int read_body_to_string(struct archive_read *, struct tar *,
|
||||
struct archive_string *, const void *h, size_t *);
|
||||
struct archive_string *, const void *h, int64_t *);
|
||||
static int read_bytes_to_string(struct archive_read *,
|
||||
struct archive_string *, size_t, size_t *);
|
||||
struct archive_string *, size_t, int64_t *);
|
||||
static int64_t tar_atol(const char *, size_t);
|
||||
static int64_t tar_atol10(const char *, size_t);
|
||||
static int64_t tar_atol256(const char *, size_t);
|
||||
static int64_t tar_atol8(const char *, size_t);
|
||||
static int tar_read_header(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, size_t *);
|
||||
struct archive_entry *, int64_t *);
|
||||
static int tohex(int c);
|
||||
static char *url_decode(const char *, size_t);
|
||||
static void tar_flush_unconsumed(struct archive_read *, size_t *);
|
||||
static void tar_flush_unconsumed(struct archive_read *, int64_t *);
|
||||
|
||||
/* Sanity limits: These numbers should be low enough to
|
||||
* prevent a maliciously-crafted archive from forcing us to
|
||||
@@ -467,7 +478,7 @@ archive_read_format_tar_options(struct archive_read *a,
|
||||
* anything outstanding since we're going to do read_aheads
|
||||
*/
|
||||
static void
|
||||
tar_flush_unconsumed(struct archive_read *a, size_t *unconsumed)
|
||||
tar_flush_unconsumed(struct archive_read *a, int64_t *unconsumed)
|
||||
{
|
||||
if (*unconsumed) {
|
||||
/*
|
||||
@@ -515,7 +526,8 @@ archive_read_format_tar_read_header(struct archive_read *a,
|
||||
const char *p;
|
||||
const wchar_t *wp;
|
||||
int r;
|
||||
size_t l, unconsumed = 0;
|
||||
size_t l;
|
||||
int64_t unconsumed = 0;
|
||||
|
||||
/* Assign default device/inode values. */
|
||||
archive_entry_set_dev(entry, 1 + default_dev); /* Don't use zero. */
|
||||
@@ -529,8 +541,7 @@ archive_read_format_tar_read_header(struct archive_read *a,
|
||||
tar = (struct tar *)(a->format->data);
|
||||
tar->entry_offset = 0;
|
||||
gnu_clear_sparse_list(tar);
|
||||
tar->realsize = -1; /* Mark this as "unset" */
|
||||
tar->realsize_override = 0;
|
||||
tar->size_fields = 0; /* We don't have any size info yet */
|
||||
|
||||
/* Setup default string conversion. */
|
||||
tar->sconv = tar->opt_sconv;
|
||||
@@ -617,12 +628,15 @@ archive_read_format_tar_read_data(struct archive_read *a,
|
||||
/* If we're at end of file, return EOF. */
|
||||
if (tar->sparse_list == NULL ||
|
||||
tar->entry_bytes_remaining == 0) {
|
||||
if (__archive_read_consume(a, tar->entry_padding) < 0)
|
||||
int64_t request = tar->entry_bytes_remaining +
|
||||
tar->entry_padding;
|
||||
|
||||
if (__archive_read_consume(a, request) != request)
|
||||
return (ARCHIVE_FATAL);
|
||||
tar->entry_padding = 0;
|
||||
*buff = NULL;
|
||||
*size = 0;
|
||||
*offset = tar->realsize;
|
||||
*offset = tar->disk_size;
|
||||
return (ARCHIVE_EOF);
|
||||
}
|
||||
|
||||
@@ -655,29 +669,15 @@ archive_read_format_tar_read_data(struct archive_read *a,
|
||||
static int
|
||||
archive_read_format_tar_skip(struct archive_read *a)
|
||||
{
|
||||
int64_t bytes_skipped;
|
||||
int64_t request;
|
||||
struct sparse_block *p;
|
||||
struct tar* tar;
|
||||
|
||||
tar = (struct tar *)(a->format->data);
|
||||
|
||||
/* Do not consume the hole of a sparse file. */
|
||||
request = 0;
|
||||
for (p = tar->sparse_list; p != NULL; p = p->next) {
|
||||
if (!p->hole) {
|
||||
if (p->remaining >= INT64_MAX - request) {
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
request += p->remaining;
|
||||
}
|
||||
}
|
||||
if (request > tar->entry_bytes_remaining)
|
||||
request = tar->entry_bytes_remaining;
|
||||
request += tar->entry_padding + tar->entry_bytes_unconsumed;
|
||||
request = tar->entry_bytes_remaining + tar->entry_padding +
|
||||
tar->entry_bytes_unconsumed;
|
||||
|
||||
bytes_skipped = __archive_read_consume(a, request);
|
||||
if (bytes_skipped < 0)
|
||||
if (__archive_read_consume(a, request) != request)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
tar->entry_bytes_remaining = 0;
|
||||
@@ -690,13 +690,29 @@ archive_read_format_tar_skip(struct archive_read *a)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function resets the accumulated state while reading
|
||||
* a header.
|
||||
*/
|
||||
static void
|
||||
tar_reset_header_state(struct tar *tar)
|
||||
{
|
||||
tar->pax_hdrcharset_utf8 = 1;
|
||||
tar->sparse_gnu_attributes_seen = 0;
|
||||
archive_string_empty(&(tar->entry_gname));
|
||||
archive_string_empty(&(tar->entry_pathname));
|
||||
archive_string_empty(&(tar->entry_pathname_override));
|
||||
archive_string_empty(&(tar->entry_uname));
|
||||
archive_string_empty(&tar->entry_linkpath);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function reads and interprets all of the headers associated
|
||||
* with a single entry.
|
||||
*/
|
||||
static int
|
||||
tar_read_header(struct archive_read *a, struct tar *tar,
|
||||
struct archive_entry *entry, size_t *unconsumed)
|
||||
struct archive_entry *entry, int64_t *unconsumed)
|
||||
{
|
||||
ssize_t bytes;
|
||||
int err = ARCHIVE_OK, err2;
|
||||
@@ -715,13 +731,7 @@ tar_read_header(struct archive_read *a, struct tar *tar,
|
||||
static const int32_t seen_x_header = 32; /* Also X */
|
||||
static const int32_t seen_mac_metadata = 512;
|
||||
|
||||
tar->pax_hdrcharset_utf8 = 1;
|
||||
tar->sparse_gnu_attributes_seen = 0;
|
||||
archive_string_empty(&(tar->entry_gname));
|
||||
archive_string_empty(&(tar->entry_pathname));
|
||||
archive_string_empty(&(tar->entry_pathname_override));
|
||||
archive_string_empty(&(tar->entry_uname));
|
||||
archive_string_empty(&tar->entry_linkpath);
|
||||
tar_reset_header_state(tar);
|
||||
|
||||
/* Ensure format is set. */
|
||||
if (a->archive.archive_format_name == NULL) {
|
||||
@@ -750,7 +760,7 @@ tar_read_header(struct archive_read *a, struct tar *tar,
|
||||
* if there's no regular header, then this is
|
||||
* a premature EOF. */
|
||||
archive_set_error(&a->archive, EINVAL,
|
||||
"Damaged tar archive");
|
||||
"Damaged tar archive (end-of-archive within a sequence of headers)");
|
||||
return (ARCHIVE_FATAL);
|
||||
} else {
|
||||
return (ARCHIVE_EOF);
|
||||
@@ -760,7 +770,7 @@ tar_read_header(struct archive_read *a, struct tar *tar,
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Truncated tar archive"
|
||||
" detected while reading next heaader");
|
||||
" detected while reading next header");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
*unconsumed += 512;
|
||||
@@ -787,7 +797,8 @@ tar_read_header(struct archive_read *a, struct tar *tar,
|
||||
/* This is NOT a null block, so it must be a valid header. */
|
||||
if (!checksum(a, h)) {
|
||||
tar_flush_unconsumed(a, unconsumed);
|
||||
archive_set_error(&a->archive, EINVAL, "Damaged tar archive");
|
||||
archive_set_error(&a->archive, EINVAL,
|
||||
"Damaged tar archive (bad header checksum)");
|
||||
/* If we've read some critical information (pax headers, etc)
|
||||
* and _then_ see a bad header, we can't really recover. */
|
||||
if (eof_fatal) {
|
||||
@@ -804,6 +815,8 @@ tar_read_header(struct archive_read *a, struct tar *tar,
|
||||
switch(header->typeflag[0]) {
|
||||
case 'A': /* Solaris tar ACL */
|
||||
if (seen_headers & seen_A_header) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Redundant 'A' header");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
seen_headers |= seen_A_header;
|
||||
@@ -813,6 +826,8 @@ tar_read_header(struct archive_read *a, struct tar *tar,
|
||||
break;
|
||||
case 'g': /* POSIX-standard 'g' header. */
|
||||
if (seen_headers & seen_g_header) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Redundant 'g' header");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
seen_headers |= seen_g_header;
|
||||
@@ -822,27 +837,41 @@ tar_read_header(struct archive_read *a, struct tar *tar,
|
||||
break;
|
||||
case 'K': /* Long link name (GNU tar, others) */
|
||||
if (seen_headers & seen_K_header) {
|
||||
return (ARCHIVE_FATAL);
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Damaged archive: Redundant 'K' headers may cause linknames to be incorrect");
|
||||
err = err_combine(err, ARCHIVE_WARN);
|
||||
}
|
||||
seen_headers |= seen_K_header;
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_TAR_GNUTAR;
|
||||
a->archive.archive_format_name = "GNU tar format";
|
||||
err2 = header_gnu_longlink(a, tar, entry, h, unconsumed);
|
||||
break;
|
||||
case 'L': /* Long filename (GNU tar, others) */
|
||||
if (seen_headers & seen_L_header) {
|
||||
return (ARCHIVE_FATAL);
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Damaged archive: Redundant 'L' headers may cause filenames to be incorrect");
|
||||
err = err_combine(err, ARCHIVE_WARN);
|
||||
}
|
||||
seen_headers |= seen_L_header;
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_TAR_GNUTAR;
|
||||
a->archive.archive_format_name = "GNU tar format";
|
||||
err2 = header_gnu_longname(a, tar, entry, h, unconsumed);
|
||||
break;
|
||||
case 'V': /* GNU volume header */
|
||||
if (seen_headers & seen_V_header) {
|
||||
return (ARCHIVE_FATAL);
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Redundant 'V' header");
|
||||
err = err_combine(err, ARCHIVE_WARN);
|
||||
}
|
||||
seen_headers |= seen_V_header;
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_TAR_GNUTAR;
|
||||
a->archive.archive_format_name = "GNU tar format";
|
||||
err2 = header_volume(a, tar, entry, h, unconsumed);
|
||||
break;
|
||||
case 'X': /* Used by SUN tar; same as 'x'. */
|
||||
if (seen_headers & seen_x_header) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Redundant 'X'/'x' header");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
seen_headers |= seen_x_header;
|
||||
@@ -853,6 +882,8 @@ tar_read_header(struct archive_read *a, struct tar *tar,
|
||||
break;
|
||||
case 'x': /* POSIX-standard 'x' header. */
|
||||
if (seen_headers & seen_x_header) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Redundant 'x' header");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
seen_headers |= seen_x_header;
|
||||
@@ -904,6 +935,7 @@ tar_read_header(struct archive_read *a, struct tar *tar,
|
||||
err = err_combine(err, err2);
|
||||
/* Note: Other headers can appear again. */
|
||||
seen_headers = seen_mac_metadata;
|
||||
tar_reset_header_state(tar);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1032,13 +1064,13 @@ archive_block_is_null(const char *p)
|
||||
*/
|
||||
static int
|
||||
header_Solaris_ACL(struct archive_read *a, struct tar *tar,
|
||||
struct archive_entry *entry, const void *h, size_t *unconsumed)
|
||||
struct archive_entry *entry, const void *h, int64_t *unconsumed)
|
||||
{
|
||||
const struct archive_entry_header_ustar *header;
|
||||
struct archive_string acl_text;
|
||||
size_t size;
|
||||
int err, acl_type;
|
||||
int64_t type;
|
||||
uint64_t type;
|
||||
char *acl, *p;
|
||||
|
||||
header = (const struct archive_entry_header_ustar *)h;
|
||||
@@ -1075,7 +1107,7 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar,
|
||||
}
|
||||
p++;
|
||||
}
|
||||
switch ((int)type & ~0777777) {
|
||||
switch (type & ~0777777) {
|
||||
case 01000000:
|
||||
/* POSIX.1e ACL */
|
||||
acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
|
||||
@@ -1086,8 +1118,8 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar,
|
||||
break;
|
||||
default:
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Malformed Solaris ACL attribute (unsupported type %o)",
|
||||
(int)type);
|
||||
"Malformed Solaris ACL attribute (unsupported type %llu)",
|
||||
(unsigned long long)type);
|
||||
archive_string_free(&acl_text);
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
@@ -1138,14 +1170,16 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar,
|
||||
*/
|
||||
static int
|
||||
header_gnu_longlink(struct archive_read *a, struct tar *tar,
|
||||
struct archive_entry *entry, const void *h, size_t *unconsumed)
|
||||
struct archive_entry *entry, const void *h, int64_t *unconsumed)
|
||||
{
|
||||
int err;
|
||||
|
||||
struct archive_string linkpath;
|
||||
archive_string_init(&linkpath);
|
||||
err = read_body_to_string(a, tar, &linkpath, h, unconsumed);
|
||||
archive_entry_set_link(entry, linkpath.s);
|
||||
if (err == ARCHIVE_OK) {
|
||||
archive_entry_set_link(entry, linkpath.s);
|
||||
}
|
||||
archive_string_free(&linkpath);
|
||||
return (err);
|
||||
}
|
||||
@@ -1170,7 +1204,7 @@ set_conversion_failed_error(struct archive_read *a,
|
||||
*/
|
||||
static int
|
||||
header_gnu_longname(struct archive_read *a, struct tar *tar,
|
||||
struct archive_entry *entry, const void *h, size_t *unconsumed)
|
||||
struct archive_entry *entry, const void *h, int64_t *unconsumed)
|
||||
{
|
||||
int err;
|
||||
struct archive_string longname;
|
||||
@@ -1191,7 +1225,7 @@ header_gnu_longname(struct archive_read *a, struct tar *tar,
|
||||
*/
|
||||
static int
|
||||
header_volume(struct archive_read *a, struct tar *tar,
|
||||
struct archive_entry *entry, const void *h, size_t *unconsumed)
|
||||
struct archive_entry *entry, const void *h, int64_t *unconsumed)
|
||||
{
|
||||
const struct archive_entry_header_ustar *header;
|
||||
int64_t size, to_consume;
|
||||
@@ -1217,7 +1251,7 @@ header_volume(struct archive_read *a, struct tar *tar,
|
||||
static int
|
||||
read_bytes_to_string(struct archive_read *a,
|
||||
struct archive_string *as, size_t size,
|
||||
size_t *unconsumed) {
|
||||
int64_t *unconsumed) {
|
||||
const void *src;
|
||||
|
||||
/* Fail if we can't make our buffer big enough. */
|
||||
@@ -1250,7 +1284,7 @@ read_bytes_to_string(struct archive_read *a,
|
||||
*/
|
||||
static int
|
||||
read_body_to_string(struct archive_read *a, struct tar *tar,
|
||||
struct archive_string *as, const void *h, size_t *unconsumed)
|
||||
struct archive_string *as, const void *h, int64_t *unconsumed)
|
||||
{
|
||||
int64_t size;
|
||||
const struct archive_entry_header_ustar *header;
|
||||
@@ -1259,18 +1293,21 @@ read_body_to_string(struct archive_read *a, struct tar *tar,
|
||||
(void)tar; /* UNUSED */
|
||||
header = (const struct archive_entry_header_ustar *)h;
|
||||
size = tar_atol(header->size, sizeof(header->size));
|
||||
if (size > entry_limit) {
|
||||
if (size < 0 || size > entry_limit) {
|
||||
archive_set_error(&a->archive, EINVAL,
|
||||
"Special header has invalid size: %lld",
|
||||
(long long)size);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if ((size > (int64_t)pathname_limit) || (size < 0)) {
|
||||
if (size > (int64_t)pathname_limit) {
|
||||
archive_string_empty(as);
|
||||
int64_t to_consume = ((size + 511) & ~511);
|
||||
if (to_consume != __archive_read_consume(a, to_consume)) {
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
archive_set_error(&a->archive, EINVAL,
|
||||
"Special header too large: %d > 1MiB",
|
||||
(int)size);
|
||||
"Special header too large: %lld > 1MiB",
|
||||
(long long)size);
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
r = read_bytes_to_string(a, as, size, unconsumed);
|
||||
@@ -1287,6 +1324,11 @@ read_body_to_string(struct archive_read *a, struct tar *tar,
|
||||
* allows header_old_tar and header_ustar
|
||||
* to handle filenames differently, while still putting most of the
|
||||
* common parsing into one place.
|
||||
*
|
||||
* This is called _after_ ustar, GNU tar, Schily, etc, special
|
||||
* fields have already been parsed into the `tar` structure.
|
||||
* So we can make final decisions here about how to reconcile
|
||||
* size, mode, etc, information.
|
||||
*/
|
||||
static int
|
||||
header_common(struct archive_read *a, struct tar *tar,
|
||||
@@ -1308,34 +1350,73 @@ header_common(struct archive_read *a, struct tar *tar,
|
||||
archive_entry_set_perm(entry,
|
||||
(mode_t)tar_atol(header->mode, sizeof(header->mode)));
|
||||
}
|
||||
|
||||
/* Set uid, gid, mtime if not already set */
|
||||
if (!archive_entry_uid_is_set(entry)) {
|
||||
archive_entry_set_uid(entry, tar_atol(header->uid, sizeof(header->uid)));
|
||||
}
|
||||
if (!archive_entry_gid_is_set(entry)) {
|
||||
archive_entry_set_gid(entry, tar_atol(header->gid, sizeof(header->gid)));
|
||||
}
|
||||
if (!archive_entry_mtime_is_set(entry)) {
|
||||
archive_entry_set_mtime(entry, tar_atol(header->mtime, sizeof(header->mtime)), 0);
|
||||
}
|
||||
|
||||
tar->entry_bytes_remaining = tar_atol(header->size, sizeof(header->size));
|
||||
/* Reconcile the size info. */
|
||||
/* First, how big is the file on disk? */
|
||||
if ((tar->size_fields & TAR_SIZE_GNU_SPARSE_REALSIZE) != 0) {
|
||||
/* GNU sparse format 1.0 uses `GNU.sparse.realsize`
|
||||
* to hold the size of the file on disk. */
|
||||
tar->disk_size = tar->GNU_sparse_realsize;
|
||||
} else if ((tar->size_fields & TAR_SIZE_GNU_SPARSE_SIZE) != 0
|
||||
&& (tar->sparse_gnu_major == 0)) {
|
||||
/* GNU sparse format 0.0 and 0.1 use `GNU.sparse.size`
|
||||
* to hold the size of the file on disk. */
|
||||
tar->disk_size = tar->GNU_sparse_size;
|
||||
} else if ((tar->size_fields & TAR_SIZE_SCHILY_SPARSE_REALSIZE) != 0) {
|
||||
tar->disk_size = tar->SCHILY_sparse_realsize;
|
||||
} else if ((tar->size_fields & TAR_SIZE_PAX_SIZE) != 0) {
|
||||
tar->disk_size = tar->pax_size;
|
||||
} else {
|
||||
/* There wasn't a suitable pax header, so use the ustar info */
|
||||
tar->disk_size = tar_atol(header->size, sizeof(header->size));
|
||||
}
|
||||
|
||||
if (tar->disk_size < 0) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Tar entry has negative file size");
|
||||
return (ARCHIVE_FATAL);
|
||||
} else if (tar->disk_size > entry_limit) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Tar entry size overflow");
|
||||
return (ARCHIVE_FATAL);
|
||||
} else {
|
||||
archive_entry_set_size(entry, tar->disk_size);
|
||||
}
|
||||
|
||||
/* Second, how big is the data in the archive? */
|
||||
if ((tar->size_fields & TAR_SIZE_GNU_SPARSE_SIZE) != 0
|
||||
&& (tar->sparse_gnu_major == 1)) {
|
||||
/* GNU sparse format 1.0 uses `GNU.sparse.size`
|
||||
* to hold the size of the data in the archive. */
|
||||
tar->entry_bytes_remaining = tar->GNU_sparse_size;
|
||||
} else if ((tar->size_fields & TAR_SIZE_PAX_SIZE) != 0) {
|
||||
tar->entry_bytes_remaining = tar->pax_size;
|
||||
} else {
|
||||
tar->entry_bytes_remaining
|
||||
= tar_atol(header->size, sizeof(header->size));
|
||||
}
|
||||
if (tar->entry_bytes_remaining < 0) {
|
||||
tar->entry_bytes_remaining = 0;
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Tar entry has negative size");
|
||||
"Tar entry has negative size");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (tar->entry_bytes_remaining > entry_limit) {
|
||||
} else if (tar->entry_bytes_remaining > entry_limit) {
|
||||
tar->entry_bytes_remaining = 0;
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Tar entry size overflow");
|
||||
"Tar entry size overflow");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (!tar->realsize_override) {
|
||||
tar->realsize = tar->entry_bytes_remaining;
|
||||
}
|
||||
archive_entry_set_size(entry, tar->realsize);
|
||||
|
||||
if (!archive_entry_mtime_is_set(entry)) {
|
||||
archive_entry_set_mtime(entry, tar_atol(header->mtime, sizeof(header->mtime)), 0);
|
||||
}
|
||||
|
||||
/* Handle the tar type flag appropriately. */
|
||||
tar->filetype = header->typeflag[0];
|
||||
@@ -1597,7 +1678,7 @@ is_mac_metadata_entry(struct archive_entry *entry) {
|
||||
*/
|
||||
static int
|
||||
read_mac_metadata_blob(struct archive_read *a,
|
||||
struct archive_entry *entry, size_t *unconsumed)
|
||||
struct archive_entry *entry, int64_t *unconsumed)
|
||||
{
|
||||
int64_t size;
|
||||
size_t msize;
|
||||
@@ -1654,7 +1735,7 @@ read_mac_metadata_blob(struct archive_read *a,
|
||||
*/
|
||||
static int
|
||||
header_pax_global(struct archive_read *a, struct tar *tar,
|
||||
struct archive_entry *entry, const void *h, size_t *unconsumed)
|
||||
struct archive_entry *entry, const void *h, int64_t *unconsumed)
|
||||
{
|
||||
const struct archive_entry_header_ustar *header;
|
||||
int64_t size, to_consume;
|
||||
@@ -1665,7 +1746,10 @@ header_pax_global(struct archive_read *a, struct tar *tar,
|
||||
|
||||
header = (const struct archive_entry_header_ustar *)h;
|
||||
size = tar_atol(header->size, sizeof(header->size));
|
||||
if (size > entry_limit) {
|
||||
if (size < 0 || size > entry_limit) {
|
||||
archive_set_error(&a->archive, EINVAL,
|
||||
"Special header has invalid size: %lld",
|
||||
(long long)size);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
to_consume = ((size + 511) & ~511);
|
||||
@@ -1761,7 +1845,7 @@ header_ustar(struct archive_read *a, struct tar *tar,
|
||||
|
||||
static int
|
||||
header_pax_extension(struct archive_read *a, struct tar *tar,
|
||||
struct archive_entry *entry, const void *h, size_t *unconsumed)
|
||||
struct archive_entry *entry, const void *h, int64_t *unconsumed)
|
||||
{
|
||||
/* Sanity checks: The largest `x` body I've ever heard of was
|
||||
* a little over 4MB. So I doubt there has ever been a
|
||||
@@ -1812,8 +1896,8 @@ header_pax_extension(struct archive_read *a, struct tar *tar,
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
archive_set_error(&a->archive, EINVAL,
|
||||
"Ignoring oversized pax extensions: %d > %d",
|
||||
(int)ext_size, (int)ext_size_limit);
|
||||
"Ignoring oversized pax extensions: %lld > %lld",
|
||||
(long long)ext_size, (long long)ext_size_limit);
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
tar_flush_unconsumed(a, unconsumed);
|
||||
@@ -1912,6 +1996,13 @@ header_pax_extension(struct archive_read *a, struct tar *tar,
|
||||
*unconsumed += p - attr_start;
|
||||
tar_flush_unconsumed(a, unconsumed);
|
||||
|
||||
if (value_length == 0) {
|
||||
archive_set_error(&a->archive, EINVAL,
|
||||
"Malformed pax attributes");
|
||||
*unconsumed += ext_size + ext_padding;
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
/* pax_attribute will consume value_length - 1 */
|
||||
r = pax_attribute(a, tar, entry, attr_name.s, archive_strlen(&attr_name), value_length - 1, unconsumed);
|
||||
ext_size -= value_length - 1;
|
||||
@@ -2121,8 +2212,9 @@ pax_attribute_SCHILY_acl(struct archive_read *a, struct tar *tar,
|
||||
if (value_length > acl_limit) {
|
||||
__archive_read_consume(a, value_length);
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Unreasonably large ACL: %d > %d",
|
||||
(int)value_length, (int)acl_limit);
|
||||
"Unreasonably large ACL: %llu > %llu",
|
||||
(unsigned long long)value_length,
|
||||
(unsigned long long)acl_limit);
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
@@ -2154,7 +2246,7 @@ pax_attribute_SCHILY_acl(struct archive_read *a, struct tar *tar,
|
||||
}
|
||||
|
||||
static int
|
||||
pax_attribute_read_time(struct archive_read *a, size_t value_length, int64_t *ps, long *pn, size_t *unconsumed) {
|
||||
pax_attribute_read_time(struct archive_read *a, size_t value_length, int64_t *ps, long *pn, int64_t *unconsumed) {
|
||||
struct archive_string as;
|
||||
int r;
|
||||
|
||||
@@ -2169,12 +2261,16 @@ pax_attribute_read_time(struct archive_read *a, size_t value_length, int64_t *ps
|
||||
r = read_bytes_to_string(a, &as, value_length, unconsumed);
|
||||
if (r < ARCHIVE_OK) {
|
||||
archive_string_free(&as);
|
||||
*ps = 0;
|
||||
*pn = 0;
|
||||
return (r);
|
||||
}
|
||||
|
||||
pax_time(as.s, archive_strlen(&as), ps, pn);
|
||||
archive_string_free(&as);
|
||||
if (*ps < 0 || *ps == INT64_MAX) {
|
||||
if (*ps == INT64_MIN) {
|
||||
*ps = 0;
|
||||
*pn = 0;
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
@@ -2183,7 +2279,7 @@ pax_attribute_read_time(struct archive_read *a, size_t value_length, int64_t *ps
|
||||
static int
|
||||
pax_attribute_read_number(struct archive_read *a, size_t value_length, int64_t *result) {
|
||||
struct archive_string as;
|
||||
size_t unconsumed = 0;
|
||||
int64_t unconsumed = 0;
|
||||
int r;
|
||||
|
||||
if (value_length > 64) {
|
||||
@@ -2197,6 +2293,7 @@ pax_attribute_read_number(struct archive_read *a, size_t value_length, int64_t *
|
||||
tar_flush_unconsumed(a, &unconsumed);
|
||||
if (r < ARCHIVE_OK) {
|
||||
archive_string_free(&as);
|
||||
*result = 0;
|
||||
return (r);
|
||||
}
|
||||
|
||||
@@ -2223,7 +2320,7 @@ pax_attribute_read_number(struct archive_read *a, size_t value_length, int64_t *
|
||||
*/
|
||||
static int
|
||||
pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *entry,
|
||||
const char *key, size_t key_length, size_t value_length, size_t *unconsumed)
|
||||
const char *key, size_t key_length, size_t value_length, int64_t *unconsumed)
|
||||
{
|
||||
int64_t t;
|
||||
long n;
|
||||
@@ -2289,10 +2386,13 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
|
||||
}
|
||||
else if (key_length == 4 && memcmp(key, "size", 4) == 0) {
|
||||
/* GNU.sparse.size */
|
||||
/* This is either the size of stored entry OR the size of data on disk,
|
||||
* depending on which GNU sparse format version is in use.
|
||||
* Since pax attributes can be in any order, we may not actually
|
||||
* know at this point how to interpret this. */
|
||||
if ((err = pax_attribute_read_number(a, value_length, &t)) == ARCHIVE_OK) {
|
||||
tar->realsize = t;
|
||||
archive_entry_set_size(entry, tar->realsize);
|
||||
tar->realsize_override = 1;
|
||||
tar->GNU_sparse_size = t;
|
||||
tar->size_fields |= TAR_SIZE_GNU_SPARSE_SIZE;
|
||||
}
|
||||
return (err);
|
||||
}
|
||||
@@ -2304,8 +2404,9 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
|
||||
tar->sparse_gnu_minor = 1;
|
||||
if (value_length > sparse_map_limit) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Unreasonably large sparse map: %d > %d",
|
||||
(int)value_length, (int)sparse_map_limit);
|
||||
"Unreasonably large sparse map: %llu > %llu",
|
||||
(unsigned long long)value_length,
|
||||
(unsigned long long)sparse_map_limit);
|
||||
err = ARCHIVE_FAILED;
|
||||
} else {
|
||||
p = __archive_read_ahead(a, value_length, &bytes_read);
|
||||
@@ -2360,11 +2461,10 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
|
||||
return (err);
|
||||
}
|
||||
else if (key_length == 8 && memcmp(key, "realsize", 8) == 0) {
|
||||
/* GNU.sparse.realsize */
|
||||
/* GNU.sparse.realsize = size of file on disk */
|
||||
if ((err = pax_attribute_read_number(a, value_length, &t)) == ARCHIVE_OK) {
|
||||
tar->realsize = t;
|
||||
archive_entry_set_size(entry, tar->realsize);
|
||||
tar->realsize_override = 1;
|
||||
tar->GNU_sparse_realsize = t;
|
||||
tar->size_fields |= TAR_SIZE_GNU_SPARSE_REALSIZE;
|
||||
}
|
||||
return (err);
|
||||
}
|
||||
@@ -2413,8 +2513,8 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
|
||||
} else {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"symlink type is very long"
|
||||
"(longest recognized value is 4 bytes, this is %d)",
|
||||
(int)value_length);
|
||||
"(longest recognized value is 4 bytes, this is %llu)",
|
||||
(unsigned long long)value_length);
|
||||
err = ARCHIVE_WARN;
|
||||
}
|
||||
__archive_read_consume(a, value_length);
|
||||
@@ -2450,8 +2550,9 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
|
||||
if (value_length > xattr_limit) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Ignoring unreasonably large security.selinux attribute:"
|
||||
" %d > %d",
|
||||
(int)value_length, (int)xattr_limit);
|
||||
" %llu > %llu",
|
||||
(unsigned long long)value_length,
|
||||
(unsigned long long)xattr_limit);
|
||||
/* TODO: Should this be FAILED instead? */
|
||||
err = ARCHIVE_WARN;
|
||||
} else {
|
||||
@@ -2545,12 +2646,12 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
|
||||
}
|
||||
else if (key_length == 8 && memcmp(key, "realsize", 8) == 0) {
|
||||
if ((err = pax_attribute_read_number(a, value_length, &t)) == ARCHIVE_OK) {
|
||||
tar->realsize = t;
|
||||
tar->realsize_override = 1;
|
||||
archive_entry_set_size(entry, tar->realsize);
|
||||
tar->SCHILY_sparse_realsize = t;
|
||||
tar->size_fields |= TAR_SIZE_SCHILY_SPARSE_REALSIZE;
|
||||
}
|
||||
return (err);
|
||||
}
|
||||
/* TODO: Is there a SCHILY.sparse.size similar to GNU.sparse.size ? */
|
||||
else if (key_length > 6 && memcmp(key, "xattr.", 6) == 0) {
|
||||
key_length -= 6;
|
||||
key += 6;
|
||||
@@ -2568,8 +2669,9 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
|
||||
}
|
||||
} else {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Unreasonably large xattr: %d > %d",
|
||||
(int)value_length, (int)xattr_limit);
|
||||
"Unreasonably large xattr: %llu > %llu",
|
||||
(unsigned long long)value_length,
|
||||
(unsigned long long)xattr_limit);
|
||||
err = ARCHIVE_WARN;
|
||||
}
|
||||
__archive_read_consume(a, value_length);
|
||||
@@ -2599,8 +2701,9 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
|
||||
}
|
||||
} else {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Unreasonably large sparse map: %d > %d",
|
||||
(int)value_length, (int)sparse_map_limit);
|
||||
"Unreasonably large sparse map: %llu > %llu",
|
||||
(unsigned long long)value_length,
|
||||
(unsigned long long)sparse_map_limit);
|
||||
err = ARCHIVE_FAILED;
|
||||
}
|
||||
__archive_read_consume(a, value_length);
|
||||
@@ -2669,8 +2772,8 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
|
||||
}
|
||||
} else {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"hdrcharset attribute is unreasonably large (%d bytes)",
|
||||
(int)value_length);
|
||||
"hdrcharset attribute is unreasonably large (%llu bytes)",
|
||||
(unsigned long long)value_length);
|
||||
err = ARCHIVE_WARN;
|
||||
}
|
||||
__archive_read_consume(a, value_length);
|
||||
@@ -2717,19 +2820,8 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
|
||||
if (key_length == 4 && memcmp(key, "size", 4) == 0) {
|
||||
/* "size" is the size of the data in the entry. */
|
||||
if ((err = pax_attribute_read_number(a, value_length, &t)) == ARCHIVE_OK) {
|
||||
tar->entry_bytes_remaining = t;
|
||||
/*
|
||||
* The "size" pax header keyword always overrides the
|
||||
* "size" field in the tar header.
|
||||
* GNU.sparse.realsize, GNU.sparse.size and
|
||||
* SCHILY.realsize override this value.
|
||||
*/
|
||||
if (!tar->realsize_override) {
|
||||
archive_entry_set_size(entry,
|
||||
tar->entry_bytes_remaining);
|
||||
tar->realsize
|
||||
= tar->entry_bytes_remaining;
|
||||
}
|
||||
tar->pax_size = t;
|
||||
tar->size_fields |= TAR_SIZE_PAX_SIZE;
|
||||
}
|
||||
else if (t == INT64_MAX) {
|
||||
/* Note: pax_attr_read_number returns INT64_MAX on overflow or < 0 */
|
||||
@@ -2768,7 +2860,9 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
|
||||
|
||||
|
||||
/*
|
||||
* parse a decimal time value, which may include a fractional portion
|
||||
* Parse a decimal time value, which may include a fractional portion
|
||||
*
|
||||
* Sets ps to INT64_MIN on error.
|
||||
*/
|
||||
static void
|
||||
pax_time(const char *p, size_t length, int64_t *ps, long *pn)
|
||||
@@ -2784,6 +2878,7 @@ pax_time(const char *p, size_t length, int64_t *ps, long *pn)
|
||||
|
||||
if (length <= 0) {
|
||||
*ps = 0;
|
||||
*pn = 0;
|
||||
return;
|
||||
}
|
||||
s = 0;
|
||||
@@ -2797,8 +2892,9 @@ pax_time(const char *p, size_t length, int64_t *ps, long *pn)
|
||||
digit = *p - '0';
|
||||
if (s > limit ||
|
||||
(s == limit && digit > last_digit_limit)) {
|
||||
s = INT64_MAX;
|
||||
break;
|
||||
*ps = INT64_MIN;
|
||||
*pn = 0;
|
||||
return;
|
||||
}
|
||||
s = (s * 10) + digit;
|
||||
++p;
|
||||
@@ -2829,7 +2925,7 @@ pax_time(const char *p, size_t length, int64_t *ps, long *pn)
|
||||
*/
|
||||
static int
|
||||
header_gnutar(struct archive_read *a, struct tar *tar,
|
||||
struct archive_entry *entry, const void *h, size_t *unconsumed)
|
||||
struct archive_entry *entry, const void *h, int64_t *unconsumed)
|
||||
{
|
||||
const struct archive_entry_header_gnutar *header;
|
||||
int64_t t;
|
||||
@@ -2841,11 +2937,6 @@ header_gnutar(struct archive_read *a, struct tar *tar,
|
||||
* filename is stored as in old-style archives.
|
||||
*/
|
||||
|
||||
/* Grab fields common to all tar variants. */
|
||||
err = header_common(a, tar, entry, h);
|
||||
if (err == ARCHIVE_FATAL)
|
||||
return (err);
|
||||
|
||||
/* Copy filename over (to ensure null termination). */
|
||||
header = (const struct archive_entry_header_gnutar *)h;
|
||||
const char *existing_pathname = archive_entry_pathname(entry);
|
||||
@@ -2894,8 +2985,6 @@ header_gnutar(struct archive_read *a, struct tar *tar,
|
||||
archive_entry_set_rdev(entry, 0);
|
||||
}
|
||||
|
||||
tar->entry_padding = 0x1ff & (-tar->entry_bytes_remaining);
|
||||
|
||||
/* Grab GNU-specific fields. */
|
||||
if (!archive_entry_atime_is_set(entry)) {
|
||||
t = tar_atol(header->atime, sizeof(header->atime));
|
||||
@@ -2909,10 +2998,10 @@ header_gnutar(struct archive_read *a, struct tar *tar,
|
||||
}
|
||||
|
||||
if (header->realsize[0] != 0) {
|
||||
tar->realsize
|
||||
/* Treat as a synonym for the pax GNU.sparse.realsize attr */
|
||||
tar->GNU_sparse_realsize
|
||||
= tar_atol(header->realsize, sizeof(header->realsize));
|
||||
archive_entry_set_size(entry, tar->realsize);
|
||||
tar->realsize_override = 1;
|
||||
tar->size_fields |= TAR_SIZE_GNU_SPARSE_REALSIZE;
|
||||
}
|
||||
|
||||
if (header->sparse[0].offset[0] != 0) {
|
||||
@@ -2925,6 +3014,13 @@ header_gnutar(struct archive_read *a, struct tar *tar,
|
||||
}
|
||||
}
|
||||
|
||||
/* Grab fields common to all tar variants. */
|
||||
err = header_common(a, tar, entry, h);
|
||||
if (err == ARCHIVE_FATAL)
|
||||
return (err);
|
||||
|
||||
tar->entry_padding = 0x1ff & (-tar->entry_bytes_remaining);
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
@@ -2980,7 +3076,7 @@ gnu_clear_sparse_list(struct tar *tar)
|
||||
|
||||
static int
|
||||
gnu_sparse_old_read(struct archive_read *a, struct tar *tar,
|
||||
const struct archive_entry_header_gnutar *header, size_t *unconsumed)
|
||||
const struct archive_entry_header_gnutar *header, int64_t *unconsumed)
|
||||
{
|
||||
ssize_t bytes_read;
|
||||
const void *data;
|
||||
@@ -3104,8 +3200,7 @@ gnu_sparse_01_parse(struct archive_read *a, struct tar *tar, const char *p, size
|
||||
* it's not possible to support both variants. This code supports
|
||||
* the later variant at the expense of not supporting the former.
|
||||
*
|
||||
* This variant also replaced GNU.sparse.size with GNU.sparse.realsize
|
||||
* and introduced the GNU.sparse.major/GNU.sparse.minor attributes.
|
||||
* This variant also introduced the GNU.sparse.major/GNU.sparse.minor attributes.
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -3115,7 +3210,7 @@ gnu_sparse_01_parse(struct archive_read *a, struct tar *tar, const char *p, size
|
||||
*/
|
||||
static int64_t
|
||||
gnu_sparse_10_atol(struct archive_read *a, struct tar *tar,
|
||||
int64_t *remaining, size_t *unconsumed)
|
||||
int64_t *remaining, int64_t *unconsumed)
|
||||
{
|
||||
int64_t l, limit, last_digit_limit;
|
||||
const char *p;
|
||||
@@ -3160,12 +3255,10 @@ gnu_sparse_10_atol(struct archive_read *a, struct tar *tar,
|
||||
* Returns length (in bytes) of the sparse data description
|
||||
* that was read.
|
||||
*/
|
||||
static ssize_t
|
||||
gnu_sparse_10_read(struct archive_read *a, struct tar *tar, size_t *unconsumed)
|
||||
static int64_t
|
||||
gnu_sparse_10_read(struct archive_read *a, struct tar *tar, int64_t *unconsumed)
|
||||
{
|
||||
ssize_t bytes_read;
|
||||
int entries;
|
||||
int64_t offset, size, to_skip, remaining;
|
||||
int64_t bytes_read, entries, offset, size, to_skip, remaining;
|
||||
|
||||
/* Clear out the existing sparse list. */
|
||||
gnu_clear_sparse_list(tar);
|
||||
@@ -3173,7 +3266,7 @@ gnu_sparse_10_read(struct archive_read *a, struct tar *tar, size_t *unconsumed)
|
||||
remaining = tar->entry_bytes_remaining;
|
||||
|
||||
/* Parse entries. */
|
||||
entries = (int)gnu_sparse_10_atol(a, tar, &remaining, unconsumed);
|
||||
entries = gnu_sparse_10_atol(a, tar, &remaining, unconsumed);
|
||||
if (entries < 0)
|
||||
return (ARCHIVE_FATAL);
|
||||
/* Parse the individual entries. */
|
||||
@@ -3191,14 +3284,14 @@ gnu_sparse_10_read(struct archive_read *a, struct tar *tar, size_t *unconsumed)
|
||||
}
|
||||
/* Skip rest of block... */
|
||||
tar_flush_unconsumed(a, unconsumed);
|
||||
bytes_read = (ssize_t)(tar->entry_bytes_remaining - remaining);
|
||||
bytes_read = tar->entry_bytes_remaining - remaining;
|
||||
to_skip = 0x1ff & -bytes_read;
|
||||
/* Fail if tar->entry_bytes_remaing would get negative */
|
||||
if (to_skip > remaining)
|
||||
return (ARCHIVE_FATAL);
|
||||
if (to_skip != __archive_read_consume(a, to_skip))
|
||||
return (ARCHIVE_FATAL);
|
||||
return ((ssize_t)(bytes_read + to_skip));
|
||||
return (bytes_read + to_skip);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3408,7 +3501,7 @@ tar_atol256(const char *_p, size_t char_cnt)
|
||||
*/
|
||||
static ssize_t
|
||||
readline(struct archive_read *a, struct tar *tar, const char **start,
|
||||
ssize_t limit, size_t *unconsumed)
|
||||
ssize_t limit, int64_t *unconsumed)
|
||||
{
|
||||
ssize_t bytes_read;
|
||||
ssize_t total_size = 0;
|
||||
|
||||
@@ -386,7 +386,8 @@ _warc_rdhdr(struct archive_read *a, struct archive_entry *entry)
|
||||
case LAST_WT:
|
||||
default:
|
||||
/* consume the content and start over */
|
||||
_warc_skip(a);
|
||||
if (_warc_skip(a) < 0)
|
||||
return (ARCHIVE_FATAL);
|
||||
goto start_over;
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
@@ -439,7 +440,9 @@ _warc_skip(struct archive_read *a)
|
||||
{
|
||||
struct warc_s *w = a->format->data;
|
||||
|
||||
__archive_read_consume(a, w->cntlen + 4U/*\r\n\r\n separator*/);
|
||||
if (__archive_read_consume(a, w->cntlen) < 0 ||
|
||||
__archive_read_consume(a, 4U/*\r\n\r\n separator*/) < 0)
|
||||
return (ARCHIVE_FATAL);
|
||||
w->cntlen = 0U;
|
||||
w->cntoff = 0U;
|
||||
return (ARCHIVE_OK);
|
||||
|
||||
@@ -36,6 +36,10 @@
|
||||
#include <bsdxml.h>
|
||||
#elif HAVE_EXPAT_H
|
||||
#include <expat.h>
|
||||
#elif HAVE_XMLLITE_H
|
||||
#include <objidl.h>
|
||||
#include <initguid.h>
|
||||
#include <xmllite.h>
|
||||
#endif
|
||||
#ifdef HAVE_BZLIB_H
|
||||
#include <bzlib.h>
|
||||
@@ -56,12 +60,13 @@
|
||||
#include "archive_read_private.h"
|
||||
|
||||
#if (!defined(HAVE_LIBXML_XMLREADER_H) && \
|
||||
!defined(HAVE_BSDXML_H) && !defined(HAVE_EXPAT_H)) ||\
|
||||
!defined(HAVE_BSDXML_H) && !defined(HAVE_EXPAT_H) && \
|
||||
!defined(HAVE_XMLLITE_H)) ||\
|
||||
!defined(HAVE_ZLIB_H) || \
|
||||
!defined(ARCHIVE_HAS_MD5) || !defined(ARCHIVE_HAS_SHA1)
|
||||
/*
|
||||
* xar needs several external libraries.
|
||||
* o libxml2 or expat --- XML parser
|
||||
* o libxml2, expat or (Windows only) xmllite --- XML parser
|
||||
* o openssl or MD5/SHA1 hash function
|
||||
* o zlib
|
||||
* o bzlib2 (option)
|
||||
@@ -438,6 +443,8 @@ static void expat_start_cb(void *, const XML_Char *, const XML_Char **);
|
||||
static void expat_end_cb(void *, const XML_Char *);
|
||||
static void expat_data_cb(void *, const XML_Char *, int);
|
||||
static int expat_read_toc(struct archive_read *);
|
||||
#elif defined(HAVE_XMLLITE_H)
|
||||
static int xmllite_read_toc(struct archive_read *);
|
||||
#endif
|
||||
|
||||
int
|
||||
@@ -589,6 +596,8 @@ read_toc(struct archive_read *a)
|
||||
r = xml2_read_toc(a);
|
||||
#elif defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H)
|
||||
r = expat_read_toc(a);
|
||||
#elif defined(HAVE_XMLLITE_H)
|
||||
r = xmllite_read_toc(a);
|
||||
#endif
|
||||
if (r != ARCHIVE_OK)
|
||||
return (r);
|
||||
@@ -1110,17 +1119,17 @@ atohex(unsigned char *b, size_t bsize, const char *p, size_t psize)
|
||||
while (bsize && psize > 1) {
|
||||
unsigned char x;
|
||||
|
||||
if (p[0] >= 'a' && p[0] <= 'z')
|
||||
if (p[0] >= 'a' && p[0] <= 'f')
|
||||
x = (p[0] - 'a' + 0x0a) << 4;
|
||||
else if (p[0] >= 'A' && p[0] <= 'Z')
|
||||
else if (p[0] >= 'A' && p[0] <= 'F')
|
||||
x = (p[0] - 'A' + 0x0a) << 4;
|
||||
else if (p[0] >= '0' && p[0] <= '9')
|
||||
x = (p[0] - '0') << 4;
|
||||
else
|
||||
return (-1);
|
||||
if (p[1] >= 'a' && p[1] <= 'z')
|
||||
if (p[1] >= 'a' && p[1] <= 'f')
|
||||
x |= p[1] - 'a' + 0x0a;
|
||||
else if (p[1] >= 'A' && p[1] <= 'Z')
|
||||
else if (p[1] >= 'A' && p[1] <= 'F')
|
||||
x |= p[1] - 'A' + 0x0a;
|
||||
else if (p[1] >= '0' && p[1] <= '9')
|
||||
x |= p[1] - '0';
|
||||
@@ -1745,15 +1754,6 @@ decompression_cleanup(struct archive_read *a)
|
||||
#if defined(HAVE_LZMA_H) && defined(HAVE_LIBLZMA)
|
||||
if (xar->lzstream_valid)
|
||||
lzma_end(&(xar->lzstream));
|
||||
#elif defined(HAVE_LZMA_H) && defined(HAVE_LIBLZMA)
|
||||
if (xar->lzstream_valid) {
|
||||
if (lzmadec_end(&(xar->lzstream)) != LZMADEC_OK) {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Failed to clean up lzmadec decompressor");
|
||||
r = ARCHIVE_FATAL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return (r);
|
||||
}
|
||||
@@ -2070,7 +2070,7 @@ xml_start(struct archive_read *a, const char *name, struct xmlattr_list *list)
|
||||
if (xar->file->link > 0)
|
||||
if (add_link(a, xar, xar->file) != ARCHIVE_OK) {
|
||||
return (ARCHIVE_FATAL);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2851,7 +2851,6 @@ xml_data(void *userData, const char *s, size_t len)
|
||||
xar->file->has |= HAS_XATTR;
|
||||
archive_strncpy(&(xar->xattr->fstype), s, len);
|
||||
break;
|
||||
break;
|
||||
case FILE_ACL_DEFAULT:
|
||||
case FILE_ACL_ACCESS:
|
||||
case FILE_ACL_APPLEEXTENDED:
|
||||
@@ -3343,6 +3342,326 @@ expat_read_toc(struct archive_read *a)
|
||||
XML_ParserFree(parser);
|
||||
return (ud.state);
|
||||
}
|
||||
#endif /* defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H) */
|
||||
|
||||
#elif defined(HAVE_XMLLITE_H)
|
||||
|
||||
struct ArchiveStreamAdapter {
|
||||
const ISequentialStreamVtbl *lpVtbl; /* see asaStaticVtable */
|
||||
struct archive_read *a;
|
||||
};
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
asaQueryInterface(ISequentialStream *this, REFIID riid, void **ppv)
|
||||
{
|
||||
if (!IsEqualIID(riid, &IID_ISequentialStream)) {
|
||||
*ppv = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
*ppv = this;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* We can dispense with reference counting as we tightly manage the lifetime
|
||||
* of an ArchiveStreamAdapter.
|
||||
*/
|
||||
static ULONG STDMETHODCALLTYPE
|
||||
asaAddRef(ISequentialStream *this)
|
||||
{
|
||||
(void)this; /* UNUSED */
|
||||
return ULONG_MAX;
|
||||
}
|
||||
|
||||
static ULONG STDMETHODCALLTYPE
|
||||
asaRelease(ISequentialStream *this)
|
||||
{
|
||||
(void)this; /* UNUSED */
|
||||
return ULONG_MAX;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
asaRead(ISequentialStream *this, void *pv, ULONG cb, ULONG *pcbRead)
|
||||
{
|
||||
struct ArchiveStreamAdapter *asa = (struct ArchiveStreamAdapter *)this;
|
||||
struct archive_read *a;
|
||||
struct xar *xar;
|
||||
const void *d = pv;
|
||||
size_t outbytes = cb;
|
||||
size_t used = 0;
|
||||
int r;
|
||||
|
||||
a = asa->a;
|
||||
xar = (struct xar *)(a->format->data);
|
||||
|
||||
*pcbRead = 0;
|
||||
|
||||
if (xar->toc_remaining <= 0)
|
||||
return cb != 0 ? S_FALSE : S_OK;
|
||||
|
||||
r = rd_contents(a, &d, &outbytes, &used, xar->toc_remaining);
|
||||
if (r != ARCHIVE_OK)
|
||||
return E_FAIL;
|
||||
__archive_read_consume(a, used);
|
||||
xar->toc_remaining -= used;
|
||||
xar->offset += used;
|
||||
xar->toc_total += outbytes;
|
||||
PRINT_TOC(pv, outbytes);
|
||||
|
||||
*pcbRead = (ULONG)outbytes;
|
||||
return outbytes < cb ? S_FALSE : S_OK;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
asaWrite(ISequentialStream *this, const void *pv, ULONG cb, ULONG *pcbWritten)
|
||||
{
|
||||
(void)this; /* UNUSED */
|
||||
(void)pv; /* UNUSED */
|
||||
(void)cb; /* UNUSED */
|
||||
if (!pcbWritten) return E_INVALIDARG;
|
||||
*pcbWritten = 0;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static const ISequentialStreamVtbl asaStaticVtable = {
|
||||
.QueryInterface = asaQueryInterface,
|
||||
.AddRef = asaAddRef,
|
||||
.Release = asaRelease,
|
||||
.Read = asaRead,
|
||||
.Write = asaWrite,
|
||||
};
|
||||
|
||||
static int
|
||||
xmllite_create_stream_adapter(struct archive_read *a,
|
||||
struct ArchiveStreamAdapter **pasa)
|
||||
{
|
||||
struct ArchiveStreamAdapter *asa =
|
||||
calloc(1, sizeof(struct ArchiveStreamAdapter));
|
||||
if (!asa) {
|
||||
archive_set_error(&(a->archive), ENOMEM, "Out of memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
asa->lpVtbl = &asaStaticVtable;
|
||||
asa->a = a;
|
||||
*pasa = asa;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
typedef HRESULT(STDMETHODCALLTYPE *xmllite_wstr_func)(IXmlReader *, LPCWSTR *,
|
||||
UINT *);
|
||||
|
||||
/*
|
||||
* Returns an narrow-char archive_string in *as after calling
|
||||
* the wide-char COM API callee() on the XmlReader reader.
|
||||
* Sets an appropriate error on the archive if it fails.
|
||||
*/
|
||||
static int
|
||||
xmllite_call_return_as(struct archive_read *a, struct archive_string *as,
|
||||
IXmlReader *reader, xmllite_wstr_func callee)
|
||||
{
|
||||
LPCWSTR wcs;
|
||||
UINT wlen;
|
||||
|
||||
if (FAILED(callee(reader, &wcs, &wlen))) {
|
||||
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
|
||||
"Failed to read XML data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
archive_string_init(as);
|
||||
if (archive_string_append_from_wcs(as, wcs, (size_t)wlen) < 0) {
|
||||
archive_string_free(as);
|
||||
archive_set_error(&(a->archive), ENOMEM, "Out of memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static char *
|
||||
xmllite_call_return_mbs(struct archive_read *a, IXmlReader *reader,
|
||||
xmllite_wstr_func callee)
|
||||
{
|
||||
char *ret;
|
||||
struct archive_string as;
|
||||
|
||||
if (xmllite_call_return_as(a, &as, reader, callee) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = strdup(as.s);
|
||||
archive_string_free(&as);
|
||||
if (ret == NULL) {
|
||||
archive_set_error(&(a->archive), ENOMEM, "Out of memory");
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
xmllite_xmlattr_setup(struct archive_read *a,
|
||||
struct xmlattr_list *list, IXmlReader *reader)
|
||||
{
|
||||
struct xmlattr *attr;
|
||||
HRESULT hr;
|
||||
|
||||
list->first = NULL;
|
||||
list->last = &(list->first);
|
||||
hr = reader->lpVtbl->MoveToFirstAttribute(reader);
|
||||
/* Contrary to other checks, we're not using SUCCEEDED/FAILED
|
||||
* because MoveToNextAttribute returns *S_FALSE* (success!)
|
||||
* when it runs out of attributes.
|
||||
*/
|
||||
while (hr == S_OK) {
|
||||
/* Attributes implied as being default by the DTD are ignored */
|
||||
if (reader->lpVtbl->IsDefault(reader))
|
||||
continue;
|
||||
|
||||
attr = malloc(sizeof*(attr));
|
||||
if (attr == NULL) {
|
||||
archive_set_error(&(a->archive), ENOMEM,
|
||||
"Out of memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
attr->name = xmllite_call_return_mbs(a, reader,
|
||||
reader->lpVtbl->GetLocalName);
|
||||
if (attr->name == NULL) {
|
||||
free(attr);
|
||||
/* xmllite_call_return_mbs sets an appropriate error */
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
attr->value = xmllite_call_return_mbs(a, reader,
|
||||
reader->lpVtbl->GetValue);
|
||||
if (attr->value == NULL) {
|
||||
free(attr->name);
|
||||
free(attr);
|
||||
/* xmllite_call_return_mbs sets an appropriate error */
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
attr->next = NULL;
|
||||
*list->last = attr;
|
||||
list->last = &(attr->next);
|
||||
hr = reader->lpVtbl->MoveToNextAttribute(reader);
|
||||
}
|
||||
|
||||
if (FAILED(hr)) {
|
||||
archive_set_error(&(a->archive), ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Failed to parse XML document");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
xmllite_read_toc(struct archive_read *a)
|
||||
{
|
||||
struct ArchiveStreamAdapter *asa = NULL;
|
||||
char *name;
|
||||
struct archive_string as;
|
||||
BOOL empty;
|
||||
XmlNodeType type;
|
||||
struct xmlattr_list list;
|
||||
IXmlReader *reader = NULL;
|
||||
int r = ARCHIVE_OK;
|
||||
|
||||
if ((r = xmllite_create_stream_adapter(a, &asa)) < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (FAILED(CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL))) {
|
||||
r = ARCHIVE_FATAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (FAILED(reader->lpVtbl->SetInput(reader, (IUnknown *)asa))) {
|
||||
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
|
||||
"Failed to prepare XML stream");
|
||||
r = ARCHIVE_FATAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (!reader->lpVtbl->IsEOF(reader)) {
|
||||
if (FAILED(reader->lpVtbl->Read(reader, &type))) {
|
||||
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
|
||||
"Failed to read XML stream");
|
||||
r = ARCHIVE_FATAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case XmlNodeType_Element:
|
||||
empty = reader->lpVtbl->IsEmptyElement(reader);
|
||||
|
||||
name = xmllite_call_return_mbs(a, reader,
|
||||
reader->lpVtbl->GetLocalName);
|
||||
if (name == NULL) {
|
||||
/* xmllite_call_return_mbs sets an appropriate error */
|
||||
r = ARCHIVE_FATAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = xmllite_xmlattr_setup(a, &list, reader);
|
||||
if (r == ARCHIVE_OK) {
|
||||
r = xml_start(a, name, &list);
|
||||
}
|
||||
xmlattr_cleanup(&list);
|
||||
if (r == ARCHIVE_OK && empty) {
|
||||
xml_end(a, name);
|
||||
}
|
||||
|
||||
free(name);
|
||||
if (r != ARCHIVE_OK) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
break;
|
||||
case XmlNodeType_EndElement:
|
||||
name = xmllite_call_return_mbs(a, reader,
|
||||
reader->lpVtbl->GetLocalName);
|
||||
if (name == NULL) {
|
||||
/* xmllite_call_return_mbs sets an appropriate error */
|
||||
r = ARCHIVE_FATAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
xml_end(a, name);
|
||||
free(name);
|
||||
break;
|
||||
case XmlNodeType_Text:
|
||||
r = xmllite_call_return_as(a, &as, reader,
|
||||
reader->lpVtbl->GetValue);
|
||||
if (r != ARCHIVE_OK) {
|
||||
/* xmllite_call_return_as sets an appropriate error */
|
||||
goto out;
|
||||
}
|
||||
|
||||
xml_data(a, as.s, (int)archive_strlen(&as));
|
||||
archive_string_free(&as);
|
||||
|
||||
case XmlNodeType_None:
|
||||
case XmlNodeType_Attribute:
|
||||
case XmlNodeType_CDATA:
|
||||
case XmlNodeType_ProcessingInstruction:
|
||||
case XmlNodeType_Comment:
|
||||
case XmlNodeType_DocumentType:
|
||||
case XmlNodeType_Whitespace:
|
||||
case XmlNodeType_XmlDeclaration:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (reader)
|
||||
reader->lpVtbl->Release(reader);
|
||||
|
||||
free(asa);
|
||||
|
||||
return r;
|
||||
}
|
||||
#endif /* defined(XMLLITE) */
|
||||
|
||||
#endif /* Support xar format */
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
#include "archive_private.h"
|
||||
#include "archive_rb.h"
|
||||
#include "archive_read_private.h"
|
||||
#include "archive_time_private.h"
|
||||
#include "archive_ppmd8_private.h"
|
||||
|
||||
#ifndef HAVE_ZLIB_H
|
||||
@@ -465,27 +466,6 @@ compression_name(const int compression)
|
||||
return "??";
|
||||
}
|
||||
|
||||
/* Convert an MSDOS-style date/time into Unix-style time. */
|
||||
static time_t
|
||||
zip_time(const char *p)
|
||||
{
|
||||
int msTime, msDate;
|
||||
struct tm ts;
|
||||
|
||||
msTime = (0xff & (unsigned)p[0]) + 256 * (0xff & (unsigned)p[1]);
|
||||
msDate = (0xff & (unsigned)p[2]) + 256 * (0xff & (unsigned)p[3]);
|
||||
|
||||
memset(&ts, 0, sizeof(ts));
|
||||
ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */
|
||||
ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */
|
||||
ts.tm_mday = msDate & 0x1f; /* Day of month. */
|
||||
ts.tm_hour = (msTime >> 11) & 0x1f;
|
||||
ts.tm_min = (msTime >> 5) & 0x3f;
|
||||
ts.tm_sec = (msTime << 1) & 0x3e;
|
||||
ts.tm_isdst = -1;
|
||||
return mktime(&ts);
|
||||
}
|
||||
|
||||
/*
|
||||
* The extra data is stored as a list of
|
||||
* id1+size1+data1 + id2+size2+data2 ...
|
||||
@@ -978,7 +958,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
|
||||
}
|
||||
zip->init_decryption = (zip_entry->zip_flags & ZIP_ENCRYPTED);
|
||||
zip_entry->compression = (char)archive_le16dec(p + 8);
|
||||
zip_entry->mtime = zip_time(p + 10);
|
||||
zip_entry->mtime = dos_to_unix(archive_le32dec(p + 10));
|
||||
zip_entry->crc32 = archive_le32dec(p + 14);
|
||||
if (zip_entry->zip_flags & ZIP_LENGTH_AT_END)
|
||||
zip_entry->decdat = p[11];
|
||||
@@ -2134,15 +2114,15 @@ zipx_ppmd8_init(struct archive_read *a, struct zip *zip)
|
||||
|
||||
if(order < 2 || restore_method > 2) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Invalid parameter set in PPMd8 stream (order=%" PRId32 ", "
|
||||
"restore=%" PRId32 ")", order, restore_method);
|
||||
"Invalid parameter set in PPMd8 stream (order=%" PRIu32 ", "
|
||||
"restore=%" PRIu32 ")", order, restore_method);
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
|
||||
/* Allocate the memory needed to properly decompress the file. */
|
||||
if(!__archive_ppmd8_functions.Ppmd8_Alloc(&zip->ppmd8, mem << 20)) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Unable to allocate memory for PPMd8 stream: %" PRId32 " bytes",
|
||||
"Unable to allocate memory for PPMd8 stream: %" PRIu32 " bytes",
|
||||
mem << 20);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@@ -3168,7 +3148,6 @@ archive_read_format_zip_read_data(struct archive_read *a,
|
||||
/* We can't decompress this entry, but we will
|
||||
* be able to skip() it and try the next entry. */
|
||||
return (ARCHIVE_FAILED);
|
||||
break;
|
||||
}
|
||||
if (r != ARCHIVE_OK)
|
||||
return (r);
|
||||
@@ -3987,7 +3966,7 @@ slurp_central_directory(struct archive_read *a, struct archive_entry* entry,
|
||||
zip->has_encrypted_entries = 1;
|
||||
}
|
||||
zip_entry->compression = (char)archive_le16dec(p + 10);
|
||||
zip_entry->mtime = zip_time(p + 12);
|
||||
zip_entry->mtime = dos_to_unix(archive_le32dec(p + 12));
|
||||
zip_entry->crc32 = archive_le32dec(p + 16);
|
||||
if (zip_entry->zip_flags & ZIP_LENGTH_AT_END)
|
||||
zip_entry->decdat = p[13];
|
||||
|
||||
@@ -154,7 +154,6 @@ static int archive_wstring_append_from_mbs_in_codepage(
|
||||
struct archive_string_conv *);
|
||||
static int archive_string_append_from_wcs_in_codepage(struct archive_string *,
|
||||
const wchar_t *, size_t, struct archive_string_conv *);
|
||||
static int is_big_endian(void);
|
||||
static int strncat_in_codepage(struct archive_string *, const void *,
|
||||
size_t, struct archive_string_conv *);
|
||||
static int win_strncat_from_utf16be(struct archive_string *, const void *,
|
||||
@@ -199,6 +198,29 @@ static int archive_string_normalize_D(struct archive_string *, const void *,
|
||||
static int archive_string_append_unicode(struct archive_string *,
|
||||
const void *, size_t, struct archive_string_conv *);
|
||||
|
||||
#if defined __LITTLE_ENDIAN__
|
||||
#define IS_BIG_ENDIAN 0
|
||||
#elif defined __BIG_ENDIAN__
|
||||
#define IS_BIG_ENDIAN 1
|
||||
#elif defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
|
||||
#define IS_BIG_ENDIAN 0
|
||||
#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
|
||||
#define IS_BIG_ENDIAN 1
|
||||
#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64) || defined(_M_ARM64))
|
||||
#define IS_BIG_ENDIAN 0
|
||||
#else
|
||||
// Detect endianness at runtime.
|
||||
static int
|
||||
is_big_endian(void)
|
||||
{
|
||||
uint16_t d = 1;
|
||||
|
||||
return (archive_be16dec(&d) == 1);
|
||||
}
|
||||
|
||||
#define IS_BIG_ENDIAN is_big_endian()
|
||||
#endif
|
||||
|
||||
static struct archive_string *
|
||||
archive_string_append(struct archive_string *as, const char *p, size_t s)
|
||||
{
|
||||
@@ -450,7 +472,8 @@ static int
|
||||
archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
|
||||
const char *s, size_t length, struct archive_string_conv *sc)
|
||||
{
|
||||
int count, ret = 0;
|
||||
int ret = 0;
|
||||
size_t count;
|
||||
UINT from_cp;
|
||||
|
||||
if (sc != NULL)
|
||||
@@ -472,7 +495,7 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
|
||||
ws = dest->s + dest->length;
|
||||
mp = (const unsigned char *)s;
|
||||
count = 0;
|
||||
while (count < (int)length && *mp) {
|
||||
while (count < length && *mp) {
|
||||
*ws++ = (wchar_t)*mp++;
|
||||
count++;
|
||||
}
|
||||
@@ -485,7 +508,7 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
|
||||
struct archive_string u16;
|
||||
int saved_flag = sc->flag;/* save current flag. */
|
||||
|
||||
if (is_big_endian())
|
||||
if (IS_BIG_ENDIAN)
|
||||
sc->flag |= SCONV_TO_UTF16BE;
|
||||
else
|
||||
sc->flag |= SCONV_TO_UTF16LE;
|
||||
@@ -495,16 +518,16 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
|
||||
* UTF-16BE/LE NFD ===> UTF-16 NFC
|
||||
* UTF-16BE/LE NFC ===> UTF-16 NFD
|
||||
*/
|
||||
count = (int)utf16nbytes(s, length);
|
||||
count = utf16nbytes(s, length);
|
||||
} else {
|
||||
/*
|
||||
* UTF-8 NFD ===> UTF-16 NFC
|
||||
* UTF-8 NFC ===> UTF-16 NFD
|
||||
*/
|
||||
count = (int)mbsnbytes(s, length);
|
||||
count = mbsnbytes(s, length);
|
||||
}
|
||||
u16.s = (char *)dest->s;
|
||||
u16.length = dest->length << 1;;
|
||||
u16.length = dest->length << 1;
|
||||
u16.buffer_length = dest->buffer_length;
|
||||
if (sc->flag & SCONV_NORMALIZATION_C)
|
||||
ret = archive_string_normalize_C(&u16, s, count, sc);
|
||||
@@ -516,23 +539,23 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
|
||||
sc->flag = saved_flag;/* restore the saved flag. */
|
||||
return (ret);
|
||||
} else if (sc != NULL && (sc->flag & SCONV_FROM_UTF16)) {
|
||||
count = (int)utf16nbytes(s, length);
|
||||
count = utf16nbytes(s, length);
|
||||
count >>= 1; /* to be WCS length */
|
||||
/* Allocate memory for WCS. */
|
||||
if (NULL == archive_wstring_ensure(dest,
|
||||
dest->length + count + 1))
|
||||
return (-1);
|
||||
wmemcpy(dest->s + dest->length, (const wchar_t *)s, count);
|
||||
if ((sc->flag & SCONV_FROM_UTF16BE) && !is_big_endian()) {
|
||||
if ((sc->flag & SCONV_FROM_UTF16BE) && !IS_BIG_ENDIAN) {
|
||||
uint16_t *u16 = (uint16_t *)(dest->s + dest->length);
|
||||
int b;
|
||||
size_t b;
|
||||
for (b = 0; b < count; b++) {
|
||||
uint16_t val = archive_le16dec(u16+b);
|
||||
archive_be16enc(u16+b, val);
|
||||
}
|
||||
} else if ((sc->flag & SCONV_FROM_UTF16LE) && is_big_endian()) {
|
||||
} else if ((sc->flag & SCONV_FROM_UTF16LE) && IS_BIG_ENDIAN) {
|
||||
uint16_t *u16 = (uint16_t *)(dest->s + dest->length);
|
||||
int b;
|
||||
size_t b;
|
||||
for (b = 0; b < count; b++) {
|
||||
uint16_t val = archive_be16dec(u16+b);
|
||||
archive_le16enc(u16+b, val);
|
||||
@@ -556,21 +579,28 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
|
||||
|
||||
buffsize = dest->length + length + 1;
|
||||
do {
|
||||
int r;
|
||||
|
||||
/* MultiByteToWideChar is limited to int. */
|
||||
if (length > (size_t)INT_MAX ||
|
||||
(dest->buffer_length >> 1) > (size_t)INT_MAX)
|
||||
return (-1);
|
||||
/* Allocate memory for WCS. */
|
||||
if (NULL == archive_wstring_ensure(dest, buffsize))
|
||||
return (-1);
|
||||
/* Convert MBS to WCS. */
|
||||
count = MultiByteToWideChar(from_cp,
|
||||
r = MultiByteToWideChar(from_cp,
|
||||
mbflag, s, (int)length, dest->s + dest->length,
|
||||
(int)(dest->buffer_length >> 1) -1);
|
||||
if (count == 0 &&
|
||||
if (r == 0 &&
|
||||
GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
||||
/* Expand the WCS buffer. */
|
||||
buffsize = dest->buffer_length << 1;
|
||||
continue;
|
||||
}
|
||||
if (count == 0 && length != 0)
|
||||
if (r == 0 && length != 0)
|
||||
ret = -1;
|
||||
count = (size_t)r;
|
||||
break;
|
||||
} while (1);
|
||||
}
|
||||
@@ -679,9 +709,9 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as,
|
||||
const wchar_t *ws, size_t len, struct archive_string_conv *sc)
|
||||
{
|
||||
BOOL defchar_used, *dp;
|
||||
int count, ret = 0;
|
||||
int ret = 0;
|
||||
UINT to_cp;
|
||||
int wslen = (int)len;
|
||||
size_t count, wslen = len;
|
||||
|
||||
if (sc != NULL)
|
||||
to_cp = sc->to_cp;
|
||||
@@ -720,13 +750,13 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as,
|
||||
count = 0;
|
||||
defchar_used = 0;
|
||||
if (sc->flag & SCONV_TO_UTF16BE) {
|
||||
while (count < (int)len && *ws) {
|
||||
while (count < len && *ws) {
|
||||
archive_be16enc(u16+count, *ws);
|
||||
ws++;
|
||||
count++;
|
||||
}
|
||||
} else {
|
||||
while (count < (int)len && *ws) {
|
||||
while (count < len && *ws) {
|
||||
archive_le16enc(u16+count, *ws);
|
||||
ws++;
|
||||
count++;
|
||||
@@ -739,15 +769,21 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as,
|
||||
archive_string_ensure(as, as->length + len * 2 + 1))
|
||||
return (-1);
|
||||
do {
|
||||
int r;
|
||||
|
||||
defchar_used = 0;
|
||||
if (to_cp == CP_UTF8 || sc == NULL)
|
||||
dp = NULL;
|
||||
else
|
||||
dp = &defchar_used;
|
||||
count = WideCharToMultiByte(to_cp, 0, ws, wslen,
|
||||
/* WideCharToMultiByte is limited to int. */
|
||||
if (as->buffer_length - as->length - 1 > (size_t)INT_MAX ||
|
||||
wslen > (size_t)INT_MAX)
|
||||
return (-1);
|
||||
r = WideCharToMultiByte(to_cp, 0, ws, (int)wslen,
|
||||
as->s + as->length,
|
||||
(int)as->buffer_length - (int)as->length - 1, NULL, dp);
|
||||
if (count == 0 &&
|
||||
(int)(as->buffer_length - as->length - 1), NULL, dp);
|
||||
if (r == 0 &&
|
||||
GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
||||
/* Expand the MBS buffer and retry. */
|
||||
if (NULL == archive_string_ensure(as,
|
||||
@@ -755,8 +791,9 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as,
|
||||
return (-1);
|
||||
continue;
|
||||
}
|
||||
if (count == 0)
|
||||
if (r == 0)
|
||||
ret = -1;
|
||||
count = (size_t)r;
|
||||
break;
|
||||
} while (1);
|
||||
}
|
||||
@@ -2032,7 +2069,7 @@ iconv_strncat_in_locale(struct archive_string *as, const void *_p,
|
||||
char *outp;
|
||||
size_t avail, bs;
|
||||
int return_value = 0; /* success */
|
||||
int to_size, from_size;
|
||||
size_t to_size, from_size;
|
||||
|
||||
if (sc->flag & SCONV_TO_UTF16)
|
||||
to_size = 2;
|
||||
@@ -2051,7 +2088,7 @@ iconv_strncat_in_locale(struct archive_string *as, const void *_p,
|
||||
remaining = length;
|
||||
outp = as->s + as->length;
|
||||
avail = as->buffer_length - as->length - to_size;
|
||||
while (remaining >= (size_t)from_size) {
|
||||
while (remaining >= from_size) {
|
||||
size_t result = iconv(cd, &itp, &remaining, &outp, &avail);
|
||||
|
||||
if (result != (size_t)-1)
|
||||
@@ -2174,6 +2211,8 @@ invalid_mbs(const void *_p, size_t n, struct archive_string_conv *sc)
|
||||
if (codepage != CP_UTF8)
|
||||
mbflag |= MB_PRECOMPOSED;
|
||||
|
||||
if (n > (size_t)INT_MAX)
|
||||
return (-1); /* Invalid */
|
||||
if (MultiByteToWideChar(codepage, mbflag, p, (int)n, NULL, 0) == 0)
|
||||
return (-1); /* Invalid */
|
||||
return (0); /* Okay */
|
||||
@@ -2327,7 +2366,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
|
||||
cnt = utf8_count[ch];
|
||||
|
||||
/* Invalid sequence or there are not plenty bytes. */
|
||||
if ((int)n < cnt) {
|
||||
if (n < (size_t)cnt) {
|
||||
cnt = (int)n;
|
||||
for (i = 1; i < cnt; i++) {
|
||||
if ((s[i] & 0xc0) != 0x80) {
|
||||
@@ -2396,7 +2435,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
|
||||
cnt = 6;
|
||||
else
|
||||
cnt = 1;
|
||||
if ((int)n < cnt)
|
||||
if (n < (size_t)cnt)
|
||||
cnt = (int)n;
|
||||
for (i = 1; i < cnt; i++) {
|
||||
if ((s[i] & 0xc0) != 0x80) {
|
||||
@@ -2612,7 +2651,7 @@ unicode_to_utf16be(char *p, size_t remaining, uint32_t uc)
|
||||
} else {
|
||||
if (remaining < 2)
|
||||
return (0);
|
||||
archive_be16enc(utf16, uc);
|
||||
archive_be16enc(utf16, (uint16_t)uc);
|
||||
return (2);
|
||||
}
|
||||
}
|
||||
@@ -2634,7 +2673,7 @@ unicode_to_utf16le(char *p, size_t remaining, uint32_t uc)
|
||||
} else {
|
||||
if (remaining < 2)
|
||||
return (0);
|
||||
archive_le16enc(utf16, uc);
|
||||
archive_le16enc(utf16, (uint16_t)uc);
|
||||
return (2);
|
||||
}
|
||||
}
|
||||
@@ -3499,10 +3538,9 @@ win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes,
|
||||
{
|
||||
struct archive_string tmp;
|
||||
const char *u16;
|
||||
int ll;
|
||||
BOOL defchar;
|
||||
char *mbs;
|
||||
size_t mbs_size, b;
|
||||
size_t mbs_size, b, ll;
|
||||
int ret = 0;
|
||||
|
||||
bytes &= ~1;
|
||||
@@ -3538,7 +3576,7 @@ win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes,
|
||||
|
||||
archive_string_init(&tmp);
|
||||
if (be) {
|
||||
if (is_big_endian()) {
|
||||
if (IS_BIG_ENDIAN) {
|
||||
u16 = _p;
|
||||
} else {
|
||||
if (archive_string_ensure(&tmp, bytes+2) == NULL)
|
||||
@@ -3551,7 +3589,7 @@ win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes,
|
||||
u16 = tmp.s;
|
||||
}
|
||||
} else {
|
||||
if (!is_big_endian()) {
|
||||
if (!IS_BIG_ENDIAN) {
|
||||
u16 = _p;
|
||||
} else {
|
||||
if (archive_string_ensure(&tmp, bytes+2) == NULL)
|
||||
@@ -3566,18 +3604,24 @@ win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes,
|
||||
}
|
||||
|
||||
do {
|
||||
int r;
|
||||
defchar = 0;
|
||||
ll = WideCharToMultiByte(sc->to_cp, 0,
|
||||
/* WideCharToMultiByte is limited to int. */
|
||||
if (bytes > (size_t)INT_MAX || mbs_size > (size_t)INT_MAX)
|
||||
return (-1);
|
||||
r = WideCharToMultiByte(sc->to_cp, 0,
|
||||
(LPCWSTR)u16, (int)bytes>>1, mbs, (int)mbs_size,
|
||||
NULL, &defchar);
|
||||
/* Exit loop if we succeeded */
|
||||
if (ll != 0 ||
|
||||
if (r != 0 ||
|
||||
GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
||||
ll = (size_t)r;
|
||||
break;
|
||||
}
|
||||
/* Else expand buffer and loop to try again. */
|
||||
ll = WideCharToMultiByte(sc->to_cp, 0,
|
||||
r = WideCharToMultiByte(sc->to_cp, 0,
|
||||
(LPCWSTR)u16, (int)bytes, NULL, 0, NULL, NULL);
|
||||
ll = (size_t)r;
|
||||
if (archive_string_ensure(as, ll +1) == NULL)
|
||||
return (-1);
|
||||
mbs = as->s + as->length;
|
||||
@@ -3605,14 +3649,6 @@ win_strncat_from_utf16le(struct archive_string *as, const void *_p,
|
||||
return (win_strncat_from_utf16(as, _p, bytes, sc, 0));
|
||||
}
|
||||
|
||||
static int
|
||||
is_big_endian(void)
|
||||
{
|
||||
uint16_t d = 1;
|
||||
|
||||
return (archive_be16dec(&d) == 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a current locale string to UTF-16BE/LE and copy the result.
|
||||
* Return -1 if conversion fails.
|
||||
@@ -3651,16 +3687,21 @@ win_strncat_to_utf16(struct archive_string *as16, const void *_p,
|
||||
return (0);
|
||||
}
|
||||
do {
|
||||
count = MultiByteToWideChar(sc->from_cp,
|
||||
int r;
|
||||
if (length > (size_t)INT_MAX || (avail >> 1) > (size_t)INT_MAX)
|
||||
return (-1);
|
||||
r = MultiByteToWideChar(sc->from_cp,
|
||||
MB_PRECOMPOSED, s, (int)length, (LPWSTR)u16, (int)avail>>1);
|
||||
/* Exit loop if we succeeded */
|
||||
if (count != 0 ||
|
||||
if (r != 0 ||
|
||||
GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
||||
count = (size_t)r;
|
||||
break;
|
||||
}
|
||||
/* Expand buffer and try again */
|
||||
count = MultiByteToWideChar(sc->from_cp,
|
||||
r = MultiByteToWideChar(sc->from_cp,
|
||||
MB_PRECOMPOSED, s, (int)length, NULL, 0);
|
||||
count = (size_t)r;
|
||||
if (archive_string_ensure(as16, (count +1) * 2)
|
||||
== NULL)
|
||||
return (-1);
|
||||
@@ -3673,7 +3714,7 @@ win_strncat_to_utf16(struct archive_string *as16, const void *_p,
|
||||
if (count == 0)
|
||||
return (-1);
|
||||
|
||||
if (is_big_endian()) {
|
||||
if (IS_BIG_ENDIAN) {
|
||||
if (!bigendian) {
|
||||
while (count > 0) {
|
||||
uint16_t v = archive_be16dec(u16);
|
||||
@@ -3811,9 +3852,9 @@ best_effort_strncat_to_utf16(struct archive_string *as16, const void *_p,
|
||||
ret = -1;
|
||||
}
|
||||
if (bigendian)
|
||||
archive_be16enc(utf16, c);
|
||||
archive_be16enc(utf16, (uint16_t)c);
|
||||
else
|
||||
archive_le16enc(utf16, c);
|
||||
archive_le16enc(utf16, (uint16_t)c);
|
||||
utf16 += 2;
|
||||
}
|
||||
as16->length = utf16 - as16->s;
|
||||
|
||||
@@ -2286,5 +2286,4 @@ static const struct unicode_decomposition_table u_decomposition_table[] = {
|
||||
{ 0x110AB , 0x110A5 , 0x110BA },
|
||||
};
|
||||
|
||||
#endif /* ARCHIVE_STRING_COMPOSITION_H_INCLUDED */
|
||||
|
||||
#endif /* !ARCHIVE_STRING_COMPOSITION_H_INCLUDED */
|
||||
|
||||
@@ -116,8 +116,14 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt,
|
||||
|
||||
long_flag = '\0';
|
||||
switch(*p) {
|
||||
case 'j':
|
||||
case 'l':
|
||||
if (p[1] == 'l') {
|
||||
long_flag = 'L';
|
||||
p += 2;
|
||||
break;
|
||||
}
|
||||
__LA_FALLTHROUGH;
|
||||
case 'j':
|
||||
case 'z':
|
||||
long_flag = *p;
|
||||
p++;
|
||||
@@ -136,6 +142,7 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt,
|
||||
switch(long_flag) {
|
||||
case 'j': s = va_arg(ap, intmax_t); break;
|
||||
case 'l': s = va_arg(ap, long); break;
|
||||
case 'L': s = va_arg(ap, long long); break;
|
||||
case 'z': s = va_arg(ap, ssize_t); break;
|
||||
default: s = va_arg(ap, int); break;
|
||||
}
|
||||
@@ -144,6 +151,7 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt,
|
||||
case 's':
|
||||
switch(long_flag) {
|
||||
case 'l':
|
||||
case 'L':
|
||||
pw = va_arg(ap, wchar_t *);
|
||||
if (pw == NULL)
|
||||
pw = L"(null)";
|
||||
@@ -172,6 +180,7 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt,
|
||||
switch(long_flag) {
|
||||
case 'j': u = va_arg(ap, uintmax_t); break;
|
||||
case 'l': u = va_arg(ap, unsigned long); break;
|
||||
case 'L': u = va_arg(ap, unsigned long long); break;
|
||||
case 'z': u = va_arg(ap, size_t); break;
|
||||
default: u = va_arg(ap, unsigned int); break;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
/*-
|
||||
* Copyright © 2025 ARJANEN Loïc Jean David
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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 AUTHOR(S) 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 "archive_platform.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_time_private.h"
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define NTFS_EPOC_TIME ARCHIVE_LITERAL_ULL(11644473600)
|
||||
#define NTFS_TICKS ARCHIVE_LITERAL_ULL(10000000)
|
||||
#define NTFS_EPOC_TICKS (NTFS_EPOC_TIME * NTFS_TICKS)
|
||||
#define DOS_MIN_TIME 0x00210000U
|
||||
#define DOS_MAX_TIME 0xff9fbf7dU
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#include <winnt.h>
|
||||
/* Windows FILETIME to NTFS time. */
|
||||
uint64_t
|
||||
FILETIME_to_ntfs(const FILETIME* filetime)
|
||||
{
|
||||
ULARGE_INTEGER utc;
|
||||
utc.HighPart = filetime->dwHighDateTime;
|
||||
utc.LowPart = filetime->dwLowDateTime;
|
||||
return utc.QuadPart;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Convert an MSDOS-style date/time into Unix-style time. */
|
||||
int64_t
|
||||
dos_to_unix(uint32_t dos_time)
|
||||
{
|
||||
uint16_t msTime, msDate;
|
||||
struct tm ts;
|
||||
time_t t;
|
||||
|
||||
msTime = (0xFFFF & dos_time);
|
||||
msDate = (dos_time >> 16);
|
||||
|
||||
memset(&ts, 0, sizeof(ts));
|
||||
ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */
|
||||
ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */
|
||||
ts.tm_mday = msDate & 0x1f; /* Day of month. */
|
||||
ts.tm_hour = (msTime >> 11) & 0x1f;
|
||||
ts.tm_min = (msTime >> 5) & 0x3f;
|
||||
ts.tm_sec = (msTime << 1) & 0x3e;
|
||||
ts.tm_isdst = -1;
|
||||
t = mktime(&ts);
|
||||
return (int64_t)(t == (time_t)-1 ? INT32_MAX : t);
|
||||
}
|
||||
|
||||
/* Convert into MSDOS-style date/time. */
|
||||
uint32_t
|
||||
unix_to_dos(int64_t unix_time)
|
||||
{
|
||||
struct tm *t;
|
||||
uint32_t dt;
|
||||
time_t ut = unix_time;
|
||||
#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S)
|
||||
struct tm tmbuf;
|
||||
#endif
|
||||
|
||||
if (sizeof(time_t) < sizeof(int64_t) && (int64_t)ut != unix_time) {
|
||||
ut = (time_t)(unix_time > 0 ? INT32_MAX : INT32_MIN);
|
||||
}
|
||||
|
||||
#if defined(HAVE_LOCALTIME_S)
|
||||
t = localtime_s(&tmbuf, &ut) ? NULL : &tmbuf;
|
||||
#elif defined(HAVE_LOCALTIME_R)
|
||||
t = localtime_r(&ut, &tmbuf);
|
||||
#else
|
||||
t = localtime(&ut);
|
||||
#endif
|
||||
dt = 0;
|
||||
if (t != NULL && t->tm_year >= INT_MIN + 80) {
|
||||
const int year = t->tm_year - 80;
|
||||
|
||||
if (year & ~0x7f) {
|
||||
dt = year > 0 ? DOS_MAX_TIME : DOS_MIN_TIME;
|
||||
}
|
||||
else {
|
||||
dt += (year & 0x7f) << 9;
|
||||
dt += ((t->tm_mon + 1) & 0x0f) << 5;
|
||||
dt += (t->tm_mday & 0x1f);
|
||||
dt <<= 16;
|
||||
dt += (t->tm_hour & 0x1f) << 11;
|
||||
dt += (t->tm_min & 0x3f) << 5;
|
||||
/* Only counting every 2 seconds. */
|
||||
dt += (t->tm_sec & 0x3e) >> 1;
|
||||
}
|
||||
}
|
||||
if (dt > DOS_MAX_TIME) {
|
||||
dt = DOS_MAX_TIME;
|
||||
}
|
||||
else if (dt < DOS_MIN_TIME) {
|
||||
dt = DOS_MIN_TIME;
|
||||
}
|
||||
return dt;
|
||||
}
|
||||
|
||||
/* Convert NTFS time to Unix sec/nsec */
|
||||
void
|
||||
ntfs_to_unix(uint64_t ntfs, int64_t* secs, uint32_t* nsecs)
|
||||
{
|
||||
if (ntfs > INT64_MAX) {
|
||||
ntfs -= NTFS_EPOC_TICKS;
|
||||
*secs = ntfs / NTFS_TICKS;
|
||||
*nsecs = 100 * (ntfs % NTFS_TICKS);
|
||||
}
|
||||
else {
|
||||
lldiv_t tdiv;
|
||||
int64_t value = (int64_t)ntfs - (int64_t)NTFS_EPOC_TICKS;
|
||||
|
||||
tdiv = lldiv(value, NTFS_TICKS);
|
||||
*secs = tdiv.quot;
|
||||
*nsecs = (uint32_t)(tdiv.rem * 100);
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert Unix sec/nsec to NTFS time */
|
||||
uint64_t
|
||||
unix_to_ntfs(int64_t secs, uint32_t nsecs)
|
||||
{
|
||||
uint64_t ntfs;
|
||||
|
||||
if (secs < -(int64_t)NTFS_EPOC_TIME)
|
||||
return 0;
|
||||
|
||||
ntfs = secs + NTFS_EPOC_TIME;
|
||||
|
||||
if (ntfs > UINT64_MAX / NTFS_TICKS)
|
||||
return UINT64_MAX;
|
||||
|
||||
ntfs *= NTFS_TICKS;
|
||||
|
||||
if (ntfs > UINT64_MAX - nsecs/100)
|
||||
return UINT64_MAX;
|
||||
|
||||
return ntfs + nsecs/100;
|
||||
}
|
||||
+18
-8
@@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2015 Tim Kientzle
|
||||
* Copyright © 2025 ARJANEN Loïc Jean David
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -22,16 +22,26 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef ARCHIVE_GETDATE_H_INCLUDED
|
||||
#define ARCHIVE_GETDATE_H_INCLUDED
|
||||
#ifndef ARCHIVE_TIME_PRIVATE_H_INCLUDED
|
||||
#define ARCHIVE_TIME_PRIVATE_H_INCLUDED
|
||||
|
||||
#ifndef __LIBARCHIVE_BUILD
|
||||
#error This header is only to be used internally to libarchive.
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
#include <time.h>
|
||||
|
||||
time_t __archive_get_date(time_t now, const char *);
|
||||
|
||||
/* NTFS time to Unix sec/nsec. */
|
||||
void ntfs_to_unix(uint64_t ntfs, int64_t* secs, uint32_t* nsecs);
|
||||
/* DOS time to Unix sec. */
|
||||
int64_t dos_to_unix(uint32_t dos);
|
||||
/* Unix sec/nsec to NTFS time. */
|
||||
uint64_t unix_to_ntfs(int64_t secs, uint32_t nsecs);
|
||||
/* Unix sec to DOS time. */
|
||||
uint32_t unix_to_dos(int64_t secs);
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
/* Windows FILETIME to NTFS time. */
|
||||
uint64_t FILETIME_to_ntfs(const FILETIME* filetime);
|
||||
#endif
|
||||
#endif /* ARCHIVE_TIME_PRIVATE_H_INCLUDED */
|
||||
@@ -77,7 +77,9 @@
|
||||
#define O_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
static int archive_utility_string_sort_helper(char **, unsigned int);
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
static int __LA_LIBC_CC archive_utility_string_sort_helper(const void *, const void *);
|
||||
#endif
|
||||
|
||||
/* Generic initialization of 'struct archive' objects. */
|
||||
int
|
||||
@@ -629,74 +631,28 @@ __archive_ensure_cloexec_flag(int fd)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/*
|
||||
* Utility function to sort a group of strings using quicksort.
|
||||
* Utility functions to sort a group of strings using quicksort.
|
||||
*/
|
||||
static int
|
||||
archive_utility_string_sort_helper(char **strings, unsigned int n)
|
||||
__LA_LIBC_CC
|
||||
archive_utility_string_sort_helper(const void *p1, const void *p2)
|
||||
{
|
||||
unsigned int i, lesser_count, greater_count;
|
||||
char **lesser, **greater, **tmp, *pivot;
|
||||
int retval1, retval2;
|
||||
const char * const * const s1 = p1;
|
||||
const char * const * const s2 = p2;
|
||||
|
||||
/* A list of 0 or 1 elements is already sorted */
|
||||
if (n <= 1)
|
||||
return (ARCHIVE_OK);
|
||||
|
||||
lesser_count = greater_count = 0;
|
||||
lesser = greater = NULL;
|
||||
pivot = strings[0];
|
||||
for (i = 1; i < n; i++)
|
||||
{
|
||||
if (strcmp(strings[i], pivot) < 0)
|
||||
{
|
||||
lesser_count++;
|
||||
tmp = realloc(lesser, lesser_count * sizeof(*tmp));
|
||||
if (!tmp) {
|
||||
free(greater);
|
||||
free(lesser);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
lesser = tmp;
|
||||
lesser[lesser_count - 1] = strings[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
greater_count++;
|
||||
tmp = realloc(greater, greater_count * sizeof(*tmp));
|
||||
if (!tmp) {
|
||||
free(greater);
|
||||
free(lesser);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
greater = tmp;
|
||||
greater[greater_count - 1] = strings[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* quicksort(lesser) */
|
||||
retval1 = archive_utility_string_sort_helper(lesser, lesser_count);
|
||||
for (i = 0; i < lesser_count; i++)
|
||||
strings[i] = lesser[i];
|
||||
free(lesser);
|
||||
|
||||
/* pivot */
|
||||
strings[lesser_count] = pivot;
|
||||
|
||||
/* quicksort(greater) */
|
||||
retval2 = archive_utility_string_sort_helper(greater, greater_count);
|
||||
for (i = 0; i < greater_count; i++)
|
||||
strings[lesser_count + 1 + i] = greater[i];
|
||||
free(greater);
|
||||
|
||||
return (retval1 < retval2) ? retval1 : retval2;
|
||||
return strcmp(*s1, *s2);
|
||||
}
|
||||
|
||||
int
|
||||
archive_utility_string_sort(char **strings)
|
||||
{
|
||||
unsigned int size = 0;
|
||||
while (strings[size] != NULL)
|
||||
size_t size = 0;
|
||||
while (strings[size] != NULL)
|
||||
size++;
|
||||
return archive_utility_string_sort_helper(strings, size);
|
||||
qsort(strings, size, sizeof(char *),
|
||||
archive_utility_string_sort_helper);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -46,11 +46,125 @@
|
||||
#endif
|
||||
#ifdef HAVE_ZSTD_H
|
||||
#include <zstd.h>
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#ifdef HAVE_LZO_LZOCONF_H
|
||||
#include <lzo/lzoconf.h>
|
||||
#endif
|
||||
#if HAVE_LIBXML_XMLVERSION_H
|
||||
#include <libxml/xmlversion.h>
|
||||
#elif HAVE_BSDXML_H
|
||||
#include <bsdxml.h>
|
||||
#elif HAVE_EXPAT_H
|
||||
#include <expat.h>
|
||||
#endif
|
||||
#if HAVE_MBEDTLS_VERSION_H
|
||||
#include <mbedtls/version.h>
|
||||
#endif
|
||||
#if HAVE_NETTLE_VERSION_H
|
||||
#include <nettle/version.h>
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#if HAVE_OPENSSL_OPENSSLV_H
|
||||
#include <openssl/opensslv.h>
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#if HAVE_ICONV_H
|
||||
#include <iconv.h>
|
||||
#endif
|
||||
#if HAVE_PCRE_H
|
||||
#include <pcre.h>
|
||||
#endif
|
||||
#if HAVE_PCRE2_H
|
||||
#include <pcre2.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_string.h"
|
||||
#include "archive_cryptor_private.h"
|
||||
#include "archive_digest_private.h"
|
||||
|
||||
static void
|
||||
archive_regex_version(struct archive_string* str)
|
||||
{
|
||||
#if HAVE_LIBPCREPOSIX && HAVE_PCRE_H
|
||||
archive_strcat(str, " libpcre/");
|
||||
archive_strcat(str, archive_libpcre_version());
|
||||
#elif HAVE_LIBPCRE2POSIX && HAVE_PCRE2_H
|
||||
archive_strcat(str, " libpcre2/");
|
||||
archive_strcat(str, archive_libpcre2_version());
|
||||
#else
|
||||
(void)str; /* UNUSED */
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
archive_xml_version(struct archive_string* str)
|
||||
{
|
||||
#if HAVE_LIBXML_XMLVERSION_H && HAVE_LIBXML2
|
||||
archive_strcat(str, " libxml2/");
|
||||
archive_strcat(str, archive_libxml2_version());
|
||||
#elif HAVE_BSDXML_H && HAVE_LIBBSDXML
|
||||
archive_strcat(str, " bsdxml/");
|
||||
archive_strcat(str, archive_libbsdxml_version());
|
||||
#elif HAVE_EXPAT_H && HAVE_LIBEXPAT
|
||||
archive_strcat(str, " expat/");
|
||||
archive_strcat(str, archive_libexpat_version());
|
||||
#else
|
||||
(void)str; /* UNUSED */
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
archive_libb2_version(struct archive_string* str)
|
||||
{
|
||||
archive_strcat(str, " libb2/");
|
||||
#if HAVE_BLAKE2_H && HAVE_LIBB2
|
||||
#if defined(LIBB2_PKGCONFIG_VERSION)
|
||||
archive_strcat(str, LIBB2_PKGCONFIG_VERSION);
|
||||
#else
|
||||
archive_strcat(str, "system");
|
||||
#endif
|
||||
#else
|
||||
archive_strcat(str, "bundled");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
archive_crypto_version(struct archive_string* str)
|
||||
{
|
||||
#if defined(ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto)
|
||||
archive_strcat(str, " CommonCrypto/");
|
||||
archive_strcat(str, archive_commoncrypto_version());
|
||||
#endif
|
||||
#if defined(ARCHIVE_CRYPTOR_USE_CNG)
|
||||
archive_strcat(str, " cng/");
|
||||
archive_strcat(str, archive_cng_version());
|
||||
#endif
|
||||
#if defined(ARCHIVE_CRYPTOR_USE_MBED)
|
||||
archive_strcat(str, " mbedtls/");
|
||||
archive_strcat(str, archive_mbedtls_version());
|
||||
#endif
|
||||
#if defined(ARCHIVE_CRYPTOR_USE_NETTLE)
|
||||
archive_strcat(str, " nettle/");
|
||||
archive_strcat(str, archive_nettle_version());
|
||||
#endif
|
||||
#if defined(ARCHIVE_CRYPTOR_USE_OPENSSL)
|
||||
archive_strcat(str, " openssl/");
|
||||
archive_strcat(str, archive_openssl_version());
|
||||
#endif
|
||||
#if defined(ARCHIVE_CRYPTOR_USE_LIBMD)
|
||||
archive_strcat(str, " libmd/");
|
||||
archive_strcat(str, archive_libmd_version());
|
||||
#endif
|
||||
#if defined(ARCHIVE_CRYPTOR_USE_WINCRYPT)
|
||||
archive_strcat(str, " WinCrypt/");
|
||||
archive_strcat(str, archive_wincrypt_version());
|
||||
#endif
|
||||
// Just in case
|
||||
(void)str; /* UNUSED */
|
||||
}
|
||||
|
||||
const char *
|
||||
archive_version_details(void)
|
||||
@@ -62,12 +176,17 @@ archive_version_details(void)
|
||||
const char *bzlib = archive_bzlib_version();
|
||||
const char *liblz4 = archive_liblz4_version();
|
||||
const char *libzstd = archive_libzstd_version();
|
||||
const char *liblzo = archive_liblzo2_version();
|
||||
const char *libiconv = archive_libiconv_version();
|
||||
const char *libacl = archive_libacl_version();
|
||||
const char *librichacl = archive_librichacl_version();
|
||||
const char *libattr = archive_libacl_version();
|
||||
|
||||
if (!init) {
|
||||
archive_string_init(&str);
|
||||
|
||||
archive_strcat(&str, ARCHIVE_VERSION_STRING);
|
||||
if (zlib != NULL) {
|
||||
if (zlib) {
|
||||
archive_strcat(&str, " zlib/");
|
||||
archive_strcat(&str, zlib);
|
||||
}
|
||||
@@ -91,6 +210,30 @@ archive_version_details(void)
|
||||
archive_strcat(&str, " libzstd/");
|
||||
archive_strcat(&str, libzstd);
|
||||
}
|
||||
if (liblzo) {
|
||||
archive_strcat(&str, " liblzo2/");
|
||||
archive_strcat(&str, liblzo);
|
||||
}
|
||||
archive_xml_version(&str);
|
||||
archive_regex_version(&str);
|
||||
archive_crypto_version(&str);
|
||||
archive_libb2_version(&str);
|
||||
if (librichacl) {
|
||||
archive_strcat(&str, " librichacl/");
|
||||
archive_strcat(&str, librichacl);
|
||||
}
|
||||
if (libacl) {
|
||||
archive_strcat(&str, " libacl/");
|
||||
archive_strcat(&str, libacl);
|
||||
}
|
||||
if (libattr) {
|
||||
archive_strcat(&str, " libattr/");
|
||||
archive_strcat(&str, libattr);
|
||||
}
|
||||
if (libiconv) {
|
||||
archive_strcat(&str, " libiconv/");
|
||||
archive_strcat(&str, libiconv);
|
||||
}
|
||||
}
|
||||
return str.s;
|
||||
}
|
||||
@@ -98,8 +241,8 @@ archive_version_details(void)
|
||||
const char *
|
||||
archive_zlib_version(void)
|
||||
{
|
||||
#ifdef HAVE_ZLIB_H
|
||||
return ZLIB_VERSION;
|
||||
#if HAVE_ZLIB_H && HAVE_LIBZ
|
||||
return zlibVersion();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
@@ -108,8 +251,8 @@ archive_zlib_version(void)
|
||||
const char *
|
||||
archive_liblzma_version(void)
|
||||
{
|
||||
#ifdef HAVE_LZMA_H
|
||||
return LZMA_VERSION_STRING;
|
||||
#if HAVE_LZMA_H && HAVE_LIBLZMA
|
||||
return lzma_version_string();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
@@ -118,7 +261,7 @@ archive_liblzma_version(void)
|
||||
const char *
|
||||
archive_bzlib_version(void)
|
||||
{
|
||||
#ifdef HAVE_BZLIB_H
|
||||
#if HAVE_BZLIB_H && HAVE_LIBBZ2
|
||||
return BZ2_bzlibVersion();
|
||||
#else
|
||||
return NULL;
|
||||
@@ -128,12 +271,22 @@ archive_bzlib_version(void)
|
||||
const char *
|
||||
archive_liblz4_version(void)
|
||||
{
|
||||
#if defined(HAVE_LZ4_H) && defined(HAVE_LIBLZ4)
|
||||
#if HAVE_LZ4_H && HAVE_LIBLZ4
|
||||
#if LZ4_VERSION_NUMBER > 10705
|
||||
return LZ4_versionString();
|
||||
#elif LZ4_VERSION_NUMBER > 10300
|
||||
div_t major = div(LZ4_versionNumber(), 10000);
|
||||
div_t minor = div(major.rem, 100);
|
||||
static char lz4_version[9];
|
||||
snprintf(lz4_version, 9, "%d.%d.%d", major.quot, minor.quot, minor.rem);
|
||||
return lz4_version;
|
||||
#else
|
||||
#define str(s) #s
|
||||
#define NUMBER(x) str(x)
|
||||
return NUMBER(LZ4_VERSION_MAJOR) "." NUMBER(LZ4_VERSION_MINOR) "." NUMBER(LZ4_VERSION_RELEASE);
|
||||
#undef NUMBER
|
||||
#undef str
|
||||
#endif
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
@@ -143,7 +296,243 @@ const char *
|
||||
archive_libzstd_version(void)
|
||||
{
|
||||
#if HAVE_ZSTD_H && HAVE_LIBZSTD
|
||||
return ZSTD_VERSION_STRING;
|
||||
#if ZSTD_VERSION_NUMBER > 10300
|
||||
return ZSTD_versionString();
|
||||
#else
|
||||
div_t major = div(ZSTD_versionNumber(), 10000);
|
||||
div_t minor = div(major.rem, 100);
|
||||
static char zstd_version[9];
|
||||
snprintf(zstd_version, 9, "%d.%d.%d", major.quot, minor.quot, minor.rem);
|
||||
return zstd_version;
|
||||
#endif
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *
|
||||
archive_liblzo2_version(void)
|
||||
{
|
||||
#if HAVE_LZO_LZOCONF_H && HAVE_LIBLZO2
|
||||
return LZO_VERSION_STRING;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *
|
||||
archive_libbsdxml_version(void)
|
||||
{
|
||||
#if HAVE_BSDXML_H && HAVE_LIBBSDXML
|
||||
return XML_ExpatVersion();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *
|
||||
archive_libxml2_version(void)
|
||||
{
|
||||
#if HAVE_LIBXML_XMLREADER_H && HAVE_LIBXML2
|
||||
return LIBXML_DOTTED_VERSION;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *
|
||||
archive_libexpat_version(void)
|
||||
{
|
||||
#if HAVE_EXPAT_H && HAVE_LIBEXPAT
|
||||
return XML_ExpatVersion();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *
|
||||
archive_mbedtls_version(void)
|
||||
{
|
||||
#if defined(ARCHIVE_CRYPTOR_USE_MBED) || defined(ARCHIVE_CRYPTO_MBED)
|
||||
static char mbed_version[9];
|
||||
mbedtls_version_get_string(mbed_version);
|
||||
return mbed_version;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *
|
||||
archive_nettle_version(void)
|
||||
{
|
||||
#if defined(ARCHIVE_CRYPTOR_USE_NETTLE) || defined(ARCHIVE_CRYPTO_NETTLE)
|
||||
static char nettle_version[6];
|
||||
snprintf(nettle_version, 6, "%d.%d", nettle_version_major(), nettle_version_minor());
|
||||
return nettle_version;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *
|
||||
archive_openssl_version(void)
|
||||
{
|
||||
#if defined(ARCHIVE_CRYPTOR_USE_OPENSSL) || defined(ARCHIVE_CRYPTO_OPENSSL)
|
||||
#ifdef OPENSSL_VERSION_STR
|
||||
return OPENSSL_VERSION_STR;
|
||||
#else
|
||||
#define OPENSSL_MAJOR (OPENSSL_VERSION_NUMBER >> 28)
|
||||
#define OPENSSL_MINOR ((OPENSSL_VERSION_NUMBER >> 20) & 0xFF)
|
||||
static char openssl_version[6];
|
||||
snprintf(openssl_version, 6, "%ld.%ld", OPENSSL_MAJOR, OPENSSL_MINOR);
|
||||
return openssl_version;
|
||||
#undef OPENSSL_MAJOR
|
||||
#undef OPENSSL_MINOR
|
||||
#endif
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *
|
||||
archive_libmd_version(void)
|
||||
{
|
||||
#if defined(ARCHIVE_CRYPTOR_USE_LIBMD) || defined(ARCHIVE_CRYPTO_LIBMD)
|
||||
return "system";
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *
|
||||
archive_commoncrypto_version(void)
|
||||
{
|
||||
#if defined(ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto) || defined(ARCHIVE_CRYPTO_CommonCrypto)
|
||||
return "system";
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *
|
||||
archive_cng_version(void)
|
||||
{
|
||||
#if defined(ARCHIVE_CRYPTOR_USE_CNG) || defined(ARCHIVE_CRYPTO_CNG)
|
||||
#ifdef BCRYPT_HASH_INTERFACE_MAJORVERSION_2
|
||||
return "2.0";
|
||||
#else
|
||||
return "1.0";
|
||||
#endif
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *
|
||||
archive_wincrypt_version(void)
|
||||
{
|
||||
#if defined(ARCHIVE_CRYPTOR_USE_WINCRYPT) || defined(ARCHIVE_CRYPTO_WINCRYPT)
|
||||
HCRYPTPROV prov;
|
||||
if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
|
||||
if (GetLastError() != (DWORD)NTE_BAD_KEYSET)
|
||||
return NULL;
|
||||
if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
|
||||
return NULL;
|
||||
}
|
||||
DWORD version, length = sizeof(version);
|
||||
if (!CryptGetProvParam(prov, PP_VERSION, (BYTE *)&version, &length, 0)) {
|
||||
return NULL;
|
||||
} else {
|
||||
char major = (version >> 8) & 0xFF;
|
||||
char minor = version & 0xFF;
|
||||
static char wincrypt_version[6];
|
||||
snprintf(wincrypt_version, 6, "%hhd.%hhd", major, minor);
|
||||
return wincrypt_version;
|
||||
}
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *
|
||||
archive_librichacl_version(void)
|
||||
{
|
||||
#if HAVE_LIBRICHACL
|
||||
#if defined(LIBRICHACL_PKGCONFIG_VERSION)
|
||||
return LIBRICHACL_PKGCONFIG_VERSION;
|
||||
#else
|
||||
return "system";
|
||||
#endif
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *
|
||||
archive_libacl_version(void)
|
||||
{
|
||||
#if HAVE_LIBACL
|
||||
#if defined(LIBACL_PKGCONFIG_VERSION)
|
||||
return LIBACL_PKGCONFIG_VERSION;
|
||||
#else
|
||||
return "system";
|
||||
#endif
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *
|
||||
archive_libattr_version(void)
|
||||
{
|
||||
#if HAVE_LIBATTR
|
||||
#if defined(LIBATTR_PKGCONFIG_VERSION)
|
||||
return LIBATTR_PKGCONFIG_VERSION;
|
||||
#else
|
||||
return "system";
|
||||
#endif
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *
|
||||
archive_libiconv_version(void)
|
||||
{
|
||||
#if HAVE_LIBCHARSET && HAVE_ICONV_H
|
||||
char major = _libiconv_version >> 8;
|
||||
char minor = _libiconv_version & 0xFF;
|
||||
static char charset_version[6];
|
||||
snprintf(charset_version, 6, "%hhd.%hhd", major, minor);
|
||||
return charset_version;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *
|
||||
archive_libpcre_version(void)
|
||||
{
|
||||
#if HAVE_LIBPCREPOSIX && HAVE_PCRE_H
|
||||
#define str(s) #s
|
||||
#define NUMBER(x) str(x)
|
||||
return NUMBER(PCRE_MAJOR) "." NUMBER(PCRE_MINOR);
|
||||
#undef NUMBER
|
||||
#undef str
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *
|
||||
archive_libpcre2_version(void)
|
||||
{
|
||||
#if HAVE_LIBPCRE2POSIX && HAVE_PCRE2_H
|
||||
#define str(s) #s
|
||||
#define NUMBER(x) str(x)
|
||||
return NUMBER(PCRE2_MAJOR) "." NUMBER(PCRE2_MINOR);
|
||||
#undef NUMBER
|
||||
#undef str
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
@@ -283,7 +283,7 @@ __archive_write_filters_open(struct archive_write *a)
|
||||
}
|
||||
|
||||
/*
|
||||
* Close all filtes
|
||||
* Close all filters
|
||||
*/
|
||||
static int
|
||||
__archive_write_filters_close(struct archive_write *a)
|
||||
|
||||
@@ -166,7 +166,7 @@ archive_filter_b64encode_open(struct archive_write_filter *f)
|
||||
}
|
||||
|
||||
archive_string_sprintf(&state->encoded_buff, "begin-base64 %o %s\n",
|
||||
state->mode, state->name.s);
|
||||
(unsigned int)state->mode, state->name.s);
|
||||
|
||||
f->data = state;
|
||||
return (0);
|
||||
|
||||
@@ -58,6 +58,7 @@ archive_write_set_compression_gzip(struct archive *a)
|
||||
struct private_data {
|
||||
int compression_level;
|
||||
int timestamp;
|
||||
char *original_filename;
|
||||
#ifdef HAVE_ZLIB_H
|
||||
z_stream stream;
|
||||
int64_t total_in;
|
||||
@@ -113,6 +114,8 @@ archive_write_add_filter_gzip(struct archive *_a)
|
||||
f->free = &archive_compressor_gzip_free;
|
||||
f->code = ARCHIVE_FILTER_GZIP;
|
||||
f->name = "gzip";
|
||||
|
||||
data->original_filename = NULL;
|
||||
#ifdef HAVE_ZLIB_H
|
||||
data->compression_level = Z_DEFAULT_COMPRESSION;
|
||||
return (ARCHIVE_OK);
|
||||
@@ -140,6 +143,7 @@ archive_compressor_gzip_free(struct archive_write_filter *f)
|
||||
#else
|
||||
__archive_write_program_free(data->pdata);
|
||||
#endif
|
||||
free((void*)data->original_filename);
|
||||
free(data);
|
||||
f->data = NULL;
|
||||
return (ARCHIVE_OK);
|
||||
@@ -165,6 +169,13 @@ archive_compressor_gzip_options(struct archive_write_filter *f, const char *key,
|
||||
data->timestamp = (value == NULL)?-1:1;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
if (strcmp(key, "original-filename") == 0) {
|
||||
free((void*)data->original_filename);
|
||||
data->original_filename = NULL;
|
||||
if (value)
|
||||
data->original_filename = strdup(value);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/* Note: The "warn" return is just to inform the options
|
||||
* supervisor that we didn't handle it. It will generate
|
||||
@@ -210,7 +221,7 @@ archive_compressor_gzip_open(struct archive_write_filter *f)
|
||||
data->compressed[0] = 0x1f; /* GZip signature bytes */
|
||||
data->compressed[1] = 0x8b;
|
||||
data->compressed[2] = 0x08; /* "Deflate" compression */
|
||||
data->compressed[3] = 0; /* No options */
|
||||
data->compressed[3] = data->original_filename == NULL ? 0 : 0x8;
|
||||
if (data->timestamp >= 0) {
|
||||
time_t t = time(NULL);
|
||||
data->compressed[4] = (uint8_t)(t)&0xff; /* Timestamp */
|
||||
@@ -229,6 +240,12 @@ archive_compressor_gzip_open(struct archive_write_filter *f)
|
||||
data->stream.next_out += 10;
|
||||
data->stream.avail_out -= 10;
|
||||
|
||||
if (data->original_filename != NULL) {
|
||||
strcpy((char*)data->compressed + 10, data->original_filename);
|
||||
data->stream.next_out += strlen(data->original_filename) + 1;
|
||||
data->stream.avail_out -= strlen(data->original_filename) + 1;
|
||||
}
|
||||
|
||||
f->write = archive_compressor_gzip_write;
|
||||
|
||||
/* Initialize compression library. */
|
||||
|
||||
@@ -155,7 +155,7 @@ archive_filter_uuencode_open(struct archive_write_filter *f)
|
||||
}
|
||||
|
||||
archive_string_sprintf(&state->encoded_buff, "begin %o %s\n",
|
||||
state->mode, state->name.s);
|
||||
(unsigned int)state->mode, state->name.s);
|
||||
|
||||
f->data = state;
|
||||
return (0);
|
||||
|
||||
@@ -478,9 +478,11 @@ la_verify_filetype(mode_t mode, __LA_MODE_T filetype) {
|
||||
case AE_IFLNK:
|
||||
ret = (S_ISLNK(mode));
|
||||
break;
|
||||
#ifdef S_ISSOCK
|
||||
case AE_IFSOCK:
|
||||
ret = (S_ISSOCK(mode));
|
||||
break;
|
||||
#endif
|
||||
case AE_IFCHR:
|
||||
ret = (S_ISCHR(mode));
|
||||
break;
|
||||
@@ -3605,7 +3607,7 @@ set_time_tru64(int fd, int mode, const char *name,
|
||||
tstamp.atime.tv_sec = atime;
|
||||
tstamp.mtime.tv_sec = mtime;
|
||||
tstamp.ctime.tv_sec = ctime;
|
||||
#if defined (__hpux) && defined (__ia64)
|
||||
#if defined (__hpux) && ( defined (__ia64) || defined (__hppa) )
|
||||
tstamp.atime.tv_nsec = atime_nsec;
|
||||
tstamp.mtime.tv_nsec = mtime_nsec;
|
||||
tstamp.ctime.tv_nsec = ctime_nsec;
|
||||
@@ -3788,7 +3790,7 @@ set_mode(struct archive_write_disk *a, int mode)
|
||||
* permissions on symlinks, so a failure here has no
|
||||
* impact.
|
||||
*/
|
||||
if (lchmod(a->name, mode) != 0) {
|
||||
if (lchmod(a->name, (mode_t)mode) != 0) {
|
||||
switch (errno) {
|
||||
case ENOTSUP:
|
||||
case ENOSYS:
|
||||
@@ -3803,7 +3805,8 @@ set_mode(struct archive_write_disk *a, int mode)
|
||||
break;
|
||||
default:
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Can't set permissions to 0%o", (int)mode);
|
||||
"Can't set permissions to 0%o",
|
||||
(unsigned int)mode);
|
||||
r = ARCHIVE_WARN;
|
||||
}
|
||||
}
|
||||
@@ -3817,16 +3820,16 @@ set_mode(struct archive_write_disk *a, int mode)
|
||||
*/
|
||||
#ifdef HAVE_FCHMOD
|
||||
if (a->fd >= 0)
|
||||
r2 = fchmod(a->fd, mode);
|
||||
r2 = fchmod(a->fd, (mode_t)mode);
|
||||
else
|
||||
#endif
|
||||
/* If this platform lacks fchmod(), then
|
||||
* we'll just use chmod(). */
|
||||
r2 = chmod(a->name, mode);
|
||||
r2 = chmod(a->name, (mode_t)mode);
|
||||
|
||||
if (r2 != 0) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Can't set permissions to 0%o", (int)mode);
|
||||
"Can't set permissions to 0%o", (unsigned int)mode);
|
||||
r = ARCHIVE_WARN;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ open_filename(struct archive *a, int mbs_fn, const void *filename)
|
||||
(const char *)filename);
|
||||
else
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
"Can't convert '%S' to MBS",
|
||||
"Can't convert '%ls' to MBS",
|
||||
(const wchar_t *)filename);
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
@@ -170,7 +170,7 @@ file_open(struct archive *a, void *client_data)
|
||||
else {
|
||||
archive_mstring_get_wcs(a, &mine->filename, &wcs);
|
||||
archive_set_error(a, errno,
|
||||
"Can't convert '%S' to MBS", wcs);
|
||||
"Can't convert '%ls' to MBS", wcs);
|
||||
}
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@@ -181,7 +181,7 @@ file_open(struct archive *a, void *client_data)
|
||||
if (mbs != NULL)
|
||||
archive_set_error(a, errno, "Failed to open '%s'", mbs);
|
||||
else
|
||||
archive_set_error(a, errno, "Failed to open '%S'", wcs);
|
||||
archive_set_error(a, errno, "Failed to open '%ls'", wcs);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ file_open(struct archive *a, void *client_data)
|
||||
if (mbs != NULL)
|
||||
archive_set_error(a, errno, "Couldn't stat '%s'", mbs);
|
||||
else
|
||||
archive_set_error(a, errno, "Couldn't stat '%S'", wcs);
|
||||
archive_set_error(a, errno, "Couldn't stat '%ls'", wcs);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,12 @@
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_BZLIB_H
|
||||
#include <bzlib.h>
|
||||
#endif
|
||||
@@ -38,6 +43,9 @@
|
||||
#ifdef HAVE_ZLIB_H
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_ZSTD_H
|
||||
#include <zstd.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#ifndef HAVE_ZLIB_H
|
||||
@@ -50,6 +58,7 @@
|
||||
#include "archive_private.h"
|
||||
#include "archive_rb.h"
|
||||
#include "archive_string.h"
|
||||
#include "archive_time_private.h"
|
||||
#include "archive_write_private.h"
|
||||
#include "archive_write_set_format_private.h"
|
||||
|
||||
@@ -63,6 +72,8 @@
|
||||
#define _7Z_BZIP2 0x040202
|
||||
#define _7Z_PPMD 0x030401
|
||||
|
||||
#define _7Z_ZSTD 0x4F71101 /* Copied from https://github.com/mcmilk/7-Zip-zstd.git */
|
||||
|
||||
/*
|
||||
* 7-Zip header property IDs.
|
||||
*/
|
||||
@@ -110,6 +121,9 @@
|
||||
// the attr field along with the unix permissions.
|
||||
#define FILE_ATTRIBUTE_UNIX_EXTENSION 0x8000
|
||||
|
||||
// Many systems define min or MIN, but not all.
|
||||
#define sevenzipmin(a,b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
enum la_zaction {
|
||||
ARCHIVE_Z_FINISH,
|
||||
ARCHIVE_Z_RUN
|
||||
@@ -209,7 +223,11 @@ struct _7zip {
|
||||
#define ENCODED_CRC32 2
|
||||
|
||||
unsigned opt_compression;
|
||||
|
||||
int opt_compression_level;
|
||||
int opt_zstd_compression_level; // This requires a different default value.
|
||||
|
||||
int opt_threads;
|
||||
|
||||
struct la_zstream stream;
|
||||
struct coder coder;
|
||||
@@ -285,12 +303,19 @@ static int compression_code_lzma(struct archive *,
|
||||
static int compression_end_lzma(struct archive *, struct la_zstream *);
|
||||
#endif
|
||||
static int compression_init_encoder_ppmd(struct archive *,
|
||||
struct la_zstream *, unsigned, uint32_t);
|
||||
struct la_zstream *, uint8_t, uint32_t);
|
||||
static int compression_code_ppmd(struct archive *,
|
||||
struct la_zstream *, enum la_zaction);
|
||||
static int compression_end_ppmd(struct archive *, struct la_zstream *);
|
||||
static int _7z_compression_init_encoder(struct archive_write *, unsigned,
|
||||
int);
|
||||
static int compression_init_encoder_zstd(struct archive *,
|
||||
struct la_zstream *, int, int);
|
||||
#if defined(HAVE_ZSTD_H)
|
||||
static int compression_code_zstd(struct archive *,
|
||||
struct la_zstream *, enum la_zaction);
|
||||
static int compression_end_zstd(struct archive *, struct la_zstream *);
|
||||
#endif
|
||||
static int compression_code(struct archive *,
|
||||
struct la_zstream *, enum la_zaction);
|
||||
static int compression_end(struct archive *,
|
||||
@@ -301,6 +326,21 @@ static int make_header(struct archive_write *, uint64_t, uint64_t,
|
||||
static int make_streamsInfo(struct archive_write *, uint64_t, uint64_t,
|
||||
uint64_t, int, struct coder *, int, uint32_t);
|
||||
|
||||
static int
|
||||
string_to_number(const char *string, intmax_t *numberp)
|
||||
{
|
||||
char *end;
|
||||
|
||||
if (string == NULL || *string == '\0')
|
||||
return (ARCHIVE_WARN);
|
||||
*numberp = strtoimax(string, &end, 10);
|
||||
if (end == string || *end != '\0' || errno == EOVERFLOW) {
|
||||
*numberp = 0;
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
int
|
||||
archive_write_set_format_7zip(struct archive *_a)
|
||||
{
|
||||
@@ -335,11 +375,24 @@ archive_write_set_format_7zip(struct archive *_a)
|
||||
zip->opt_compression = _7Z_BZIP2;
|
||||
#elif defined(HAVE_ZLIB_H)
|
||||
zip->opt_compression = _7Z_DEFLATE;
|
||||
#elif HAVE_ZSTD_H
|
||||
zip->opt_compression = _7Z_ZSTD;
|
||||
#else
|
||||
zip->opt_compression = _7Z_COPY;
|
||||
#endif
|
||||
|
||||
zip->opt_compression_level = 6;
|
||||
|
||||
#ifdef ZSTD_CLEVEL_DEFAULT
|
||||
// Zstandard compression needs a different default
|
||||
// value than other encoders.
|
||||
zip->opt_zstd_compression_level = ZSTD_CLEVEL_DEFAULT;
|
||||
#else
|
||||
zip->opt_zstd_compression_level = 3;
|
||||
#endif
|
||||
|
||||
zip->opt_threads = 1;
|
||||
|
||||
a->format_data = zip;
|
||||
|
||||
a->format_name = "7zip";
|
||||
@@ -397,6 +450,13 @@ _7z_options(struct archive_write *a, const char *key, const char *value)
|
||||
zip->opt_compression = _7Z_LZMA2;
|
||||
#else
|
||||
name = "lzma2";
|
||||
#endif
|
||||
else if (strcmp(value, "zstd") == 0 ||
|
||||
strcmp(value, "ZSTD") == 0)
|
||||
#if HAVE_ZSTD_H
|
||||
zip->opt_compression = _7Z_ZSTD;
|
||||
#else
|
||||
name = "zstd";
|
||||
#endif
|
||||
else if (strcmp(value, "ppmd") == 0 ||
|
||||
strcmp(value, "PPMD") == 0 ||
|
||||
@@ -420,16 +480,68 @@ _7z_options(struct archive_write *a, const char *key, const char *value)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
if (strcmp(key, "compression-level") == 0) {
|
||||
if (value == NULL ||
|
||||
!(value[0] >= '0' && value[0] <= '9') ||
|
||||
value[1] != '\0') {
|
||||
archive_set_error(&(a->archive),
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Illegal value `%s'",
|
||||
value);
|
||||
if (value == NULL || *value == '\0') {
|
||||
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
|
||||
"Invalid compression-level option value `%s'", value);
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
zip->opt_compression_level = value[0] - '0';
|
||||
|
||||
char *end = NULL;
|
||||
long lvl = strtol(value, &end, 10);
|
||||
if (end == NULL || *end != '\0') {
|
||||
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
|
||||
"parsing compression-level option value failed `%s'", value);
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
|
||||
#if HAVE_ZSTD_H && HAVE_ZSTD_compressStream && HAVE_ZSTD_minCLevel
|
||||
int min_level = sevenzipmin(0, ZSTD_minCLevel());
|
||||
#else
|
||||
const int min_level = 0;
|
||||
#endif
|
||||
|
||||
#if HAVE_ZSTD_H && HAVE_ZSTD_compressStream
|
||||
int max_level = ZSTD_maxCLevel();
|
||||
#else
|
||||
const int max_level = 9;
|
||||
#endif
|
||||
|
||||
if (lvl < min_level || lvl > max_level) {
|
||||
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
|
||||
"compression-level option value `%ld' out of range", lvl);
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
|
||||
// Note: we don't know here if this value is for zstd (negative to ~22),
|
||||
// or zlib-style 0-9. If zstd is enabled but not in use, we will need to
|
||||
// validate opt_compression_level before use.
|
||||
zip->opt_compression_level = (int)lvl;
|
||||
|
||||
zip->opt_zstd_compression_level = (int)lvl;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
if (strcmp(key, "threads") == 0) {
|
||||
intmax_t threads;
|
||||
if (string_to_number(value, &threads) != ARCHIVE_OK) {
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
if (threads < 0) {
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
if (threads == 0) {
|
||||
#if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
|
||||
threads = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
#elif !defined(__CYGWIN__) && defined(_WIN32_WINNT) && \
|
||||
_WIN32_WINNT >= 0x0601 /* _WIN32_WINNT_WIN7 */
|
||||
DWORD winCores = GetActiveProcessorCount(
|
||||
ALL_PROCESSOR_GROUPS);
|
||||
threads = (intmax_t)winCores;
|
||||
#else
|
||||
threads = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
zip->opt_threads = (int)threads;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
@@ -495,8 +607,20 @@ _7z_write_header(struct archive_write *a, struct archive_entry *entry)
|
||||
* Init compression.
|
||||
*/
|
||||
if ((zip->total_number_entry - zip->total_number_empty_entry) == 1) {
|
||||
r = _7z_compression_init_encoder(a, zip->opt_compression,
|
||||
zip->opt_compression_level);
|
||||
|
||||
int level = zip->opt_compression_level;
|
||||
#if HAVE_ZSTD_H
|
||||
if (zip->opt_compression == _7Z_ZSTD) {
|
||||
level = zip->opt_zstd_compression_level;
|
||||
} else if (level < 0 || level > 9) {
|
||||
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
|
||||
"compression-level option value `%d' out of range 0-9", level);
|
||||
file_free(file);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
#endif
|
||||
|
||||
r = _7z_compression_init_encoder(a, zip->opt_compression, level);
|
||||
if (r < 0) {
|
||||
file_free(file);
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -785,8 +909,12 @@ _7z_close(struct archive_write *a)
|
||||
#else
|
||||
header_compression = _7Z_COPY;
|
||||
#endif
|
||||
r = _7z_compression_init_encoder(a, header_compression,
|
||||
zip->opt_compression_level);
|
||||
|
||||
int level = zip->opt_compression_level;
|
||||
if (level < 0) level = 0;
|
||||
else if (level > 9) level = 9;
|
||||
|
||||
r = _7z_compression_init_encoder(a, header_compression, level);
|
||||
if (r < 0)
|
||||
return (r);
|
||||
zip->crc32flg = PRECODE_CRC32;
|
||||
@@ -844,7 +972,7 @@ _7z_close(struct archive_write *a)
|
||||
header_offset = header_size = 0;
|
||||
header_crc32 = 0;
|
||||
}
|
||||
|
||||
|
||||
length = zip->temp_offset;
|
||||
|
||||
/*
|
||||
@@ -1164,20 +1292,6 @@ make_streamsInfo(struct archive_write *a, uint64_t offset, uint64_t pack_size,
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
|
||||
#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
|
||||
static uint64_t
|
||||
utcToFiletime(time_t t, long ns)
|
||||
{
|
||||
uint64_t fileTime;
|
||||
|
||||
fileTime = t;
|
||||
fileTime *= 10000000;
|
||||
fileTime += ns / 100;
|
||||
fileTime += EPOC_TIME;
|
||||
return (fileTime);
|
||||
}
|
||||
|
||||
static int
|
||||
make_time(struct archive_write *a, uint8_t type, unsigned flg, int ti)
|
||||
{
|
||||
@@ -1249,7 +1363,6 @@ make_time(struct archive_write *a, uint8_t type, unsigned flg, int ti)
|
||||
if (r < 0)
|
||||
return (r);
|
||||
|
||||
|
||||
/*
|
||||
* Make Times.
|
||||
*/
|
||||
@@ -1257,7 +1370,7 @@ make_time(struct archive_write *a, uint8_t type, unsigned flg, int ti)
|
||||
for (;file != NULL; file = file->next) {
|
||||
if ((file->flg & flg) == 0)
|
||||
continue;
|
||||
archive_le64enc(filetime, utcToFiletime(file->times[ti].time,
|
||||
archive_le64enc(filetime, unix_to_ntfs(file->times[ti].time,
|
||||
file->times[ti].time_ns));
|
||||
r = (int)compress_out(a, filetime, 8, ARCHIVE_Z_RUN);
|
||||
if (r < 0)
|
||||
@@ -1504,7 +1617,7 @@ file_cmp_node(const struct archive_rb_node *n1,
|
||||
return (memcmp(f1->utf16name, f2->utf16name, f1->name_len));
|
||||
return (f1->name_len > f2->name_len)?1:-1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
file_cmp_key(const struct archive_rb_node *n, const void *key)
|
||||
{
|
||||
@@ -1646,7 +1759,8 @@ file_init_register_empty(struct _7zip *zip)
|
||||
}
|
||||
|
||||
#if !defined(HAVE_ZLIB_H) || !defined(HAVE_BZLIB_H) ||\
|
||||
!defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H)
|
||||
!defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H) ||\
|
||||
!(HAVE_ZSTD_H && HAVE_ZSTD_compressStream)
|
||||
static int
|
||||
compression_unsupported_encoder(struct archive *a,
|
||||
struct la_zstream *lastrm, const char *name)
|
||||
@@ -2159,7 +2273,7 @@ ppmd_write(void *p, Byte b)
|
||||
|
||||
static int
|
||||
compression_init_encoder_ppmd(struct archive *a,
|
||||
struct la_zstream *lastrm, unsigned maxOrder, uint32_t msize)
|
||||
struct la_zstream *lastrm, uint8_t maxOrder, uint32_t msize)
|
||||
{
|
||||
struct ppmd_stream *strm;
|
||||
uint8_t *props;
|
||||
@@ -2279,6 +2393,117 @@ compression_end_ppmd(struct archive *a, struct la_zstream *lastrm)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#if HAVE_ZSTD_H && HAVE_ZSTD_compressStream
|
||||
static int
|
||||
compression_init_encoder_zstd(struct archive *a, struct la_zstream *lastrm, int level, int threads)
|
||||
{
|
||||
if (lastrm->valid)
|
||||
compression_end(a, lastrm);
|
||||
|
||||
ZSTD_CStream *strm = ZSTD_createCStream();
|
||||
if (strm == NULL) {
|
||||
archive_set_error(a, ENOMEM,
|
||||
"Can't allocate memory for zstd stream");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
if (ZSTD_isError(ZSTD_initCStream(strm, level))) {
|
||||
ZSTD_freeCStream(strm);
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
"Internal error initializing zstd compressor object");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
ZSTD_CCtx_setParameter(strm, ZSTD_c_nbWorkers, threads);
|
||||
|
||||
// p7zip-zstd fails to unpack archives that don't have prop_size 5.
|
||||
// 7-Zip-zstd fails to unpack archives that don't have prop_size 3 or 5.
|
||||
// So let's use 5...
|
||||
lastrm->prop_size = 5;
|
||||
lastrm->props = calloc(5, 1);
|
||||
if (lastrm->props == NULL) {
|
||||
ZSTD_freeCStream(strm);
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
"Internal error initializing zstd compressor properties");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
// Refer to the DProps struct in 7-Zip-zstd's ZstdDecoder.h:
|
||||
// https://github.com/mcmilk/7-Zip-zstd/blob/79b2c78e9e7735ddf90147129b75cf2797ff6522/CPP/7zip/Compress/ZstdDecoder.h#L34S
|
||||
lastrm->props[0] = ZSTD_VERSION_MAJOR;
|
||||
lastrm->props[1] = ZSTD_VERSION_MINOR;
|
||||
lastrm->props[2] = level;
|
||||
// lastrm->props[3] and lastrm->props[4] are reserved. Leave them as 0.
|
||||
|
||||
lastrm->real_stream = strm;
|
||||
lastrm->valid = 1;
|
||||
lastrm->code = compression_code_zstd;
|
||||
lastrm->end = compression_end_zstd;
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
compression_code_zstd(struct archive *a,
|
||||
struct la_zstream *lastrm, enum la_zaction action)
|
||||
{
|
||||
ZSTD_CStream *strm = (ZSTD_CStream *)lastrm->real_stream;
|
||||
|
||||
ZSTD_outBuffer out = { .dst = lastrm->next_out, .size = lastrm->avail_out, .pos = 0 };
|
||||
ZSTD_inBuffer in = { .src = lastrm->next_in, .size = lastrm->avail_in, .pos = 0 };
|
||||
|
||||
size_t zret;
|
||||
|
||||
ZSTD_EndDirective mode = (action == ARCHIVE_Z_RUN) ? ZSTD_e_continue : ZSTD_e_end;
|
||||
|
||||
zret = ZSTD_compressStream2(strm, &out, &in, mode);
|
||||
if (ZSTD_isError(zret)) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
"zstd compression failed, ZSTD_compressStream2 returned: %s",
|
||||
ZSTD_getErrorName(zret));
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
lastrm->next_in += in.pos;
|
||||
lastrm->avail_in -= in.pos;
|
||||
lastrm->total_in += in.pos;
|
||||
|
||||
lastrm->next_out += out.pos;
|
||||
lastrm->avail_out -= out.pos;
|
||||
lastrm->total_out += out.pos;
|
||||
|
||||
if (action == ARCHIVE_Z_FINISH && zret == 0)
|
||||
return (ARCHIVE_EOF); // All done.
|
||||
|
||||
return (ARCHIVE_OK); // More work to do.
|
||||
}
|
||||
|
||||
static int
|
||||
compression_end_zstd(struct archive *a, struct la_zstream *lastrm)
|
||||
{
|
||||
ZSTD_CStream *strm;
|
||||
|
||||
(void)a; /* UNUSED */
|
||||
strm = (ZSTD_CStream *)lastrm->real_stream;
|
||||
ZSTD_freeCStream(strm);
|
||||
lastrm->valid = 0;
|
||||
lastrm->real_stream = NULL;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int
|
||||
compression_init_encoder_zstd(struct archive *a, struct la_zstream *lastrm, int level, int threads)
|
||||
{
|
||||
(void) level; /* UNUSED */
|
||||
(void) threads; /* UNUSED */
|
||||
if (lastrm->valid)
|
||||
compression_end(a, lastrm);
|
||||
return (compression_unsupported_encoder(a, lastrm, "zstd"));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Universal compressor initializer.
|
||||
*/
|
||||
@@ -2316,6 +2541,11 @@ _7z_compression_init_encoder(struct archive_write *a, unsigned compression,
|
||||
&(a->archive), &(zip->stream),
|
||||
PPMD7_DEFAULT_ORDER, PPMD7_DEFAULT_MEM_SIZE);
|
||||
break;
|
||||
case _7Z_ZSTD:
|
||||
r = compression_init_encoder_zstd(
|
||||
&(a->archive), &(zip->stream),
|
||||
compression_level, zip->opt_threads);
|
||||
break;
|
||||
case _7Z_COPY:
|
||||
default:
|
||||
r = compression_init_encoder_copy(
|
||||
@@ -2352,5 +2582,3 @@ compression_end(struct archive *a, struct la_zstream *lastrm)
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@ static const char template_header[] = {
|
||||
static int archive_write_gnutar_options(struct archive_write *,
|
||||
const char *, const char *);
|
||||
static int archive_format_gnutar_header(struct archive_write *, char h[512],
|
||||
struct archive_entry *, int tartype);
|
||||
struct archive_entry *, char tartype);
|
||||
static int archive_write_gnutar_header(struct archive_write *,
|
||||
struct archive_entry *entry);
|
||||
static ssize_t archive_write_gnutar_data(struct archive_write *a, const void *buff,
|
||||
@@ -274,7 +274,7 @@ archive_write_gnutar_header(struct archive_write *a,
|
||||
{
|
||||
char buff[512];
|
||||
int r, ret, ret2 = ARCHIVE_OK;
|
||||
int tartype;
|
||||
char tartype;
|
||||
struct gnutar *gnutar;
|
||||
struct archive_string_conv *sconv;
|
||||
struct archive_entry *entry_main;
|
||||
@@ -504,7 +504,7 @@ archive_write_gnutar_header(struct archive_write *a,
|
||||
archive_entry_set_uname(temp, "root");
|
||||
archive_entry_set_gname(temp, "wheel");
|
||||
|
||||
archive_entry_set_pathname(temp, "././@LongLink");
|
||||
archive_entry_set_pathname(temp, "././@LongName");
|
||||
archive_entry_set_size(temp, length);
|
||||
ret = archive_format_gnutar_header(a, buff, temp, 'L');
|
||||
archive_entry_free(temp);
|
||||
@@ -562,7 +562,7 @@ archive_write_gnutar_header(struct archive_write *a,
|
||||
|
||||
static int
|
||||
archive_format_gnutar_header(struct archive_write *a, char h[512],
|
||||
struct archive_entry *entry, int tartype)
|
||||
struct archive_entry *entry, char tartype)
|
||||
{
|
||||
unsigned int checksum;
|
||||
int i, ret;
|
||||
@@ -640,7 +640,7 @@ archive_format_gnutar_header(struct archive_write *a, char h[512],
|
||||
if (format_number(archive_entry_uid(entry), h + GNUTAR_uid_offset,
|
||||
GNUTAR_uid_size, GNUTAR_uid_max_size)) {
|
||||
archive_set_error(&a->archive, ERANGE,
|
||||
"Numeric user ID %jd too large",
|
||||
"Numeric user ID %jd too large for gnutar format",
|
||||
(intmax_t)archive_entry_uid(entry));
|
||||
ret = ARCHIVE_FAILED;
|
||||
}
|
||||
@@ -649,7 +649,7 @@ archive_format_gnutar_header(struct archive_write *a, char h[512],
|
||||
if (format_number(archive_entry_gid(entry), h + GNUTAR_gid_offset,
|
||||
GNUTAR_gid_size, GNUTAR_gid_max_size)) {
|
||||
archive_set_error(&a->archive, ERANGE,
|
||||
"Numeric group ID %jd too large",
|
||||
"Numeric group ID %jd too large for gnutar format",
|
||||
(intmax_t)archive_entry_gid(entry));
|
||||
ret = ARCHIVE_FAILED;
|
||||
}
|
||||
@@ -672,7 +672,7 @@ archive_format_gnutar_header(struct archive_write *a, char h[512],
|
||||
h + GNUTAR_rdevmajor_offset,
|
||||
GNUTAR_rdevmajor_size)) {
|
||||
archive_set_error(&a->archive, ERANGE,
|
||||
"Major device number too large");
|
||||
"Major device number too large for gnutar format");
|
||||
ret = ARCHIVE_FAILED;
|
||||
}
|
||||
|
||||
@@ -680,7 +680,7 @@ archive_format_gnutar_header(struct archive_write *a, char h[512],
|
||||
h + GNUTAR_rdevminor_offset,
|
||||
GNUTAR_rdevminor_size)) {
|
||||
archive_set_error(&a->archive, ERANGE,
|
||||
"Minor device number too large");
|
||||
"Minor device number too large for gnutar format");
|
||||
ret = ARCHIVE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -911,7 +911,7 @@ static int iso9660_finish_entry(struct archive_write *);
|
||||
static int iso9660_close(struct archive_write *);
|
||||
static int iso9660_free(struct archive_write *);
|
||||
|
||||
static void get_system_identitier(char *, size_t);
|
||||
static void get_system_identifier(char *, size_t);
|
||||
static void set_str(unsigned char *, const char *, size_t, char,
|
||||
const char *);
|
||||
static inline int joliet_allowed_char(unsigned char, unsigned char);
|
||||
@@ -1167,7 +1167,12 @@ archive_write_set_format_iso9660(struct archive *_a)
|
||||
iso9660->primary.rootent->parent = iso9660->primary.rootent;
|
||||
iso9660->cur_dirent = iso9660->primary.rootent;
|
||||
archive_string_init(&(iso9660->cur_dirstr));
|
||||
archive_string_ensure(&(iso9660->cur_dirstr), 1);
|
||||
if (archive_string_ensure(&(iso9660->cur_dirstr), 1) == NULL) {
|
||||
free(iso9660);
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
iso9660->cur_dirstr.s[0] = 0;
|
||||
iso9660->sconv_to_utf16be = NULL;
|
||||
iso9660->sconv_from_utf16be = NULL;
|
||||
@@ -2166,7 +2171,7 @@ iso9660_free(struct archive_write *a)
|
||||
* Get the System Identifier
|
||||
*/
|
||||
static void
|
||||
get_system_identitier(char *system_id, size_t size)
|
||||
get_system_identifier(char *system_id, size_t size)
|
||||
{
|
||||
#if defined(HAVE_SYS_UTSNAME_H)
|
||||
struct utsname u;
|
||||
@@ -3872,7 +3877,7 @@ write_VD(struct archive_write *a, struct vdd *vdd)
|
||||
/* Unused Field */
|
||||
set_unused_field_bp(bp, 8, 8);
|
||||
/* System Identifier */
|
||||
get_system_identitier(identifier, sizeof(identifier));
|
||||
get_system_identifier(identifier, sizeof(identifier));
|
||||
r = set_str_a_characters_bp(a, bp, 9, 40, identifier, vdc);
|
||||
if (r != ARCHIVE_OK)
|
||||
return (r);
|
||||
@@ -4037,7 +4042,7 @@ set_option_info(struct archive_string *info, int *opt, const char *key,
|
||||
case KEY_HEX:
|
||||
d = va_arg(ap, int);
|
||||
archive_string_sprintf(info, "%c%s=%x",
|
||||
prefix, key, d);
|
||||
prefix, key, (unsigned int)d);
|
||||
break;
|
||||
}
|
||||
va_end(ap);
|
||||
@@ -5666,9 +5671,15 @@ isoent_tree(struct archive_write *a, struct isoent **isoentpp)
|
||||
* inserted. */
|
||||
iso9660->cur_dirent = dent;
|
||||
archive_string_empty(&(iso9660->cur_dirstr));
|
||||
archive_string_ensure(&(iso9660->cur_dirstr),
|
||||
if (archive_string_ensure(&(iso9660->cur_dirstr),
|
||||
archive_strlen(&(dent->file->parentdir)) +
|
||||
archive_strlen(&(dent->file->basename)) + 2);
|
||||
archive_strlen(&(dent->file->basename)) + 2) == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate memory");
|
||||
_isoent_free(isoent);
|
||||
*isoentpp = NULL;
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (archive_strlen(&(dent->file->parentdir)) +
|
||||
archive_strlen(&(dent->file->basename)) == 0)
|
||||
iso9660->cur_dirstr.s[0] = 0;
|
||||
|
||||
@@ -54,7 +54,7 @@ struct attr_counter {
|
||||
int count;
|
||||
};
|
||||
|
||||
struct att_counter_set {
|
||||
struct attr_counter_set {
|
||||
struct attr_counter *uid_list;
|
||||
struct attr_counter *gid_list;
|
||||
struct attr_counter *mode_list;
|
||||
@@ -82,6 +82,7 @@ struct dir_info {
|
||||
struct reg_info {
|
||||
int compute_sum;
|
||||
uint32_t crc;
|
||||
uint_least32_t mset_digest;
|
||||
struct ae_digest digest;
|
||||
};
|
||||
|
||||
@@ -141,7 +142,7 @@ struct mtree_writer {
|
||||
unsigned long fflags_set;
|
||||
unsigned long fflags_clear;
|
||||
} set;
|
||||
struct att_counter_set acs;
|
||||
struct attr_counter_set acs;
|
||||
int classic;
|
||||
int depth;
|
||||
|
||||
@@ -437,7 +438,7 @@ write_global(struct mtree_writer *mtree)
|
||||
{
|
||||
struct archive_string setstr;
|
||||
struct archive_string unsetstr;
|
||||
struct att_counter_set *acs;
|
||||
struct attr_counter_set *acs;
|
||||
int keys, oldkeys, effkeys;
|
||||
|
||||
archive_string_init(&setstr);
|
||||
@@ -638,7 +639,7 @@ static int
|
||||
attr_counter_set_collect(struct mtree_writer *mtree, struct mtree_entry *me)
|
||||
{
|
||||
struct attr_counter *ac, *last;
|
||||
struct att_counter_set *acs = &mtree->acs;
|
||||
struct attr_counter_set *acs = &mtree->acs;
|
||||
int keys = mtree->keys;
|
||||
|
||||
if (keys & (F_UNAME | F_UID)) {
|
||||
@@ -714,7 +715,7 @@ attr_counter_set_collect(struct mtree_writer *mtree, struct mtree_entry *me)
|
||||
static void
|
||||
attr_counter_set_free(struct mtree_writer *mtree)
|
||||
{
|
||||
struct att_counter_set *acs = &mtree->acs;
|
||||
struct attr_counter_set *acs = &mtree->acs;
|
||||
|
||||
attr_counter_free(&acs->uid_list);
|
||||
attr_counter_free(&acs->gid_list);
|
||||
@@ -862,6 +863,50 @@ mtree_entry_free(struct mtree_entry *me)
|
||||
free(me);
|
||||
}
|
||||
|
||||
static void
|
||||
mtree_copy_ae_digests(struct reg_info *reg, struct archive_entry *entry, int compute_sum)
|
||||
{
|
||||
reg->compute_sum = compute_sum;
|
||||
reg->mset_digest = entry->mset_digest;
|
||||
|
||||
if ((reg->compute_sum & F_MD5)
|
||||
&& (reg->mset_digest & AE_MSET_DIGEST_MD5)) {
|
||||
|
||||
memcpy(®->digest.md5, entry->digest.md5,
|
||||
sizeof(reg->digest.md5));
|
||||
}
|
||||
if ((reg->compute_sum & F_RMD160)
|
||||
&& (reg->mset_digest & AE_MSET_DIGEST_RMD160)) {
|
||||
|
||||
memcpy(®->digest.rmd160, entry->digest.rmd160,
|
||||
sizeof(reg->digest.rmd160));
|
||||
}
|
||||
if ((reg->compute_sum & F_SHA1)
|
||||
&& (reg->mset_digest & AE_MSET_DIGEST_SHA1)) {
|
||||
|
||||
memcpy(®->digest.sha1, entry->digest.sha1,
|
||||
sizeof(reg->digest.sha1));
|
||||
}
|
||||
if ((reg->compute_sum & F_SHA256)
|
||||
&& (reg->mset_digest & AE_MSET_DIGEST_SHA256)) {
|
||||
|
||||
memcpy(®->digest.sha256, entry->digest.sha256,
|
||||
sizeof(reg->digest.sha256));
|
||||
}
|
||||
if ((reg->compute_sum & F_SHA384)
|
||||
&& (reg->mset_digest & AE_MSET_DIGEST_SHA384)) {
|
||||
|
||||
memcpy(®->digest.sha384, entry->digest.sha384,
|
||||
sizeof(reg->digest.sha384));
|
||||
}
|
||||
if ((reg->compute_sum & F_SHA512)
|
||||
&& (reg->mset_digest & AE_MSET_DIGEST_SHA512)) {
|
||||
|
||||
memcpy(®->digest.sha512, entry->digest.sha512,
|
||||
sizeof(reg->digest.sha512));
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_mtree_header(struct archive_write *a,
|
||||
struct archive_entry *entry)
|
||||
@@ -896,8 +941,12 @@ archive_write_mtree_header(struct archive_write *a,
|
||||
/* If the current file is a regular file, we have to
|
||||
* compute the sum of its content.
|
||||
* Initialize a bunch of checksum context. */
|
||||
if (mtree_entry->reg_info)
|
||||
if (mtree_entry->reg_info) {
|
||||
sum_init(mtree);
|
||||
/* honor archive_entry_set_digest() calls. These values will be
|
||||
* overwritten if archive_write_mtree_data() is called */
|
||||
mtree_copy_ae_digests(mtree_entry->reg_info, entry, mtree->compute_sum);
|
||||
}
|
||||
|
||||
return (r2);
|
||||
}
|
||||
@@ -1516,28 +1565,46 @@ sum_update(struct mtree_writer *mtree, const void *buff, size_t n)
|
||||
mtree->crc_len += n;
|
||||
}
|
||||
#ifdef ARCHIVE_HAS_MD5
|
||||
if (mtree->compute_sum & F_MD5)
|
||||
if (mtree->compute_sum & F_MD5) {
|
||||
archive_md5_update(&mtree->md5ctx, buff, n);
|
||||
mtree->mtree_entry->reg_info->mset_digest &=
|
||||
~AE_MSET_DIGEST_MD5;
|
||||
}
|
||||
#endif
|
||||
#ifdef ARCHIVE_HAS_RMD160
|
||||
if (mtree->compute_sum & F_RMD160)
|
||||
if (mtree->compute_sum & F_RMD160) {
|
||||
archive_rmd160_update(&mtree->rmd160ctx, buff, n);
|
||||
mtree->mtree_entry->reg_info->mset_digest &=
|
||||
~AE_MSET_DIGEST_RMD160;
|
||||
}
|
||||
#endif
|
||||
#ifdef ARCHIVE_HAS_SHA1
|
||||
if (mtree->compute_sum & F_SHA1)
|
||||
if (mtree->compute_sum & F_SHA1) {
|
||||
archive_sha1_update(&mtree->sha1ctx, buff, n);
|
||||
mtree->mtree_entry->reg_info->mset_digest &=
|
||||
~AE_MSET_DIGEST_SHA1;
|
||||
}
|
||||
#endif
|
||||
#ifdef ARCHIVE_HAS_SHA256
|
||||
if (mtree->compute_sum & F_SHA256)
|
||||
if (mtree->compute_sum & F_SHA256) {
|
||||
archive_sha256_update(&mtree->sha256ctx, buff, n);
|
||||
mtree->mtree_entry->reg_info->mset_digest &=
|
||||
~AE_MSET_DIGEST_SHA256;
|
||||
}
|
||||
#endif
|
||||
#ifdef ARCHIVE_HAS_SHA384
|
||||
if (mtree->compute_sum & F_SHA384)
|
||||
if (mtree->compute_sum & F_SHA384) {
|
||||
archive_sha384_update(&mtree->sha384ctx, buff, n);
|
||||
mtree->mtree_entry->reg_info->mset_digest &=
|
||||
~AE_MSET_DIGEST_SHA384;
|
||||
}
|
||||
#endif
|
||||
#ifdef ARCHIVE_HAS_SHA512
|
||||
if (mtree->compute_sum & F_SHA512)
|
||||
if (mtree->compute_sum & F_SHA512) {
|
||||
archive_sha512_update(&mtree->sha512ctx, buff, n);
|
||||
mtree->mtree_entry->reg_info->mset_digest &=
|
||||
~AE_MSET_DIGEST_SHA512;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1553,27 +1620,39 @@ sum_final(struct mtree_writer *mtree, struct reg_info *reg)
|
||||
reg->crc = ~mtree->crc;
|
||||
}
|
||||
#ifdef ARCHIVE_HAS_MD5
|
||||
if (mtree->compute_sum & F_MD5)
|
||||
if ((mtree->compute_sum & F_MD5)
|
||||
&& !(reg->mset_digest & AE_MSET_DIGEST_MD5))
|
||||
|
||||
archive_md5_final(&mtree->md5ctx, reg->digest.md5);
|
||||
#endif
|
||||
#ifdef ARCHIVE_HAS_RMD160
|
||||
if (mtree->compute_sum & F_RMD160)
|
||||
if ((mtree->compute_sum & F_RMD160)
|
||||
&& !(reg->mset_digest & AE_MSET_DIGEST_RMD160))
|
||||
|
||||
archive_rmd160_final(&mtree->rmd160ctx, reg->digest.rmd160);
|
||||
#endif
|
||||
#ifdef ARCHIVE_HAS_SHA1
|
||||
if (mtree->compute_sum & F_SHA1)
|
||||
if ((mtree->compute_sum & F_SHA1)
|
||||
&& !(reg->mset_digest & AE_MSET_DIGEST_SHA1))
|
||||
|
||||
archive_sha1_final(&mtree->sha1ctx, reg->digest.sha1);
|
||||
#endif
|
||||
#ifdef ARCHIVE_HAS_SHA256
|
||||
if (mtree->compute_sum & F_SHA256)
|
||||
if ((mtree->compute_sum & F_SHA256)
|
||||
&& !(reg->mset_digest & AE_MSET_DIGEST_SHA256))
|
||||
|
||||
archive_sha256_final(&mtree->sha256ctx, reg->digest.sha256);
|
||||
#endif
|
||||
#ifdef ARCHIVE_HAS_SHA384
|
||||
if (mtree->compute_sum & F_SHA384)
|
||||
if ((mtree->compute_sum & F_SHA384)
|
||||
&& !(reg->mset_digest & AE_MSET_DIGEST_SHA384))
|
||||
|
||||
archive_sha384_final(&mtree->sha384ctx, reg->digest.sha384);
|
||||
#endif
|
||||
#ifdef ARCHIVE_HAS_SHA512
|
||||
if (mtree->compute_sum & F_SHA512)
|
||||
if ((mtree->compute_sum & F_SHA512)
|
||||
&& !(reg->mset_digest & AE_MSET_DIGEST_SHA512))
|
||||
|
||||
archive_sha512_final(&mtree->sha512ctx, reg->digest.sha512);
|
||||
#endif
|
||||
/* Save what types of sum are computed. */
|
||||
@@ -2130,9 +2209,13 @@ mtree_entry_tree_add(struct archive_write *a, struct mtree_entry **filep)
|
||||
* inserted. */
|
||||
mtree->cur_dirent = dent;
|
||||
archive_string_empty(&(mtree->cur_dirstr));
|
||||
archive_string_ensure(&(mtree->cur_dirstr),
|
||||
if (archive_string_ensure(&(mtree->cur_dirstr),
|
||||
archive_strlen(&(dent->parentdir)) +
|
||||
archive_strlen(&(dent->basename)) + 2);
|
||||
archive_strlen(&(dent->basename)) + 2) == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (archive_strlen(&(dent->parentdir)) +
|
||||
archive_strlen(&(dent->basename)) == 0)
|
||||
mtree->cur_dirstr.s[0] = 0;
|
||||
|
||||
@@ -1414,7 +1414,7 @@ archive_write_pax_header(struct archive_write *a,
|
||||
struct archive_entry *pax_attr_entry;
|
||||
time_t s;
|
||||
int64_t uid, gid;
|
||||
int mode;
|
||||
__LA_MODE_T mode;
|
||||
|
||||
pax_attr_entry = archive_entry_new2(&a->archive);
|
||||
p = entry_name.s;
|
||||
@@ -1571,7 +1571,7 @@ build_ustar_entry_name(char *dest, const char *src, size_t src_length,
|
||||
const char *filename, *filename_end;
|
||||
char *p;
|
||||
int need_slash = 0; /* Was there a trailing slash? */
|
||||
size_t suffix_length = 99;
|
||||
size_t suffix_length = 98; /* 99 - 1 for trailing slash */
|
||||
size_t insert_length;
|
||||
|
||||
/* Length of additional dir element to be added. */
|
||||
@@ -1623,7 +1623,7 @@ build_ustar_entry_name(char *dest, const char *src, size_t src_length,
|
||||
/* Step 2: Locate the "prefix" section of the dirname, including
|
||||
* trailing '/'. */
|
||||
prefix = src;
|
||||
prefix_end = prefix + 155;
|
||||
prefix_end = prefix + 154 /* 155 - 1 for trailing / */;
|
||||
if (prefix_end > filename)
|
||||
prefix_end = filename;
|
||||
while (prefix_end > prefix && *prefix_end != '/')
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -263,7 +263,7 @@ decimal integer specifying log2 window size in bytes. Values from
|
||||
The value is interpreted as a decimal integer specifying the
|
||||
number of threads for multi-threaded zstd compression.
|
||||
If set to 0, zstd will attempt to detect and use the number
|
||||
of physical CPU cores.
|
||||
of active physical CPU cores.
|
||||
.El
|
||||
.It Format 7zip
|
||||
.Bl -tag -compact -width indent
|
||||
@@ -274,9 +274,10 @@ The value is one of
|
||||
.Dq deflate ,
|
||||
.Dq bzip2 ,
|
||||
.Dq lzma1 ,
|
||||
.Dq lzma2
|
||||
.Dq lzma2 ,
|
||||
.Dq ppmd ,
|
||||
or
|
||||
.Dq ppmd
|
||||
.Dq zstd
|
||||
to indicate how the following entries should be compressed.
|
||||
The values
|
||||
.Dq store
|
||||
@@ -289,9 +290,16 @@ and other special entries.
|
||||
The value is interpreted as a decimal integer specifying the
|
||||
compression level.
|
||||
Values between 0 and 9 are supported, with the exception of bzip2
|
||||
which only supports values between 1 and 9.
|
||||
which only supports values between 1 and 9, and zstd which may
|
||||
support negative values depending on the library version and
|
||||
commonly used values 1 through 22.
|
||||
The interpretation of the compression level depends on the chosen
|
||||
compression method.
|
||||
.It Cm threads
|
||||
The value is interpreted as a decimal integer specifying the
|
||||
number of threads for multi-threaded compression (for compressors
|
||||
like zstd that support it). If set to 0, an attempt will be made
|
||||
to discover the number of CPU cores.
|
||||
.El
|
||||
.It Format bin
|
||||
.Bl -tag -compact -width indent
|
||||
@@ -632,9 +640,13 @@ and
|
||||
.Bl -tag -compact -width indent
|
||||
.It Cm compression
|
||||
The value is either
|
||||
.Dq store
|
||||
.Dq store ,
|
||||
.Dq deflate ,
|
||||
.Dq bzip2 ,
|
||||
.Dq lzma ,
|
||||
.Dq xz ,
|
||||
or
|
||||
.Dq deflate
|
||||
.Dq zstd
|
||||
to indicate how the following entries should be compressed.
|
||||
Note that this setting is ignored for directories, symbolic links,
|
||||
and other special entries.
|
||||
@@ -645,8 +657,23 @@ Values between 0 and 9 are supported.
|
||||
A compression level of 0 switches the compression method to
|
||||
.Dq store ,
|
||||
other values will enable
|
||||
.Dq deflate
|
||||
compression with the given level.
|
||||
.Dq deflate ,
|
||||
.Dq bzip2 ,
|
||||
.Dq lzma ,
|
||||
or
|
||||
.Dq zstd
|
||||
compression (in order of priority, depending on what libraries
|
||||
are linked) with the given level.
|
||||
.It Cm threads
|
||||
The value is interpreted as a decimal integer specifying the
|
||||
number of threads to use for compression.
|
||||
It is supported only for
|
||||
.Dq xz
|
||||
or
|
||||
.Dq zstd
|
||||
compression and ignored for any other.
|
||||
A threads value of 0 is a special one requesting to detect and use as
|
||||
many threads as the number of active physical CPU cores.
|
||||
.It Cm encryption
|
||||
Enable encryption using traditional zip encryption.
|
||||
.It Cm encryption Ns = Ns Ar type
|
||||
|
||||
@@ -327,10 +327,26 @@ by the usual environment variables.
|
||||
Libarchive can read and write zip format archives that have
|
||||
uncompressed entries and entries compressed with the
|
||||
.Dq deflate
|
||||
,
|
||||
.Dq LZMA
|
||||
,
|
||||
.Dq XZ
|
||||
,
|
||||
.Dq BZIP2
|
||||
and
|
||||
.Dq ZSTD
|
||||
algorithms.
|
||||
Libarchive can also read, but not write, zip format archives that
|
||||
have entries compressed with the
|
||||
.Dq PPMd
|
||||
algorithm.
|
||||
Other zip compression algorithms are not supported.
|
||||
It can extract jar archives, archives that use Zip64 extensions and
|
||||
self-extracting zip archives.
|
||||
The extensions supported by libarchive are Zip64, Libarchive's
|
||||
extensions to better support streaming, PKZIP's traditional
|
||||
ZIP encryption, Info-ZIP's Unix extra fields, extra time, and
|
||||
Unicode path, as well as WinZIP's AES encryption.
|
||||
It can extract jar archives, __MACOSX resource forks extension
|
||||
for OS X, and self-extracting zip archives.
|
||||
Libarchive can use either of two different strategies for
|
||||
reading Zip archives:
|
||||
a streaming strategy which is fast and can handle extremely
|
||||
|
||||
@@ -167,7 +167,7 @@ memory_read_skip(struct archive *a, void *client_data, int64_t skip)
|
||||
|
||||
(void)a; /* UNUSED */
|
||||
/* We can't skip by more than is available. */
|
||||
if ((off_t)skip > (off_t)(mine->end - mine->p))
|
||||
if (skip > mine->end - mine->p)
|
||||
skip = mine->end - mine->p;
|
||||
/* Always do small skips by prime amounts. */
|
||||
if (skip > 71)
|
||||
|
||||
@@ -1,100 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2018
|
||||
* 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
|
||||
* in this position and unchanged.
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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 AUTHOR(S) 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 "test.h"
|
||||
|
||||
DEFINE_TEST(test_7zip_filename_encoding_UTF16_win)
|
||||
{
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
skipping("This test is meant to verify unicode string handling"
|
||||
" on Windows with UTF-16 names");
|
||||
return;
|
||||
#else
|
||||
struct archive *a;
|
||||
struct archive_entry *entry;
|
||||
char buff[4096];
|
||||
size_t used;
|
||||
|
||||
/*
|
||||
* Don't call setlocale because we're verifying that the '_w' functions
|
||||
* work as expected
|
||||
*/
|
||||
|
||||
a = archive_write_new();
|
||||
assertEqualInt(ARCHIVE_OK, archive_write_set_format_7zip(a));
|
||||
assertEqualInt(ARCHIVE_OK,
|
||||
archive_write_open_memory(a, buff, sizeof(buff), &used));
|
||||
|
||||
/* Part 1: file */
|
||||
entry = archive_entry_new2(a);
|
||||
archive_entry_copy_pathname_w(entry, L"\u8868.txt");
|
||||
archive_entry_set_filetype(entry, AE_IFREG);
|
||||
archive_entry_set_size(entry, 0);
|
||||
assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
|
||||
|
||||
/* Part 2: directory */
|
||||
archive_entry_clear(entry);
|
||||
archive_entry_copy_pathname_w(entry, L"\u8868");
|
||||
archive_entry_set_filetype(entry, AE_IFDIR);
|
||||
archive_entry_set_size(entry, 0);
|
||||
assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
|
||||
|
||||
/* Part 3: symlink */
|
||||
archive_entry_clear(entry);
|
||||
archive_entry_set_pathname(entry, "link.txt");
|
||||
archive_entry_copy_symlink_w(entry, L"\u8868.txt");
|
||||
archive_entry_set_filetype(entry, AE_IFLNK);
|
||||
archive_entry_set_symlink_type(entry, AE_SYMLINK_TYPE_FILE);
|
||||
archive_entry_set_size(entry, 0);
|
||||
assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
|
||||
|
||||
/* NOTE: 7zip does not support hardlinks */
|
||||
|
||||
archive_entry_free(entry);
|
||||
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
|
||||
|
||||
/* Ensure that the archive contents can be read properly */
|
||||
/* NOTE: 7zip file contents are not in the order we wrote them! */
|
||||
a = archive_read_new();
|
||||
archive_read_support_format_all(a);
|
||||
archive_read_support_filter_all(a);
|
||||
assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, used, 7));
|
||||
|
||||
/* Read part 3: symlink */
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &entry));
|
||||
assertEqualWString(L"\u8868.txt", archive_entry_symlink_w(entry));
|
||||
|
||||
/* Read part 1: file */
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &entry));
|
||||
assertEqualWString(L"\u8868.txt", archive_entry_pathname_w(entry));
|
||||
|
||||
/* Read part 2: directory */
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &entry));
|
||||
/* NOTE: Trailing slash added automatically for us */
|
||||
assertEqualWString(L"\u8868/", archive_entry_pathname_w(entry));
|
||||
|
||||
archive_read_free(a);
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Copyright (c) 2003-2018
|
||||
* 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
|
||||
* in this position and unchanged.
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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 AUTHOR(S) 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 "test.h"
|
||||
|
||||
DEFINE_TEST(test_7zip_filename_encoding_UTF16_win)
|
||||
{
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
skipping("This test is meant to verify unicode string handling"
|
||||
" on Windows with UTF-16 names");
|
||||
return;
|
||||
#else
|
||||
struct archive *a;
|
||||
struct archive_entry *entry;
|
||||
char buff[4096];
|
||||
size_t used;
|
||||
|
||||
/*
|
||||
* Don't call setlocale because we're verifying that the '_w' functions
|
||||
* work as expected
|
||||
*/
|
||||
|
||||
a = archive_write_new();
|
||||
assertEqualInt(ARCHIVE_OK, archive_write_set_format_7zip(a));
|
||||
assertEqualInt(ARCHIVE_OK,
|
||||
archive_write_open_memory(a, buff, sizeof(buff), &used));
|
||||
|
||||
/* Part 1: file */
|
||||
entry = archive_entry_new2(a);
|
||||
archive_entry_copy_pathname_w(entry, L"\u8868.txt");
|
||||
archive_entry_set_filetype(entry, AE_IFREG);
|
||||
archive_entry_set_size(entry, 0);
|
||||
assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
|
||||
|
||||
/* Part 2: directory */
|
||||
archive_entry_clear(entry);
|
||||
archive_entry_copy_pathname_w(entry, L"\u8868");
|
||||
archive_entry_set_filetype(entry, AE_IFDIR);
|
||||
archive_entry_set_size(entry, 0);
|
||||
assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
|
||||
|
||||
/* Part 3: symlink */
|
||||
archive_entry_clear(entry);
|
||||
archive_entry_set_pathname(entry, "link.txt");
|
||||
archive_entry_copy_symlink_w(entry, L"\u8868.txt");
|
||||
archive_entry_set_filetype(entry, AE_IFLNK);
|
||||
archive_entry_set_symlink_type(entry, AE_SYMLINK_TYPE_FILE);
|
||||
archive_entry_set_size(entry, 0);
|
||||
assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
|
||||
|
||||
/* NOTE: 7zip does not support hardlinks */
|
||||
|
||||
archive_entry_free(entry);
|
||||
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
|
||||
|
||||
/* Ensure that the archive contents can be read properly */
|
||||
/* NOTE: 7zip file contents are not in the order we wrote them! */
|
||||
a = archive_read_new();
|
||||
archive_read_support_format_all(a);
|
||||
archive_read_support_filter_all(a);
|
||||
assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, used, 7));
|
||||
|
||||
/* Read part 3: symlink */
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &entry));
|
||||
assertEqualWString(L"\u8868.txt", archive_entry_symlink_w(entry));
|
||||
|
||||
/* Read part 1: file */
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &entry));
|
||||
assertEqualWString(L"\u8868.txt", archive_entry_pathname_w(entry));
|
||||
|
||||
/* Read part 2: directory */
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &entry));
|
||||
/* NOTE: Trailing slash added automatically for us */
|
||||
assertEqualWString(L"\u8868/", archive_entry_pathname_w(entry));
|
||||
|
||||
archive_read_free(a);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -287,7 +287,7 @@ DEFINE_TEST(test_acl_pax_posix1e)
|
||||
failure("Basic ACLs shouldn't be stored as extended ACLs");
|
||||
assert(0 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
|
||||
failure("Basic ACLs should set mode to 0142, not %04o",
|
||||
archive_entry_mode(ae)&0777);
|
||||
(unsigned int)archive_entry_mode(ae)&0777);
|
||||
assert((archive_entry_mode(ae) & 0777) == 0142);
|
||||
|
||||
/* Second item has a few ACLs */
|
||||
@@ -297,7 +297,7 @@ DEFINE_TEST(test_acl_pax_posix1e)
|
||||
assertEntryCompareAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
|
||||
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0142);
|
||||
failure("Basic ACLs should set mode to 0142, not %04o",
|
||||
archive_entry_mode(ae)&0777);
|
||||
(unsigned int)archive_entry_mode(ae)&0777);
|
||||
assert((archive_entry_mode(ae) & 0777) == 0142);
|
||||
|
||||
/* Third item has pretty extensive ACLs */
|
||||
@@ -307,7 +307,7 @@ DEFINE_TEST(test_acl_pax_posix1e)
|
||||
assertEntryCompareAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]),
|
||||
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0543);
|
||||
failure("Basic ACLs should set mode to 0543, not %04o",
|
||||
archive_entry_mode(ae)&0777);
|
||||
(unsigned int)archive_entry_mode(ae)&0777);
|
||||
assert((archive_entry_mode(ae) & 0777) == 0543);
|
||||
|
||||
/* Fourth item has no ACLs */
|
||||
@@ -315,7 +315,7 @@ DEFINE_TEST(test_acl_pax_posix1e)
|
||||
failure("Basic ACLs shouldn't be stored as extended ACLs");
|
||||
assert(0 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
|
||||
failure("Basic ACLs should set mode to 0142, not %04o",
|
||||
archive_entry_mode(ae)&0777);
|
||||
(unsigned int)archive_entry_mode(ae)&0777);
|
||||
assert((archive_entry_mode(ae) & 0777) == 0142);
|
||||
|
||||
/* Close the archive. */
|
||||
|
||||
@@ -424,7 +424,7 @@ acl_flagset_to_bitmap(acl_flagset_t opaque_fs)
|
||||
#if ARCHIVE_ACL_SUNOS_NFS4 || ARCHIVE_ACL_LIBRICHACL
|
||||
if (flags & perms[i].machine)
|
||||
#else
|
||||
if (acl_get_flag_np(opaque_fs, perms[i].machine))
|
||||
if (acl_get_flag_np(opaque_fs, (acl_flag_t)perms[i].machine))
|
||||
#endif
|
||||
flagset |= perms[i].portable;
|
||||
return flagset;
|
||||
@@ -772,7 +772,8 @@ compare_acls(
|
||||
failure(" ACL entry %d missing from %s: "
|
||||
"type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s''\n",
|
||||
marker[i], filename,
|
||||
myacls[marker[i]].type, myacls[marker[i]].permset,
|
||||
(unsigned int)myacls[marker[i]].type,
|
||||
(unsigned int)myacls[marker[i]].permset,
|
||||
myacls[marker[i]].tag, myacls[marker[i]].qual,
|
||||
myacls[marker[i]].name);
|
||||
assert(0); /* Record this as a failure. */
|
||||
@@ -824,7 +825,7 @@ compare_entry_acls(struct archive_entry *ae, struct myacl_t *myacls, const char
|
||||
|
||||
failure("ACL entry on file that shouldn't be there: "
|
||||
"type=%#010x,permset=%#010x,tag=%d,qual=%d",
|
||||
type,permset,tag,qual);
|
||||
(unsigned int)type, (unsigned int)permset, tag, qual);
|
||||
assert(matched == 1);
|
||||
}
|
||||
|
||||
@@ -833,7 +834,8 @@ compare_entry_acls(struct archive_entry *ae, struct myacl_t *myacls, const char
|
||||
failure(" ACL entry %d missing from %s: "
|
||||
"type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s''\n",
|
||||
marker[i], filename,
|
||||
myacls[marker[i]].type, myacls[marker[i]].permset,
|
||||
(unsigned int)myacls[marker[i]].type,
|
||||
(unsigned int)myacls[marker[i]].permset,
|
||||
myacls[marker[i]].tag, myacls[marker[i]].qual,
|
||||
myacls[marker[i]].name);
|
||||
assert(0); /* Record this as a failure. */
|
||||
|
||||
@@ -274,7 +274,8 @@ compare_acls(
|
||||
for (i = 0; i < n; ++i) {
|
||||
failure(" ACL entry missing from file: "
|
||||
"type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s''\n",
|
||||
myacls[marker[i]].type, myacls[marker[i]].permset,
|
||||
(unsigned int)myacls[marker[i]].type,
|
||||
(unsigned int)myacls[marker[i]].permset,
|
||||
myacls[marker[i]].tag, myacls[marker[i]].qual,
|
||||
myacls[marker[i]].name);
|
||||
assert(0); /* Record this as a failure. */
|
||||
|
||||
@@ -119,7 +119,7 @@ DEFINE_TEST(test_acl_posix1e)
|
||||
failure("Basic ACLs shouldn't be stored as extended ACLs");
|
||||
assert(0 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
|
||||
failure("Basic ACLs should set mode to 0142, not %04o",
|
||||
archive_entry_mode(ae)&0777);
|
||||
(unsigned int)archive_entry_mode(ae)&0777);
|
||||
assert((archive_entry_mode(ae) & 0777) == 0142);
|
||||
|
||||
/* With any extended ACL entry, we should read back a full set. */
|
||||
@@ -136,7 +136,7 @@ DEFINE_TEST(test_acl_posix1e)
|
||||
assertEntryCompareAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
|
||||
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0142);
|
||||
failure("Basic ACLs should set mode to 0142, not %04o",
|
||||
archive_entry_mode(ae)&0777);
|
||||
(unsigned int)archive_entry_mode(ae)&0777);
|
||||
assert((archive_entry_mode(ae) & 0777) == 0142);
|
||||
|
||||
|
||||
@@ -146,7 +146,7 @@ DEFINE_TEST(test_acl_posix1e)
|
||||
assertEntryCompareAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]),
|
||||
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0543);
|
||||
failure("Basic ACLs should set mode to 0543, not %04o",
|
||||
archive_entry_mode(ae)&0777);
|
||||
(unsigned int)archive_entry_mode(ae)&0777);
|
||||
assert((archive_entry_mode(ae) & 0777) == 0543);
|
||||
|
||||
/*
|
||||
@@ -157,7 +157,7 @@ DEFINE_TEST(test_acl_posix1e)
|
||||
failure("Basic ACLs shouldn't be stored as extended ACLs");
|
||||
assert(0 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
|
||||
failure("Basic ACLs should set mode to 0142, not %04o",
|
||||
archive_entry_mode(ae)&0777);
|
||||
(unsigned int)archive_entry_mode(ae)&0777);
|
||||
assert((archive_entry_mode(ae) & 0777) == 0142);
|
||||
|
||||
/*
|
||||
|
||||
@@ -132,7 +132,7 @@ static struct archive_test_acl_t acls1[] = {
|
||||
ARCHIVE_ENTRY_ACL_EVERYONE, 0, "" },
|
||||
};
|
||||
|
||||
const char* acltext[] = {
|
||||
static const char* acltext[] = {
|
||||
"user::rwx\n"
|
||||
"group::r-x\n"
|
||||
"other::r-x\n"
|
||||
|
||||
@@ -25,8 +25,7 @@
|
||||
|
||||
#include "test.h"
|
||||
|
||||
#define __LIBARCHIVE_BUILD 1
|
||||
#include "archive_getdate.h"
|
||||
#define parse_date archive_parse_date
|
||||
|
||||
static void
|
||||
test_newer_time(void)
|
||||
@@ -102,27 +101,27 @@ test_newer_time_str(void)
|
||||
|
||||
/* Test1: Allow newer time. */
|
||||
archive_entry_copy_pathname(ae, "file1");
|
||||
t = __archive_get_date(now, "1980/2/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/2/1 0:0:0 UTC");
|
||||
archive_entry_set_mtime(ae, t, 0);
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Both Its mtime and ctime should be excluded");
|
||||
assertEqualInt(1, archive_match_time_excluded(m, ae));
|
||||
assertEqualInt(1, archive_match_excluded(m, ae));
|
||||
t = __archive_get_date(now, "1980/1/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/1/1 0:0:0 UTC");
|
||||
archive_entry_set_mtime(ae, t, 0);
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Both Its mtime and ctime should be excluded");
|
||||
assertEqualInt(1, archive_match_time_excluded(m, ae));
|
||||
assertEqualInt(1, archive_match_excluded(m, ae));
|
||||
|
||||
t = __archive_get_date(now, "1980/2/1 0:0:1 UTC");
|
||||
t = parse_date(now, "1980/2/1 0:0:1 UTC");
|
||||
archive_entry_set_mtime(ae, t, 0);
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Both Its mtime and ctime should not be excluded");
|
||||
assertEqualInt(0, archive_match_time_excluded(m, ae));
|
||||
assertEqualInt(0, archive_match_excluded(m, ae));
|
||||
|
||||
t = __archive_get_date(now, "1980/2/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/2/1 0:0:0 UTC");
|
||||
archive_entry_set_mtime(ae, t, 1);
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Its mtime should be excluded");
|
||||
@@ -143,20 +142,20 @@ test_newer_time_str(void)
|
||||
"1980/2/1 0:0:0 UTC"));
|
||||
|
||||
archive_entry_copy_pathname(ae, "file1");
|
||||
t = __archive_get_date(now, "1980/2/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/2/1 0:0:0 UTC");
|
||||
archive_entry_set_mtime(ae, t, 0);
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Both Its mtime and ctime should not be excluded");
|
||||
assertEqualInt(0, archive_match_time_excluded(m, ae));
|
||||
assertEqualInt(0, archive_match_excluded(m, ae));
|
||||
t = __archive_get_date(now, "1980/1/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/1/1 0:0:0 UTC");
|
||||
archive_entry_set_mtime(ae, t, 0);
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Both Its mtime and ctime should be excluded");
|
||||
assertEqualInt(1, archive_match_time_excluded(m, ae));
|
||||
assertEqualInt(1, archive_match_excluded(m, ae));
|
||||
|
||||
t = __archive_get_date(now, "1980/2/1 0:0:1 UTC");
|
||||
t = parse_date(now, "1980/2/1 0:0:1 UTC");
|
||||
archive_entry_set_mtime(ae, t, 0);
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Both Its mtime and ctime should not be excluded");
|
||||
@@ -190,27 +189,27 @@ test_newer_time_str_w(void)
|
||||
|
||||
/* Test1: Allow newer time. */
|
||||
archive_entry_copy_pathname(ae, "file1");
|
||||
t = __archive_get_date(now, "1980/2/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/2/1 0:0:0 UTC");
|
||||
archive_entry_set_mtime(ae, t, 0);
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Both Its mtime and ctime should be excluded");
|
||||
assertEqualInt(1, archive_match_time_excluded(m, ae));
|
||||
assertEqualInt(1, archive_match_excluded(m, ae));
|
||||
t = __archive_get_date(now, "1980/1/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/1/1 0:0:0 UTC");
|
||||
archive_entry_set_mtime(ae, t, 0);
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Both Its mtime and ctime should be excluded");
|
||||
assertEqualInt(1, archive_match_time_excluded(m, ae));
|
||||
assertEqualInt(1, archive_match_excluded(m, ae));
|
||||
|
||||
t = __archive_get_date(now, "1980/2/1 0:0:1 UTC");
|
||||
t = parse_date(now, "1980/2/1 0:0:1 UTC");
|
||||
archive_entry_set_mtime(ae, t, 0);
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Both Its mtime and ctime should not be excluded");
|
||||
assertEqualInt(0, archive_match_time_excluded(m, ae));
|
||||
assertEqualInt(0, archive_match_excluded(m, ae));
|
||||
|
||||
t = __archive_get_date(now, "1980/2/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/2/1 0:0:0 UTC");
|
||||
archive_entry_set_mtime(ae, t, 1);
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Its mtime should be excluded");
|
||||
@@ -231,20 +230,20 @@ test_newer_time_str_w(void)
|
||||
L"1980/2/1 0:0:0 UTC"));
|
||||
|
||||
archive_entry_copy_pathname(ae, "file1");
|
||||
t = __archive_get_date(now, "1980/2/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/2/1 0:0:0 UTC");
|
||||
archive_entry_set_mtime(ae, t, 0);
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Both Its mtime and ctime should not be excluded");
|
||||
assertEqualInt(0, archive_match_time_excluded(m, ae));
|
||||
assertEqualInt(0, archive_match_excluded(m, ae));
|
||||
t = __archive_get_date(now, "1980/1/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/1/1 0:0:0 UTC");
|
||||
archive_entry_set_mtime(ae, t, 0);
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Both Its mtime and ctime should be excluded");
|
||||
assertEqualInt(1, archive_match_time_excluded(m, ae));
|
||||
assertEqualInt(1, archive_match_excluded(m, ae));
|
||||
|
||||
t = __archive_get_date(now, "1980/2/1 0:0:1 UTC");
|
||||
t = parse_date(now, "1980/2/1 0:0:1 UTC");
|
||||
archive_entry_set_mtime(ae, t, 0);
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Both Its mtime and ctime should not be excluded");
|
||||
@@ -569,37 +568,37 @@ test_older_time_str(void)
|
||||
ARCHIVE_MATCH_OLDER, "1980/2/1 0:0:0 UTC"));
|
||||
|
||||
archive_entry_copy_pathname(ae, "file1");
|
||||
t = __archive_get_date(now, "1980/2/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/2/1 0:0:0 UTC");
|
||||
archive_entry_set_mtime(ae, t, 0);
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Both Its mtime and ctime should be excluded");
|
||||
assertEqualInt(1, archive_match_time_excluded(m, ae));
|
||||
assertEqualInt(1, archive_match_excluded(m, ae));
|
||||
t = __archive_get_date(now, "1980/1/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/1/1 0:0:0 UTC");
|
||||
archive_entry_set_mtime(ae, t, 0);
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Both Its mtime and ctime should not be excluded");
|
||||
assertEqualInt(0, archive_match_time_excluded(m, ae));
|
||||
assertEqualInt(0, archive_match_excluded(m, ae));
|
||||
|
||||
t = __archive_get_date(now, "1980/3/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/3/1 0:0:0 UTC");
|
||||
archive_entry_set_mtime(ae, t, 0);
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Both Its mtime and ctime should be excluded");
|
||||
assertEqualInt(1, archive_match_time_excluded(m, ae));
|
||||
assertEqualInt(1, archive_match_excluded(m, ae));
|
||||
|
||||
t = __archive_get_date(now, "1980/3/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/3/1 0:0:0 UTC");
|
||||
archive_entry_set_mtime(ae, t, 0);
|
||||
t = __archive_get_date(now, "1980/1/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/1/1 0:0:0 UTC");
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Its mtime should be excluded");
|
||||
assertEqualInt(1, archive_match_time_excluded(m, ae));
|
||||
assertEqualInt(1, archive_match_excluded(m, ae));
|
||||
|
||||
t = __archive_get_date(now, "1980/1/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/1/1 0:0:0 UTC");
|
||||
archive_entry_set_mtime(ae, t, 0);
|
||||
t = __archive_get_date(now, "1980/3/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/3/1 0:0:0 UTC");
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Its ctime should be excluded");
|
||||
assertEqualInt(1, archive_match_time_excluded(m, ae));
|
||||
@@ -612,20 +611,20 @@ test_older_time_str(void)
|
||||
"1980/2/1 0:0:0 UTC"));
|
||||
|
||||
archive_entry_copy_pathname(ae, "file1");
|
||||
t = __archive_get_date(now, "1980/2/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/2/1 0:0:0 UTC");
|
||||
archive_entry_set_mtime(ae, t, 0);
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Both Its mtime and ctime should not be excluded");
|
||||
assertEqualInt(0, archive_match_time_excluded(m, ae));
|
||||
assertEqualInt(0, archive_match_excluded(m, ae));
|
||||
t = __archive_get_date(now, "1980/1/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/1/1 0:0:0 UTC");
|
||||
archive_entry_set_mtime(ae, t, 0);
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Both Its mtime and ctime should not be excluded");
|
||||
assertEqualInt(0, archive_match_time_excluded(m, ae));
|
||||
assertEqualInt(0, archive_match_excluded(m, ae));
|
||||
|
||||
t = __archive_get_date(now, "1980/3/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/3/1 0:0:0 UTC");
|
||||
archive_entry_set_mtime(ae, t, 0);
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Both Its mtime and ctime should be excluded");
|
||||
@@ -659,37 +658,37 @@ test_older_time_str_w(void)
|
||||
ARCHIVE_MATCH_OLDER, L"1980/2/1 0:0:0 UTC"));
|
||||
|
||||
archive_entry_copy_pathname(ae, "file1");
|
||||
t = __archive_get_date(now, "1980/2/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/2/1 0:0:0 UTC");
|
||||
archive_entry_set_mtime(ae, t, 0);
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Both Its mtime and ctime should be excluded");
|
||||
assertEqualInt(1, archive_match_time_excluded(m, ae));
|
||||
assertEqualInt(1, archive_match_excluded(m, ae));
|
||||
t = __archive_get_date(now, "1980/1/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/1/1 0:0:0 UTC");
|
||||
archive_entry_set_mtime(ae, t, 0);
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Both Its mtime and ctime should not be excluded");
|
||||
assertEqualInt(0, archive_match_time_excluded(m, ae));
|
||||
assertEqualInt(0, archive_match_excluded(m, ae));
|
||||
|
||||
t = __archive_get_date(now, "1980/3/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/3/1 0:0:0 UTC");
|
||||
archive_entry_set_mtime(ae, t, 0);
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Both Its mtime and ctime should be excluded");
|
||||
assertEqualInt(1, archive_match_time_excluded(m, ae));
|
||||
assertEqualInt(1, archive_match_excluded(m, ae));
|
||||
|
||||
t = __archive_get_date(now, "1980/3/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/3/1 0:0:0 UTC");
|
||||
archive_entry_set_mtime(ae, t, 0);
|
||||
t = __archive_get_date(now, "1980/1/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/1/1 0:0:0 UTC");
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Its mtime should be excluded");
|
||||
assertEqualInt(1, archive_match_time_excluded(m, ae));
|
||||
assertEqualInt(1, archive_match_excluded(m, ae));
|
||||
|
||||
t = __archive_get_date(now, "1980/1/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/1/1 0:0:0 UTC");
|
||||
archive_entry_set_mtime(ae, t, 0);
|
||||
t = __archive_get_date(now, "1980/3/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/3/1 0:0:0 UTC");
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Its ctime should be excluded");
|
||||
assertEqualInt(1, archive_match_time_excluded(m, ae));
|
||||
@@ -702,20 +701,20 @@ test_older_time_str_w(void)
|
||||
L"1980/2/1 0:0:0 UTC"));
|
||||
|
||||
archive_entry_copy_pathname(ae, "file1");
|
||||
t = __archive_get_date(now, "1980/2/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/2/1 0:0:0 UTC");
|
||||
archive_entry_set_mtime(ae, t, 0);
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Both Its mtime and ctime should not be excluded");
|
||||
assertEqualInt(0, archive_match_time_excluded(m, ae));
|
||||
assertEqualInt(0, archive_match_excluded(m, ae));
|
||||
t = __archive_get_date(now, "1980/1/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/1/1 0:0:0 UTC");
|
||||
archive_entry_set_mtime(ae, t, 0);
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Both Its mtime and ctime should not be excluded");
|
||||
assertEqualInt(0, archive_match_time_excluded(m, ae));
|
||||
assertEqualInt(0, archive_match_excluded(m, ae));
|
||||
|
||||
t = __archive_get_date(now, "1980/3/1 0:0:0 UTC");
|
||||
t = parse_date(now, "1980/3/1 0:0:0 UTC");
|
||||
archive_entry_set_mtime(ae, t, 0);
|
||||
archive_entry_set_ctime(ae, t, 0);
|
||||
failure("Both Its mtime and ctime should be excluded");
|
||||
|
||||
+15
-6
@@ -26,16 +26,13 @@
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#define __LIBARCHIVE_BUILD 1
|
||||
#include "archive_getdate.h"
|
||||
|
||||
/*
|
||||
* Verify that the getdate() function works.
|
||||
* Verify that the archive_parse_date() function works.
|
||||
*/
|
||||
|
||||
#define get_date __archive_get_date
|
||||
#define get_date archive_parse_date
|
||||
|
||||
DEFINE_TEST(test_archive_getdate)
|
||||
DEFINE_TEST(test_archive_parse_date)
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
|
||||
@@ -84,5 +81,17 @@ DEFINE_TEST(test_archive_getdate)
|
||||
/* "last tuesday" is one week before "tuesday" */
|
||||
assertEqualInt(get_date(now, "last tuesday UTC"),
|
||||
now - 6 * 24 * 60 * 60);
|
||||
|
||||
/* Unix epoch timestamps */
|
||||
assertEqualInt(get_date(now, "@0"), 0);
|
||||
assertEqualInt(get_date(now, "@100"), 100);
|
||||
assertEqualInt(get_date(now, "@+100"), 100);
|
||||
|
||||
assertEqualInt(get_date(now, "@"), -1);
|
||||
assertEqualInt(get_date(now, "@-"), -1);
|
||||
assertEqualInt(get_date(now, "@+"), -1);
|
||||
assertEqualInt(get_date(now, "@tenth"), -1);
|
||||
assertEqualInt(get_date(now, "@100 tomorrow"), -1);
|
||||
|
||||
/* TODO: Lots more tests here. */
|
||||
}
|
||||
@@ -91,7 +91,7 @@ unicode_to_utf16be(char *p, uint32_t uc)
|
||||
archive_be16enc(utf16+2, (uc & 0x3ff) + 0xDC00);
|
||||
return (4);
|
||||
} else {
|
||||
archive_be16enc(utf16, uc);
|
||||
archive_be16enc(utf16, (uint16_t)uc);
|
||||
return (2);
|
||||
}
|
||||
}
|
||||
@@ -118,7 +118,7 @@ unicode_to_utf16le(char *p, uint32_t uc)
|
||||
archive_le16enc(utf16+2, (uc & 0x3ff) + 0xDC00);
|
||||
return (4);
|
||||
} else {
|
||||
archive_le16enc(utf16, uc);
|
||||
archive_le16enc(utf16, (uint16_t)uc);
|
||||
return (2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2024 Tim Kientzle
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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 AUTHOR(S) 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 "test.h"
|
||||
|
||||
/*
|
||||
* Verify reading a GNU tar pax format archive with >8GB entry.
|
||||
*
|
||||
* Sample data created with GNU tar 1.35:
|
||||
* $ dd if=/dev/zero of=test.bin bs=1048576 count=8192
|
||||
* $ gnutar --format=posix -cvf test.tar test.bin
|
||||
* $ hexdump -C -v test.tar | head -n 96
|
||||
*/
|
||||
|
||||
static const unsigned char test_compat_gtar_large_data[] = {
|
||||
/* 00000000 */ 0x2e, 0x2f, 0x50, 0x61, 0x78, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x2f, 0x74, 0x65, 0x73, /* |./PaxHeaders/tes| */
|
||||
/* 00000010 */ 0x74, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |t.bin...........| */
|
||||
/* 00000020 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000030 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000040 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000050 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000060 */ 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x36, 0x34, 0x34, 0x00, 0x30, 0x30, 0x30, 0x30, /* |....0000644.0000| */
|
||||
/* 00000070 */ 0x30, 0x30, 0x30, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x30, 0x30, 0x30, 0x30, /* |000.0000000.0000| */
|
||||
/* 00000080 */ 0x30, 0x30, 0x30, 0x30, 0x31, 0x35, 0x35, 0x00, 0x31, 0x34, 0x37, 0x31, 0x31, 0x35, 0x36, 0x36, /* |0000155.14711566| */
|
||||
/* 00000090 */ 0x30, 0x31, 0x33, 0x00, 0x30, 0x31, 0x31, 0x37, 0x35, 0x33, 0x00, 0x20, 0x78, 0x00, 0x00, 0x00, /* |013.011753. x...| */
|
||||
/* 000000a0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000000b0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000000c0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000000d0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000000e0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000000f0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000100 */ 0x00, 0x75, 0x73, 0x74, 0x61, 0x72, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |.ustar.00.......| */
|
||||
/* 00000110 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000130 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000140 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000150 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000160 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000170 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000180 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000190 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000001a0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000001b0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000001c0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000001d0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000001e0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000001f0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000200 */ 0x31, 0x39, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x3d, 0x38, 0x35, 0x38, 0x39, 0x39, 0x33, 0x34, 0x35, /* |19 size=85899345| */
|
||||
/* 00000210 */ 0x39, 0x32, 0x0a, 0x33, 0x30, 0x20, 0x6d, 0x74, 0x69, 0x6d, 0x65, 0x3d, 0x31, 0x37, 0x33, 0x30, /* |92.30 mtime=1730| */
|
||||
/* 00000220 */ 0x36, 0x30, 0x34, 0x30, 0x34, 0x33, 0x2e, 0x30, 0x34, 0x36, 0x38, 0x33, 0x33, 0x30, 0x31, 0x31, /* |604043.046833011| */
|
||||
/* 00000230 */ 0x0a, 0x33, 0x30, 0x20, 0x61, 0x74, 0x69, 0x6d, 0x65, 0x3d, 0x31, 0x37, 0x33, 0x30, 0x36, 0x30, /* |.30 atime=173060| */
|
||||
/* 00000240 */ 0x34, 0x30, 0x33, 0x39, 0x2e, 0x38, 0x30, 0x37, 0x30, 0x38, 0x31, 0x33, 0x31, 0x39, 0x0a, 0x33, /* |4039.807081319.3| */
|
||||
/* 00000250 */ 0x30, 0x20, 0x63, 0x74, 0x69, 0x6d, 0x65, 0x3d, 0x31, 0x37, 0x33, 0x30, 0x36, 0x30, 0x34, 0x30, /* |0 ctime=17306040| */
|
||||
/* 00000260 */ 0x34, 0x33, 0x2e, 0x30, 0x34, 0x36, 0x38, 0x33, 0x33, 0x30, 0x31, 0x31, 0x0a, 0x00, 0x00, 0x00, /* |43.046833011....| */
|
||||
/* 00000270 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000280 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000290 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000002a0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000002b0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000002c0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000002d0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000002e0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000002f0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000300 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000310 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000320 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000330 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000340 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000350 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000360 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000370 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000380 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000390 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000003a0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000003b0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000003c0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000003d0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000003e0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000003f0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000400 */ 0x74, 0x65, 0x73, 0x74, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |test.bin........| */
|
||||
/* 00000410 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000420 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000430 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000440 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000450 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000460 */ 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x36, 0x34, 0x34, 0x00, 0x30, 0x30, 0x30, 0x30, /* |....0000644.0000| */
|
||||
/* 00000470 */ 0x37, 0x36, 0x35, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x34, 0x00, 0x30, 0x30, 0x30, 0x30, /* |765.0000024.0000| */
|
||||
/* 00000480 */ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x31, 0x34, 0x37, 0x31, 0x31, 0x35, 0x36, 0x36, /* |0000000.14711566| */
|
||||
/* 00000490 */ 0x30, 0x31, 0x33, 0x00, 0x30, 0x31, 0x31, 0x32, 0x33, 0x35, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, /* |013.011235. 0...| */
|
||||
/* 000004a0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000004b0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000004c0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000004d0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000004e0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000004f0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000500 */ 0x00, 0x75, 0x73, 0x74, 0x61, 0x72, 0x00, 0x30, 0x30, 0x74, 0x69, 0x6d, 0x00, 0x00, 0x00, 0x00, /* |.ustar.00tim....| */
|
||||
/* 00000510 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000520 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x74, 0x61, 0x66, 0x66, 0x00, 0x00, /* |.........staff..| */
|
||||
/* 00000530 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000540 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000550 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000560 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000570 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000580 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 00000590 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000005a0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000005b0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000005c0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000005d0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000005e0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
/* 000005f0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
|
||||
};
|
||||
|
||||
/*
|
||||
* Followed by 16777218 blocks, each consisting of 512 zeros:
|
||||
* Entry is 8GB = 2^24 = 16777216 blocks
|
||||
* Plus 2 zero blocks for end-of-archive
|
||||
*/
|
||||
|
||||
struct my_reader {
|
||||
const void *prefix;
|
||||
int prefix_length;
|
||||
int zero_blocks_remaining;
|
||||
void *zero_block;
|
||||
};
|
||||
|
||||
/*
|
||||
* Custom reader returns first the prefix, then
|
||||
* the expected number of zero blocks, then EOF.
|
||||
*/
|
||||
static ssize_t
|
||||
myread(struct archive *a, void *client_data, const void **buff)
|
||||
{
|
||||
struct my_reader *reader = client_data;
|
||||
(void)a; /* UNUSED */
|
||||
|
||||
if (reader->prefix != NULL) {
|
||||
*buff = reader->prefix;
|
||||
reader->prefix = NULL;
|
||||
return reader->prefix_length;
|
||||
} else if (reader->zero_blocks_remaining > 0) {
|
||||
*buff = reader->zero_block;
|
||||
reader->zero_blocks_remaining -= 1;
|
||||
return 512;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* test_compat_gtar_large verifies that we can read
|
||||
* the archive encoded above.
|
||||
*/
|
||||
DEFINE_TEST(test_compat_gtar_large)
|
||||
{
|
||||
struct archive *a;
|
||||
struct archive_entry *ae;
|
||||
struct my_reader reader = {
|
||||
test_compat_gtar_large_data,
|
||||
sizeof(test_compat_gtar_large_data),
|
||||
16777218, /* 2^24 + 2 ; See above */
|
||||
NULL
|
||||
};
|
||||
int r;
|
||||
|
||||
reader.zero_block = calloc(1, 512);
|
||||
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_open(a, &reader, NULL, myread, NULL));
|
||||
|
||||
/* Read first entry. */
|
||||
assertEqualIntA(a, ARCHIVE_OK, r = archive_read_next_header(a, &ae));
|
||||
if (r != ARCHIVE_OK) {
|
||||
archive_read_free(a);
|
||||
return;
|
||||
}
|
||||
assertEqualString("test.bin", archive_entry_pathname(ae));
|
||||
assertEqualInt(1730604043, archive_entry_mtime(ae));
|
||||
assertEqualInt(501, archive_entry_uid(ae));
|
||||
assertEqualString("tim", archive_entry_uname(ae));
|
||||
assertEqualInt(20, archive_entry_gid(ae));
|
||||
assertEqualString("staff", archive_entry_gname(ae));
|
||||
assertEqualInt(0100644, archive_entry_mode(ae));
|
||||
assertEqualInt(8589934592LL, archive_entry_size(ae));
|
||||
|
||||
/* TODO: Read and verify contents: 8GB of zeros */
|
||||
|
||||
/* Verify the end-of-archive. */
|
||||
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
|
||||
|
||||
/* Verify that the format detection worked. */
|
||||
assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE);
|
||||
assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE);
|
||||
|
||||
/* Verify that the reader actually read to the end of data */
|
||||
assertEqualInt(reader.zero_blocks_remaining, 0);
|
||||
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
||||
free(reader.zero_block);
|
||||
}
|
||||
@@ -229,7 +229,7 @@ DEFINE_TEST(test_compat_solaris_tar_acl)
|
||||
assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
|
||||
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0644);
|
||||
failure("Basic ACLs should set mode to 0644, not %04o",
|
||||
archive_entry_mode(ae)&0777);
|
||||
(unsigned int)archive_entry_mode(ae)&0777);
|
||||
assert((archive_entry_mode(ae) & 0777) == 0644);
|
||||
|
||||
/* Second item has default and access ACLs */
|
||||
@@ -239,7 +239,7 @@ DEFINE_TEST(test_compat_solaris_tar_acl)
|
||||
assertEntryCompareAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
|
||||
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0750);
|
||||
failure("Basic ACLs should set mode to 0750, not %04o",
|
||||
archive_entry_mode(ae)&0777);
|
||||
(unsigned int)archive_entry_mode(ae)&0777);
|
||||
assert((archive_entry_mode(ae) & 0777) == 0750);
|
||||
assertEqualInt(6, archive_entry_acl_reset(ae,
|
||||
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
|
||||
|
||||
@@ -251,7 +251,7 @@ DEFINE_TEST(test_compat_star_acl_posix1e)
|
||||
assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
|
||||
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0142);
|
||||
failure("Basic ACLs should set mode to 0142, not %04o",
|
||||
archive_entry_mode(ae)&0777);
|
||||
(unsigned int)archive_entry_mode(ae)&0777);
|
||||
assert((archive_entry_mode(ae) & 0777) == 0142);
|
||||
|
||||
/* Second item has pretty extensive ACLs */
|
||||
@@ -261,7 +261,7 @@ DEFINE_TEST(test_compat_star_acl_posix1e)
|
||||
assertEntryCompareAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
|
||||
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0543);
|
||||
failure("Basic ACLs should set mode to 0543, not %04o",
|
||||
archive_entry_mode(ae)&0777);
|
||||
(unsigned int)archive_entry_mode(ae)&0777);
|
||||
assert((archive_entry_mode(ae) & 0777) == 0543);
|
||||
|
||||
/* Third item has default ACLs */
|
||||
@@ -271,7 +271,7 @@ DEFINE_TEST(test_compat_star_acl_posix1e)
|
||||
assertEntryCompareAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]),
|
||||
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, 0142);
|
||||
failure("Basic ACLs should set mode to 0142, not %04o",
|
||||
archive_entry_mode(ae)&0777);
|
||||
(unsigned int)archive_entry_mode(ae)&0777);
|
||||
assert((archive_entry_mode(ae) & 0777) == 0142);
|
||||
|
||||
/* Close the archive. */
|
||||
|
||||
@@ -436,7 +436,7 @@ DEFINE_TEST(test_entry)
|
||||
archive_entry_fflags(e, &set, &clear);
|
||||
assertEqualInt(UF_HIDDEN, set);
|
||||
assertEqualInt(UF_NODUMP | UF_IMMUTABLE | UF_APPEND, clear);
|
||||
#elif defined(_WIN32) && !defined(CYGWIN)
|
||||
#elif defined(_WIN32) && !defined(__CYGWIN__)
|
||||
archive_entry_copy_fflags_text_w(e, L"rdonly,hidden,nosystem");
|
||||
archive_entry_fflags(e, &set, &clear);
|
||||
assertEqualInt(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN, set);
|
||||
|
||||
@@ -31,14 +31,14 @@ DEFINE_TEST(test_open_file)
|
||||
struct archive *a;
|
||||
FILE *f;
|
||||
|
||||
f = fopen("test.tar", "wb");
|
||||
f = fopen("test.7z", "wb");
|
||||
assert(f != NULL);
|
||||
if (f == NULL)
|
||||
return;
|
||||
|
||||
/* Write an archive through this FILE *. */
|
||||
assert((a = archive_write_new()) != NULL);
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_7zip(a));
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a));
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_write_open_FILE(a, f));
|
||||
|
||||
@@ -70,9 +70,10 @@ DEFINE_TEST(test_open_file)
|
||||
fclose(f);
|
||||
|
||||
/*
|
||||
* Now, read the data back.
|
||||
* Now, read the data back. 7z requiring seeking, that also
|
||||
* tests that the seeking support works.
|
||||
*/
|
||||
f = fopen("test.tar", "rb");
|
||||
f = fopen("test.7z", "rb");
|
||||
assert(f != NULL);
|
||||
if (f == NULL)
|
||||
return;
|
||||
|
||||
@@ -39,7 +39,7 @@ atimeIsUpdated(void)
|
||||
{
|
||||
const char *fn = "fs_noatime";
|
||||
struct stat st;
|
||||
#if defined(_WIN32) && !defined(CYGWIN)
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
char *buff = NULL;
|
||||
char *ptr;
|
||||
int r;
|
||||
|
||||
@@ -24,13 +24,16 @@
|
||||
*/
|
||||
#include "test.h"
|
||||
|
||||
#if HAVE_LZMA_H
|
||||
#include <lzma.h>
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#define close _close
|
||||
#define open _open
|
||||
#endif
|
||||
|
||||
#define __LIBARCHIVE_BUILD
|
||||
#include <archive_crc32.h>
|
||||
|
||||
/*
|
||||
* Extract a non-encoded file.
|
||||
@@ -402,7 +405,7 @@ test_extract_file_zstd_bcj_nobjc(const char *refname)
|
||||
la_ssize_t bytes_read = archive_read_data(a, buff, sizeof(buff));
|
||||
assert(bytes_read >= 0);
|
||||
if (bytes_read == 0) break;
|
||||
computed_crc = crc32(computed_crc, buff, bytes_read);
|
||||
computed_crc = bitcrc32(computed_crc, buff, bytes_read);
|
||||
}
|
||||
assertEqualInt(computed_crc, expected_crc);
|
||||
|
||||
@@ -929,6 +932,10 @@ DEFINE_TEST(test_read_format_7zip_zstd)
|
||||
if (ARCHIVE_OK != archive_read_support_filter_zstd(a)) {
|
||||
skipping(
|
||||
"7zip:zstd decoding is not supported on this platform");
|
||||
} else if (ARCHIVE_OK != archive_read_support_filter_xz(a)) {
|
||||
// The directory header entries in the test file uses lzma.
|
||||
skipping(
|
||||
"7zip:lzma decoding is not supported on this platform");
|
||||
} else {
|
||||
test_extract_all_files_zstd("test_read_format_7zip_zstd.7z");
|
||||
}
|
||||
@@ -946,6 +953,10 @@ DEFINE_TEST(test_read_format_7zip_zstd_solid)
|
||||
if (ARCHIVE_OK != archive_read_support_filter_zstd(a)) {
|
||||
skipping(
|
||||
"7zip:zstd decoding is not supported on this platform");
|
||||
} else if (ARCHIVE_OK != archive_read_support_filter_xz(a)) {
|
||||
// The directory header entries in the test file uses lzma.
|
||||
skipping(
|
||||
"7zip:lzma decoding is not supported on this platform");
|
||||
} else {
|
||||
test_extract_all_files_zstd("test_read_format_7zip_solid_zstd.7z");
|
||||
}
|
||||
@@ -1063,7 +1074,7 @@ test_arm_filter(const char *refname)
|
||||
assertEqualString("hw-gnueabihf", archive_entry_pathname(ae));
|
||||
assertEqualInt(sizeof(buff), archive_entry_size(ae));
|
||||
assertEqualInt(sizeof(buff), archive_read_data(a, buff, sizeof(buff)));
|
||||
computed_crc = crc32(computed_crc, buff, sizeof(buff));
|
||||
computed_crc = bitcrc32(computed_crc, buff, sizeof(buff));
|
||||
assertEqualInt(computed_crc, expected_crc);
|
||||
|
||||
assertEqualInt(1, archive_file_count(a));
|
||||
@@ -1137,7 +1148,7 @@ test_arm64_filter(const char *refname)
|
||||
assertEqualString("hw-arm64", archive_entry_pathname(ae));
|
||||
assertEqualInt(sizeof(buff), archive_entry_size(ae));
|
||||
assertEqualInt(sizeof(buff), archive_read_data(a, buff, sizeof(buff)));
|
||||
computed_crc = crc32(computed_crc, buff, sizeof(buff));
|
||||
computed_crc = bitcrc32(computed_crc, buff, sizeof(buff));
|
||||
assertEqualInt(computed_crc, expected_crc);
|
||||
|
||||
assertEqualInt(1, archive_file_count(a));
|
||||
@@ -1150,7 +1161,7 @@ test_arm64_filter(const char *refname)
|
||||
|
||||
DEFINE_TEST(test_read_format_7zip_lzma2_arm64)
|
||||
{
|
||||
#ifdef HAVE_LZMA_FILTER_ARM64
|
||||
#ifdef LZMA_FILTER_ARM64
|
||||
struct archive *a;
|
||||
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
@@ -1260,6 +1271,97 @@ DEFINE_TEST(test_read_format_7zip_win_attrib)
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_read_format_7zip_sfx_pe)
|
||||
{
|
||||
/*
|
||||
* This is a regular 7z SFX PE file
|
||||
* created by 7z tool v22.01 on Windows 64-bit
|
||||
*/
|
||||
struct archive *a;
|
||||
struct archive_entry *ae;
|
||||
int bs = 10240;
|
||||
char buff[32];
|
||||
const char reffile[] = "test_read_format_7zip_sfx_pe.exe";
|
||||
const char test_txt[] = "123";
|
||||
int size = sizeof(test_txt) - 1;
|
||||
|
||||
extract_reference_file(reffile);
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertA(0 == archive_read_support_filter_all(a));
|
||||
assertA(0 == archive_read_support_format_all(a));
|
||||
assertA(0 == archive_read_open_filename(a, reffile, bs));
|
||||
|
||||
assertA(0 == archive_read_next_header(a, &ae));
|
||||
assertEqualString("test.txt.txt", archive_entry_pathname(ae));
|
||||
|
||||
assertA(size == archive_read_data(a, buff, size));
|
||||
assertEqualMem(buff, test_txt, size);
|
||||
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_read_format_7zip_sfx_modified_pe)
|
||||
{
|
||||
/*
|
||||
* This test simulates a modified 7z SFX PE
|
||||
* the compressed data in the SFX file is still stored as PE overlay
|
||||
* but the decompressor code is replaced
|
||||
*/
|
||||
struct archive *a;
|
||||
struct archive_entry *ae;
|
||||
int bs = 10240;
|
||||
char buff[32];
|
||||
const char reffile[] = "test_read_format_7zip_sfx_modified_pe.exe";
|
||||
const char test_txt[] = "123";
|
||||
int size = sizeof(test_txt) - 1;
|
||||
|
||||
extract_reference_file(reffile);
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertA(0 == archive_read_support_filter_all(a));
|
||||
assertA(0 == archive_read_support_format_all(a));
|
||||
assertA(0 == archive_read_open_filename(a, reffile, bs));
|
||||
|
||||
assertA(0 == archive_read_next_header(a, &ae));
|
||||
assertEqualString("test.txt.txt", archive_entry_pathname(ae));
|
||||
|
||||
assertA(size == archive_read_data(a, buff, size));
|
||||
assertEqualMem(buff, test_txt, size);
|
||||
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_read_format_7zip_sfx_elf)
|
||||
{
|
||||
/*
|
||||
* This is a regular 7z SFX ELF file
|
||||
* created by 7z tool v16.02 on Ubuntu
|
||||
*/
|
||||
struct archive *a;
|
||||
struct archive_entry *ae;
|
||||
int bs = 10240;
|
||||
char buff[32];
|
||||
const char reffile[] = "test_read_format_7zip_sfx_elf.elf";
|
||||
const char test_txt[] = "123";
|
||||
int size = sizeof(test_txt) - 1;
|
||||
|
||||
extract_reference_file(reffile);
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertA(0 == archive_read_support_filter_all(a));
|
||||
assertA(0 == archive_read_support_format_all(a));
|
||||
assertA(0 == archive_read_open_filename(a, reffile, bs));
|
||||
|
||||
assertA(0 == archive_read_next_header(a, &ae));
|
||||
assertEqualString("test.txt.txt", archive_entry_pathname(ae));
|
||||
|
||||
assertA(size == archive_read_data(a, buff, size));
|
||||
assertEqualMem(buff, test_txt, size);
|
||||
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_read_format_7zip_extract_second)
|
||||
{
|
||||
struct archive *a;
|
||||
@@ -1301,3 +1403,206 @@ DEFINE_TEST(test_read_format_7zip_extract_second)
|
||||
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
||||
}
|
||||
|
||||
#ifdef LZMA_FILTER_RISCV
|
||||
static void
|
||||
test_riscv_filter(const char *refname)
|
||||
{
|
||||
struct archive *a;
|
||||
struct archive_entry *ae;
|
||||
char buff[8488];
|
||||
uint32_t computed_crc = 0;
|
||||
uint32_t expected_crc = 0xf7ed24e7;
|
||||
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
|
||||
extract_reference_file(refname);
|
||||
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
|
||||
|
||||
assertEqualIntA(a, ARCHIVE_OK,
|
||||
archive_read_open_filename(a, refname, 10240));
|
||||
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
|
||||
assertEqualInt((AE_IFREG | 0775), archive_entry_mode(ae));
|
||||
assertEqualString("hw-riscv64", archive_entry_pathname(ae));
|
||||
assertEqualInt(sizeof(buff), archive_entry_size(ae));
|
||||
assertEqualInt(sizeof(buff), archive_read_data(a, buff, sizeof(buff)));
|
||||
|
||||
computed_crc = bitcrc32(computed_crc, buff, sizeof(buff));
|
||||
assertEqualInt(computed_crc, expected_crc);
|
||||
|
||||
assertEqualInt(1, archive_file_count(a));
|
||||
|
||||
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
|
||||
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
||||
}
|
||||
#endif
|
||||
|
||||
DEFINE_TEST(test_read_format_7zip_lzma2_riscv)
|
||||
{
|
||||
#ifdef LZMA_FILTER_RISCV
|
||||
struct archive *a;
|
||||
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
|
||||
if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) {
|
||||
skipping("7zip:lzma decoding is not supported on this platform");
|
||||
} else {
|
||||
test_riscv_filter("test_read_format_7zip_lzma2_riscv.7z");
|
||||
}
|
||||
#else
|
||||
skipping("This version of liblzma does not support LZMA_FILTER_RISCV");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
test_sparc_filter(const char *refname)
|
||||
{
|
||||
struct archive *a;
|
||||
struct archive_entry *ae;
|
||||
size_t expected_entry_size = 1053016;
|
||||
char *buff = malloc(expected_entry_size);
|
||||
uint32_t computed_crc = 0;
|
||||
uint32_t expected_crc = 0x6b5b364d;
|
||||
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
|
||||
extract_reference_file(refname);
|
||||
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
|
||||
|
||||
assertEqualIntA(a, ARCHIVE_OK,
|
||||
archive_read_open_filename(a, refname, 10240));
|
||||
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
|
||||
assertEqualInt((AE_IFREG | 0775), archive_entry_mode(ae));
|
||||
assertEqualString("hw-sparc64", archive_entry_pathname(ae));
|
||||
assertEqualInt(expected_entry_size, archive_entry_size(ae));
|
||||
assertEqualInt(expected_entry_size, archive_read_data(a, buff, expected_entry_size));
|
||||
|
||||
computed_crc = bitcrc32(computed_crc, buff, expected_entry_size);
|
||||
assertEqualInt(computed_crc, expected_crc);
|
||||
|
||||
assertEqualInt(1, archive_file_count(a));
|
||||
|
||||
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
|
||||
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
||||
|
||||
free(buff);
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_read_format_7zip_lzma2_sparc)
|
||||
{
|
||||
struct archive *a;
|
||||
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
|
||||
if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) {
|
||||
skipping(
|
||||
"7zip:lzma decoding is not supported on this platform");
|
||||
} else {
|
||||
test_sparc_filter("test_read_format_7zip_lzma2_sparc.7z");
|
||||
}
|
||||
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_read_format_7zip_zstd_sparc)
|
||||
{
|
||||
struct archive *a;
|
||||
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
|
||||
if (ARCHIVE_OK != archive_read_support_filter_zstd(a)) {
|
||||
skipping(
|
||||
"7zip:zstd decoding is not supported on this platform");
|
||||
} else {
|
||||
test_sparc_filter("test_read_format_7zip_zstd_sparc.7z");
|
||||
}
|
||||
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
||||
}
|
||||
|
||||
static void
|
||||
test_powerpc_filter(const char *refname)
|
||||
{
|
||||
struct archive *a;
|
||||
struct archive_entry *ae;
|
||||
size_t expected_entry_size = 68340;
|
||||
char *buff = malloc(expected_entry_size);
|
||||
uint32_t computed_crc = 0;
|
||||
uint32_t expected_crc = 0x71fb03c9;
|
||||
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
|
||||
extract_reference_file(refname);
|
||||
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
|
||||
|
||||
assertEqualIntA(a, ARCHIVE_OK,
|
||||
archive_read_open_filename(a, refname, 10240));
|
||||
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
|
||||
assertEqualInt((AE_IFREG | 0775), archive_entry_mode(ae));
|
||||
assertEqualString("hw-powerpc", archive_entry_pathname(ae));
|
||||
assertEqualInt(expected_entry_size, archive_entry_size(ae));
|
||||
assertEqualInt(expected_entry_size, archive_read_data(a, buff, expected_entry_size));
|
||||
|
||||
computed_crc = bitcrc32(computed_crc, buff, expected_entry_size);
|
||||
assertEqualInt(computed_crc, expected_crc);
|
||||
|
||||
assertEqualInt(1, archive_file_count(a));
|
||||
|
||||
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
|
||||
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
||||
|
||||
free(buff);
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_read_format_7zip_deflate_powerpc)
|
||||
{
|
||||
struct archive *a;
|
||||
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
|
||||
if (ARCHIVE_OK != archive_read_support_filter_gzip(a)) {
|
||||
skipping(
|
||||
"7zip:deflate decoding is not supported on this platform");
|
||||
} else {
|
||||
test_powerpc_filter("test_read_format_7zip_deflate_powerpc.7z");
|
||||
}
|
||||
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_read_format_7zip_lzma2_powerpc)
|
||||
{
|
||||
struct archive *a;
|
||||
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
|
||||
if (ARCHIVE_OK != archive_read_support_filter_gzip(a)) {
|
||||
skipping(
|
||||
"7zip:deflate decoding is not supported on this platform");
|
||||
} else {
|
||||
test_powerpc_filter("test_read_format_7zip_lzma2_powerpc.7z");
|
||||
}
|
||||
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
begin 664 test_read_format_7zip_deflate_powerpc.7z
|
||||
M-WJ\KR<<``2:7;DH@`@```````!R`````````#:LFQ3LU$MK$U$4P/$SDZB1
|
||||
M)#)*%$'1$0,JB&\D14M,?56J]8%N=)%6(QJ,5FW%(BD97XC@HN(#7(@K@QO!
|
||||
MA6Y%-R*"7\$GKMQTX4*P.IX[<Z>*%#_!_U=.YMZYY][<<S.=UM:=VQS7D0FN
|
||||
M%/33\23EZW6=.%-OZ]6T?)DN2V6^S-/>5'/'LZ'I?AR2MI'2_G[/AO;S)NR8
|
||||
M8T.\*(PIHU'H1SQB/G]]]YPXM+M<8U7TO8[=I83B.7&H,1M3_^S!J7DVM+_%
|
||||
M1#)6&_JR1[_*]VSHO?E1_!G?*Y.PZWLZON^?_65,)/6M;-0/KVS45@P.K%AM
|
||||
M)MG[!7,NVWL/2->;^Z^F/4M_>]9U<U'OW8>;/KU\<LWF>&:^R;%2<:UQS7_.
|
||||
MSVS:3W+2+S[W/)YDK[.3QJSXXOW3WV:[R4J.GD7.K#=39(94=^RN#@[5ZJ>J
|
||||
MYP:/UN3TN:%!J5:ULB-ZN__L4/5D?_V4F+ZI<[ULW[FC:W-US8I5$ZVUZW3"
|
||||
ML9,#I^R$:ER%UN28OZB>)<F^\O6Z9^M=;>Y-O7OSJ:UY@X;YG<=TN!"UW6B[
|
||||
MLVT[K6E).Z,Y4?OVHG"LF7';HXX4;KV43-<#F=)Z[;;+[\3=\.YG)E@0CJ\,
|
||||
M1"K/)=,MZ8N!YC4SJ?9ES2TM$J\WB(^EN2P[O'^1K#?S1QZY[=+$VBFSMI3?
|
||||
MBMN9-VN.O[[Z:/Q#MQYCG^8DL;'/<SM]SRT=D6+',BDVI\^579?$[]35M2_+
|
||||
MITO4'UF6:O<&:?_O_-)US;_L[VE>F7.Z>66&AG/G?W/[[-YN?91<^8/G7B]+
|
||||
MT>1LTISD++HEU=_ABV/JO:?C4<V:G]3<$X:!KO'!YA=UK?G-<G9XM"6YT0>2
|
||||
MT;U)J3[%TS,[H^O(R.*>X8Z6^$%6TM%:7\/QD?Y#P[I6M)].K>?B"<VKQWNT
|
||||
M_?0__4S2__OLHOF!GL>),0ERX?>.$S].-Z>GVLWLP<+%&_H]?0<+R9Q)XS_/
|
||||
MP:2_MRO.\:.-QL!R__S`V48M>LKFI<SS-]<\BV'XZYMYCX1AN$FOJY)GU[FP
|
||||
M3XNO./-R$Z^UN9ICW@>!_1<K:BS7^8_TVBV5&?[FF976`Z>27]B3RTKE?=X1
|
||||
M````````````````````````````````````````````````````````````
|
||||
M``````````````````````````````````````````````````````#PN]UJ
|
||||
M!Y$:BJ(WF5E===2L_R\,..`_C!\4Q,+9CQ_PA^X*-CXSF[@3G$G6)*.[%B*B
|
||||
MJ""B:*%6EEM:J+5@8R%BIZ4V%F*AH"(BCN?EW;CCD$8;FQPX\][)/;EY[[Z7
|
||||
MO,F0(4.&#!DR9,B0(4.&#!DR9/C?,"AO&)1[B:X&K@0+!NFOT<Y$[`W:Q8;V
|
||||
M\QO:I6`>7`+]`^TRJ?W6SR\&:1/H=^&^16BG0#]#.QT<`F>`!CB?%'*&3A+R
|
||||
MMP3.`Z>""W'_0]E'*_-U@V5P&E@8E4FTUF>_U?J)^!C:EAPSVH_0'OT#D*^]
|
||||
M#C?`V^`=0S]?0CN/.K"KKV];<=50M>E%S>*&3>8FL[Q^2S.6&\]MW&R6-Z_F
|
||||
MRY0*U&60@!R1QMIFK;.^PCK'>H)UGO4SUET$R'JSGL+:8SV5]1CK;M9)OFFL
|
||||
M'[*>SOHUZQE*YXJL"URC-ZQG*MU58#V+=>*?S7H[:X,`N8]8][#^P7I.LAZL
|
||||
MY[+^R'I>K'5*XO-9)\]?P+K$>B$Q6,LZ:<3(4^L3FFZN=U%3]9Z#^:XC"37?
|
||||
M91W^E8@?)T!7\=70-]KT=GZ/$GV(QZ-I:CS'DOEJ:KZ7Y+O7YK^9U$=3]7G0
|
||||
M_OR4\3Q"?:^QWR"@(_Y4[F..R_J\2.JKJ?J^2M:+U'J]E^\7Q^?)WP1SU%WK
|
||||
M#%V-H1CGTY8G]3:4+B7[8XY.,Z'7L#^);^W(MY,81:6'#%UU>_387^7]E>^)
|
||||
M]Y=V"O%5G&\A=)GWYV;D*T"?YO$D\0O\#N_F^&6.)_EOR?W.XYU!PT&TP?1)
|
||||
M"*OJBL@:H1$_$G6KZM1E*(R:)TZ8PV0[@3/BAI$3B*@AANN^YX2XQ_;%2-VO
|
||||
M6G5A1WX0"JLY1L-^8[3N1(YMEM,=XH3KN<(*`FM<.%X4C-.)P&HXPFXV&N.X
|
||||
MI4T).*,_K+4S&(T0.P]5]@V(@?W]0I`XW%\1O97#`^CV']U?V;>G#XY=^X?$
|
||||
MP&XV[NX_1&+7W@.]E;WBP,Z=AP<&Q6"E=Z^\0]3=ZK`((RN(1,-RO1V[]N[I
|
||||
M[1,;S4V;23BV%5D4#QA.*9231IM1F#CC>8XT?(^S"&D-?5&S/+OND-AS``';
|
||||
M]40S=&S"/&P8JF'(J>1#<6%P7Q_/)YXTD1F.-R*KBC8*5%M+>JZ'A1@ET_,C
|
||||
MQQSQFF:UZ=;M]:[-ERJ]>];+I8QC-2NLD6F/>\@7M\BB(J>=('1][P\A$`N<
|
||||
MNB6-W!NM1_*1+GXC9PR_LAR(^7%Q3*?&*U:S@TDE[TB63MW!?9G8:KC#>*J/
|
||||
M7"H'JD$F-DX#BTQ_@Z7\?=/5&2-),XG!,8D5X%3VV1232C2)/"EL:?-=(?Y.
|
||||
MIOCZ<?Y^9=\$@>SK2GS,_>`,]CVCF'20U+FEL<<`CX`YY</9%I.&4N9Q3)[_
|
||||
M[/,H)DUO>Z[./"G_+[!OC&)2N>.Y$F=EGWT3%),*[?-@?9'[O>KLE*02^^:W
|
||||
M^:YS_BGJ&R-)_2GUNSWIRQ4IIO:$)F&0PKW$I[ZQDK0N)=]]]NGJVRE)/2F^
|
||||
MB39?D6+2LA3?XS;?=HI)@RD^.>998$Z=82#'&'GF<SYK<NHL!--]K^5<E:^%
|
||||
M1I(^\K7$UPV^!37V(2Y)1DJ^J[]]NNH!A91YO)OT(:[%GD4IO@]@-_M*I(&(
|
||||
MI>S33]PO$\"^M1V^A'K;U8-(_4#^U^9U3MZ/:6!NTI>7/W=3GMOSIZ]+>KYW
|
||||
M^GX!`00&``$)B(``!PL!``(#!`$(!`,#`@4!``S!]`K!]`H`"`H!R0/[<0``
|
||||
M!0$9#P```````````````````!$7`&@`=P`M`'``;P!W`&4`<@!P`&,````9
|
||||
;!``````4"@$`>7-\NFY9VP$5!@$`((#]@0``
|
||||
`
|
||||
end
|
||||
@@ -1,11 +1,11 @@
|
||||
begin 644 test_read_format_7zip_extract_second.7z
|
||||
M-WJ\KR<<``-N%=VX!@$````````B`````````*R\U.<`&`Q"DFIGO`[1,RO\
|
||||
MN,RA7-QU1L&_]O_/$0MMLIEBUR3'BDX@M2C-5'VG./-4,5@W3Q@*__^7_,[H
|
||||
MEO`DB'[ZI>@H2_E>/W.2G$$.P01-X!YN5";SS[3#7Z4Q1G/EF.0'^D*[S8&8
|
||||
M[FV9DYX7,SA%^.Q\'?__P!@`````@3,'K@_4WV/Q0A7VLXG$X?GH4=5W^`UM
|
||||
M$N_EX$)LE*?K$W5?WLP:X0T[Q%V^?A!0E\VZRBB,)(MO`C`LO[O!3(1YL)<:
|
||||
MJ."`';WU;>GP5',%Z=6?*/H9*Z)&\*!2^<F\P&>,RV`R30UOBH8+5.;;2IKF
|
||||
M0W://&'?"L?0L2!)`*]F30B0&/_'<4``%P9Z`0F`C``'"P$``2,#`0$%70``
|
||||
-@``,@*@*`6]FB2D`````
|
||||
`
|
||||
end
|
||||
begin 644 test_read_format_7zip_extract_second.7z
|
||||
M-WJ\KR<<``-N%=VX!@$````````B`````````*R\U.<`&`Q"DFIGO`[1,RO\
|
||||
MN,RA7-QU1L&_]O_/$0MMLIEBUR3'BDX@M2C-5'VG./-4,5@W3Q@*__^7_,[H
|
||||
MEO`DB'[ZI>@H2_E>/W.2G$$.P01-X!YN5";SS[3#7Z4Q1G/EF.0'^D*[S8&8
|
||||
M[FV9DYX7,SA%^.Q\'?__P!@`````@3,'K@_4WV/Q0A7VLXG$X?GH4=5W^`UM
|
||||
M$N_EX$)LE*?K$W5?WLP:X0T[Q%V^?A!0E\VZRBB,)(MO`C`LO[O!3(1YL)<:
|
||||
MJ."`';WU;>GP5',%Z=6?*/H9*Z)&\*!2^<F\P&>,RV`R30UOBH8+5.;;2IKF
|
||||
M0W://&'?"L?0L2!)`*]F30B0&/_'<4``%P9Z`0F`C``'"P$``2,#`0$%70``
|
||||
-@``,@*@*`6]FB2D`````
|
||||
`
|
||||
end
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user