mirror of
https://github.com/Kitware/CMake.git
synced 2026-04-24 23:28:32 -05:00
Merge branch 'upstream-LibArchive' into update-libarchive
* upstream-LibArchive: LibArchive 2018-09-03 (5fe69dd0)
This commit is contained in:
@@ -71,6 +71,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)
|
||||
|
||||
@@ -328,7 +329,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)
|
||||
@@ -347,15 +348,19 @@ IF(0) # CMake does not need LZ4 support in libarchive
|
||||
#
|
||||
# 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)
|
||||
@@ -371,6 +376,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)
|
||||
ENDIF()
|
||||
|
||||
#
|
||||
@@ -451,6 +481,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)
|
||||
|
||||
@@ -728,6 +728,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
|
||||
|
||||
@@ -1071,6 +1074,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
|
||||
|
||||
@@ -1185,6 +1192,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
|
||||
|
||||
|
||||
@@ -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@
|
||||
|
||||
@@ -1 +1 @@
|
||||
3003002
|
||||
3003003
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
@@ -152,7 +152,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);
|
||||
|
||||
@@ -174,6 +174,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;
|
||||
@@ -273,6 +274,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
|
||||
@@ -430,6 +432,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 *);
|
||||
@@ -775,6 +778,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. */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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__)
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -196,4 +196,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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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 ***/
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
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");
|
||||
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 dr_len needs at least 34. */
|
||||
if (dr_len < 34) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Invalid length of directory record");
|
||||
return (NULL);
|
||||
}
|
||||
/* 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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 }
|
||||
};
|
||||
|
||||
|
||||
@@ -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 }
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user