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:
Martin Matuska
2025-06-01 22:16:26 +02:00
181 changed files with 25591 additions and 2349 deletions
+1 -1
View File
@@ -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:
+8
View File
@@ -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
+6 -3
View File
@@ -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
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -52,7 +52,7 @@ test_create(void)
* #ifdef this section out. Most of the test below is
* still valid. */
memset(&times, 0, sizeof(times));
#if defined(_WIN32) && !defined(CYGWIN)
#if defined(_WIN32) && !defined(__CYGWIN__)
times.actime = 86400;
times.modtime = 86400;
#else
+4 -4
View File
@@ -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 */
+54 -3
View File
@@ -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
}
+12 -2
View File
@@ -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;
+214 -130
View File
@@ -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");
+32 -22
View File
@@ -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;
+58 -26
View File
@@ -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 */
+37 -65
View File
@@ -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 */
@@ -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)
{
+11 -4
View File
@@ -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 */
+1 -1
View File
@@ -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];
+91 -50
View File
@@ -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;
}
@@ -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 */
+16 -60
View File
@@ -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(&reg->digest.md5, entry->digest.md5,
sizeof(reg->digest.md5));
}
if ((reg->compute_sum & F_RMD160)
&& (reg->mset_digest & AE_MSET_DIGEST_RMD160)) {
memcpy(&reg->digest.rmd160, entry->digest.rmd160,
sizeof(reg->digest.rmd160));
}
if ((reg->compute_sum & F_SHA1)
&& (reg->mset_digest & AE_MSET_DIGEST_SHA1)) {
memcpy(&reg->digest.sha1, entry->digest.sha1,
sizeof(reg->digest.sha1));
}
if ((reg->compute_sum & F_SHA256)
&& (reg->mset_digest & AE_MSET_DIGEST_SHA256)) {
memcpy(&reg->digest.sha256, entry->digest.sha256,
sizeof(reg->digest.sha256));
}
if ((reg->compute_sum & F_SHA384)
&& (reg->mset_digest & AE_MSET_DIGEST_SHA384)) {
memcpy(&reg->digest.sha384, entry->digest.sha384,
sizeof(reg->digest.sha384));
}
if ((reg->compute_sum & F_SHA512)
&& (reg->mset_digest & AE_MSET_DIGEST_SHA512)) {
memcpy(&reg->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");
@@ -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