summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibArchive Upstream <libarchive-discuss@googlegroups.com>2018-09-04 03:07:16 (GMT)
committerBrad King <brad.king@kitware.com>2018-09-26 13:52:15 (GMT)
commit2aaed7a05053c3bcbebbff5ae1beb51e590b3ad1 (patch)
tree9758c689fd63e2c7c82b14a2672283c9c913bc4c
parent11f3dcb04887fccf38a8eda19d498bf7a5060486 (diff)
downloadCMake-2aaed7a05053c3bcbebbff5ae1beb51e590b3ad1.zip
CMake-2aaed7a05053c3bcbebbff5ae1beb51e590b3ad1.tar.gz
CMake-2aaed7a05053c3bcbebbff5ae1beb51e590b3ad1.tar.bz2
LibArchive 2018-09-03 (5fe69dd0)
Code extracted from: https://github.com/libarchive/libarchive.git at commit 5fe69dd018745a88eecf1f7db40daf12d26f7ed0 (v3.3.3).
-rw-r--r--CMakeLists.txt49
-rw-r--r--build/cmake/config.h.in10
-rw-r--r--build/pkgconfig/libarchive.pc.in1
-rw-r--r--build/version2
-rw-r--r--libarchive/CMakeLists.txt2
-rw-r--r--libarchive/archive.h8
-rw-r--r--libarchive/archive_acl.c2
-rw-r--r--libarchive/archive_cmdline.c6
-rw-r--r--libarchive/archive_cryptor.c2
-rw-r--r--libarchive/archive_cryptor_private.h2
-rw-r--r--libarchive/archive_disk_acl_freebsd.c2
-rw-r--r--libarchive/archive_entry.c4
-rw-r--r--libarchive/archive_entry.h3
-rw-r--r--libarchive/archive_match.c4
-rw-r--r--libarchive/archive_openssl_hmac_private.h3
-rw-r--r--libarchive/archive_pack_dev.c3
-rw-r--r--libarchive/archive_platform.h17
-rw-r--r--libarchive/archive_ppmd7.c10
-rw-r--r--libarchive/archive_ppmd7_private.h4
-rw-r--r--libarchive/archive_ppmd_private.h7
-rw-r--r--libarchive/archive_read.c12
-rw-r--r--libarchive/archive_read_append_filter.c4
-rw-r--r--libarchive/archive_read_disk_entry_from_file.c2
-rw-r--r--libarchive/archive_read_disk_posix.c8
-rw-r--r--libarchive/archive_read_disk_windows.c19
-rw-r--r--libarchive/archive_read_filter.36
-rw-r--r--libarchive/archive_read_support_filter_all.c2
-rw-r--r--libarchive/archive_read_support_filter_zstd.c292
-rw-r--r--libarchive/archive_read_support_format_7zip.c21
-rw-r--r--libarchive/archive_read_support_format_cpio.c7
-rw-r--r--libarchive/archive_read_support_format_iso9660.c29
-rw-r--r--libarchive/archive_read_support_format_lha.c6
-rw-r--r--libarchive/archive_read_support_format_mtree.c109
-rw-r--r--libarchive/archive_read_support_format_rar.c30
-rw-r--r--libarchive/archive_read_support_format_tar.c10
-rw-r--r--libarchive/archive_read_support_format_xar.c32
-rw-r--r--libarchive/archive_read_support_format_zip.c32
-rw-r--r--libarchive/archive_string.c3
-rw-r--r--libarchive/archive_util.c4
-rw-r--r--libarchive/archive_version_details.c18
-rw-r--r--libarchive/archive_virtual.c11
-rw-r--r--libarchive/archive_write.32
-rw-r--r--libarchive/archive_write.c2
-rw-r--r--libarchive/archive_write_add_filter.c1
-rw-r--r--libarchive/archive_write_add_filter_by_name.c1
-rw-r--r--libarchive/archive_write_add_filter_gzip.c7
-rw-r--r--libarchive/archive_write_add_filter_zstd.c335
-rw-r--r--libarchive/archive_write_disk_posix.c12
-rw-r--r--libarchive/archive_write_disk_windows.c19
-rw-r--r--libarchive/archive_write_filter.36
-rw-r--r--libarchive/archive_write_set_format_7zip.c17
-rw-r--r--libarchive/archive_write_set_format_ar.c17
-rw-r--r--libarchive/archive_write_set_format_pax.c2
53 files changed, 1015 insertions, 204 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 73bf07b..80871bc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -179,6 +179,7 @@ include(CTest)
OPTION(ENABLE_NETTLE "Enable use of Nettle" ON)
OPTION(ENABLE_OPENSSL "Enable use of OpenSSL" ON)
+OPTION(ENABLE_LZ4 "Enable the use of the system LZ4 library if found" ON)
OPTION(ENABLE_LZO "Enable the use of the system LZO library if found" OFF)
OPTION(ENABLE_LZMA "Enable the use of the system LZMA library if found" ON)
@@ -492,7 +493,7 @@ IF(ENABLE_LZO)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZO2 DEFAULT_MSG LZO2_LIBRARY LZO2_INCLUDE_DIR)
ELSE(ENABLE_LZO)
- SET(LIBZMA_FOUND FALSE) # Override cached value
+ SET(LZO2_FOUND FALSE) # Override cached value
ENDIF(ENABLE_LZO)
IF(LZO2_FOUND)
SET(HAVE_LIBLZO2 1)
@@ -509,15 +510,19 @@ MARK_AS_ADVANCED(CLEAR LZO2_LIBRARY)
#
# Find LZ4
#
-IF (LZ4_INCLUDE_DIR)
- # Already in cache, be silent
- SET(LZ4_FIND_QUIETLY TRUE)
-ENDIF (LZ4_INCLUDE_DIR)
+IF(ENABLE_LZ4)
+ IF (LZ4_INCLUDE_DIR)
+ # Already in cache, be silent
+ SET(LZ4_FIND_QUIETLY TRUE)
+ ENDIF (LZ4_INCLUDE_DIR)
-FIND_PATH(LZ4_INCLUDE_DIR lz4.h)
-FIND_LIBRARY(LZ4_LIBRARY NAMES lz4 liblz4)
-INCLUDE(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZ4 DEFAULT_MSG LZ4_LIBRARY LZ4_INCLUDE_DIR)
+ FIND_PATH(LZ4_INCLUDE_DIR lz4.h)
+ FIND_LIBRARY(LZ4_LIBRARY NAMES lz4 liblz4)
+ INCLUDE(FindPackageHandleStandardArgs)
+ FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZ4 DEFAULT_MSG LZ4_LIBRARY LZ4_INCLUDE_DIR)
+ELSE(ENABLE_LZ4)
+ SET(LZ4_FOUND FALSE) # Override cached value
+ENDIF(ENABLE_LZ4)
IF(LZ4_FOUND)
SET(HAVE_LIBLZ4 1)
SET(HAVE_LZ4_H 1)
@@ -533,6 +538,31 @@ IF(LZ4_FOUND)
ENDIF(LZ4_FOUND)
MARK_AS_ADVANCED(CLEAR LZ4_INCLUDE_DIR)
MARK_AS_ADVANCED(CLEAR LZ4_LIBRARY)
+#
+# Find Zstd
+#
+IF (ZSTD_INCLUDE_DIR)
+ # Already in cache, be silent
+ SET(ZSTD_FIND_QUIETLY TRUE)
+ENDIF (ZSTD_INCLUDE_DIR)
+
+FIND_PATH(ZSTD_INCLUDE_DIR zstd.h)
+FIND_LIBRARY(ZSTD_LIBRARY NAMES zstd libzstd)
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(ZSTD DEFAULT_MSG ZSTD_LIBRARY ZSTD_INCLUDE_DIR)
+IF(ZSTD_FOUND)
+ SET(HAVE_ZSTD_H 1)
+ INCLUDE_DIRECTORIES(${ZSTD_INCLUDE_DIR})
+ LIST(APPEND ADDITIONAL_LIBS ${ZSTD_LIBRARY})
+ SET(CMAKE_REQUIRED_LIBRARIES ${ZSTD_LIBRARY})
+ SET(CMAKE_REQUIRED_INCLUDES ${ZSTD_INCLUDE_DIR})
+ CHECK_FUNCTION_EXISTS(ZSTD_compressStream HAVE_LIBZSTD)
+ #
+ # TODO: test for static library.
+ #
+ENDIF(ZSTD_FOUND)
+MARK_AS_ADVANCED(CLEAR ZSTD_INCLUDE_DIR)
+MARK_AS_ADVANCED(CLEAR ZSTD_LIBRARY)
#
# Check headers
@@ -609,6 +639,7 @@ LA_CHECK_INCLUDE_FILE("sys/select.h" HAVE_SYS_SELECT_H)
LA_CHECK_INCLUDE_FILE("sys/stat.h" HAVE_SYS_STAT_H)
LA_CHECK_INCLUDE_FILE("sys/statfs.h" HAVE_SYS_STATFS_H)
LA_CHECK_INCLUDE_FILE("sys/statvfs.h" HAVE_SYS_STATVFS_H)
+LA_CHECK_INCLUDE_FILE("sys/sysmacros.h" HAVE_SYS_SYSMACROS_H)
LA_CHECK_INCLUDE_FILE("sys/time.h" HAVE_SYS_TIME_H)
LA_CHECK_INCLUDE_FILE("sys/utime.h" HAVE_SYS_UTIME_H)
LA_CHECK_INCLUDE_FILE("sys/utsname.h" HAVE_SYS_UTSNAME_H)
diff --git a/build/cmake/config.h.in b/build/cmake/config.h.in
index e646213..04f938d 100644
--- a/build/cmake/config.h.in
+++ b/build/cmake/config.h.in
@@ -725,6 +725,9 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the `z' library (-lz). */
#cmakedefine HAVE_LIBZ 1
+/* Define to 1 if you have the `zstd' library (-lzstd). */
+#cmakedefine HAVE_LIBZSTD 1
+
/* Define to 1 if you have the <limits.h> header file. */
#cmakedefine HAVE_LIMITS_H 1
@@ -1065,6 +1068,10 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the <sys/stat.h> header file. */
#cmakedefine HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/sysmacros.h> header file. */
+#cmakedefine HAVE_SYS_SYSMACROS_H 1
+
/* Define to 1 if you have the <sys/time.h> header file. */
#cmakedefine HAVE_SYS_TIME_H 1
@@ -1179,6 +1186,9 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the <zlib.h> header file. */
#cmakedefine HAVE_ZLIB_H 1
+/* Define to 1 if you have the <zstd.h> header file. */
+#cmakedefine HAVE_ZSTD_H 1
+
/* Define to 1 if you have the `_ctime64_s' function. */
#cmakedefine HAVE__CTIME64_S 1
diff --git a/build/pkgconfig/libarchive.pc.in b/build/pkgconfig/libarchive.pc.in
index 95d7159..4b631e6 100644
--- a/build/pkgconfig/libarchive.pc.in
+++ b/build/pkgconfig/libarchive.pc.in
@@ -7,5 +7,6 @@ Name: libarchive
Description: library that can create and read several streaming archive formats
Version: @VERSION@
Cflags: -I${includedir}
+Cflags.private: -DLIBARCHIVE_STATIC
Libs: -L${libdir} -larchive
Libs.private: @LIBS@
diff --git a/build/version b/build/version
index 2dd0839..2427eab 100644
--- a/build/version
+++ b/build/version
@@ -1 +1 @@
-3003002
+3003003
diff --git a/libarchive/CMakeLists.txt b/libarchive/CMakeLists.txt
index 5e958da..82dd56c 100644
--- a/libarchive/CMakeLists.txt
+++ b/libarchive/CMakeLists.txt
@@ -88,6 +88,7 @@ SET(libarchive_SOURCES
archive_read_support_filter_rpm.c
archive_read_support_filter_uu.c
archive_read_support_filter_xz.c
+ archive_read_support_filter_zstd.c
archive_read_support_format_7zip.c
archive_read_support_format_all.c
archive_read_support_format_ar.c
@@ -134,6 +135,7 @@ SET(libarchive_SOURCES
archive_write_add_filter_program.c
archive_write_add_filter_uuencode.c
archive_write_add_filter_xz.c
+ archive_write_add_filter_zstd.c
archive_write_set_format.c
archive_write_set_format_7zip.c
archive_write_set_format_ar.c
diff --git a/libarchive/archive.h b/libarchive/archive.h
index 316a68a..cdbbedd 100644
--- a/libarchive/archive.h
+++ b/libarchive/archive.h
@@ -36,7 +36,7 @@
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
*/
/* Note: Compiler will complain if this does not match archive_entry.h! */
-#define ARCHIVE_VERSION_NUMBER 3003002
+#define ARCHIVE_VERSION_NUMBER 3003003
#include <sys/stat.h>
#include <stddef.h> /* for wchar_t */
@@ -155,7 +155,7 @@ __LA_DECL int archive_version_number(void);
/*
* Textual name/version of the library, useful for version displays.
*/
-#define ARCHIVE_VERSION_ONLY_STRING "3.3.2"
+#define ARCHIVE_VERSION_ONLY_STRING "3.3.3"
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
__LA_DECL const char * archive_version_string(void);
@@ -177,6 +177,7 @@ __LA_DECL const char * archive_zlib_version(void);
__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);
/* Declare our basic types. */
struct archive;
@@ -276,6 +277,7 @@ typedef const char *archive_passphrase_callback(struct archive *,
#define ARCHIVE_FILTER_LZOP 11
#define ARCHIVE_FILTER_GRZIP 12
#define ARCHIVE_FILTER_LZ4 13
+#define ARCHIVE_FILTER_ZSTD 14
#if ARCHIVE_VERSION_NUMBER < 4000000
#define ARCHIVE_COMPRESSION_NONE ARCHIVE_FILTER_NONE
@@ -433,6 +435,7 @@ __LA_DECL int archive_read_support_filter_program_signature
__LA_DECL int archive_read_support_filter_rpm(struct archive *);
__LA_DECL int archive_read_support_filter_uu(struct archive *);
__LA_DECL int archive_read_support_filter_xz(struct archive *);
+__LA_DECL int archive_read_support_filter_zstd(struct archive *);
__LA_DECL int archive_read_support_format_7zip(struct archive *);
__LA_DECL int archive_read_support_format_all(struct archive *);
@@ -778,6 +781,7 @@ __LA_DECL int archive_write_add_filter_program(struct archive *,
const char *cmd);
__LA_DECL int archive_write_add_filter_uuencode(struct archive *);
__LA_DECL int archive_write_add_filter_xz(struct archive *);
+__LA_DECL int archive_write_add_filter_zstd(struct archive *);
/* A convenience function to set the format based on the code or name. */
diff --git a/libarchive/archive_acl.c b/libarchive/archive_acl.c
index b8b6b63..4736531 100644
--- a/libarchive/archive_acl.c
+++ b/libarchive/archive_acl.c
@@ -1159,6 +1159,7 @@ archive_acl_from_text_w(struct archive_acl *acl, const wchar_t *text,
switch (want_type) {
case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
want_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+ __LA_FALLTHROUGH;
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
numfields = 5;
@@ -1626,6 +1627,7 @@ archive_acl_from_text_l(struct archive_acl *acl, const char *text,
switch (want_type) {
case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
want_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+ __LA_FALLTHROUGH;
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
numfields = 5;
diff --git a/libarchive/archive_cmdline.c b/libarchive/archive_cmdline.c
index 7d3bac5..5c519cd 100644
--- a/libarchive/archive_cmdline.c
+++ b/libarchive/archive_cmdline.c
@@ -100,10 +100,10 @@ get_argument(struct archive_string *as, const char *p)
/*
* Set up command line arguments.
- * Returns ARChIVE_OK if everything okey.
- * Returns ARChIVE_FAILED if there is a lack of the `"' terminator or an
+ * Returns ARCHIVE_OK if everything okey.
+ * Returns ARCHIVE_FAILED if there is a lack of the `"' terminator or an
* empty command line.
- * Returns ARChIVE_FATAL if no memory.
+ * Returns ARCHIVE_FATAL if no memory.
*/
int
__archive_cmdline_parse(struct archive_cmdline *data, const char *cmd)
diff --git a/libarchive/archive_cryptor.c b/libarchive/archive_cryptor.c
index ced52fd..71967c9 100644
--- a/libarchive/archive_cryptor.c
+++ b/libarchive/archive_cryptor.c
@@ -153,7 +153,7 @@ aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
CCCryptorStatus r;
r = CCCryptorReset(ref, NULL);
- if (r != kCCSuccess)
+ if (r != kCCSuccess && r != kCCUnimplemented)
return -1;
r = CCCryptorUpdate(ref, ctx->nonce, AES_BLOCK_SIZE, ctx->encr_buf,
AES_BLOCK_SIZE, NULL);
diff --git a/libarchive/archive_cryptor_private.h b/libarchive/archive_cryptor_private.h
index 0ca544b..b975922 100644
--- a/libarchive/archive_cryptor_private.h
+++ b/libarchive/archive_cryptor_private.h
@@ -64,7 +64,7 @@ typedef struct {
} archive_crypto_ctx;
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
-#include <Bcrypt.h>
+#include <bcrypt.h>
/* Common in other bcrypt implementations, but missing from VS2008. */
#ifndef BCRYPT_SUCCESS
diff --git a/libarchive/archive_disk_acl_freebsd.c b/libarchive/archive_disk_acl_freebsd.c
index 07d08ff..aba41e5 100644
--- a/libarchive/archive_disk_acl_freebsd.c
+++ b/libarchive/archive_disk_acl_freebsd.c
@@ -93,7 +93,9 @@ static const acl_perm_map_t acl_nfs4_flag_map[] = {
{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY},
{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
+#ifdef ACL_ENTRY_INHERITED
{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}
+#endif
};
static const int acl_nfs4_flag_map_size =
diff --git a/libarchive/archive_entry.c b/libarchive/archive_entry.c
index 30fb456..f722bbe 100644
--- a/libarchive/archive_entry.c
+++ b/libarchive/archive_entry.c
@@ -1491,7 +1491,7 @@ archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type,
* the style of the generated ACL.
*/
wchar_t *
-archive_entry_acl_to_text_w(struct archive_entry *entry, ssize_t *len,
+archive_entry_acl_to_text_w(struct archive_entry *entry, la_ssize_t *len,
int flags)
{
return (archive_acl_to_text_w(&entry->acl, len, flags,
@@ -1499,7 +1499,7 @@ archive_entry_acl_to_text_w(struct archive_entry *entry, ssize_t *len,
}
char *
-archive_entry_acl_to_text(struct archive_entry *entry, ssize_t *len,
+archive_entry_acl_to_text(struct archive_entry *entry, la_ssize_t *len,
int flags)
{
return (archive_acl_to_text_l(&entry->acl, len, flags, NULL));
diff --git a/libarchive/archive_entry.h b/libarchive/archive_entry.h
index bcc2962..78a060c 100644
--- a/libarchive/archive_entry.h
+++ b/libarchive/archive_entry.h
@@ -30,7 +30,7 @@
#define ARCHIVE_ENTRY_H_INCLUDED
/* Note: Compiler will complain if this does not match archive.h! */
-#define ARCHIVE_VERSION_NUMBER 3003002
+#define ARCHIVE_VERSION_NUMBER 3003003
/*
* Note: archive_entry.h is for use outside of libarchive; the
@@ -42,6 +42,7 @@
#include <sys/types.h>
#include <stddef.h> /* for wchar_t */
+#include <stdint.h>
#include <time.h>
#if defined(_WIN32) && !defined(__CYGWIN__)
diff --git a/libarchive/archive_match.c b/libarchive/archive_match.c
index be72066..f150e82 100644
--- a/libarchive/archive_match.c
+++ b/libarchive/archive_match.c
@@ -1582,7 +1582,7 @@ time_excluded(struct archive_match *a, struct archive_entry *entry)
*/
int
-archive_match_include_uid(struct archive *_a, int64_t uid)
+archive_match_include_uid(struct archive *_a, la_int64_t uid)
{
struct archive_match *a;
@@ -1593,7 +1593,7 @@ archive_match_include_uid(struct archive *_a, int64_t uid)
}
int
-archive_match_include_gid(struct archive *_a, int64_t gid)
+archive_match_include_gid(struct archive *_a, la_int64_t gid)
{
struct archive_match *a;
diff --git a/libarchive/archive_openssl_hmac_private.h b/libarchive/archive_openssl_hmac_private.h
index 59f95b8..921249b 100644
--- a/libarchive/archive_openssl_hmac_private.h
+++ b/libarchive/archive_openssl_hmac_private.h
@@ -28,7 +28,8 @@
#include <openssl/hmac.h>
#include <openssl/opensslv.h>
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
+ (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
#include <stdlib.h> /* malloc, free */
#include <string.h> /* memset */
static inline HMAC_CTX *HMAC_CTX_new(void)
diff --git a/libarchive/archive_pack_dev.c b/libarchive/archive_pack_dev.c
index 098881b..53bddd7 100644
--- a/libarchive/archive_pack_dev.c
+++ b/libarchive/archive_pack_dev.c
@@ -57,6 +57,9 @@ __RCSID("$NetBSD$");
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
+#ifdef HAVE_SYS_SYSMACROS_H
+#include <sys/sysmacros.h>
+#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
diff --git a/libarchive/archive_platform.h b/libarchive/archive_platform.h
index 34be8ed..32b884c 100644
--- a/libarchive/archive_platform.h
+++ b/libarchive/archive_platform.h
@@ -52,6 +52,17 @@
#error Oops: No config.h and no pre-built configuration in archive_platform.h.
#endif
+/* On macOS check for some symbols based on the deployment target version. */
+#if defined(__APPLE__)
+# undef HAVE_FUTIMENS
+# undef HAVE_UTIMENSAT
+# include <AvailabilityMacros.h>
+# if MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
+# define HAVE_FUTIMENS 1
+# define HAVE_UTIMENSAT 1
+# endif
+#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
@@ -180,4 +191,10 @@
#define ARCHIVE_ERRNO_MISC (-1)
#endif
+#if defined(__GNUC__) && (__GNUC__ >= 7)
+#define __LA_FALLTHROUGH __attribute__((fallthrough))
+#else
+#define __LA_FALLTHROUGH
+#endif
+
#endif /* !ARCHIVE_PLATFORM_H_INCLUDED */
diff --git a/libarchive/archive_ppmd7.c b/libarchive/archive_ppmd7.c
index 1aed922..d0bacc6 100644
--- a/libarchive/archive_ppmd7.c
+++ b/libarchive/archive_ppmd7.c
@@ -115,14 +115,14 @@ static void Ppmd7_Construct(CPpmd7 *p)
memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40);
}
-static void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc)
+static void Ppmd7_Free(CPpmd7 *p)
{
- alloc->Free(alloc, p->Base);
+ free(p->Base);
p->Size = 0;
p->Base = 0;
}
-static Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc)
+static Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size)
{
if (p->Base == 0 || p->Size != size)
{
@@ -131,14 +131,14 @@ static Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc)
if (size < UNIT_SIZE) {
return False;
}
- Ppmd7_Free(p, alloc);
+ Ppmd7_Free(p);
p->AlignOffset =
#ifdef PPMD_32BIT
(4 - size) & 3;
#else
4 - (size & 3);
#endif
- if ((p->Base = (Byte *)alloc->Alloc(alloc, p->AlignOffset + size
+ if ((p->Base = (Byte *)malloc(p->AlignOffset + size
#ifndef PPMD_32BIT
+ UNIT_SIZE
#endif
diff --git a/libarchive/archive_ppmd7_private.h b/libarchive/archive_ppmd7_private.h
index 06c99e8..577d6fb 100644
--- a/libarchive/archive_ppmd7_private.h
+++ b/libarchive/archive_ppmd7_private.h
@@ -95,8 +95,8 @@ typedef struct
{
/* Base Functions */
void (*Ppmd7_Construct)(CPpmd7 *p);
- Bool (*Ppmd7_Alloc)(CPpmd7 *p, UInt32 size, ISzAlloc *alloc);
- void (*Ppmd7_Free)(CPpmd7 *p, ISzAlloc *alloc);
+ Bool (*Ppmd7_Alloc)(CPpmd7 *p, UInt32 size);
+ void (*Ppmd7_Free)(CPpmd7 *p);
void (*Ppmd7_Init)(CPpmd7 *p, unsigned maxOrder);
#define Ppmd7_WasAllocated(p) ((p)->Base != NULL)
diff --git a/libarchive/archive_ppmd_private.h b/libarchive/archive_ppmd_private.h
index e78bde5..a83b851 100644
--- a/libarchive/archive_ppmd_private.h
+++ b/libarchive/archive_ppmd_private.h
@@ -69,13 +69,6 @@ typedef struct
void (*Write)(void *p, Byte b);
} IByteOut;
-
-typedef struct
-{
- void *(*Alloc)(void *p, size_t size);
- void (*Free)(void *p, void *address); /* address can be 0 */
-} ISzAlloc;
-
/*** End defined in Types.h ***/
/*** Begin defined in CpuArch.h ***/
diff --git a/libarchive/archive_read.c b/libarchive/archive_read.c
index a642a33..0e56e76 100644
--- a/libarchive/archive_read.c
+++ b/libarchive/archive_read.c
@@ -120,7 +120,8 @@ archive_read_new(void)
* Record the do-not-extract-to file. This belongs in archive_read_extract.c.
*/
void
-archive_read_extract_set_skip_file(struct archive *_a, int64_t d, int64_t i)
+archive_read_extract_set_skip_file(struct archive *_a, la_int64_t d,
+ la_int64_t i)
{
struct archive_read *a = (struct archive_read *)_a;
@@ -747,7 +748,7 @@ choose_format(struct archive_read *a)
* Return the file offset (within the uncompressed data stream) where
* the last header started.
*/
-int64_t
+la_int64_t
archive_read_header_position(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
@@ -820,7 +821,7 @@ archive_read_format_capabilities(struct archive *_a)
* DO NOT intermingle calls to this function and archive_read_data_block
* to read a single entry body.
*/
-ssize_t
+la_ssize_t
archive_read_data(struct archive *_a, void *buff, size_t s)
{
struct archive *a = (struct archive *)_a;
@@ -943,7 +944,7 @@ archive_read_data_skip(struct archive *_a)
return (r);
}
-int64_t
+la_int64_t
archive_seek_data(struct archive *_a, int64_t offset, int whence)
{
struct archive_read *a = (struct archive_read *)_a;
@@ -1626,7 +1627,8 @@ __archive_read_filter_seek(struct archive_read_filter *filter, int64_t offset,
switch (whence) {
case SEEK_CUR:
/* Adjust the offset and use SEEK_SET instead */
- offset += filter->position;
+ offset += filter->position;
+ __LA_FALLTHROUGH;
case SEEK_SET:
cursor = 0;
while (1)
diff --git a/libarchive/archive_read_append_filter.c b/libarchive/archive_read_append_filter.c
index 5e4d163..da7c55b 100644
--- a/libarchive/archive_read_append_filter.c
+++ b/libarchive/archive_read_append_filter.c
@@ -89,6 +89,10 @@ archive_read_append_filter(struct archive *_a, int code)
strcpy(str, "lz4");
r1 = archive_read_support_filter_lz4(_a);
break;
+ case ARCHIVE_FILTER_ZSTD:
+ strcpy(str, "zstd");
+ r1 = archive_read_support_filter_zstd(_a);
+ break;
case ARCHIVE_FILTER_LZIP:
strcpy(str, "lzip");
r1 = archive_read_support_filter_lzip(_a);
diff --git a/libarchive/archive_read_disk_entry_from_file.c b/libarchive/archive_read_disk_entry_from_file.c
index 548ba89..1786cff 100644
--- a/libarchive/archive_read_disk_entry_from_file.c
+++ b/libarchive/archive_read_disk_entry_from_file.c
@@ -127,7 +127,7 @@ archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
/*
* Enter working directory and return working pathname of archive_entry.
* If a pointer to an integer is provided and its value is below zero
- * open a file descriptor on this pahtname.
+ * open a file descriptor on this pathname.
*/
const char *
archive_read_disk_entry_setup_path(struct archive_read_disk *a,
diff --git a/libarchive/archive_read_disk_posix.c b/libarchive/archive_read_disk_posix.c
index 6961ae6..cdf7541 100644
--- a/libarchive/archive_read_disk_posix.c
+++ b/libarchive/archive_read_disk_posix.c
@@ -387,7 +387,7 @@ archive_read_disk_vtable(void)
}
const char *
-archive_read_disk_gname(struct archive *_a, int64_t gid)
+archive_read_disk_gname(struct archive *_a, la_int64_t gid)
{
struct archive_read_disk *a = (struct archive_read_disk *)_a;
if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
@@ -399,7 +399,7 @@ archive_read_disk_gname(struct archive *_a, int64_t gid)
}
const char *
-archive_read_disk_uname(struct archive *_a, int64_t uid)
+archive_read_disk_uname(struct archive *_a, la_int64_t uid)
{
struct archive_read_disk *a = (struct archive_read_disk *)_a;
if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
@@ -413,7 +413,7 @@ archive_read_disk_uname(struct archive *_a, int64_t uid)
int
archive_read_disk_set_gname_lookup(struct archive *_a,
void *private_data,
- const char * (*lookup_gname)(void *private, int64_t gid),
+ const char * (*lookup_gname)(void *private, la_int64_t gid),
void (*cleanup_gname)(void *private))
{
struct archive_read_disk *a = (struct archive_read_disk *)_a;
@@ -432,7 +432,7 @@ archive_read_disk_set_gname_lookup(struct archive *_a,
int
archive_read_disk_set_uname_lookup(struct archive *_a,
void *private_data,
- const char * (*lookup_uname)(void *private, int64_t uid),
+ const char * (*lookup_uname)(void *private, la_int64_t uid),
void (*cleanup_uname)(void *private))
{
struct archive_read_disk *a = (struct archive_read_disk *)_a;
diff --git a/libarchive/archive_read_disk_windows.c b/libarchive/archive_read_disk_windows.c
index 3b90330..d82048d 100644
--- a/libarchive/archive_read_disk_windows.c
+++ b/libarchive/archive_read_disk_windows.c
@@ -117,7 +117,7 @@ struct filesystem {
*/
#define MAX_OVERLAPPED 8
-#define BUFFER_SIZE (1024 * 8)
+#define READ_BUFFER_SIZE (1024 * 64) /* Default to 64KB per https://technet.microsoft.com/en-us/library/cc938632.aspx */
#define DIRECT_IO 0/* Disabled */
#define ASYNC_IO 1/* Enabled */
@@ -320,7 +320,7 @@ archive_read_disk_vtable(void)
}
const char *
-archive_read_disk_gname(struct archive *_a, int64_t gid)
+archive_read_disk_gname(struct archive *_a, la_int64_t gid)
{
struct archive_read_disk *a = (struct archive_read_disk *)_a;
if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
@@ -332,7 +332,7 @@ archive_read_disk_gname(struct archive *_a, int64_t gid)
}
const char *
-archive_read_disk_uname(struct archive *_a, int64_t uid)
+archive_read_disk_uname(struct archive *_a, la_int64_t uid)
{
struct archive_read_disk *a = (struct archive_read_disk *)_a;
if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
@@ -346,7 +346,7 @@ archive_read_disk_uname(struct archive *_a, int64_t uid)
int
archive_read_disk_set_gname_lookup(struct archive *_a,
void *private_data,
- const char * (*lookup_gname)(void *private, int64_t gid),
+ const char * (*lookup_gname)(void *private, la_int64_t gid),
void (*cleanup_gname)(void *private))
{
struct archive_read_disk *a = (struct archive_read_disk *)_a;
@@ -567,7 +567,7 @@ start_next_async_read(struct archive_read_disk *a, struct tree *t)
/* Allocate read buffer. */
if (olp->buff == NULL) {
void *p;
- size_t s = (size_t)align_num_per_sector(t, BUFFER_SIZE);
+ size_t s = (size_t)align_num_per_sector(t, READ_BUFFER_SIZE);
p = VirtualAlloc(NULL, s, MEM_COMMIT, PAGE_READWRITE);
if (p == NULL) {
archive_set_error(&a->archive, ENOMEM,
@@ -683,7 +683,7 @@ _archive_read_data_block(struct archive *_a, const void **buff,
break;
} while (r == ARCHIVE_OK && t->ol_num_doing < MAX_OVERLAPPED);
} else {
- if (start_next_async_read(a, t) == ARCHIVE_FATAL)
+ if ((r = start_next_async_read(a, t)) == ARCHIVE_FATAL)
goto abort_read_data;
}
@@ -923,6 +923,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
t->entry_fh = CreateFileW(tree_current_access_path(t),
GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, flags, NULL);
if (t->entry_fh == INVALID_HANDLE_VALUE) {
+ la_dosmaperr(GetLastError());
archive_set_error(&a->archive, errno,
"Couldn't open %ls", tree_current_path(a->tree));
return (ARCHIVE_FAILED);
@@ -2275,10 +2276,10 @@ setup_sparse_from_disk(struct archive_read_disk *a,
if (range.Length.QuadPart > 0)
continue;
} else {
- /* The remaining data is hole. */
+ /* The entire file is a hole. Add one data block of size 0 at the end. */
archive_entry_sparse_add_entry(entry,
- range.FileOffset.QuadPart,
- range.Length.QuadPart);
+ entry_size,
+ 0);
}
break;
} else {
diff --git a/libarchive/archive_read_filter.3 b/libarchive/archive_read_filter.3
index 7f020e3..ef0a701 100644
--- a/libarchive/archive_read_filter.3
+++ b/libarchive/archive_read_filter.3
@@ -38,6 +38,7 @@
.Nm archive_read_support_filter_rpm ,
.Nm archive_read_support_filter_uu ,
.Nm archive_read_support_filter_xz ,
+.Nm archive_read_support_filter_zstd ,
.Nm archive_read_support_filter_program ,
.Nm archive_read_support_filter_program_signature
.Nd functions for reading streaming archives
@@ -73,6 +74,8 @@ Streaming Archive Library (libarchive, -larchive)
.Ft int
.Fn archive_read_support_filter_xz "struct archive *"
.Ft int
+.Fn archive_read_support_filter_zstd "struct archive *"
+.Ft int
.Fo archive_read_support_filter_program
.Fa "struct archive *"
.Fa "const char *cmd"
@@ -99,7 +102,8 @@ Streaming Archive Library (libarchive, -larchive)
.Fn archive_read_support_filter_none ,
.Fn archive_read_support_filter_rpm ,
.Fn archive_read_support_filter_uu ,
-.Fn archive_read_support_filter_xz
+.Fn archive_read_support_filter_xz ,
+.Fn archive_read_support_filter_zstd ,
.Xc
Enables auto-detection code and decompression support for the
specified compression.
diff --git a/libarchive/archive_read_support_filter_all.c b/libarchive/archive_read_support_filter_all.c
index 68c53de..edb508c 100644
--- a/libarchive/archive_read_support_filter_all.c
+++ b/libarchive/archive_read_support_filter_all.c
@@ -71,6 +71,8 @@ archive_read_support_filter_all(struct archive *a)
archive_read_support_filter_grzip(a);
/* Lz4 falls back to "lz4 -d" command-line program. */
archive_read_support_filter_lz4(a);
+ /* Zstd falls back to "zstd -d" command-line program. */
+ archive_read_support_filter_zstd(a);
/* Note: We always return ARCHIVE_OK here, even if some of the
* above return ARCHIVE_WARN. The intent here is to enable
diff --git a/libarchive/archive_read_support_filter_zstd.c b/libarchive/archive_read_support_filter_zstd.c
new file mode 100644
index 0000000..c8bb36b
--- /dev/null
+++ b/libarchive/archive_read_support_filter_zstd.c
@@ -0,0 +1,292 @@
+/*-
+ * Copyright (c) 2009-2011 Sean Purcell
+ * 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"
+
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_ZSTD_H
+#include <zstd.h>
+#endif
+
+#include "archive.h"
+#include "archive_endian.h"
+#include "archive_private.h"
+#include "archive_read_private.h"
+
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+
+struct private_data {
+ ZSTD_DStream *dstream;
+ unsigned char *out_block;
+ size_t out_block_size;
+ int64_t total_out;
+ char in_frame; /* True = in the middle of a zstd frame. */
+ char eof; /* True = found end of compressed data. */
+};
+
+/* Zstd Filter. */
+static ssize_t zstd_filter_read(struct archive_read_filter *, const void**);
+static int zstd_filter_close(struct archive_read_filter *);
+#endif
+
+/*
+ * Note that we can detect zstd compressed files even if we can't decompress
+ * them. (In fact, we like detecting them because we can give better error
+ * messages.) So the bid framework here gets compiled even if no zstd library
+ * is available.
+ */
+static int zstd_bidder_bid(struct archive_read_filter_bidder *,
+ struct archive_read_filter *);
+static int zstd_bidder_init(struct archive_read_filter *);
+
+int
+archive_read_support_filter_zstd(struct archive *_a)
+{
+ struct archive_read *a = (struct archive_read *)_a;
+ struct archive_read_filter_bidder *bidder;
+
+ archive_check_magic(_a, ARCHIVE_READ_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_read_support_filter_zstd");
+
+ if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK)
+ return (ARCHIVE_FATAL);
+
+ bidder->data = NULL;
+ bidder->name = "zstd";
+ bidder->bid = zstd_bidder_bid;
+ bidder->init = zstd_bidder_init;
+ bidder->options = NULL;
+ bidder->free = NULL;
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+ return (ARCHIVE_OK);
+#else
+ archive_set_error(_a, ARCHIVE_ERRNO_MISC,
+ "Using external zstd program for zstd decompression");
+ return (ARCHIVE_WARN);
+#endif
+}
+
+/*
+ * Test whether we can handle this data.
+ */
+static int
+zstd_bidder_bid(struct archive_read_filter_bidder *self,
+ struct archive_read_filter *filter)
+{
+ const unsigned char *buffer;
+ ssize_t avail;
+ unsigned prefix;
+
+ /* Zstd frame magic values */
+ const unsigned zstd_magic = 0xFD2FB528U;
+
+ (void) self; /* UNUSED */
+
+ buffer = __archive_read_filter_ahead(filter, 4, &avail);
+ if (buffer == NULL)
+ return (0);
+
+ prefix = archive_le32dec(buffer);
+ if (prefix == zstd_magic)
+ return (32);
+
+ return (0);
+}
+
+#if !(HAVE_ZSTD_H && HAVE_LIBZSTD)
+
+/*
+ * If we don't have the library on this system, we can't do the
+ * decompression directly. We can, however, try to run "zstd -d"
+ * in case that's available.
+ */
+static int
+zstd_bidder_init(struct archive_read_filter *self)
+{
+ int r;
+
+ r = __archive_read_program(self, "zstd -d -qq");
+ /* Note: We set the format here even if __archive_read_program()
+ * above fails. We do, after all, know what the format is
+ * even if we weren't able to read it. */
+ self->code = ARCHIVE_FILTER_ZSTD;
+ self->name = "zstd";
+ return (r);
+}
+
+#else
+
+/*
+ * Initialize the filter object
+ */
+static int
+zstd_bidder_init(struct archive_read_filter *self)
+{
+ struct private_data *state;
+ const size_t out_block_size = ZSTD_DStreamOutSize();
+ void *out_block;
+ ZSTD_DStream *dstream;
+
+ self->code = ARCHIVE_FILTER_ZSTD;
+ self->name = "zstd";
+
+ state = (struct private_data *)calloc(sizeof(*state), 1);
+ out_block = (unsigned char *)malloc(out_block_size);
+ dstream = ZSTD_createDStream();
+
+ if (state == NULL || out_block == NULL || dstream == NULL) {
+ free(out_block);
+ free(state);
+ ZSTD_freeDStream(dstream); /* supports free on NULL */
+ archive_set_error(&self->archive->archive, ENOMEM,
+ "Can't allocate data for zstd decompression");
+ return (ARCHIVE_FATAL);
+ }
+
+ self->data = state;
+
+ state->out_block_size = out_block_size;
+ state->out_block = out_block;
+ state->dstream = dstream;
+ self->read = zstd_filter_read;
+ self->skip = NULL; /* not supported */
+ self->close = zstd_filter_close;
+
+ state->eof = 0;
+ state->in_frame = 0;
+
+ return (ARCHIVE_OK);
+}
+
+static ssize_t
+zstd_filter_read(struct archive_read_filter *self, const void **p)
+{
+ struct private_data *state;
+ size_t decompressed;
+ ssize_t avail_in;
+ ZSTD_outBuffer out;
+ ZSTD_inBuffer in;
+
+ state = (struct private_data *)self->data;
+
+ out = (ZSTD_outBuffer) { state->out_block, state->out_block_size, 0 };
+
+ /* Try to fill the output buffer. */
+ while (out.pos < out.size && !state->eof) {
+ if (!state->in_frame) {
+ const size_t ret = ZSTD_initDStream(state->dstream);
+ if (ZSTD_isError(ret)) {
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_MISC,
+ "Error initializing zstd decompressor: %s",
+ ZSTD_getErrorName(ret));
+ return (ARCHIVE_FATAL);
+ }
+ }
+ in.src = __archive_read_filter_ahead(self->upstream, 1,
+ &avail_in);
+ if (avail_in < 0) {
+ return avail_in;
+ }
+ if (in.src == NULL && avail_in == 0) {
+ if (!state->in_frame) {
+ /* end of stream */
+ state->eof = 1;
+ break;
+ } else {
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_MISC,
+ "Truncated zstd input");
+ return (ARCHIVE_FATAL);
+ }
+ }
+ in.size = avail_in;
+ in.pos = 0;
+
+ {
+ const size_t ret =
+ ZSTD_decompressStream(state->dstream, &out, &in);
+
+ if (ZSTD_isError(ret)) {
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_MISC,
+ "Zstd decompression failed: %s",
+ ZSTD_getErrorName(ret));
+ return (ARCHIVE_FATAL);
+ }
+
+ /* Decompressor made some progress */
+ __archive_read_filter_consume(self->upstream, in.pos);
+
+ /* ret guaranteed to be > 0 if frame isn't done yet */
+ state->in_frame = (ret != 0);
+ }
+ }
+
+ decompressed = out.pos;
+ state->total_out += decompressed;
+ if (decompressed == 0)
+ *p = NULL;
+ else
+ *p = state->out_block;
+ return (decompressed);
+}
+
+/*
+ * Clean up the decompressor.
+ */
+static int
+zstd_filter_close(struct archive_read_filter *self)
+{
+ struct private_data *state;
+
+ state = (struct private_data *)self->data;
+
+ ZSTD_freeDStream(state->dstream);
+ free(state->out_block);
+ free(state);
+
+ return (ARCHIVE_OK);
+}
+
+#endif /* HAVE_ZLIB_H && HAVE_LIBZSTD */
diff --git a/libarchive/archive_read_support_format_7zip.c b/libarchive/archive_read_support_format_7zip.c
index 3387eaf..bccbf89 100644
--- a/libarchive/archive_read_support_format_7zip.c
+++ b/libarchive/archive_read_support_format_7zip.c
@@ -975,18 +975,6 @@ decode_codec_id(const unsigned char *codecId, size_t id_size)
return (id);
}
-static void *
-ppmd_alloc(void *p, size_t size)
-{
- (void)p;
- return malloc(size);
-}
-static void
-ppmd_free(void *p, void *address)
-{
- (void)p;
- free(address);
-}
static Byte
ppmd_read(void *p)
{
@@ -1006,8 +994,6 @@ ppmd_read(void *p)
return (b);
}
-static ISzAlloc g_szalloc = { ppmd_alloc, ppmd_free };
-
static int
init_decompression(struct archive_read *a, struct _7zip *zip,
const struct _7z_coder *coder1, const struct _7z_coder *coder2)
@@ -1237,7 +1223,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
if (zip->ppmd7_valid) {
__archive_ppmd7_functions.Ppmd7_Free(
- &zip->ppmd7_context, &g_szalloc);
+ &zip->ppmd7_context);
zip->ppmd7_valid = 0;
}
@@ -1256,7 +1242,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
}
__archive_ppmd7_functions.Ppmd7_Construct(&zip->ppmd7_context);
r = __archive_ppmd7_functions.Ppmd7_Alloc(
- &zip->ppmd7_context, msize, &g_szalloc);
+ &zip->ppmd7_context, msize);
if (r == 0) {
archive_set_error(&a->archive, ENOMEM,
"Coludn't allocate memory for PPMd");
@@ -1636,7 +1622,7 @@ free_decompression(struct archive_read *a, struct _7zip *zip)
#endif
if (zip->ppmd7_valid) {
__archive_ppmd7_functions.Ppmd7_Free(
- &zip->ppmd7_context, &g_szalloc);
+ &zip->ppmd7_context);
zip->ppmd7_valid = 0;
}
return (r);
@@ -2569,6 +2555,7 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
case kDummy:
if (ll == 0)
break;
+ __LA_FALLTHROUGH;
default:
if (header_bytes(a, ll) == NULL)
return (-1);
diff --git a/libarchive/archive_read_support_format_cpio.c b/libarchive/archive_read_support_format_cpio.c
index ad9f782..67d5b21 100644
--- a/libarchive/archive_read_support_format_cpio.c
+++ b/libarchive/archive_read_support_format_cpio.c
@@ -633,6 +633,13 @@ header_newc(struct archive_read *a, struct cpio *cpio,
/* Pad name to 2 more than a multiple of 4. */
*name_pad = (2 - *namelength) & 3;
+ /* Make sure that the padded name length fits into size_t. */
+ if (*name_pad > SIZE_MAX - *namelength) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "cpio archive has invalid namelength");
+ return (ARCHIVE_FATAL);
+ }
+
/*
* Note: entry_bytes_remaining is at least 64 bits and
* therefore guaranteed to be big enough for a 33-bit file
diff --git a/libarchive/archive_read_support_format_iso9660.c b/libarchive/archive_read_support_format_iso9660.c
index f01d37b..28acfef 100644
--- a/libarchive/archive_read_support_format_iso9660.c
+++ b/libarchive/archive_read_support_format_iso9660.c
@@ -409,7 +409,8 @@ static int next_entry_seek(struct archive_read *, struct iso9660 *,
struct file_info **);
static struct file_info *
parse_file_info(struct archive_read *a,
- struct file_info *parent, const unsigned char *isodirrec);
+ struct file_info *parent, const unsigned char *isodirrec,
+ size_t reclen);
static int parse_rockridge(struct archive_read *a,
struct file_info *file, const unsigned char *start,
const unsigned char *end);
@@ -1022,7 +1023,7 @@ read_children(struct archive_read *a, struct file_info *parent)
if (*(p + DR_name_len_offset) == 1
&& *(p + DR_name_offset) == '\001')
continue;
- child = parse_file_info(a, parent, p);
+ child = parse_file_info(a, parent, p, b - p);
if (child == NULL) {
__archive_read_consume(a, skip_size);
return (ARCHIVE_FATAL);
@@ -1112,7 +1113,7 @@ choose_volume(struct archive_read *a, struct iso9660 *iso9660)
*/
seenJoliet = iso9660->seenJoliet;/* Save flag. */
iso9660->seenJoliet = 0;
- file = parse_file_info(a, NULL, block);
+ file = parse_file_info(a, NULL, block, vd->size);
if (file == NULL)
return (ARCHIVE_FATAL);
iso9660->seenJoliet = seenJoliet;
@@ -1144,7 +1145,7 @@ choose_volume(struct archive_read *a, struct iso9660 *iso9660)
return (ARCHIVE_FATAL);
}
iso9660->seenJoliet = 0;
- file = parse_file_info(a, NULL, block);
+ file = parse_file_info(a, NULL, block, vd->size);
if (file == NULL)
return (ARCHIVE_FATAL);
iso9660->seenJoliet = seenJoliet;
@@ -1749,7 +1750,7 @@ archive_read_format_iso9660_cleanup(struct archive_read *a)
*/
static struct file_info *
parse_file_info(struct archive_read *a, struct file_info *parent,
- const unsigned char *isodirrec)
+ const unsigned char *isodirrec, size_t reclen)
{
struct iso9660 *iso9660;
struct file_info *file, *filep;
@@ -1763,16 +1764,20 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
iso9660 = (struct iso9660 *)(a->format->data);
- dr_len = (size_t)isodirrec[DR_length_offset];
- name_len = (size_t)isodirrec[DR_name_len_offset];
- location = archive_le32dec(isodirrec + DR_extent_offset);
- fsize = toi(isodirrec + DR_size_offset, DR_size_size);
- /* Sanity check that dr_len needs at least 34. */
- if (dr_len < 34) {
+ if (reclen != 0)
+ dr_len = (size_t)isodirrec[DR_length_offset];
+ /*
+ * Sanity check that reclen is not zero and dr_len is greater than
+ * reclen but at least 34
+ */
+ if (reclen == 0 || reclen < dr_len || dr_len < 34) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Invalid length of directory record");
+ "Invalid length of directory record");
return (NULL);
}
+ name_len = (size_t)isodirrec[DR_name_len_offset];
+ location = archive_le32dec(isodirrec + DR_extent_offset);
+ fsize = toi(isodirrec + DR_size_offset, DR_size_size);
/* Sanity check that name_len doesn't exceed dr_len. */
if (dr_len - 33 < name_len || name_len == 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
diff --git a/libarchive/archive_read_support_format_lha.c b/libarchive/archive_read_support_format_lha.c
index b8ef4ae..95c99bb 100644
--- a/libarchive/archive_read_support_format_lha.c
+++ b/libarchive/archive_read_support_format_lha.c
@@ -701,6 +701,12 @@ archive_read_format_lha_read_header(struct archive_read *a,
* Prepare variables used to read a file content.
*/
lha->entry_bytes_remaining = lha->compsize;
+ if (lha->entry_bytes_remaining < 0) {
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "Invalid LHa entry size");
+ return (ARCHIVE_FATAL);
+ }
lha->entry_offset = 0;
lha->entry_crc_calculated = 0;
diff --git a/libarchive/archive_read_support_format_mtree.c b/libarchive/archive_read_support_format_mtree.c
index 44b6083..5b0eadc 100644
--- a/libarchive/archive_read_support_format_mtree.c
+++ b/libarchive/archive_read_support_format_mtree.c
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_mtree.c 2011
#include "archive.h"
#include "archive_entry.h"
#include "archive_private.h"
+#include "archive_rb.h"
#include "archive_read_private.h"
#include "archive_string.h"
#include "archive_pack_dev.h"
@@ -75,7 +76,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_mtree.c 2011
#define MTREE_HAS_OPTIONAL 0x0800
#define MTREE_HAS_NOCHANGE 0x1000 /* FreeBSD specific */
-#define MTREE_HASHTABLE_SIZE 1024
+#define MAX_LINE_LEN (1024 * 1024)
struct mtree_option {
struct mtree_option *next;
@@ -83,13 +84,13 @@ struct mtree_option {
};
struct mtree_entry {
+ struct archive_rb_node rbnode;
+ struct mtree_entry *next_dup;
struct mtree_entry *next;
struct mtree_option *options;
char *name;
char full;
char used;
- unsigned int name_hash;
- struct mtree_entry *hashtable_next;
};
struct mtree {
@@ -102,11 +103,12 @@ struct mtree {
const char *archive_format_name;
struct mtree_entry *entries;
struct mtree_entry *this_entry;
- struct mtree_entry *entry_hashtable[MTREE_HASHTABLE_SIZE];
+ struct archive_rb_tree entry_rbtree;
struct archive_string current_dir;
struct archive_string contents_name;
struct archive_entry_linkresolver *resolver;
+ struct archive_rb_tree rbtree;
int64_t cur_size;
char checkfs;
@@ -115,7 +117,6 @@ struct mtree {
static int bid_keycmp(const char *, const char *, ssize_t);
static int cleanup(struct archive_read *);
static int detect_form(struct archive_read *, int *);
-static unsigned int hash(const char *);
static int mtree_bid(struct archive_read *, int);
static int parse_file(struct archive_read *, struct archive_entry *,
struct mtree *, struct mtree_entry *, int *);
@@ -217,9 +218,30 @@ free_options(struct mtree_option *head)
}
}
+static int
+mtree_cmp_node(const struct archive_rb_node *n1,
+ const struct archive_rb_node *n2)
+{
+ const struct mtree_entry *e1 = (const struct mtree_entry *)n1;
+ const struct mtree_entry *e2 = (const struct mtree_entry *)n2;
+
+ return (strcmp(e1->name, e2->name));
+}
+
+static int
+mtree_cmp_key(const struct archive_rb_node *n, const void *key)
+{
+ const struct mtree_entry *e = (const struct mtree_entry *)n;
+
+ return (strcmp(e->name, key));
+}
+
int
archive_read_support_format_mtree(struct archive *_a)
{
+ static const struct archive_rb_tree_ops rb_ops = {
+ mtree_cmp_node, mtree_cmp_key,
+ };
struct archive_read *a = (struct archive_read *)_a;
struct mtree *mtree;
int r;
@@ -235,6 +257,8 @@ archive_read_support_format_mtree(struct archive *_a)
}
mtree->fd = -1;
+ __archive_rb_tree_init(&mtree->rbtree, &rb_ops);
+
r = __archive_read_register_format(a, mtree, "mtree",
mtree_bid, archive_read_format_mtree_options, read_header, read_data, skip, NULL, cleanup, NULL, NULL);
@@ -334,6 +358,14 @@ next_line(struct archive_read *a,
size_t nbytes_req = (*ravail+1023) & ~1023U;
ssize_t tested;
+ /*
+ * Place an arbitrary limit on the line length.
+ * mtree is almost free-form input and without line length limits,
+ * it can consume a lot of memory.
+ */
+ if (len >= MAX_LINE_LEN)
+ return (-1);
+
/* Increase reading bytes if it is not enough to at least
* new two lines. */
if (nbytes_req < (size_t)*ravail + 160)
@@ -865,12 +897,11 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
struct mtree_option **global, const char *line, ssize_t line_len,
struct mtree_entry **last_entry, int is_form_d)
{
- struct mtree_entry *entry, *ht_iter;
+ struct mtree_entry *entry;
struct mtree_option *iter;
const char *next, *eq, *name, *end;
size_t name_len, len;
int r, i;
- unsigned int ht_idx;
if ((entry = malloc(sizeof(*entry))) == NULL) {
archive_set_error(&a->archive, errno, "Can't allocate memory");
@@ -881,8 +912,6 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
entry->name = NULL;
entry->used = 0;
entry->full = 0;
- entry->name_hash = 0;
- entry->hashtable_next = NULL;
/* Add this entry to list. */
if (*last_entry == NULL)
@@ -935,15 +964,17 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
memcpy(entry->name, name, name_len);
entry->name[name_len] = '\0';
parse_escapes(entry->name, entry);
- entry->name_hash = hash(entry->name);
- ht_idx = entry->name_hash % MTREE_HASHTABLE_SIZE;
- if ((ht_iter = mtree->entry_hashtable[ht_idx]) != NULL) {
- while (ht_iter->hashtable_next)
- ht_iter = ht_iter->hashtable_next;
- ht_iter->hashtable_next = entry;
- } else {
- mtree->entry_hashtable[ht_idx] = entry;
+ entry->next_dup = NULL;
+ if (entry->full) {
+ if (!__archive_rb_tree_insert_node(&mtree->rbtree, &entry->rbnode)) {
+ struct mtree_entry *alt;
+ alt = (struct mtree_entry *)__archive_rb_tree_find_node(
+ &mtree->rbtree, entry->name);
+ while (alt->next_dup)
+ alt = alt->next_dup;
+ alt->next_dup = entry;
+ }
}
for (iter = *global; iter != NULL; iter = iter->next) {
@@ -1138,14 +1169,13 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
* with pathname canonicalization, which is a very
* tricky subject.)
*/
- for (mp = mentry->hashtable_next; mp != NULL; mp = mp->hashtable_next) {
- if (mp->full && !mp->used
- && mentry->name_hash == mp->name_hash
- && strcmp(mentry->name, mp->name) == 0) {
+ mp = (struct mtree_entry *)__archive_rb_tree_find_node(
+ &mtree->rbtree, mentry->name);
+ for (; mp; mp = mp->next_dup) {
+ if (mp->full && !mp->used) {
/* Later lines override earlier ones. */
mp->used = 1;
- r1 = parse_line(a, entry, mtree, mp,
- &parsed_kws);
+ r1 = parse_line(a, entry, mtree, mp, &parsed_kws);
if (r1 < r)
r = r1;
}
@@ -1489,6 +1519,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
}
if (strcmp(key, "cksum") == 0)
break;
+ __LA_FALLTHROUGH;
case 'd':
if (strcmp(key, "device") == 0) {
/* stat(2) st_rdev field, e.g. the major/minor IDs
@@ -1502,12 +1533,14 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
archive_entry_set_rdev(entry, dev);
return r;
}
+ __LA_FALLTHROUGH;
case 'f':
if (strcmp(key, "flags") == 0) {
*parsed_kws |= MTREE_HAS_FFLAGS;
archive_entry_copy_fflags_text(entry, val);
break;
}
+ __LA_FALLTHROUGH;
case 'g':
if (strcmp(key, "gid") == 0) {
*parsed_kws |= MTREE_HAS_GID;
@@ -1519,16 +1552,19 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
archive_entry_copy_gname(entry, val);
break;
}
+ __LA_FALLTHROUGH;
case 'i':
if (strcmp(key, "inode") == 0) {
archive_entry_set_ino(entry, mtree_atol(&val, 10));
break;
}
+ __LA_FALLTHROUGH;
case 'l':
if (strcmp(key, "link") == 0) {
archive_entry_copy_symlink(entry, val);
break;
}
+ __LA_FALLTHROUGH;
case 'm':
if (strcmp(key, "md5") == 0 || strcmp(key, "md5digest") == 0)
break;
@@ -1545,6 +1581,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
}
break;
}
+ __LA_FALLTHROUGH;
case 'n':
if (strcmp(key, "nlink") == 0) {
*parsed_kws |= MTREE_HAS_NLINK;
@@ -1552,6 +1589,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
(unsigned int)mtree_atol(&val, 10));
break;
}
+ __LA_FALLTHROUGH;
case 'r':
if (strcmp(key, "resdevice") == 0) {
/* stat(2) st_dev field, e.g. the device ID where the
@@ -1567,6 +1605,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
if (strcmp(key, "rmd160") == 0 ||
strcmp(key, "rmd160digest") == 0)
break;
+ __LA_FALLTHROUGH;
case 's':
if (strcmp(key, "sha1") == 0 || strcmp(key, "sha1digest") == 0)
break;
@@ -1583,6 +1622,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
archive_entry_set_size(entry, mtree_atol(&val, 10));
break;
}
+ __LA_FALLTHROUGH;
case 't':
if (strcmp(key, "tags") == 0) {
/*
@@ -1625,18 +1665,21 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
archive_entry_set_filetype(entry, AE_IFBLK);
break;
}
+ __LA_FALLTHROUGH;
case 'c':
if (strcmp(val, "char") == 0) {
archive_entry_set_filetype(entry,
AE_IFCHR);
break;
}
+ __LA_FALLTHROUGH;
case 'd':
if (strcmp(val, "dir") == 0) {
archive_entry_set_filetype(entry,
AE_IFDIR);
break;
}
+ __LA_FALLTHROUGH;
case 'f':
if (strcmp(val, "fifo") == 0) {
archive_entry_set_filetype(entry,
@@ -1648,12 +1691,14 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
AE_IFREG);
break;
}
+ __LA_FALLTHROUGH;
case 'l':
if (strcmp(val, "link") == 0) {
archive_entry_set_filetype(entry,
AE_IFLNK);
break;
}
+ __LA_FALLTHROUGH;
default:
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
@@ -1665,6 +1710,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
*parsed_kws |= MTREE_HAS_TYPE;
break;
}
+ __LA_FALLTHROUGH;
case 'u':
if (strcmp(key, "uid") == 0) {
*parsed_kws |= MTREE_HAS_UID;
@@ -1676,6 +1722,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
archive_entry_copy_uname(entry, val);
break;
}
+ __LA_FALLTHROUGH;
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Unrecognized key %s=%s", key, val);
@@ -1962,19 +2009,3 @@ readline(struct archive_read *a, struct mtree *mtree, char **start,
find_off = u - mtree->line.s;
}
}
-
-static unsigned int
-hash(const char *p)
-{
- /* A 32-bit version of Peter Weinberger's (PJW) hash algorithm,
- as used by ELF for hashing function names. */
- unsigned g, h = 0;
- while (*p != '\0') {
- h = (h << 4) + *p++;
- if ((g = h & 0xF0000000) != 0) {
- h ^= g >> 24;
- h &= 0x0FFFFFFF;
- }
- }
- return h;
-}
diff --git a/libarchive/archive_read_support_format_rar.c b/libarchive/archive_read_support_format_rar.c
index cbb14c3..2345222 100644
--- a/libarchive/archive_read_support_format_rar.c
+++ b/libarchive/archive_read_support_format_rar.c
@@ -604,20 +604,6 @@ lzss_emit_match(struct rar *rar, int offset, int length)
rar->lzss.position += length;
}
-static void *
-ppmd_alloc(void *p, size_t size)
-{
- (void)p;
- return malloc(size);
-}
-static void
-ppmd_free(void *p, void *address)
-{
- (void)p;
- free(address);
-}
-static ISzAlloc g_szalloc = { ppmd_alloc, ppmd_free };
-
static Byte
ppmd_read(void *p)
{
@@ -1038,7 +1024,7 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff,
case COMPRESS_METHOD_BEST:
ret = read_data_compressed(a, buff, size, offset);
if (ret != ARCHIVE_OK && ret != ARCHIVE_WARN)
- __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context, &g_szalloc);
+ __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
break;
default:
@@ -1253,7 +1239,7 @@ archive_read_format_rar_cleanup(struct archive_read *a)
free(rar->dbo);
free(rar->unp_buffer);
free(rar->lzss.window);
- __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context, &g_szalloc);
+ __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
free(rar);
(a->format->data) = NULL;
return (ARCHIVE_OK);
@@ -1496,7 +1482,11 @@ read_header(struct archive_read *a, struct archive_entry *entry,
return (ARCHIVE_FATAL);
}
filename[filename_size++] = '\0';
- filename[filename_size++] = '\0';
+ /*
+ * Do not increment filename_size here as the computations below
+ * add the space for the terminating NUL explicitly.
+ */
+ filename[filename_size] = '\0';
/* Decoded unicode form is UTF-16BE, so we have to update a string
* conversion object for it. */
@@ -1654,7 +1644,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
rar->unp_offset = 0;
rar->unp_buffer_size = UNP_BUFFER_SIZE;
memset(rar->lengthtable, 0, sizeof(rar->lengthtable));
- __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context, &g_szalloc);
+ __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
rar->ppmd_valid = rar->ppmd_eod = 0;
/* Don't set any archive entries for non-file header types */
@@ -2118,7 +2108,7 @@ parse_codes(struct archive_read *a)
/* Make sure ppmd7_contest is freed before Ppmd7_Construct
* because reading a broken file cause this abnormal sequence. */
- __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context, &g_szalloc);
+ __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
rar->bytein.a = a;
rar->bytein.Read = &ppmd_read;
@@ -2133,7 +2123,7 @@ parse_codes(struct archive_read *a)
}
if (!__archive_ppmd7_functions.Ppmd7_Alloc(&rar->ppmd7_context,
- rar->dictionary_size, &g_szalloc))
+ rar->dictionary_size))
{
archive_set_error(&a->archive, ENOMEM,
"Out of memory");
diff --git a/libarchive/archive_read_support_format_tar.c b/libarchive/archive_read_support_format_tar.c
index 30d5bc8..60800bb 100644
--- a/libarchive/archive_read_support_format_tar.c
+++ b/libarchive/archive_read_support_format_tar.c
@@ -251,15 +251,15 @@ archive_read_support_format_tar(struct archive *_a)
ARCHIVE_STATE_NEW, "archive_read_support_format_tar");
tar = (struct tar *)calloc(1, sizeof(*tar));
-#ifdef HAVE_COPYFILE_H
- /* Set this by default on Mac OS. */
- tar->process_mac_extensions = 1;
-#endif
if (tar == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate tar data");
return (ARCHIVE_FATAL);
}
+#ifdef HAVE_COPYFILE_H
+ /* Set this by default on Mac OS. */
+ tar->process_mac_extensions = 1;
+#endif
r = __archive_read_register_format(a, tar, "tar",
archive_read_format_tar_bid,
@@ -2241,7 +2241,7 @@ gnu_add_sparse_entry(struct archive_read *a, struct tar *tar,
else
tar->sparse_list = p;
tar->sparse_last = p;
- if (remaining < 0 || offset < 0) {
+ if (remaining < 0 || offset < 0 || offset > INT64_MAX - remaining) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Malformed sparse map data");
return (ARCHIVE_FATAL);
}
diff --git a/libarchive/archive_read_support_format_xar.c b/libarchive/archive_read_support_format_xar.c
index 7a22beb..602fc77 100644
--- a/libarchive/archive_read_support_format_xar.c
+++ b/libarchive/archive_read_support_format_xar.c
@@ -1040,6 +1040,9 @@ atol10(const char *p, size_t char_cnt)
uint64_t l;
int digit;
+ if (char_cnt == 0)
+ return (0);
+
l = 0;
digit = *p - '0';
while (digit >= 0 && digit < 10 && char_cnt-- > 0) {
@@ -1054,7 +1057,10 @@ atol8(const char *p, size_t char_cnt)
{
int64_t l;
int digit;
-
+
+ if (char_cnt == 0)
+ return (0);
+
l = 0;
while (char_cnt-- > 0) {
if (*p >= '0' && *p <= '7')
@@ -2623,6 +2629,14 @@ strappend_base64(struct xar *xar,
archive_strncat(as, (const char *)buff, len);
}
+static int
+is_string(const char *known, const char *data, size_t len)
+{
+ if (strlen(known) != len)
+ return -1;
+ return memcmp(data, known, len);
+}
+
static void
xml_data(void *userData, const char *s, int len)
{
@@ -2674,26 +2688,26 @@ xml_data(void *userData, const char *s, int len)
archive_strncpy(&(xar->file->symlink), s, len);
break;
case FILE_TYPE:
- if (strncmp("file", s, len) == 0 ||
- strncmp("hardlink", s, len) == 0)
+ if (is_string("file", s, len) == 0 ||
+ is_string("hardlink", s, len) == 0)
xar->file->mode =
(xar->file->mode & ~AE_IFMT) | AE_IFREG;
- if (strncmp("directory", s, len) == 0)
+ if (is_string("directory", s, len) == 0)
xar->file->mode =
(xar->file->mode & ~AE_IFMT) | AE_IFDIR;
- if (strncmp("symlink", s, len) == 0)
+ if (is_string("symlink", s, len) == 0)
xar->file->mode =
(xar->file->mode & ~AE_IFMT) | AE_IFLNK;
- if (strncmp("character special", s, len) == 0)
+ if (is_string("character special", s, len) == 0)
xar->file->mode =
(xar->file->mode & ~AE_IFMT) | AE_IFCHR;
- if (strncmp("block special", s, len) == 0)
+ if (is_string("block special", s, len) == 0)
xar->file->mode =
(xar->file->mode & ~AE_IFMT) | AE_IFBLK;
- if (strncmp("socket", s, len) == 0)
+ if (is_string("socket", s, len) == 0)
xar->file->mode =
(xar->file->mode & ~AE_IFMT) | AE_IFSOCK;
- if (strncmp("fifo", s, len) == 0)
+ if (is_string("fifo", s, len) == 0)
xar->file->mode =
(xar->file->mode & ~AE_IFMT) | AE_IFIFO;
xar->file->has |= HAS_TYPE;
diff --git a/libarchive/archive_read_support_format_zip.c b/libarchive/archive_read_support_format_zip.c
index 4c4f6fa..18f0d04 100644
--- a/libarchive/archive_read_support_format_zip.c
+++ b/libarchive/archive_read_support_format_zip.c
@@ -511,7 +511,13 @@ process_extra(struct archive_read *a, const char *p, size_t extra_length, struct
case 0x5455:
{
/* Extended time field "UT". */
- int flags = p[offset];
+ int flags;
+ if (datasize == 0) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Incomplete extended time field");
+ return ARCHIVE_FAILED;
+ }
+ flags = p[offset];
offset++;
datasize--;
/* Flag bits indicate which dates are present. */
@@ -723,6 +729,11 @@ process_extra(struct archive_read *a, const char *p, size_t extra_length, struct
}
case 0x9901:
/* WinZip AES extra data field. */
+ if (datasize < 6) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Incomplete AES field");
+ return ARCHIVE_FAILED;
+ }
if (p[offset + 2] == 'A' && p[offset + 3] == 'E') {
/* Vendor version. */
zip_entry->aes_extra.vendor =
@@ -881,6 +892,24 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
zip_entry->mode |= 0664;
}
+ /* Windows archivers sometimes use backslash as the directory separator.
+ Normalize to slash. */
+ if (zip_entry->system == 0 &&
+ (wp = archive_entry_pathname_w(entry)) != NULL) {
+ if (wcschr(wp, L'/') == NULL && wcschr(wp, L'\\') != NULL) {
+ size_t i;
+ struct archive_wstring s;
+ archive_string_init(&s);
+ archive_wstrcpy(&s, wp);
+ for (i = 0; i < archive_strlen(&s); i++) {
+ if (s.s[i] == '\\')
+ s.s[i] = '/';
+ }
+ archive_entry_copy_pathname_w(entry, s.s);
+ archive_wstring_free(&s);
+ }
+ }
+
/* Make sure that entries with a trailing '/' are marked as directories
* even if the External File Attributes contains bogus values. If this
* is not a directory and there is no type, assume regularfile. */
@@ -1056,6 +1085,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
zip->end_of_entry = 1;
/* Set up a more descriptive format name. */
+ archive_string_empty(&zip->format_name);
archive_string_sprintf(&zip->format_name, "ZIP %d.%d (%s)",
version / 10, version % 10,
compression_name(zip->entry->compression));
diff --git a/libarchive/archive_string.c b/libarchive/archive_string.c
index 5ae09b6..554533e 100644
--- a/libarchive/archive_string.c
+++ b/libarchive/archive_string.c
@@ -214,7 +214,8 @@ archive_wstring_append(struct archive_wstring *as, const wchar_t *p, size_t s)
{
if (archive_wstring_ensure(as, as->length + s + 1) == NULL)
return (NULL);
- wmemmove(as->s + as->length, p, s);
+ if (s)
+ wmemmove(as->s + as->length, p, s);
as->length += s;
as->s[as->length] = 0;
return (as);
diff --git a/libarchive/archive_util.c b/libarchive/archive_util.c
index bac9ba1..96d6145 100644
--- a/libarchive/archive_util.c
+++ b/libarchive/archive_util.c
@@ -140,7 +140,7 @@ archive_compression_name(struct archive *a)
/*
* Return a count of the number of compressed bytes processed.
*/
-int64_t
+la_int64_t
archive_position_compressed(struct archive *a)
{
return archive_filter_bytes(a, -1);
@@ -149,7 +149,7 @@ archive_position_compressed(struct archive *a)
/*
* Return a count of the number of uncompressed bytes processed.
*/
-int64_t
+la_int64_t
archive_position_uncompressed(struct archive *a)
{
return archive_filter_bytes(a, 0);
diff --git a/libarchive/archive_version_details.c b/libarchive/archive_version_details.c
index 813f0f3..bfb20ea 100644
--- a/libarchive/archive_version_details.c
+++ b/libarchive/archive_version_details.c
@@ -45,6 +45,9 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_util.c 201098 2009-12-28 02:58:1
#ifdef HAVE_LZ4_H
#include <lz4.h>
#endif
+#ifdef HAVE_ZSTD_H
+#include <zstd.h>
+#endif
#include "archive.h"
#include "archive_private.h"
@@ -59,6 +62,7 @@ archive_version_details(void)
const char *liblzma = archive_liblzma_version();
const char *bzlib = archive_bzlib_version();
const char *liblz4 = archive_liblz4_version();
+ const char *libzstd = archive_libzstd_version();
if (!init) {
archive_string_init(&str);
@@ -84,6 +88,10 @@ archive_version_details(void)
archive_strcat(&str, " liblz4/");
archive_strcat(&str, liblz4);
}
+ if (libzstd) {
+ archive_strcat(&str, " libzstd/");
+ archive_strcat(&str, libzstd);
+ }
}
return str.s;
}
@@ -131,3 +139,13 @@ archive_liblz4_version(void)
return NULL;
#endif
}
+
+const char *
+archive_libzstd_version(void)
+{
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+ return ZSTD_VERSION_STRING;
+#else
+ return NULL;
+#endif
+}
diff --git a/libarchive/archive_virtual.c b/libarchive/archive_virtual.c
index de2595a..f509ee5 100644
--- a/libarchive/archive_virtual.c
+++ b/libarchive/archive_virtual.c
@@ -48,7 +48,7 @@ archive_filter_name(struct archive *a, int n)
return ((a->vtable->archive_filter_name)(a, n));
}
-int64_t
+la_int64_t
archive_filter_bytes(struct archive *a, int n)
{
return ((a->vtable->archive_filter_bytes)(a, n));
@@ -124,14 +124,15 @@ archive_write_finish_entry(struct archive *a)
return ((a->vtable->archive_write_finish_entry)(a));
}
-ssize_t
+la_ssize_t
archive_write_data(struct archive *a, const void *buff, size_t s)
{
return ((a->vtable->archive_write_data)(a, buff, s));
}
-ssize_t
-archive_write_data_block(struct archive *a, const void *buff, size_t s, int64_t o)
+la_ssize_t
+archive_write_data_block(struct archive *a, const void *buff, size_t s,
+ la_int64_t o)
{
if (a->vtable->archive_write_data_block == NULL) {
archive_set_error(a, ARCHIVE_ERRNO_MISC,
@@ -156,7 +157,7 @@ archive_read_next_header2(struct archive *a, struct archive_entry *entry)
int
archive_read_data_block(struct archive *a,
- const void **buff, size_t *s, int64_t *o)
+ const void **buff, size_t *s, la_int64_t *o)
{
return ((a->vtable->archive_read_data_block)(a, buff, s, o));
}
diff --git a/libarchive/archive_write.3 b/libarchive/archive_write.3
index 376d71d..c1164f5 100644
--- a/libarchive/archive_write.3
+++ b/libarchive/archive_write.3
@@ -71,7 +71,7 @@ support.
.\"
.Ss Set options
See
-.Xr archive_read_set_options 3 .
+.Xr archive_write_set_options 3 .
.\"
.Ss Open archive
See
diff --git a/libarchive/archive_write.c b/libarchive/archive_write.c
index 0634a22..e8daf53 100644
--- a/libarchive/archive_write.c
+++ b/libarchive/archive_write.c
@@ -190,7 +190,7 @@ archive_write_get_bytes_in_last_block(struct archive *_a)
* an archive to itself recursively.
*/
int
-archive_write_set_skip_file(struct archive *_a, int64_t d, int64_t i)
+archive_write_set_skip_file(struct archive *_a, la_int64_t d, la_int64_t i)
{
struct archive_write *a = (struct archive_write *)_a;
archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
diff --git a/libarchive/archive_write_add_filter.c b/libarchive/archive_write_add_filter.c
index 08f518a..203f414 100644
--- a/libarchive/archive_write_add_filter.c
+++ b/libarchive/archive_write_add_filter.c
@@ -53,6 +53,7 @@ struct { int code; int (*setter)(struct archive *); } codes[] =
{ ARCHIVE_FILTER_LZOP, archive_write_add_filter_lzip },
{ ARCHIVE_FILTER_UU, archive_write_add_filter_uuencode },
{ ARCHIVE_FILTER_XZ, archive_write_add_filter_xz },
+ { ARCHIVE_FILTER_ZSTD, archive_write_add_filter_zstd },
{ -1, NULL }
};
diff --git a/libarchive/archive_write_add_filter_by_name.c b/libarchive/archive_write_add_filter_by_name.c
index 85a8d47..ffa633c 100644
--- a/libarchive/archive_write_add_filter_by_name.c
+++ b/libarchive/archive_write_add_filter_by_name.c
@@ -57,6 +57,7 @@ struct { const char *name; int (*setter)(struct archive *); } names[] =
{ "lzop", archive_write_add_filter_lzop },
{ "uuencode", archive_write_add_filter_uuencode },
{ "xz", archive_write_add_filter_xz },
+ { "zstd", archive_write_add_filter_zstd },
{ NULL, NULL }
};
diff --git a/libarchive/archive_write_add_filter_gzip.c b/libarchive/archive_write_add_filter_gzip.c
index 04eb06c..e4b3435 100644
--- a/libarchive/archive_write_add_filter_gzip.c
+++ b/libarchive/archive_write_add_filter_gzip.c
@@ -226,7 +226,12 @@ archive_compressor_gzip_open(struct archive_write_filter *f)
data->compressed[7] = (uint8_t)(t>>24)&0xff;
} else
memset(&data->compressed[4], 0, 4);
- data->compressed[8] = 0; /* No deflate options */
+ if (data->compression_level == 9)
+ data->compressed[8] = 2;
+ else if(data->compression_level == 1)
+ data->compressed[8] = 4;
+ else
+ data->compressed[8] = 0;
data->compressed[9] = 3; /* OS=Unix */
data->stream.next_out += 10;
data->stream.avail_out -= 10;
diff --git a/libarchive/archive_write_add_filter_zstd.c b/libarchive/archive_write_add_filter_zstd.c
new file mode 100644
index 0000000..671fc6a
--- /dev/null
+++ b/libarchive/archive_write_add_filter_zstd.c
@@ -0,0 +1,335 @@
+/*-
+ * Copyright (c) 2017 Sean Purcell
+ * 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"
+
+__FBSDID("$FreeBSD$");
+
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_ZSTD_H
+#include <zstd.h>
+#endif
+
+#include "archive.h"
+#include "archive_private.h"
+#include "archive_string.h"
+#include "archive_write_private.h"
+
+/* Don't compile this if we don't have zstd.h */
+
+struct private_data {
+ int compression_level;
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+ ZSTD_CStream *cstream;
+ int64_t total_in;
+ ZSTD_outBuffer out;
+#else
+ struct archive_write_program_data *pdata;
+#endif
+};
+
+static int archive_compressor_zstd_options(struct archive_write_filter *,
+ const char *, const char *);
+static int archive_compressor_zstd_open(struct archive_write_filter *);
+static int archive_compressor_zstd_write(struct archive_write_filter *,
+ const void *, size_t);
+static int archive_compressor_zstd_close(struct archive_write_filter *);
+static int archive_compressor_zstd_free(struct archive_write_filter *);
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+static int drive_compressor(struct archive_write_filter *,
+ struct private_data *, int, const void *, size_t);
+#endif
+
+
+/*
+ * Add a zstd compression filter to this write handle.
+ */
+int
+archive_write_add_filter_zstd(struct archive *_a)
+{
+ struct archive_write *a = (struct archive_write *)_a;
+ struct archive_write_filter *f = __archive_write_allocate_filter(_a);
+ struct private_data *data;
+ archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_write_add_filter_zstd");
+
+ data = calloc(1, sizeof(*data));
+ if (data == NULL) {
+ archive_set_error(&a->archive, ENOMEM, "Out of memory");
+ return (ARCHIVE_FATAL);
+ }
+ f->data = data;
+ f->open = &archive_compressor_zstd_open;
+ f->options = &archive_compressor_zstd_options;
+ f->close = &archive_compressor_zstd_close;
+ f->free = &archive_compressor_zstd_free;
+ f->code = ARCHIVE_FILTER_ZSTD;
+ f->name = "zstd";
+ data->compression_level = 3; /* Default level used by the zstd CLI */
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+ data->cstream = ZSTD_createCStream();
+ if (data->cstream == NULL) {
+ free(data);
+ archive_set_error(&a->archive, ENOMEM,
+ "Failed to allocate zstd compressor object");
+ return (ARCHIVE_FATAL);
+ }
+
+ return (ARCHIVE_OK);
+#else
+ data->pdata = __archive_write_program_allocate("zstd");
+ if (data->pdata == NULL) {
+ free(data);
+ archive_set_error(&a->archive, ENOMEM, "Out of memory");
+ return (ARCHIVE_FATAL);
+ }
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Using external zstd program");
+ return (ARCHIVE_WARN);
+#endif
+}
+
+static int
+archive_compressor_zstd_free(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+ ZSTD_freeCStream(data->cstream);
+ free(data->out.dst);
+#else
+ __archive_write_program_free(data->pdata);
+#endif
+ free(data);
+ f->data = NULL;
+ return (ARCHIVE_OK);
+}
+
+/*
+ * Set write options.
+ */
+static int
+archive_compressor_zstd_options(struct archive_write_filter *f, const char *key,
+ const char *value)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+ if (strcmp(key, "compression-level") == 0) {
+ int level = atoi(value);
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+ if (level < 1 || level > ZSTD_maxCLevel()) {
+#else
+ /* If we don't have the library, hard-code the max level */
+ if (level < 1 || level > 22) {
+#endif
+ return (ARCHIVE_WARN);
+ }
+ data->compression_level = level;
+ return (ARCHIVE_OK);
+ }
+
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
+}
+
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+/*
+ * Setup callback.
+ */
+static int
+archive_compressor_zstd_open(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+ int ret;
+
+ ret = __archive_write_open_filter(f->next_filter);
+ if (ret != ARCHIVE_OK)
+ return (ret);
+
+ if (data->out.dst == NULL) {
+ size_t bs = ZSTD_CStreamOutSize(), bpb;
+ if (f->archive->magic == ARCHIVE_WRITE_MAGIC) {
+ /* Buffer size should be a multiple number of
+ * the of bytes per block for performance. */
+ bpb = archive_write_get_bytes_per_block(f->archive);
+ if (bpb > bs)
+ bs = bpb;
+ else if (bpb != 0)
+ bs -= bs % bpb;
+ }
+ data->out.size = bs;
+ data->out.pos = 0;
+ data->out.dst
+ = (unsigned char *)malloc(data->out.size);
+ if (data->out.dst == NULL) {
+ archive_set_error(f->archive, ENOMEM,
+ "Can't allocate data for compression buffer");
+ return (ARCHIVE_FATAL);
+ }
+ }
+
+ f->write = archive_compressor_zstd_write;
+
+ if (ZSTD_isError(ZSTD_initCStream(data->cstream,
+ data->compression_level))) {
+ archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
+ "Internal error initializing zstd compressor object");
+ return (ARCHIVE_FATAL);
+ }
+
+ return (ARCHIVE_OK);
+}
+
+/*
+ * Write data to the compressed stream.
+ */
+static int
+archive_compressor_zstd_write(struct archive_write_filter *f, const void *buff,
+ size_t length)
+{
+ struct private_data *data = (struct private_data *)f->data;
+ int ret;
+
+ /* Update statistics */
+ data->total_in += length;
+
+ if ((ret = drive_compressor(f, data, 0, buff, length)) != ARCHIVE_OK)
+ return (ret);
+
+ return (ARCHIVE_OK);
+}
+
+/*
+ * Finish the compression...
+ */
+static int
+archive_compressor_zstd_close(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+ int r1, r2;
+
+ /* Finish zstd frame */
+ r1 = drive_compressor(f, data, 1, NULL, 0);
+
+ r2 = __archive_write_close_filter(f->next_filter);
+
+ return r1 < r2 ? r1 : r2;
+}
+
+/*
+ * Utility function to push input data through compressor,
+ * writing full output blocks as necessary.
+ *
+ * Note that this handles both the regular write case (finishing ==
+ * false) and the end-of-archive case (finishing == true).
+ */
+static int
+drive_compressor(struct archive_write_filter *f,
+ struct private_data *data, int finishing, const void *src, size_t length)
+{
+ ZSTD_inBuffer in = (ZSTD_inBuffer) { src, length, 0 };
+
+ for (;;) {
+ if (data->out.pos == data->out.size) {
+ const int ret = __archive_write_filter(f->next_filter,
+ data->out.dst, data->out.size);
+ if (ret != ARCHIVE_OK)
+ return (ARCHIVE_FATAL);
+ data->out.pos = 0;
+ }
+
+ /* If there's nothing to do, we're done. */
+ if (!finishing && in.pos == in.size)
+ return (ARCHIVE_OK);
+
+ {
+ const size_t zstdret = !finishing ?
+ ZSTD_compressStream(data->cstream, &data->out, &in)
+ : ZSTD_endStream(data->cstream, &data->out);
+
+ if (ZSTD_isError(zstdret)) {
+ archive_set_error(f->archive,
+ ARCHIVE_ERRNO_MISC,
+ "Zstd compression failed: %s",
+ ZSTD_getErrorName(zstdret));
+ return (ARCHIVE_FATAL);
+ }
+
+ /* If we're finishing, 0 means nothing left to flush */
+ if (finishing && zstdret == 0) {
+ const int ret = __archive_write_filter(f->next_filter,
+ data->out.dst, data->out.pos);
+ return (ret);
+ }
+ }
+ }
+}
+
+#else /* HAVE_ZSTD_H && HAVE_LIBZSTD */
+
+static int
+archive_compressor_zstd_open(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+ struct archive_string as;
+ int r;
+
+ archive_string_init(&as);
+ archive_string_sprintf(&as, "zstd -%d", data->compression_level);
+
+ f->write = archive_compressor_zstd_write;
+ r = __archive_write_program_open(f, data->pdata, as.s);
+ archive_string_free(&as);
+ return (r);
+}
+
+static int
+archive_compressor_zstd_write(struct archive_write_filter *f, const void *buff,
+ size_t length)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+ return __archive_write_program_write(f, data->pdata, buff, length);
+}
+
+static int
+archive_compressor_zstd_close(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+ return __archive_write_program_close(f, data->pdata);
+}
+
+#endif /* HAVE_ZSTD_H && HAVE_LIBZSTD */
diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c
index 6ad5399..3fd5f57 100644
--- a/libarchive/archive_write_disk_posix.c
+++ b/libarchive/archive_write_disk_posix.c
@@ -835,7 +835,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
}
int
-archive_write_disk_set_skip_file(struct archive *_a, int64_t d, int64_t i)
+archive_write_disk_set_skip_file(struct archive *_a, la_int64_t d, la_int64_t i)
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
@@ -1786,7 +1786,7 @@ finish_metadata:
int
archive_write_disk_set_group_lookup(struct archive *_a,
void *private_data,
- int64_t (*lookup_gid)(void *private, const char *gname, int64_t gid),
+ la_int64_t (*lookup_gid)(void *private, const char *gname, la_int64_t gid),
void (*cleanup_gid)(void *private))
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
@@ -1822,7 +1822,7 @@ archive_write_disk_set_user_lookup(struct archive *_a,
}
int64_t
-archive_write_disk_gid(struct archive *_a, const char *name, int64_t id)
+archive_write_disk_gid(struct archive *_a, const char *name, la_int64_t id)
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
@@ -1833,7 +1833,7 @@ archive_write_disk_gid(struct archive *_a, const char *name, int64_t id)
}
int64_t
-archive_write_disk_uid(struct archive *_a, const char *name, int64_t id)
+archive_write_disk_uid(struct archive *_a, const char *name, la_int64_t id)
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
@@ -1981,6 +1981,10 @@ restore_entry(struct archive_write_disk *a)
if ((en == EISDIR || en == EEXIST)
&& (a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) {
/* If we're not overwriting, we're done. */
+ if (S_ISDIR(a->mode)) {
+ /* Don't overwrite any settings on existing directories. */
+ a->todo = 0;
+ }
archive_entry_unset_size(a->entry);
return (ARCHIVE_OK);
}
diff --git a/libarchive/archive_write_disk_windows.c b/libarchive/archive_write_disk_windows.c
index 94b016e..78eda4a 100644
--- a/libarchive/archive_write_disk_windows.c
+++ b/libarchive/archive_write_disk_windows.c
@@ -906,7 +906,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
}
int
-archive_write_disk_set_skip_file(struct archive *_a, int64_t d, int64_t i)
+archive_write_disk_set_skip_file(struct archive *_a, la_int64_t d, la_int64_t i)
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
@@ -1156,7 +1156,7 @@ _archive_write_disk_finish_entry(struct archive *_a)
int
archive_write_disk_set_group_lookup(struct archive *_a,
void *private_data,
- int64_t (*lookup_gid)(void *private, const char *gname, int64_t gid),
+ la_int64_t (*lookup_gid)(void *private, const char *gname, la_int64_t gid),
void (*cleanup_gid)(void *private))
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
@@ -1192,7 +1192,7 @@ archive_write_disk_set_user_lookup(struct archive *_a,
}
int64_t
-archive_write_disk_gid(struct archive *_a, const char *name, int64_t id)
+archive_write_disk_gid(struct archive *_a, const char *name, la_int64_t id)
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
@@ -1203,7 +1203,7 @@ archive_write_disk_gid(struct archive *_a, const char *name, int64_t id)
}
int64_t
-archive_write_disk_uid(struct archive *_a, const char *name, int64_t id)
+archive_write_disk_uid(struct archive *_a, const char *name, la_int64_t id)
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
@@ -1322,9 +1322,20 @@ restore_entry(struct archive_write_disk *a)
}
}
+ if ((en == ENOENT) && (archive_entry_hardlink(a->entry) != NULL)) {
+ archive_set_error(&a->archive, en,
+ "Hard-link target '%s' does not exist.",
+ archive_entry_hardlink(a->entry));
+ return (ARCHIVE_FAILED);
+ }
+
if ((en == EISDIR || en == EEXIST)
&& (a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) {
/* If we're not overwriting, we're done. */
+ if (S_ISDIR(a->mode)) {
+ /* Don't overwrite any settings on existing directories. */
+ a->todo = 0;
+ }
archive_entry_unset_size(a->entry);
return (ARCHIVE_OK);
}
diff --git a/libarchive/archive_write_filter.3 b/libarchive/archive_write_filter.3
index e1d1891..d6fa071 100644
--- a/libarchive/archive_write_filter.3
+++ b/libarchive/archive_write_filter.3
@@ -42,7 +42,8 @@
.Nm archive_write_add_filter_none ,
.Nm archive_write_add_filter_program ,
.Nm archive_write_add_filter_uuencode ,
-.Nm archive_write_add_filter_xz
+.Nm archive_write_add_filter_xz ,
+.Nm archive_write_add_filter_zstd ,
.Nd functions enabling output filters
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
@@ -76,6 +77,8 @@ Streaming Archive Library (libarchive, -larchive)
.Fn archive_write_add_filter_uuencode "struct archive *"
.Ft int
.Fn archive_write_add_filter_xz "struct archive *"
+.Ft int
+.Fn archive_write_add_filter_zstd "struct archive *"
.Sh DESCRIPTION
.Bl -tag -width indent
.It Xo
@@ -89,6 +92,7 @@ Streaming Archive Library (libarchive, -larchive)
.Fn archive_write_add_filter_lzma ,
.Fn archive_write_add_filter_lzop ,
.Fn archive_write_add_filter_xz ,
+.Fn archive_write_add_filter_zstd ,
.Xc
The resulting archive will be compressed as specified.
Note that the compressed output is always properly blocked.
diff --git a/libarchive/archive_write_set_format_7zip.c b/libarchive/archive_write_set_format_7zip.c
index 41ed74d..f63a226 100644
--- a/libarchive/archive_write_set_format_7zip.c
+++ b/libarchive/archive_write_set_format_7zip.c
@@ -2095,19 +2095,6 @@ compression_init_encoder_lzma2(struct archive *a,
/*
* _7_PPMD compressor.
*/
-static void *
-ppmd_alloc(void *p, size_t size)
-{
- (void)p;
- return malloc(size);
-}
-static void
-ppmd_free(void *p, void *address)
-{
- (void)p;
- free(address);
-}
-static ISzAlloc g_szalloc = { ppmd_alloc, ppmd_free };
static void
ppmd_write(void *p, Byte b)
{
@@ -2167,7 +2154,7 @@ compression_init_encoder_ppmd(struct archive *a,
archive_le32enc(props+1, msize);
__archive_ppmd7_functions.Ppmd7_Construct(&strm->ppmd7_context);
r = __archive_ppmd7_functions.Ppmd7_Alloc(
- &strm->ppmd7_context, msize, &g_szalloc);
+ &strm->ppmd7_context, msize);
if (r == 0) {
free(strm->buff);
free(strm);
@@ -2243,7 +2230,7 @@ compression_end_ppmd(struct archive *a, struct la_zstream *lastrm)
(void)a; /* UNUSED */
strm = (struct ppmd_stream *)lastrm->real_stream;
- __archive_ppmd7_functions.Ppmd7_Free(&strm->ppmd7_context, &g_szalloc);
+ __archive_ppmd7_functions.Ppmd7_Free(&strm->ppmd7_context);
free(strm->buff);
free(strm);
lastrm->real_stream = NULL;
diff --git a/libarchive/archive_write_set_format_ar.c b/libarchive/archive_write_set_format_ar.c
index c9771d8..50305cc 100644
--- a/libarchive/archive_write_set_format_ar.c
+++ b/libarchive/archive_write_set_format_ar.c
@@ -180,7 +180,7 @@ archive_write_ar_header(struct archive_write *a, struct archive_entry *entry)
}
memset(buff, ' ', 60);
- strncpy(&buff[AR_fmag_offset], "`\n", 2);
+ memcpy(&buff[AR_fmag_offset], "`\n", 2);
if (strcmp(pathname, "/") == 0 ) {
/* Entry is archive symbol table in GNU format */
@@ -189,7 +189,7 @@ archive_write_ar_header(struct archive_write *a, struct archive_entry *entry)
}
if (strcmp(pathname, "__.SYMDEF") == 0) {
/* Entry is archive symbol table in BSD format */
- strncpy(buff + AR_name_offset, "__.SYMDEF", 9);
+ memcpy(buff + AR_name_offset, "__.SYMDEF", 9);
goto stat;
}
if (strcmp(pathname, "//") == 0) {
@@ -225,7 +225,7 @@ archive_write_ar_header(struct archive_write *a, struct archive_entry *entry)
* actually 15 bytes.
*/
if (strlen(filename) <= 15) {
- strncpy(&buff[AR_name_offset],
+ memcpy(&buff[AR_name_offset],
filename, strlen(filename));
buff[AR_name_offset + strlen(filename)] = '/';
} else {
@@ -248,7 +248,7 @@ archive_write_ar_header(struct archive_write *a, struct archive_entry *entry)
return (ARCHIVE_FATAL);
}
- strncpy(se, filename, strlen(filename));
+ memcpy(se, filename, strlen(filename));
strcpy(se + strlen(filename), "/\n");
ss = strstr(ar->strtab, se);
@@ -285,11 +285,11 @@ archive_write_ar_header(struct archive_write *a, struct archive_entry *entry)
* archive header.
*/
if (strlen(filename) <= 16 && strchr(filename, ' ') == NULL) {
- strncpy(&buff[AR_name_offset], filename, strlen(filename));
+ memcpy(&buff[AR_name_offset], filename, strlen(filename));
buff[AR_name_offset + strlen(filename)] = ' ';
}
else {
- strncpy(buff + AR_name_offset, "#1/", 3);
+ memcpy(buff + AR_name_offset, "#1/", 3);
if (format_decimal(strlen(filename),
buff + AR_name_offset + 3,
AR_name_size - 3)) {
@@ -374,13 +374,14 @@ archive_write_ar_data(struct archive_write *a, const void *buff, size_t s)
return (ARCHIVE_WARN);
}
- ar->strtab = (char *)malloc(s);
+ ar->strtab = (char *)malloc(s + 1);
if (ar->strtab == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate strtab buffer");
return (ARCHIVE_FATAL);
}
- strncpy(ar->strtab, buff, s);
+ memcpy(ar->strtab, buff, s);
+ ar->strtab[s] = '\0';
ar->has_strtab = 1;
}
diff --git a/libarchive/archive_write_set_format_pax.c b/libarchive/archive_write_set_format_pax.c
index 0eaf733..3cebeae 100644
--- a/libarchive/archive_write_set_format_pax.c
+++ b/libarchive/archive_write_set_format_pax.c
@@ -1654,7 +1654,7 @@ build_pax_attribute_name(char *dest, const char *src)
* GNU PAX Format 1.0 requires the special name, which pattern is:
* <dir>/GNUSparseFile.<pid>/<original file name>
*
- * Since reproducable archives are more important, use 0 as pid.
+ * Since reproducible archives are more important, use 0 as pid.
*
* This function is used for only Sparse file, a file type of which
* is regular file.