Merge branch 'upstream-LibArchive' into update-libarchive

# By LibArchive Upstream
* upstream-LibArchive:
  LibArchive 2026-01-05 (dd897a78)
This commit is contained in:
Brad King
2026-01-26 11:13:03 -05:00
40 changed files with 431 additions and 255 deletions
+10 -7
View File
@@ -167,7 +167,12 @@ IF (CMAKE_C_COMPILER_ID MATCHES "^GNU$" OR
# either of the following two, yet neither is supported as of 3.0.2
# - check_linker_flag - does not exist
# - try_compile - does not support linker flags
IF(NOT CMAKE_SYSTEM_NAME MATCHES "Darwin")
IF(CMAKE_SYSTEM_NAME MATCHES "Darwin")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-dead_strip")
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-dead_strip")
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "SunOS")
# SunOS linker doesn't support --gc-sections
ELSE()
# Place the functions and data into separate sections, allowing the linker
# to garbage collect the unused ones.
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections")
@@ -176,10 +181,7 @@ IF (CMAKE_C_COMPILER_ID MATCHES "^GNU$" OR
# Printing the discarded section is "too much", so enable on demand.
#SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -Wl,--print-gc-sections")
#SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -Wl,--print-gc-sections")
ELSE()
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-dead_strip")
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-dead_strip")
ENDIF(NOT CMAKE_SYSTEM_NAME MATCHES "Darwin")
ENDIF()
ENDIF (CMAKE_C_COMPILER_ID MATCHES "^GNU$" OR
CMAKE_C_COMPILER_ID MATCHES "^Clang$" AND NOT MSVC)
IF (CMAKE_C_COMPILER_ID MATCHES "^XL$")
@@ -1118,8 +1120,8 @@ MACRO(CHECK_ICONV LIB TRY_ICONV_CONST)
CMAKE_C_COMPILER_ID MATCHES "^Clang$")
#
# During checking iconv proto type, we should use -Werror to avoid the
# success of iconv detection with a warning which success is a miss
# detection. So this needs for all build mode(even it's a release mode).
# success of iconv detection with a warning, which would be a false
# positive. So this is needed for all build modes, even in release mode.
#
SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror")
ENDIF (CMAKE_C_COMPILER_ID MATCHES "^GNU$" OR CMAKE_C_COMPILER_ID MATCHES "^LCC$" OR
@@ -1563,6 +1565,7 @@ CHECK_FUNCTION_EXISTS_GLIBC(nl_langinfo HAVE_NL_LANGINFO)
CHECK_FUNCTION_EXISTS_GLIBC(openat HAVE_OPENAT)
CHECK_FUNCTION_EXISTS_GLIBC(pipe HAVE_PIPE)
CHECK_FUNCTION_EXISTS_GLIBC(poll HAVE_POLL)
CHECK_FUNCTION_EXISTS_GLIBC(posix_spawn HAVE_POSIX_SPAWN)
CHECK_FUNCTION_EXISTS_GLIBC(posix_spawnp HAVE_POSIX_SPAWNP)
CHECK_FUNCTION_EXISTS_GLIBC(readlink HAVE_READLINK)
CHECK_FUNCTION_EXISTS_GLIBC(readpassphrase HAVE_READPASSPHRASE)
@@ -1,22 +1,22 @@
# - Find libgcc
# Find the libgcc library.
#
# LIBGCC_LIBRARIES - List of libraries when using libgcc
# LIBGCC_FOUND - True if libgcc found.
IF (LIBGCC_LIBRARY)
# Already in cache, be silent
SET(LIBGCC_FIND_QUIETLY TRUE)
ENDIF (LIBGCC_LIBRARY)
FIND_LIBRARY(LIBGCC_LIBRARY NAMES gcc libgcc)
# handle the QUIETLY and REQUIRED arguments and set LIBGCC_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBGCC DEFAULT_MSG LIBGCC_LIBRARY)
IF(LIBGCC_FOUND)
SET(LIBGCC_LIBRARIES ${LIBGCC_LIBRARY})
SET(HAVE_LIBGCC 1)
ENDIF(LIBGCC_FOUND)
# - Find libgcc
# Find the libgcc library.
#
# LIBGCC_LIBRARIES - List of libraries when using libgcc
# LIBGCC_FOUND - True if libgcc found.
IF (LIBGCC_LIBRARY)
# Already in cache, be silent
SET(LIBGCC_FIND_QUIETLY TRUE)
ENDIF (LIBGCC_LIBRARY)
FIND_LIBRARY(LIBGCC_LIBRARY NAMES gcc libgcc)
# handle the QUIETLY and REQUIRED arguments and set LIBGCC_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBGCC DEFAULT_MSG LIBGCC_LIBRARY)
IF(LIBGCC_FOUND)
SET(LIBGCC_LIBRARIES ${LIBGCC_LIBRARY})
SET(HAVE_LIBGCC 1)
ENDIF(LIBGCC_FOUND)
@@ -1,23 +1,23 @@
# - Find Nettle
# Find the Nettle include directory and library
#
# NETTLE_INCLUDE_DIR - where to find <nettle/sha.h>, etc.
# NETTLE_LIBRARIES - List of libraries when using libnettle.
# NETTLE_FOUND - True if libnettle found.
IF (NETTLE_INCLUDE_DIR)
# Already in cache, be silent
SET(NETTLE_FIND_QUIETLY TRUE)
ENDIF (NETTLE_INCLUDE_DIR)
FIND_PATH(NETTLE_INCLUDE_DIR nettle/md5.h nettle/ripemd160.h nettle/sha.h)
FIND_LIBRARY(NETTLE_LIBRARY NAMES nettle libnettle)
# handle the QUIETLY and REQUIRED arguments and set NETTLE_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(NETTLE DEFAULT_MSG NETTLE_LIBRARY NETTLE_INCLUDE_DIR)
IF(NETTLE_FOUND)
SET(NETTLE_LIBRARIES ${NETTLE_LIBRARY})
ENDIF(NETTLE_FOUND)
# - Find Nettle
# Find the Nettle include directory and library
#
# NETTLE_INCLUDE_DIR - where to find <nettle/sha.h>, etc.
# NETTLE_LIBRARIES - List of libraries when using libnettle.
# NETTLE_FOUND - True if libnettle found.
IF (NETTLE_INCLUDE_DIR)
# Already in cache, be silent
SET(NETTLE_FIND_QUIETLY TRUE)
ENDIF (NETTLE_INCLUDE_DIR)
FIND_PATH(NETTLE_INCLUDE_DIR nettle/md5.h nettle/ripemd160.h nettle/sha.h)
FIND_LIBRARY(NETTLE_LIBRARY NAMES nettle libnettle)
# handle the QUIETLY and REQUIRED arguments and set NETTLE_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(NETTLE DEFAULT_MSG NETTLE_LIBRARY NETTLE_INCLUDE_DIR)
IF(NETTLE_FOUND)
SET(NETTLE_LIBRARIES ${NETTLE_LIBRARY})
ENDIF(NETTLE_FOUND)
@@ -1,34 +1,34 @@
# - Find pcre2posix
# Find the native PCRE2-8 and PCRE2-POSIX include and libraries
#
# PCRE2_INCLUDE_DIR - where to find pcre2posix.h, etc.
# PCRE2POSIX_LIBRARIES - List of libraries when using libpcre2-posix.
# PCRE2_LIBRARIES - List of libraries when using libpcre2-8.
# PCRE2POSIX_FOUND - True if libpcre2-posix found.
# PCRE2_FOUND - True if libpcre2-8 found.
IF (PCRE2_INCLUDE_DIR)
# Already in cache, be silent
SET(PCRE2_FIND_QUIETLY TRUE)
ENDIF (PCRE2_INCLUDE_DIR)
FIND_PATH(PCRE2_INCLUDE_DIR pcre2posix.h)
FIND_LIBRARY(PCRE2POSIX_LIBRARY NAMES pcre2-posix libpcre2-posix pcre2-posix-static)
FIND_LIBRARY(PCRE2_LIBRARY NAMES pcre2-8 libpcre2-8 pcre2-8-static)
# handle the QUIETLY and REQUIRED arguments and set PCRE2POSIX_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE2POSIX DEFAULT_MSG PCRE2POSIX_LIBRARY PCRE2_INCLUDE_DIR)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE2 DEFAULT_MSG PCRE2_LIBRARY)
IF(PCRE2POSIX_FOUND)
SET(PCRE2POSIX_LIBRARIES ${PCRE2POSIX_LIBRARY})
SET(HAVE_LIBPCRE2POSIX 1)
SET(HAVE_PCRE2POSIX_H 1)
ENDIF(PCRE2POSIX_FOUND)
IF(PCRE2_FOUND)
SET(PCRE2_LIBRARIES ${PCRE2_LIBRARY})
SET(HAVE_LIBPCRE2 1)
ENDIF(PCRE2_FOUND)
# - Find pcre2posix
# Find the native PCRE2-8 and PCRE2-POSIX include and libraries
#
# PCRE2_INCLUDE_DIR - where to find pcre2posix.h, etc.
# PCRE2POSIX_LIBRARIES - List of libraries when using libpcre2-posix.
# PCRE2_LIBRARIES - List of libraries when using libpcre2-8.
# PCRE2POSIX_FOUND - True if libpcre2-posix found.
# PCRE2_FOUND - True if libpcre2-8 found.
IF (PCRE2_INCLUDE_DIR)
# Already in cache, be silent
SET(PCRE2_FIND_QUIETLY TRUE)
ENDIF (PCRE2_INCLUDE_DIR)
FIND_PATH(PCRE2_INCLUDE_DIR pcre2posix.h)
FIND_LIBRARY(PCRE2POSIX_LIBRARY NAMES pcre2-posix libpcre2-posix pcre2-posix-static)
FIND_LIBRARY(PCRE2_LIBRARY NAMES pcre2-8 libpcre2-8 pcre2-8-static)
# handle the QUIETLY and REQUIRED arguments and set PCRE2POSIX_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE2POSIX DEFAULT_MSG PCRE2POSIX_LIBRARY PCRE2_INCLUDE_DIR)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE2 DEFAULT_MSG PCRE2_LIBRARY)
IF(PCRE2POSIX_FOUND)
SET(PCRE2POSIX_LIBRARIES ${PCRE2POSIX_LIBRARY})
SET(HAVE_LIBPCRE2POSIX 1)
SET(HAVE_PCRE2POSIX_H 1)
ENDIF(PCRE2POSIX_FOUND)
IF(PCRE2_FOUND)
SET(PCRE2_LIBRARIES ${PCRE2_LIBRARY})
SET(HAVE_LIBPCRE2 1)
ENDIF(PCRE2_FOUND)
@@ -1,34 +1,34 @@
# - Find pcreposix
# Find the native PCRE and PCREPOSIX include and libraries
#
# PCRE_INCLUDE_DIR - where to find pcreposix.h, etc.
# PCREPOSIX_LIBRARIES - List of libraries when using libpcreposix.
# PCRE_LIBRARIES - List of libraries when using libpcre.
# PCREPOSIX_FOUND - True if libpcreposix found.
# PCRE_FOUND - True if libpcre found.
IF (PCRE_INCLUDE_DIR)
# Already in cache, be silent
SET(PCRE_FIND_QUIETLY TRUE)
ENDIF (PCRE_INCLUDE_DIR)
FIND_PATH(PCRE_INCLUDE_DIR pcreposix.h)
FIND_LIBRARY(PCREPOSIX_LIBRARY NAMES pcreposix libpcreposix)
FIND_LIBRARY(PCRE_LIBRARY NAMES pcre libpcre)
# handle the QUIETLY and REQUIRED arguments and set PCREPOSIX_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCREPOSIX DEFAULT_MSG PCREPOSIX_LIBRARY PCRE_INCLUDE_DIR)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE DEFAULT_MSG PCRE_LIBRARY)
IF(PCREPOSIX_FOUND)
SET(PCREPOSIX_LIBRARIES ${PCREPOSIX_LIBRARY})
SET(HAVE_LIBPCREPOSIX 1)
SET(HAVE_PCREPOSIX_H 1)
ENDIF(PCREPOSIX_FOUND)
IF(PCRE_FOUND)
SET(PCRE_LIBRARIES ${PCRE_LIBRARY})
SET(HAVE_LIBPCRE 1)
ENDIF(PCRE_FOUND)
# - Find pcreposix
# Find the native PCRE and PCREPOSIX include and libraries
#
# PCRE_INCLUDE_DIR - where to find pcreposix.h, etc.
# PCREPOSIX_LIBRARIES - List of libraries when using libpcreposix.
# PCRE_LIBRARIES - List of libraries when using libpcre.
# PCREPOSIX_FOUND - True if libpcreposix found.
# PCRE_FOUND - True if libpcre found.
IF (PCRE_INCLUDE_DIR)
# Already in cache, be silent
SET(PCRE_FIND_QUIETLY TRUE)
ENDIF (PCRE_INCLUDE_DIR)
FIND_PATH(PCRE_INCLUDE_DIR pcreposix.h)
FIND_LIBRARY(PCREPOSIX_LIBRARY NAMES pcreposix libpcreposix)
FIND_LIBRARY(PCRE_LIBRARY NAMES pcre libpcre)
# handle the QUIETLY and REQUIRED arguments and set PCREPOSIX_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCREPOSIX DEFAULT_MSG PCREPOSIX_LIBRARY PCRE_INCLUDE_DIR)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE DEFAULT_MSG PCRE_LIBRARY)
IF(PCREPOSIX_FOUND)
SET(PCREPOSIX_LIBRARIES ${PCREPOSIX_LIBRARY})
SET(HAVE_LIBPCREPOSIX 1)
SET(HAVE_PCREPOSIX_H 1)
ENDIF(PCREPOSIX_FOUND)
IF(PCRE_FOUND)
SET(PCRE_LIBRARIES ${PCRE_LIBRARY})
SET(HAVE_LIBPCRE 1)
ENDIF(PCRE_FOUND)
+1 -1
View File
@@ -1 +1 @@
3008002
3008005
+2 -2
View File
@@ -34,7 +34,7 @@
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
*/
/* Note: Compiler will complain if this does not match archive_entry.h! */
#define ARCHIVE_VERSION_NUMBER 3008002
#define ARCHIVE_VERSION_NUMBER 3008005
#include <sys/stat.h>
#include <stddef.h> /* for wchar_t */
@@ -174,7 +174,7 @@ __LA_DECL int archive_version_number(void);
/*
* Textual name/version of the library, useful for version displays.
*/
#define ARCHIVE_VERSION_ONLY_STRING "3.8.2"
#define ARCHIVE_VERSION_ONLY_STRING "3.8.5"
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
__LA_DECL const char * archive_version_string(void);
@@ -490,9 +490,9 @@ aes_ctr_update(archive_crypto_ctx *ctx, const uint8_t * const in,
size_t in_len, uint8_t * const out, size_t *out_len)
{
uint8_t *const ebuf = ctx->encr_buf;
unsigned pos = ctx->encr_pos;
unsigned max = (unsigned)((in_len < *out_len)? in_len: *out_len);
unsigned i;
size_t pos = ctx->encr_pos;
size_t max = (in_len < *out_len)? in_len: *out_len;
size_t i;
for (i = 0; i < max; ) {
if (pos == AES_BLOCK_SIZE) {
@@ -56,10 +56,10 @@ int __libarchive_cryptor_build_hack(void);
typedef struct {
CCCryptorRef ctx;
uint8_t key[AES_MAX_KEY_SIZE];
unsigned key_len;
size_t key_len;
uint8_t nonce[AES_BLOCK_SIZE];
uint8_t encr_buf[AES_BLOCK_SIZE];
unsigned encr_pos;
size_t encr_pos;
} archive_crypto_ctx;
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
@@ -124,7 +124,6 @@ static void
add_trivial_nfs4_acl(struct archive_entry *entry)
{
mode_t mode;
int i;
const int rperm = ARCHIVE_ENTRY_ACL_READ_DATA;
const int wperm = ARCHIVE_ENTRY_ACL_WRITE_DATA |
ARCHIVE_ENTRY_ACL_APPEND_DATA;
@@ -195,7 +194,7 @@ add_trivial_nfs4_acl(struct archive_entry *entry)
} else if ((mode & 0010) || (mode & 0001))
tacl_entry[1].permset |= eperm;
for (i = 0; i < sizeof(tacl_entry) / sizeof(tacl_entry[0]); i++) {
for (size_t i = 0; i < sizeof(tacl_entry) / sizeof(tacl_entry[0]); i++) {
if (tacl_entry[i].permset != 0) {
archive_entry_acl_add_entry(entry,
tacl_entry[i].type, tacl_entry[i].permset,
@@ -28,7 +28,7 @@
#define ARCHIVE_ENTRY_H_INCLUDED
/* Note: Compiler will complain if this does not match archive.h! */
#define ARCHIVE_VERSION_NUMBER 3008002
#define ARCHIVE_VERSION_NUMBER 3008005
/*
* Note: archive_entry.h is for use outside of libarchive; the
@@ -207,7 +207,7 @@ for setting is recommended.
The function
.Fn archive_entry_size
returns the file size, if it has been set, and 0 otherwise.
.Fn archive_entry_size
.Fn archive_entry_size_is_set
can be used to query that status.
.Fn archive_entry_set_size
and
@@ -254,7 +254,7 @@ archive_read_disk_entry_from_file(struct archive *_a,
if (S_ISLNK(st->st_mode)) {
size_t linkbuffer_len = st->st_size;
char *linkbuffer;
int lnklen;
ssize_t lnklen;
linkbuffer = malloc(linkbuffer_len + 1);
if (linkbuffer == NULL) {
@@ -358,12 +358,10 @@ setup_mac_metadata(struct archive_read_disk *a,
return (ARCHIVE_OK);
archive_string_init(&tempfile);
if (__archive_get_tempdir(&tempfile) != ARCHIVE_OK) {
ret = ARCHIVE_WARN;
goto cleanup;
}
archive_strcat(&tempfile, "tar.md.XXXXXX");
tempfd = mkstemp(tempfile.s);
archive_strcpy(&tempfile, name);
archive_string_dirname(&tempfile);
archive_strcat(&tempfile, "/tar.XXXXXXXX");
tempfd = __archive_mkstemp(tempfile.s);
if (tempfd < 0) {
archive_set_error(&a->archive, errno,
"Could not open extended attribute file");
@@ -894,7 +892,7 @@ setup_sparse_fiemap(struct archive_read_disk *a,
for (iters = 0; ; ++iters) {
int i, r;
r = ioctl(*fd, FS_IOC_FIEMAP, fm);
r = ioctl(*fd, FS_IOC_FIEMAP, fm);
if (r < 0) {
/* When something error happens, it is better we
* should return ARCHIVE_OK because an earlier
@@ -1081,4 +1079,3 @@ setup_sparse(struct archive_read_disk *a,
#endif
#endif /* !defined(_WIN32) || defined(__CYGWIN__) */
@@ -111,6 +111,8 @@
#define O_CLOEXEC 0
#endif
#define MAX_FILESYSTEM_ID 1000000
#if defined(__hpux) && !defined(HAVE_DIRFD)
#define dirfd(x) ((x)->__dd_fd)
#define HAVE_DIRFD
@@ -1420,8 +1422,12 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
* This is the new filesystem which we have to generate a new ID for.
*/
fid = t->max_filesystem_id++;
if (fid > MAX_FILESYSTEM_ID) {
archive_set_error(&a->archive, ENOMEM, "Too many filesystems");
return (ARCHIVE_FATAL);
}
if (t->max_filesystem_id > t->allocated_filesystem) {
size_t s;
int s;
void *p;
s = t->max_filesystem_id * 2;
@@ -1701,8 +1707,6 @@ setup_current_filesystem(struct archive_read_disk *a)
#endif
t->current_filesystem->noatime = 0;
/* Set maximum filename length. */
t->current_filesystem->name_max = svfs.f_namemax;
return (ARCHIVE_OK);
}
@@ -2022,11 +2026,8 @@ tree_dup(int fd)
}
#endif /* F_DUPFD_CLOEXEC */
new_fd = dup(fd);
if (new_fd != -1) {
__archive_ensure_cloexec_flag(new_fd);
return (new_fd);
}
return (-1);
__archive_ensure_cloexec_flag(new_fd);
return (new_fd);
}
/*
@@ -2148,16 +2149,11 @@ tree_reopen(struct tree *t, const char *path, int restore_time)
* so try again for execute. The consequences of not opening this are
* unhelpful and unnecessary errors later.
*/
if (t->initial_dir_fd < 0) {
if (t->initial_dir_fd < 0)
t->initial_dir_fd = open(".", o_flag | O_CLOEXEC);
if (t->initial_dir_fd < 0)
return NULL;
}
#endif
__archive_ensure_cloexec_flag(t->initial_dir_fd);
t->working_dir_fd = tree_dup(t->initial_dir_fd);
if (t->working_dir_fd < 0)
return NULL;
return (t);
}
@@ -2366,15 +2362,20 @@ static int
tree_dir_next_posix(struct tree *t)
{
int r;
#if defined(HAVE_FDOPENDIR)
int fd;
#endif
const char *name;
size_t namelen;
if (t->d == NULL) {
#if defined(HAVE_FDOPENDIR)
int fd = tree_dup(t->working_dir_fd);
if (fd != -1)
t->d = fdopendir(fd);
if (t->working_dir_fd >= 0) {
fd = tree_dup(t->working_dir_fd);
if (fd != -1)
t->d = fdopendir(fd);
}
#else /* HAVE_FDOPENDIR */
if (tree_enter_working_dir(t) == 0) {
t->d = opendir(".");
@@ -53,6 +53,8 @@
/* To deal with absolute symlink issues */
#define START_ABSOLUTE_SYMLINK_REPARSE L"\\??\\"
#define MAX_FILESYSTEM_ID 1000000
/*-
* This is a new directory-walking system that addresses a number
* of problems I've had with fts(3). In particular, it has no
@@ -1449,8 +1451,12 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
* There is a new filesystem, we generate a new ID for.
*/
fid = t->max_filesystem_id++;
if (fid > MAX_FILESYSTEM_ID) {
archive_set_error(&a->archive, ENOMEM, "Too many filesystems");
return (ARCHIVE_FATAL);
}
if (t->max_filesystem_id > t->allocated_filesystem) {
size_t s;
int s;
void *p;
s = t->max_filesystem_id * 2;
@@ -1462,7 +1468,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
return (ARCHIVE_FATAL);
}
t->filesystem_table = (struct filesystem *)p;
t->allocated_filesystem = (int)s;
t->allocated_filesystem = s;
}
t->current_filesystem_id = fid;
t->current_filesystem = &(t->filesystem_table[fid]);
@@ -49,9 +49,12 @@
#include "archive_xxhash.h"
#define LZ4_MAGICNUMBER 0x184d2204
#define LZ4_SKIPPABLED 0x184d2a50
#define LZ4_LEGACY 0x184c2102
// Note: LZ4 and zstd share the same skippable frame format with the same magic numbers.
#define LZ4_SKIPPABLE_START 0x184D2A50
#define LZ4_SKIPPABLE_MASK 0xFFFFFFF0
#if defined(HAVE_LIBLZ4)
struct private_data {
enum { SELECT_STREAM,
@@ -141,19 +144,67 @@ lz4_reader_bid(struct archive_read_filter_bidder *self,
{
const unsigned char *buffer;
ssize_t avail;
int bits_checked;
uint32_t number;
int bits_checked = 0;
ssize_t min_lz4_archive_size = 11;
(void)self; /* UNUSED */
// LZ4 skippable frames contain a 4 byte magic number followed by
// a 4 byte frame data size, then that number of bytes of data. Regular
// frames contain a 4 byte magic number followed by a 2-14 byte frame
// header, some data, and a 3 byte end marker.
ssize_t min_lz4_frame_size = 8;
/* Minimal lz4 archive is 11 bytes. */
buffer = __archive_read_filter_ahead(filter, 11, &avail);
ssize_t offset_in_buffer = 0;
ssize_t max_lookahead = 64 * 1024;
(void)self; // UNUSED
// Zstd and LZ4 skippable frame magic numbers are identical. To
// differentiate these two, we need to look for a non-skippable
// frame.
// Minimal lz4 archive is 11 bytes.
buffer = __archive_read_filter_ahead(filter, min_lz4_archive_size, &avail);
if (buffer == NULL)
return (0);
/* First four bytes must be LZ4 magic numbers. */
bits_checked = 0;
if ((number = archive_le32dec(buffer)) == LZ4_MAGICNUMBER) {
uint32_t magic_number = archive_le32dec(buffer);
while ((magic_number & LZ4_SKIPPABLE_MASK) == LZ4_SKIPPABLE_START) {
offset_in_buffer += 4; // Skip over the magic number
// Ensure that we can read another 4 bytes.
if (offset_in_buffer + 4 > avail) {
buffer = __archive_read_filter_ahead(filter, offset_in_buffer + 4, &avail);
if (buffer == NULL)
return (0);
}
uint32_t frame_data_size = archive_le32dec(buffer + offset_in_buffer);
// Skip over the 4 frame data size bytes, plus the value stored there.
offset_in_buffer += 4 + frame_data_size;
// There should be at least one more frame if this is LZ4 data.
if (offset_in_buffer + min_lz4_frame_size > avail) { // TODO: should this be >= ?
if (offset_in_buffer + min_lz4_frame_size > max_lookahead)
return (0);
buffer = __archive_read_filter_ahead(filter, offset_in_buffer + min_lz4_frame_size, &avail);
if (buffer == NULL)
return (0);
}
magic_number = archive_le32dec(buffer + offset_in_buffer);
}
// We have skipped over any skippable frames. Either a regular LZ4 frame
// follows, or this isn't LZ4 data.
bits_checked = offset_in_buffer;
buffer = buffer + offset_in_buffer;
if (magic_number == LZ4_MAGICNUMBER) {
unsigned char flag, BD;
bits_checked += 32;
@@ -175,11 +226,16 @@ lz4_reader_bid(struct archive_read_filter_bidder *self,
if (BD & ~0x70)
return (0);
bits_checked += 8;
} else if (number == LZ4_LEGACY) {
bits_checked += 32;
return (bits_checked);
}
return (bits_checked);
if (magic_number == LZ4_LEGACY) {
bits_checked += 32;
return (bits_checked);
}
return (0);
}
#if !defined(HAVE_LIBLZ4)
@@ -342,7 +398,7 @@ lz4_filter_read(struct archive_read_filter *self, const void **p)
return lz4_filter_read_default_stream(self, p);
else if (number == LZ4_LEGACY)
return lz4_filter_read_legacy_stream(self, p);
else if ((number & ~0xF) == LZ4_SKIPPABLED) {
else if ((number & LZ4_SKIPPABLE_MASK) == LZ4_SKIPPABLE_START) {
read_buf = __archive_read_filter_ahead(
self->upstream, 4, NULL);
if (read_buf == NULL) {
@@ -236,8 +236,8 @@ bid_get_line(struct archive_read_filter *filter,
size_t nbytes_req = (*ravail+1023) & ~1023U;
ssize_t tested;
/* Increase reading bytes if it is not enough to at least
* new two lines. */
/* Increase reading bytes if it is not enough for at least
* two new lines. */
if (nbytes_req < (size_t)*ravail + 160)
nbytes_req <<= 1;
@@ -415,7 +415,7 @@ ensure_in_buff_size(struct archive_read_filter *self,
/*
* Calculate a new buffer size for in_buff.
* Increase its value until it has enough size we need.
* Increase its value until it is enough for our needs.
*/
newsize = uudecode->in_allocated;
do {
@@ -498,7 +498,7 @@ read_more:
}
/*
* If there is remaining data which is saved by
* previous calling, use it first.
* a previous call, use it first.
*/
if (ensure_in_buff_size(self, uudecode,
avail_in + uudecode->in_cnt) != ARCHIVE_OK)
@@ -110,24 +110,67 @@ zstd_bidder_bid(struct archive_read_filter_bidder *self,
{
const unsigned char *buffer;
ssize_t avail;
unsigned prefix;
/* Zstd frame magic values */
unsigned zstd_magic = 0xFD2FB528U;
unsigned zstd_magic_skippable_start = 0x184D2A50U;
unsigned zstd_magic_skippable_mask = 0xFFFFFFF0;
// Zstandard skippable frames contain a 4 byte magic number followed by
// a 4 byte frame data size, then that number of bytes of data. Regular
// frames contain a 4 byte magic number followed by a 2-14 byte frame
// header, some data, and a 3 byte end marker.
ssize_t min_zstd_frame_size = 8;
(void) self; /* UNUSED */
ssize_t offset_in_buffer = 0;
ssize_t max_lookahead = 64 * 1024;
buffer = __archive_read_filter_ahead(filter, 4, &avail);
// Zstd regular frame magic number.
uint32_t zstd_magic = 0xFD2FB528U;
// Note: Zstd and LZ4 skippable frame magic numbers are identical.
// To differentiate these two, we need to look for a non-skippable
// frame.
uint32_t zstd_magic_skippable_start = 0x184D2A50;
uint32_t zstd_magic_skippable_mask = 0xFFFFFFF0;
(void) self; // UNUSED
buffer = __archive_read_filter_ahead(filter, min_zstd_frame_size, &avail);
if (buffer == NULL)
return (0);
prefix = archive_le32dec(buffer);
if (prefix == zstd_magic)
return (32);
if ((prefix & zstd_magic_skippable_mask) == zstd_magic_skippable_start)
return (32);
uint32_t magic_number = archive_le32dec(buffer);
while ((magic_number & zstd_magic_skippable_mask) == zstd_magic_skippable_start) {
offset_in_buffer += 4; // Skip over the magic number
// Ensure that we can read another 4 bytes.
if (offset_in_buffer + 4 > avail) {
buffer = __archive_read_filter_ahead(filter, offset_in_buffer + 4, &avail);
if (buffer == NULL)
return (0);
}
uint32_t frame_data_size = archive_le32dec(buffer + offset_in_buffer);
// Skip over the 4 frame data size bytes, plus the value stored there.
offset_in_buffer += 4 + frame_data_size;
// There should be at least one more frame if this is zstd data.
if (offset_in_buffer + min_zstd_frame_size > avail) {
if (offset_in_buffer + min_zstd_frame_size > max_lookahead)
return (0);
buffer = __archive_read_filter_ahead(filter, offset_in_buffer + min_zstd_frame_size, &avail);
if (buffer == NULL)
return (0);
}
magic_number = archive_le32dec(buffer + offset_in_buffer);
}
// We have skipped over any skippable frames. Either a regular zstd frame
// follows, or this isn't zstd data.
if (magic_number == zstd_magic)
return (offset_in_buffer + 4);
return (0);
}
@@ -748,6 +748,7 @@ find_elf_data_sec(struct archive_read *a)
const char *h;
char big_endian, format_64;
ssize_t bytes, min_addr = SFX_MIN_ADDR;
ssize_t request;
uint64_t e_shoff, strtab_offset, strtab_size;
uint16_t e_shentsize, e_shnum, e_shstrndx;
uint16_t (*dec16)(const void *);
@@ -800,7 +801,12 @@ find_elf_data_sec(struct archive_read *a)
if (__archive_read_seek(a, e_shoff, SEEK_SET) < 0) {
break;
}
h = __archive_read_ahead(a, (size_t)e_shnum * (size_t)e_shentsize, NULL);
if (format_64) {
request = (size_t)e_shnum * (size_t)e_shentsize + 0x28;
} else {
request = (size_t)e_shnum * (size_t)e_shentsize + 0x18;
}
h = __archive_read_ahead(a, request, &bytes);
if (h == NULL) {
break;
}
@@ -2813,7 +2813,7 @@ lzx_decode_blocks(struct lzx_stream *strm, int last)
lzx_br_bits(&bre, mt_max_bits));
lzx_br_consume(&bre, mt_bitlen[c]);
}
if (c > UCHAR_MAX)
if ((unsigned int)c > UCHAR_MAX)
break;
/*
* 'c' is exactly literal code.
@@ -825,9 +825,9 @@ header_odc(struct archive_read *a, struct cpio *cpio,
}
/*
* NOTE: if a filename suffix is ".z", it is the file gziped by afio.
* it would be nice that we can show uncompressed file size and we can
* uncompressed file contents automatically, unfortunately we have nothing
* NOTE: if a filename suffix is ".z", it is a file gzipped by afio.
* it would be nice if we could show uncompressed file size and
* uncompress file contents automatically, unfortunately we have nothing
* to get a uncompressed file size while reading each header. It means
* we also cannot uncompress file contents under our framework.
*/
@@ -689,7 +689,7 @@ archive_read_format_lha_read_header(struct archive_read *a,
* a pathname and a symlink has '\' character, a directory
* separator in DOS/Windows. So we should convert it to '/'.
*/
if (p[H_LEVEL_OFFSET] == 0)
if (lha->level == 0)
lha_replace_path_separator(lha, entry);
archive_entry_set_mode(entry, lha->mode);
@@ -2374,7 +2374,7 @@ lzh_decode_blocks(struct lzh_stream *strm, int last)
lzh_br_consume(&bre, lt_bitlen[c]);
}
blocks_avail--;
if (c > UCHAR_MAX)
if ((unsigned int)c > UCHAR_MAX)
/* Current block is a match data. */
break;
/*
@@ -392,8 +392,8 @@ next_line(struct archive_read *a,
if (len >= MAX_LINE_LEN)
return (-1);
/* Increase reading bytes if it is not enough to at least
* new two lines. */
/* Increase reading bytes if it is not enough for at least
* two new lines. */
if (nbytes_req < (size_t)*ravail + 160)
nbytes_req <<= 1;
@@ -568,8 +568,8 @@ bid_keyword_list(const char *p, ssize_t len, int unset, int last_is_path)
--len;
value = 1;
}
/* A keyword should have a its value unless
* "/unset" operation. */
/* A keyword should have a value unless this is
* an "/unset" operation. */
if (!unset && value == 0)
return (-1);
}
@@ -752,7 +752,7 @@ detect_form(struct archive_read *a, int *is_form_d)
} else if (form_D == 1) {
if (!last_is_path && keywords > 0)
/* This this is not `form D'
* and We cannot accept mixed
* and we cannot accept mixed
* format. */
break;
}
@@ -805,7 +805,7 @@ detect_form(struct archive_read *a, int *is_form_d)
* to read the entire mtree file into memory up front.
*
* The parsing is done in two steps. First, it is decided if a line
* changes the global defaults and if it is, processed accordingly.
* changes the global defaults and if it does, it is processed accordingly.
* Otherwise, the options of the line are merged with the current
* global options.
*/
@@ -1254,7 +1254,7 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
archive_entry_filetype(entry) == AE_IFDIR) {
mtree->fd = open(path, O_RDONLY | O_BINARY | O_CLOEXEC);
__archive_ensure_cloexec_flag(mtree->fd);
if (mtree->fd < 0 && (
if (mtree->fd == -1 && (
#if defined(_WIN32) && !defined(__CYGWIN__)
/*
* On Windows, attempting to open a file with an
@@ -2312,6 +2312,7 @@ pax_attribute_read_number(struct archive_read *a, size_t value_length, int64_t *
archive_string_init(&as);
r = read_bytes_to_string(a, &as, value_length, &unconsumed);
if (tar_flush_unconsumed(a, &unconsumed) != ARCHIVE_OK) {
*result = 0;
return (ARCHIVE_FATAL);
}
if (r < ARCHIVE_OK) {
@@ -78,6 +78,12 @@
#include "archive_crc32.h"
#endif
/* length of local file header, not including filename and extra */
#define ZIP_LOCHDR_LEN 30U
/* maximum length of Mac metadata in MiB */
#define ZIP_MAX_METADATA 10U
struct zip_entry {
struct archive_rb_node node;
struct zip_entry *next;
@@ -933,7 +939,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
zip->init_default_conversion = 1;
}
if ((p = __archive_read_ahead(a, 30, NULL)) == NULL) {
if ((p = __archive_read_ahead(a, ZIP_LOCHDR_LEN, NULL)) == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated ZIP file header");
return (ARCHIVE_FATAL);
@@ -969,7 +975,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
filename_length = archive_le16dec(p + 26);
extra_length = archive_le16dec(p + 28);
__archive_read_consume(a, 30);
__archive_read_consume(a, ZIP_LOCHDR_LEN);
/* Read the filename. */
if ((h = __archive_read_ahead(a, filename_length, NULL)) == NULL) {
@@ -3637,7 +3643,7 @@ read_eocd(struct zip *zip, const char *p, int64_t current_offset)
{
uint16_t disk_num;
uint32_t cd_size, cd_offset;
disk_num = archive_le16dec(p + 4);
cd_size = archive_le32dec(p + 12);
cd_offset = archive_le32dec(p + 16);
@@ -4097,7 +4103,7 @@ zip_get_local_file_header_size(struct archive_read *a, size_t extra)
const char *p;
ssize_t filename_length, extra_length;
if ((p = __archive_read_ahead(a, extra + 30, NULL)) == NULL) {
if ((p = __archive_read_ahead(a, extra + ZIP_LOCHDR_LEN, NULL)) == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated ZIP file header");
return (ARCHIVE_WARN);
@@ -4111,7 +4117,7 @@ zip_get_local_file_header_size(struct archive_read *a, size_t extra)
filename_length = archive_le16dec(p + 26);
extra_length = archive_le16dec(p + 28);
return (30 + filename_length + extra_length);
return (ZIP_LOCHDR_LEN + filename_length + extra_length);
}
static int
@@ -4148,16 +4154,16 @@ zip_read_mac_metadata(struct archive_read *a, struct archive_entry *entry,
return (ARCHIVE_WARN);
}
if (rsrc->uncompressed_size > (4 * 1024 * 1024)) {
if (rsrc->uncompressed_size > ZIP_MAX_METADATA * 1048576U) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Mac metadata is too large: %jd > 4M bytes",
(intmax_t)rsrc->uncompressed_size);
"Mac metadata is too large: %jd > %u MiB",
(intmax_t)rsrc->uncompressed_size, ZIP_MAX_METADATA);
return (ARCHIVE_WARN);
}
if (rsrc->compressed_size > (4 * 1024 * 1024)) {
if (rsrc->compressed_size > ZIP_MAX_METADATA * 1048576U) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Mac metadata is too large: %jd > 4M bytes",
(intmax_t)rsrc->compressed_size);
"Mac metadata is too large: %jd > %u MiB",
(intmax_t)rsrc->compressed_size, ZIP_MAX_METADATA);
return (ARCHIVE_WARN);
}
@@ -2059,6 +2059,26 @@ archive_strncat_l(struct archive_string *as, const void *_p, size_t n,
return (r);
}
struct archive_string *
archive_string_dirname(struct archive_string *as)
{
/* strip trailing separators */
while (as->length > 1 && as->s[as->length - 1] == '/')
as->length--;
/* strip final component */
while (as->length > 0 && as->s[as->length - 1] != '/')
as->length--;
/* empty path -> cwd */
if (as->length == 0)
return (archive_strcat(as, "."));
/* strip separator(s) */
while (as->length > 1 && as->s[as->length - 1] == '/')
as->length--;
/* terminate */
as->s[as->length] = '\0';
return (as);
}
#if HAVE_ICONV
/*
@@ -3558,7 +3578,7 @@ win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes,
if (sc->to_cp == CP_C_LOCALE) {
/*
* "C" locale special process.
* "C" locale special processing.
*/
u16 = _p;
ll = 0;
@@ -3675,7 +3695,7 @@ win_strncat_to_utf16(struct archive_string *as16, const void *_p,
avail = as16->buffer_length - 2;
if (sc->from_cp == CP_C_LOCALE) {
/*
* "C" locale special process.
* "C" locale special processing.
*/
count = 0;
while (count < length && *s) {
@@ -192,6 +192,10 @@ void archive_string_vsprintf(struct archive_string *, const char *,
void archive_string_sprintf(struct archive_string *, const char *, ...)
__LA_PRINTF(2, 3);
/* Equivalent to dirname(3) */
struct archive_string *
archive_string_dirname(struct archive_string *);
/* Translates from MBS to Unicode. */
/* Returns non-zero if conversion failed in any way. */
int archive_wstring_append_from_mbs(struct archive_wstring *dest,
@@ -456,7 +456,7 @@ __archive_issetugid(void)
return (-1);
if (ruid != euid || ruid != suid)
return (1);
if (getresgid(&ruid, &egid, &sgid) != 0)
if (getresgid(&rgid, &egid, &sgid) != 0)
return (-1);
if (rgid != egid || rgid != sgid)
return (1);
@@ -333,7 +333,7 @@ archive_libbsdxml_version(void)
const char *
archive_libxml2_version(void)
{
#if HAVE_LIBXML_XMLREADER_H && HAVE_LIBXML2
#if HAVE_LIBXML_XMLVERSION_H && HAVE_LIBXML2
return LIBXML_DOTTED_VERSION;
#else
return NULL;
@@ -253,7 +253,7 @@ la_CreateFile(const char *path, DWORD dwDesiredAccess, DWORD dwShareMode,
createExParams.dwSize = sizeof(createExParams);
createExParams.dwFileAttributes = dwFlagsAndAttributes & 0xFFFF;
createExParams.dwFileFlags = dwFlagsAndAttributes & 0xFFF00000;
createExParams.dwSecurityQosFlags = dwFlagsAndAttributes & 0x000F00000;
createExParams.dwSecurityQosFlags = dwFlagsAndAttributes & 0x000F0000;
createExParams.lpSecurityAttributes = lpSecurityAttributes;
createExParams.hTemplateFile = hTemplateFile;
handle = CreateFile2(wpath, dwDesiredAccess, dwShareMode,
@@ -747,7 +747,8 @@ __la_seek_fstat(int fd, la_seek_stat_t *st)
int ret;
ret = __hstat((HANDLE)_get_osfhandle(fd), &u);
copy_seek_stat(st, &u);
if (ret >= 0)
copy_seek_stat(st, &u);
return (ret);
}
@@ -821,7 +821,7 @@ _archive_write_data(struct archive *_a, const void *buff, size_t s)
{
struct archive_write *a = (struct archive_write *)_a;
const size_t max_write = INT_MAX;
int ret;
ssize_t ret;
archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_DATA, "archive_write_data");
@@ -412,12 +412,14 @@ static ssize_t _archive_write_disk_data_block(struct archive *, const void *,
static int
la_mktemp(struct archive_write_disk *a)
{
struct archive_string *tmp = &a->_tmpname_data;
int oerrno, fd;
mode_t mode;
archive_string_empty(&a->_tmpname_data);
archive_string_sprintf(&a->_tmpname_data, "%s.XXXXXX", a->name);
a->tmpname = a->_tmpname_data.s;
archive_strcpy(tmp, a->name);
archive_string_dirname(tmp);
archive_strcat(tmp, "/tar.XXXXXXXX");
a->tmpname = tmp->s;
fd = __archive_mkstemp(a->tmpname);
if (fd == -1)
@@ -2559,9 +2561,9 @@ _archive_write_disk_close(struct archive *_a)
* for directories. For other file types
* we need to verify via fstat() or lstat()
*/
if (fd < 0 || p->filetype != AE_IFDIR) {
if (fd == -1 || p->filetype != AE_IFDIR) {
#if HAVE_FSTAT
if (fd >= 0 && (
if (fd > 0 && (
fstat(fd, &st) != 0 ||
la_verify_filetype(st.st_mode,
p->filetype) == 0)) {
@@ -4287,8 +4289,10 @@ create_tempdatafork(struct archive_write_disk *a, const char *pathname)
int tmpfd;
archive_string_init(&tmpdatafork);
archive_strcpy(&tmpdatafork, "tar.md.XXXXXX");
tmpfd = mkstemp(tmpdatafork.s);
archive_strcpy(&tmpdatafork, pathname);
archive_string_dirname(&tmpdatafork);
archive_strcat(&tmpdatafork, "/tar.XXXXXXXX");
tmpfd = __archive_mkstemp(tmpdatafork.s);
if (tmpfd < 0) {
archive_set_error(&a->archive, errno,
"Failed to mkstemp");
@@ -4367,8 +4371,10 @@ set_mac_metadata(struct archive_write_disk *a, const char *pathname,
* silly dance of writing the data to disk just so that
* copyfile() can read it back in again. */
archive_string_init(&tmp);
archive_strcpy(&tmp, "tar.mmd.XXXXXX");
fd = mkstemp(tmp.s);
archive_strcpy(&tmp, pathname);
archive_string_dirname(&tmp);
archive_strcat(&tmp, "/tar.XXXXXXXX");
fd = __archive_mkstemp(tmp.s);
if (fd < 0) {
archive_set_error(&a->archive, errno,
@@ -4441,7 +4447,7 @@ fixup_appledouble(struct archive_write_disk *a, const char *pathname)
*/
fd = open(pathname, O_RDONLY | O_BINARY | O_CLOEXEC);
__archive_ensure_cloexec_flag(fd);
if (fd < 0) {
if (fd == -1) {
archive_set_error(&a->archive, errno,
"Failed to open a restoring file");
ret = ARCHIVE_WARN;
@@ -135,11 +135,7 @@ file_write(struct archive *a, void *client_data, const void *buff, size_t length
static int
file_free(struct archive *a, void *client_data)
{
struct write_fd_data *mine = (struct write_fd_data *)client_data;
(void)a; /* UNUSED */
if (mine == NULL)
return (ARCHIVE_OK);
free(mine);
free(client_data);
return (ARCHIVE_OK);
}
@@ -96,11 +96,7 @@ file_write(struct archive *a, void *client_data, const void *buff, size_t length
static int
file_free(struct archive *a, void *client_data)
{
struct write_FILE_data *mine = client_data;
(void)a; /* UNUSED */
if (mine == NULL)
return (ARCHIVE_OK);
free(mine);
free(client_data);
return (ARCHIVE_OK);
}
@@ -191,6 +191,8 @@ file_open(struct archive *a, void *client_data)
archive_set_error(a, errno, "Couldn't stat '%s'", mbs);
else
archive_set_error(a, errno, "Couldn't stat '%ls'", wcs);
close(mine->fd);
mine->fd = -1;
return (ARCHIVE_FATAL);
}
@@ -104,11 +104,7 @@ memory_write(struct archive *a, void *client_data, const void *buff, size_t leng
static int
memory_write_free(struct archive *a, void *client_data)
{
struct write_memory_data *mine;
(void)a; /* UNUSED */
mine = client_data;
if (mine == NULL)
return (ARCHIVE_OK);
free(mine);
free(client_data);
return (ARCHIVE_OK);
}
@@ -144,7 +144,9 @@ archive_write_set_format_shar_dump(struct archive *_a)
struct archive_write *a = (struct archive_write *)_a;
struct shar *shar;
archive_write_set_format_shar(&a->archive);
int ret = archive_write_set_format_shar(&a->archive);
if (ret != ARCHIVE_OK)
return ret;
shar = (struct shar *)a->format_data;
shar->dump = 1;
a->format_write_data = archive_write_shar_data_uuencode;
@@ -240,6 +242,7 @@ archive_write_shar_header(struct archive_write *a, struct archive_entry *entry)
shar_quote(&shar->work, p, 1);
archive_strcat(&shar->work,
" > /dev/null 2>&1\n");
free(shar->last_dir);
shar->last_dir = p;
}
} else {
@@ -539,7 +539,7 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512],
ret = ARCHIVE_WARN;
}
if (copy_length > 0) {
if (strlen(p) > USTAR_gname_size) {
if (copy_length > USTAR_gname_size) {
if (tartype != 'x') {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC, "Group name too long");
@@ -1000,13 +1000,13 @@ xmlwrite_heap(struct archive_write *a, struct xml_writer *writer,
const char *encname;
int r;
r = xmlwrite_fstring(a, writer, "length", "%ju", heap->length);
r = xmlwrite_fstring(a, writer, "length", "%ju", (uintmax_t)heap->length);
if (r < 0)
return (ARCHIVE_FATAL);
r = xmlwrite_fstring(a, writer, "offset", "%ju", heap->temp_offset);
r = xmlwrite_fstring(a, writer, "offset", "%ju", (uintmax_t)heap->temp_offset);
if (r < 0)
return (ARCHIVE_FATAL);
r = xmlwrite_fstring(a, writer, "size", "%ju", heap->size);
r = xmlwrite_fstring(a, writer, "size", "%ju", (uintmax_t)heap->size);
if (r < 0)
return (ARCHIVE_FATAL);
switch (heap->compression) {
@@ -1356,7 +1356,7 @@ make_file_entry(struct archive_write *a, struct xml_writer *writer,
* Make a inode entry, "<inode>".
*/
r = xmlwrite_fstring(a, writer, "inode",
"%jd", archive_entry_ino64(file->entry));
"%jd", (intmax_t)archive_entry_ino64(file->entry));
if (r < 0)
return (ARCHIVE_FATAL);
if (archive_entry_dev(file->entry) != 0) {
@@ -1378,7 +1378,7 @@ make_file_entry(struct archive_write *a, struct xml_writer *writer,
* Make a user entry, "<uid>" and "<user>.
*/
r = xmlwrite_fstring(a, writer, "uid",
"%d", archive_entry_uid(file->entry));
"%jd", (intmax_t)archive_entry_uid(file->entry));
if (r < 0)
return (ARCHIVE_FATAL);
r = archive_entry_uname_l(file->entry, &p, &len, xar->sconv);
@@ -1404,7 +1404,7 @@ make_file_entry(struct archive_write *a, struct xml_writer *writer,
* Make a group entry, "<gid>" and "<group>.
*/
r = xmlwrite_fstring(a, writer, "gid",
"%d", archive_entry_gid(file->entry));
"%jd", (intmax_t)archive_entry_gid(file->entry));
if (r < 0)
return (ARCHIVE_FATAL);
r = archive_entry_gname_l(file->entry, &p, &len, xar->sconv);
@@ -0,0 +1,34 @@
/*
* Clang Module Map for libarchive
*
* What this is:
* This file tells the Clang compiler how to treat libarchive as a "module" -
* a self-contained unit of code that can be imported all at once instead of
* including individual header files. Think of it like a package definition.
*
* How it works:
* - When you write `@import CArchive` (Objective-C) or `import CArchive` (Swift),
* the compiler uses this file to know which headers belong to libarchive
* - Instead of processing each #include separately, the compiler can load a
* pre-compiled version of the entire library, making builds faster
* - This also provides better dependency tracking and can catch issues like
* conflicting macro definitions between libraries
*
* When to update:
* Update this file whenever:
* - New public header files are added to libarchive's libarchive/ directory
* - Public headers are removed or renamed
* - The library's API structure changes significantly
*
* You typically don't need to update this for:
* - Internal implementation changes
* - Private/internal header modifications
* - Documentation updates
*
* NOTE: This only affects projects using Clang with modules enabled. Traditional
* #include-based builds will continue to work normally with or without this file.
*/
module CArchive {
header "archive.h"
header "archive_entry.h"
}