LibArchive 2025-10-15 (7f53fce0)

Code extracted from:

    https://github.com/libarchive/libarchive.git

at commit 7f53fce04e4e672230f4eb80b219af17975e4f83 (v3.8.2).
This commit is contained in:
LibArchive Upstream
2025-10-15 23:36:59 +02:00
committed by Brad King
parent bb6def24fe
commit 73b8b633a7
52 changed files with 694 additions and 369 deletions
+14 -7
View File
@@ -3,6 +3,9 @@ cmake_minimum_required(VERSION 3.17 FATAL_ERROR)
PROJECT(libarchive C)
#
# Include standard installation directories
include(GNUInstallDirs)
#
SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/build/cmake")
if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${libarchive_BINARY_DIR}/bin)
@@ -255,6 +258,10 @@ OPTION(ENABLE_TEST "Enable unit and regression tests" ON)
OPTION(ENABLE_COVERAGE "Enable code coverage (GCC only, automatically sets ENABLE_TEST to ON)" FALSE)
OPTION(ENABLE_INSTALL "Enable installing of libraries" ON)
IF(WIN32 AND MSVC)
OPTION(MSVC_USE_STATIC_CRT "Use static CRT" OFF)
ENDIF()
SET(POSIX_REGEX_LIB "AUTO" CACHE STRING "Choose what library should provide POSIX regular expression support")
SET(ENABLE_SAFESEH "AUTO" CACHE STRING "Enable use of /SAFESEH linker flag (MSVC only)")
SET(WINDOWS_VERSION "WIN10" CACHE STRING "Set Windows version to use (Windows only)")
@@ -1472,6 +1479,8 @@ CHECK_FUNCTION_EXISTS_GLIBC(arc4random_buf HAVE_ARC4RANDOM_BUF)
CHECK_FUNCTION_EXISTS_GLIBC(chflags HAVE_CHFLAGS)
CHECK_FUNCTION_EXISTS_GLIBC(chown HAVE_CHOWN)
CHECK_FUNCTION_EXISTS_GLIBC(chroot HAVE_CHROOT)
CHECK_FUNCTION_EXISTS_GLIBC(closefrom HAVE_CLOSEFROM)
CHECK_FUNCTION_EXISTS_GLIBC(close_range HAVE_CLOSE_RANGE)
CHECK_FUNCTION_EXISTS_GLIBC(ctime_r HAVE_CTIME_R)
CHECK_FUNCTION_EXISTS_GLIBC(fchdir HAVE_FCHDIR)
CHECK_FUNCTION_EXISTS_GLIBC(fchflags HAVE_FCHFLAGS)
@@ -1489,15 +1498,19 @@ CHECK_FUNCTION_EXISTS_GLIBC(ftruncate HAVE_FTRUNCATE)
CHECK_FUNCTION_EXISTS_GLIBC(futimens HAVE_FUTIMENS)
CHECK_FUNCTION_EXISTS_GLIBC(futimes HAVE_FUTIMES)
CHECK_FUNCTION_EXISTS_GLIBC(futimesat HAVE_FUTIMESAT)
CHECK_FUNCTION_EXISTS_GLIBC(getegid HAVE_GETEGID)
CHECK_FUNCTION_EXISTS_GLIBC(geteuid HAVE_GETEUID)
CHECK_FUNCTION_EXISTS_GLIBC(getgrgid_r HAVE_GETGRGID_R)
CHECK_FUNCTION_EXISTS_GLIBC(getgrnam_r HAVE_GETGRNAM_R)
CHECK_FUNCTION_EXISTS_GLIBC(getline HAVE_GETLINE)
CHECK_FUNCTION_EXISTS_GLIBC(getpid HAVE_GETPID)
CHECK_FUNCTION_EXISTS_GLIBC(getpwnam_r HAVE_GETPWNAM_R)
CHECK_FUNCTION_EXISTS_GLIBC(getpwuid_r HAVE_GETPWUID_R)
CHECK_FUNCTION_EXISTS_GLIBC(getpid HAVE_GETPID)
CHECK_FUNCTION_EXISTS_GLIBC(getresgid HAVE_GETRESGID)
CHECK_FUNCTION_EXISTS_GLIBC(getresuid HAVE_GETRESUID)
CHECK_FUNCTION_EXISTS_GLIBC(getvfsbyname HAVE_GETVFSBYNAME)
CHECK_FUNCTION_EXISTS_GLIBC(gmtime_r HAVE_GMTIME_R)
CHECK_FUNCTION_EXISTS_GLIBC(issetugid HAVE_ISSETUGID)
CHECK_FUNCTION_EXISTS_GLIBC(lchflags HAVE_LCHFLAGS)
CHECK_FUNCTION_EXISTS_GLIBC(lchmod HAVE_LCHMOD)
CHECK_FUNCTION_EXISTS_GLIBC(lchown HAVE_LCHOWN)
@@ -1579,12 +1592,6 @@ CHECK_C_SOURCE_COMPILES(
"#include <sys/types.h>\n#include <sys/mount.h>\nint main(void) { struct statfs s; return sizeof(s);}"
HAVE_STRUCT_STATFS)
# Make sure we have the POSIX version of readdir_r, not the
# older 2-argument version.
CHECK_C_SOURCE_COMPILES(
"#include <dirent.h>\nint main() {DIR *d = opendir(\".\"); struct dirent e,*r; return readdir_r(d,&e,&r);}"
HAVE_READDIR_R)
# dirfd can be either a function or a macro.
CHECK_C_SOURCE_COMPILES(
"#include <dirent.h>\nint main() {DIR *d = opendir(\".\"); return dirfd(d);}"
+6 -3
View File
@@ -405,6 +405,12 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the `chroot' function. */
#cmakedefine HAVE_CHROOT 1
/* Define to 1 if you have the `closefrom' function. */
#cmakedefine HAVE_CLOSEFROM 1
/* Define to 1 if you have the `close_range' function. */
#cmakedefine HAVE_CLOSE_RANGE 1
/* Define to 1 if you have the <copyfile.h> header file. */
#cmakedefine HAVE_COPYFILE_H 1
@@ -970,9 +976,6 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the <pwd.h> header file. */
#cmakedefine HAVE_PWD_H 1
/* Define to 1 if you have the `readdir_r' function. */
#cmakedefine HAVE_READDIR_R 1
/* Define to 1 if you have the `readlink' function. */
#cmakedefine HAVE_READLINK 1
+1 -1
View File
@@ -1 +1 @@
3008001
3008002
+7 -4
View File
@@ -52,6 +52,7 @@ SET(libarchive_SOURCES
archive_pathmatch.h
archive_platform.h
archive_platform_acl.h
archive_platform_stat.h
archive_platform_xattr.h
archive_ppmd_private.h
archive_ppmd8.c
@@ -253,6 +254,9 @@ IF(BUILD_SHARED_LIBS)
SOVERSION ${SOVERSION}
MACHO_COMPATIBILITY_VERSION ${MACHO_COMPATIBILITY_VERSION}
MACHO_CURRENT_VERSION ${MACHO_CURRENT_VERSION})
IF(WIN32 AND MSVC AND MSVC_USE_STATIC_CRT)
SET_PROPERTY(TARGET archive PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
ENDIF(WIN32 AND MSVC AND MSVC_USE_STATIC_CRT)
ENDIF(BUILD_SHARED_LIBS)
# archive_static is a static library
@@ -261,15 +265,14 @@ TARGET_INCLUDE_DIRECTORIES(archive_static PUBLIC .)
TARGET_LINK_LIBRARIES(archive_static ${ADDITIONAL_LIBS})
SET_TARGET_PROPERTIES(archive_static PROPERTIES COMPILE_DEFINITIONS
LIBARCHIVE_STATIC)
IF(WIN32 AND MSVC AND MSVC_USE_STATIC_CRT)
SET_PROPERTY(TARGET archive_static PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
ENDIF(WIN32 AND MSVC AND MSVC_USE_STATIC_CRT)
# On Posix systems, libarchive.so and libarchive.a can co-exist.
IF(NOT WIN32 OR CYGWIN OR NOT BUILD_SHARED_LIBS)
SET_TARGET_PROPERTIES(archive_static PROPERTIES OUTPUT_NAME archive)
ENDIF(NOT WIN32 OR CYGWIN OR NOT BUILD_SHARED_LIBS)
if(NOT DEFINED CMAKE_INSTALL_LIBDIR)
set(CMAKE_INSTALL_LIBDIR "lib")
endif()
IF(ENABLE_INSTALL)
# How to install the libraries
IF(BUILD_SHARED_LIBS)
+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 3008001
#define ARCHIVE_VERSION_NUMBER 3008002
#include <sys/stat.h>
#include <stddef.h> /* for wchar_t */
@@ -177,7 +177,7 @@ __LA_DECL int archive_version_number(void);
/*
* Textual name/version of the library, useful for version displays.
*/
#define ARCHIVE_VERSION_ONLY_STRING "3.8.1"
#define ARCHIVE_VERSION_ONLY_STRING "3.8.2"
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
__LA_DECL const char * archive_version_string(void);
+23
View File
@@ -270,6 +270,19 @@ acl_new_entry(struct archive_acl *acl,
{
struct archive_acl_entry *ap, *aq;
/* Reject an invalid type */
switch (type) {
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
case ARCHIVE_ENTRY_ACL_TYPE_DENY:
case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
break;
default:
return (NULL);
}
/* Type argument must be a valid NFS4 or POSIX.1e type.
* The type must agree with anything already set and
* the permset must be compatible. */
@@ -822,6 +835,9 @@ append_entry_w(wchar_t **wp, const wchar_t *prefix, int type,
wname = NULL;
id = -1;
break;
default:
**wp = '\0';
break;
}
*wp += wcslen(*wp);
*(*wp)++ = L':';
@@ -878,6 +894,7 @@ append_entry_w(wchar_t **wp, const wchar_t *prefix, int type,
wcscpy(*wp, L"alarm");
break;
default:
*(*wp) = L'\0';
break;
}
*wp += wcslen(*wp);
@@ -1057,6 +1074,9 @@ append_entry(char **p, const char *prefix, int type,
name = NULL;
id = -1;
break;
default:
**p = '\0';
break;
}
*p += strlen(*p);
*(*p)++ = ':';
@@ -1112,6 +1132,9 @@ append_entry(char **p, const char *prefix, int type,
case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
strcpy(*p, "alarm");
break;
default:
*(*p) = '\0';
break;
}
*p += strlen(*p);
}
+8 -1
View File
@@ -30,6 +30,7 @@
#endif
#include <stdio.h>
#include <errno.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
@@ -54,8 +55,14 @@ errmsg(const char *m)
while (s > 0) {
written = write(2, m, s);
if (written <= 0)
if (written == 0)
return;
if (written < 0)
{
if (errno == EINTR)
continue;
return;
}
m += written;
s -= written;
}
+4 -4
View File
@@ -151,7 +151,7 @@ pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
(void)rounds; /* UNUSED */
(void)derived_key; /* UNUSED */
(void)derived_key_len; /* UNUSED */
return -1; /* UNSUPPORTED */
return CRYPTOR_STUB_FUNCTION; /* UNSUPPORTED */
}
#endif
@@ -439,14 +439,14 @@ aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
(void)ctx; /* UNUSED */
(void)key; /* UNUSED */
(void)key_len; /* UNUSED */
return -1;
return CRYPTOR_STUB_FUNCTION;
}
static int
aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
{
(void)ctx; /* UNUSED */
return -1;
return CRYPTOR_STUB_FUNCTION;
}
static int
@@ -469,7 +469,7 @@ aes_ctr_update(archive_crypto_ctx *ctx, const uint8_t * const in,
(void)out; /* UNUSED */
(void)out_len; /* UNUSED */
aes_ctr_encrypt_counter(ctx); /* UNUSED */ /* Fix unused function warning */
return -1;
return CRYPTOR_STUB_FUNCTION;
}
#else
+10 -1
View File
@@ -43,7 +43,7 @@ int __libarchive_cryptor_build_hack(void);
#ifdef __APPLE__
# include <AvailabilityMacros.h>
# if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
# define ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto
# define ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto 1
# endif
#endif
@@ -144,9 +144,15 @@ typedef struct {
#else
#if defined(ARCHIVE_CRYPTO_MD5_WIN) ||\
defined(ARCHIVE_CRYPTO_SHA1_WIN) ||\
defined(ARCHIVE_CRYPTO_SHA256_WIN) ||\
defined(ARCHIVE_CRYPTO_SHA384_WIN) ||\
defined(ARCHIVE_CRYPTO_SHA512_WIN)
#if defined(_WIN32) && !defined(__CYGWIN__) && !(defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA)
#define ARCHIVE_CRYPTOR_USE_WINCRYPT 1
#endif
#endif
#define AES_BLOCK_SIZE 16
#define AES_MAX_KEY_SIZE 32
@@ -172,6 +178,9 @@ typedef int archive_crypto_ctx;
#define archive_encrypto_aes_ctr_release(ctx) \
__archive_cryptor.encrypto_aes_ctr_release(ctx)
/* Stub return value if no encryption support exists. */
#define CRYPTOR_STUB_FUNCTION -2
/* Minimal interface to cryptographic functionality for internal use in
* libarchive */
struct archive_cryptor
+1 -1
View File
@@ -28,7 +28,7 @@
#define ARCHIVE_ENTRY_H_INCLUDED
/* Note: Compiler will complain if this does not match archive.h! */
#define ARCHIVE_VERSION_NUMBER 3008001
#define ARCHIVE_VERSION_NUMBER 3008002
/*
* Note: archive_entry.h is for use outside of libarchive; the
+1 -1
View File
@@ -64,7 +64,7 @@ Streaming Archive Library (libarchive, -larchive)
.Ft void
.Fn archive_entry_copy_hardlink "struct archive_entry *a" "const char *path"
.Ft void
.Fn archive_entry_copy_hardlink_w "struct archive_entry *a "const wchar_t *path"
.Fn archive_entry_copy_hardlink_w "struct archive_entry *a" "const wchar_t *path"
.Ft int
.Fn archive_entry_update_hardlink_utf8 "struct archive_entry *a" "const char *path"
.Ft void
+5 -1
View File
@@ -38,6 +38,7 @@
const struct stat *
archive_entry_stat(struct archive_entry *entry)
{
int64_t size;
struct stat *st;
if (entry->stat == NULL) {
entry->stat = calloc(1, sizeof(*st));
@@ -74,7 +75,10 @@ archive_entry_stat(struct archive_entry *entry)
st->st_ino = (ino_t)archive_entry_ino64(entry);
st->st_nlink = archive_entry_nlink(entry);
st->st_rdev = archive_entry_rdev(entry);
st->st_size = (off_t)archive_entry_size(entry);
size = archive_entry_size(entry);
st->st_size = (off_t)size;
if (st->st_size < 0 || (int64_t)st->st_size != size)
st->st_size = 0;
st->st_mode = archive_entry_mode(entry);
/*
+1 -3
View File
@@ -703,9 +703,7 @@ Convert(time_t Month, time_t Day, time_t Year,
Year += 1900;
DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
? 29 : 28;
/* Checking for 2038 bogusly assumes that time_t is 32 bits. But
I'm too lazy to try to check for time_t overflow in another way. */
if (Year < EPOCH || Year >= 2038
if (Year < EPOCH || (sizeof(time_t) <= 4 && Year >= 2038)
|| Month < 1 || Month > 12
/* Lint fluff: "conversion from long may lose accuracy" */
|| Day < 1 || Day > DaysInMonth[(int)--Month]
-10
View File
@@ -183,16 +183,6 @@
#define CAN_RESTORE_METADATA_FD
#endif
/*
* glibc 2.24 deprecates readdir_r
* bionic c deprecates readdir_r too
*/
#if defined(HAVE_READDIR_R) && (!defined(__GLIBC__) || !defined(__GLIBC_MINOR__) || __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 24)) && (!defined(__ANDROID__))
#define USE_READDIR_R 1
#else
#undef USE_READDIR_R
#endif
/* Set up defaults for internal error codes. */
#ifndef ARCHIVE_ERRNO_FILE_FORMAT
#if HAVE_EFTYPE
+45
View File
@@ -0,0 +1,45 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2025 Tobias Stoeckmann
* All rights reserved.
*/
/* !!ONLY FOR USE INTERNALLY TO LIBARCHIVE!! */
#ifndef ARCHIVE_PLATFORM_STAT_H_INCLUDED
#define ARCHIVE_PLATFORM_STAT_H_INCLUDED
#ifndef __LIBARCHIVE_BUILD
#error This header is only to be used internally to libarchive.
#endif
#if defined(_WIN32) && !defined(__CYGWIN__)
/* We use _lseeki64() on Windows. */
typedef int64_t la_seek_t;
struct la_seek_stat {
int64_t st_mtime;
ino_t st_ino;
unsigned short st_mode;
uint32_t st_nlink;
gid_t st_gid;
la_seek_t st_size;
uid_t st_uid;
dev_t st_dev;
dev_t st_rdev;
};
typedef struct la_seek_stat la_seek_stat_t;
#define la_seek_fstat(fd, st) __la_seek_fstat((fd), (st))
#define la_seek_stat(fd, st) __la_seek_stat((fd), (st))
#else
typedef off_t la_seek_t;
typedef struct stat la_seek_stat_t;
#define la_seek_fstat(fd, st) fstat((fd), (st))
#define la_seek_stat(fd, st) stat((fd), (st))
#endif
#endif /* !ARCHIVE_PLATFORM_STAT_H_INCLUDED */
+1
View File
@@ -158,6 +158,7 @@ int __archive_check_magic(struct archive *, unsigned int magic,
__LA_NORETURN void __archive_errx(int retvalue, const char *msg);
void __archive_ensure_cloexec_flag(int fd);
int __archive_get_tempdir(struct archive_string *);
int __archive_mktemp(const char *tmpdir);
#if defined(_WIN32) && !defined(__CYGWIN__)
int __archive_mkstemp(wchar_t *templates);
+4 -3
View File
@@ -575,8 +575,7 @@ choose_filters(struct archive_read *a)
return (ARCHIVE_OK);
}
filter
= calloc(1, sizeof(*filter));
filter = calloc(1, sizeof(*filter));
if (filter == NULL)
return (ARCHIVE_FATAL);
filter->bidder = best_bidder;
@@ -834,7 +833,9 @@ archive_read_data(struct archive *_a, void *buff, size_t s)
r = archive_read_data_block(a, &read_buf,
&a->read_data_remaining, &a->read_data_offset);
a->read_data_block = read_buf;
if (r == ARCHIVE_EOF)
if (r == ARCHIVE_EOF &&
a->read_data_offset == a->read_data_output_offset &&
a->read_data_remaining == 0)
return (bytes_read);
/*
* Error codes are all negative, so the status
@@ -338,7 +338,7 @@ setup_mac_metadata(struct archive_read_disk *a,
int ret = ARCHIVE_OK;
void *buff = NULL;
int have_attrs;
const char *name, *tempdir;
const char *name;
struct archive_string tempfile;
(void)fd; /* UNUSED */
@@ -357,13 +357,11 @@ setup_mac_metadata(struct archive_read_disk *a,
if (have_attrs == 0)
return (ARCHIVE_OK);
tempdir = NULL;
if (issetugid() == 0)
tempdir = getenv("TMPDIR");
if (tempdir == NULL)
tempdir = _PATH_TMP;
archive_string_init(&tempfile);
archive_strcpy(&tempfile, tempdir);
if (__archive_get_tempdir(&tempfile) != ARCHIVE_OK) {
ret = ARCHIVE_WARN;
goto cleanup;
}
archive_strcat(&tempfile, "tar.md.XXXXXX");
tempfd = mkstemp(tempfile.s);
if (tempfd < 0) {
+15 -142
View File
@@ -168,9 +168,6 @@ struct filesystem {
int synthetic;
int remote;
int noatime;
#if defined(USE_READDIR_R)
size_t name_max;
#endif
long incr_xfer_size;
long max_xfer_size;
long min_xfer_size;
@@ -203,10 +200,6 @@ struct tree {
DIR *d;
#define INVALID_DIR_HANDLE NULL
struct dirent *de;
#if defined(USE_READDIR_R)
struct dirent *dirent;
size_t dirent_allocated;
#endif
int flags;
int visit_type;
/* Error code from last failed operation. */
@@ -869,7 +862,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
tree_enter_initial_dir(t);
return (ARCHIVE_FATAL);
case TREE_ERROR_DIR:
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
archive_set_error(&a->archive, t->tree_errno,
"%s: Couldn't visit directory",
tree_current_path(t));
tree_enter_initial_dir(t);
@@ -1578,9 +1571,6 @@ setup_current_filesystem(struct archive_read_disk *a)
# endif
#endif
int r, xr = 0;
#if !defined(HAVE_STRUCT_STATFS_F_NAMEMAX)
long nm;
#endif
t->current_filesystem->synthetic = -1;
t->current_filesystem->remote = -1;
@@ -1647,35 +1637,6 @@ setup_current_filesystem(struct archive_read_disk *a)
#endif
t->current_filesystem->noatime = 0;
#if defined(USE_READDIR_R)
/* Set maximum filename length. */
#if defined(HAVE_STRUCT_STATFS_F_NAMEMAX)
t->current_filesystem->name_max = sfs.f_namemax;
#else
# if defined(_PC_NAME_MAX)
/* Mac OS X does not have f_namemax in struct statfs. */
if (tree_current_is_symblic_link_target(t)) {
if (tree_enter_working_dir(t) != 0) {
archive_set_error(&a->archive, errno, "fchdir failed");
return (ARCHIVE_FAILED);
}
nm = pathconf(tree_current_access_path(t), _PC_NAME_MAX);
} else
nm = fpathconf(tree_current_dir_fd(t), _PC_NAME_MAX);
# else
nm = -1;
# endif
if (nm == -1)
t->current_filesystem->name_max = NAME_MAX;
else
t->current_filesystem->name_max = nm;
#endif
if (t->current_filesystem->name_max == 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Cannot determine name_max");
return (ARCHIVE_FAILED);
}
#endif /* USE_READDIR_R */
return (ARCHIVE_OK);
}
@@ -1863,19 +1824,6 @@ setup_current_filesystem(struct archive_read_disk *a)
#endif
t->current_filesystem->noatime = 0;
#if defined(USE_READDIR_R)
/* Set maximum filename length. */
#if defined(HAVE_STATVFS)
t->current_filesystem->name_max = svfs.f_namemax;
#else
t->current_filesystem->name_max = sfs.f_namelen;
#endif
if (t->current_filesystem->name_max == 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Cannot determine name_max");
return (ARCHIVE_FAILED);
}
#endif
return (ARCHIVE_OK);
}
@@ -1953,15 +1901,6 @@ setup_current_filesystem(struct archive_read_disk *a)
#endif
t->current_filesystem->noatime = 0;
#if defined(USE_READDIR_R)
/* Set maximum filename length. */
t->current_filesystem->name_max = svfs.f_namemax;
if (t->current_filesystem->name_max == 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Cannot determine name_max");
return (ARCHIVE_FAILED);
}
#endif
return (ARCHIVE_OK);
}
@@ -1975,9 +1914,6 @@ static int
setup_current_filesystem(struct archive_read_disk *a)
{
struct tree *t = a->tree;
#if defined(_PC_NAME_MAX) && defined(USE_READDIR_R)
long nm;
#endif
t->current_filesystem->synthetic = -1;/* Not supported */
t->current_filesystem->remote = -1;/* Not supported */
t->current_filesystem->noatime = 0;
@@ -1987,40 +1923,6 @@ setup_current_filesystem(struct archive_read_disk *a)
t->current_filesystem->min_xfer_size = -1;
t->current_filesystem->incr_xfer_size = -1;
#if defined(USE_READDIR_R)
/* Set maximum filename length. */
# if defined(_PC_NAME_MAX)
if (tree_current_is_symblic_link_target(t)) {
if (tree_enter_working_dir(t) != 0) {
archive_set_error(&a->archive, errno, "fchdir failed");
return (ARCHIVE_FAILED);
}
nm = pathconf(tree_current_access_path(t), _PC_NAME_MAX);
} else
nm = fpathconf(tree_current_dir_fd(t), _PC_NAME_MAX);
if (nm == -1)
# endif /* _PC_NAME_MAX */
/*
* Some systems (HP-UX or others?) incorrectly defined
* NAME_MAX macro to be a smaller value.
*/
# if defined(NAME_MAX) && NAME_MAX >= 255
t->current_filesystem->name_max = NAME_MAX;
# else
/* No way to get a trusted value of maximum filename
* length. */
t->current_filesystem->name_max = PATH_MAX;
# endif /* NAME_MAX */
# if defined(_PC_NAME_MAX)
else
t->current_filesystem->name_max = nm;
# endif /* _PC_NAME_MAX */
if (t->current_filesystem->name_max == 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Cannot determine name_max");
return (ARCHIVE_FAILED);
}
#endif /* USE_READDIR_R */
return (ARCHIVE_OK);
}
@@ -2112,8 +2014,11 @@ tree_dup(int fd)
}
#endif /* F_DUPFD_CLOEXEC */
new_fd = dup(fd);
__archive_ensure_cloexec_flag(new_fd);
return (new_fd);
if (new_fd != -1) {
__archive_ensure_cloexec_flag(new_fd);
return (new_fd);
}
return (-1);
}
/*
@@ -2235,11 +2140,16 @@ 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);
}
@@ -2449,12 +2359,11 @@ tree_dir_next_posix(struct tree *t)
size_t namelen;
if (t->d == NULL) {
#if defined(USE_READDIR_R)
size_t dirent_size;
#endif
#if defined(HAVE_FDOPENDIR)
t->d = fdopendir(tree_dup(t->working_dir_fd));
int 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(".");
@@ -2470,45 +2379,12 @@ tree_dir_next_posix(struct tree *t)
t->visit_type = r != 0 ? r : TREE_ERROR_DIR;
return (t->visit_type);
}
#if defined(USE_READDIR_R)
dirent_size = offsetof(struct dirent, d_name) +
t->filesystem_table[t->current->filesystem_id].name_max + 1;
if (t->dirent == NULL || t->dirent_allocated < dirent_size) {
free(t->dirent);
t->dirent = malloc(dirent_size);
if (t->dirent == NULL) {
closedir(t->d);
t->d = INVALID_DIR_HANDLE;
(void)tree_ascend(t);
tree_pop(t);
t->tree_errno = ENOMEM;
t->visit_type = TREE_ERROR_DIR;
return (t->visit_type);
}
t->dirent_allocated = dirent_size;
}
#endif /* USE_READDIR_R */
}
for (;;) {
errno = 0;
#if defined(USE_READDIR_R)
r = readdir_r(t->d, t->dirent, &t->de);
#ifdef _AIX
/* Note: According to the man page, return value 9 indicates
* that the readdir_r was not successful and the error code
* is set to the global errno variable. And then if the end
* of directory entries was reached, the return value is 9
* and the third parameter is set to NULL and errno is
* unchanged. */
if (r == 9)
r = errno;
#endif /* _AIX */
if (r != 0 || t->de == NULL) {
#else
t->de = readdir(t->d);
if (t->de == NULL) {
r = errno;
#endif
closedir(t->d);
t->d = INVALID_DIR_HANDLE;
if (r != 0) {
@@ -2747,9 +2623,6 @@ tree_free(struct tree *t)
if (t == NULL)
return;
archive_string_free(&t->path);
#if defined(USE_READDIR_R)
free(t->dirent);
#endif
free(t->sparse_list);
for (i = 0; i < t->max_filesystem_id; i++)
free(t->filesystem_table[i].allocation_ptr);
+13 -10
View File
@@ -48,6 +48,7 @@
#endif
#include "archive.h"
#include "archive_platform_stat.h"
struct read_fd_data {
int fd;
@@ -65,12 +66,12 @@ static int64_t file_skip(struct archive *, void *, int64_t request);
int
archive_read_open_fd(struct archive *a, int fd, size_t block_size)
{
struct stat st;
la_seek_stat_t st;
struct read_fd_data *mine;
void *b;
archive_clear_error(a);
if (fstat(fd, &st) != 0) {
if (la_seek_fstat(fd, &st) != 0) {
archive_set_error(a, errno, "Can't stat fd %d", fd);
return (ARCHIVE_FATAL);
}
@@ -133,7 +134,7 @@ static int64_t
file_skip(struct archive *a, void *client_data, int64_t request)
{
struct read_fd_data *mine = (struct read_fd_data *)client_data;
off_t skip = (off_t)request;
la_seek_t skip = (la_seek_t)request;
int64_t old_offset, new_offset;
int skip_bits = sizeof(skip) * 8 - 1; /* off_t is a signed type. */
@@ -149,7 +150,8 @@ file_skip(struct archive *a, void *client_data, int64_t request)
}
/* Reduce 'skip' to the next smallest multiple of block_size */
skip = (off_t)(((int64_t)skip / mine->block_size) * mine->block_size);
skip = (la_seek_t)(((int64_t)skip / mine->block_size) * mine->block_size);
if (skip == 0)
return (0);
@@ -185,27 +187,28 @@ static int64_t
file_seek(struct archive *a, void *client_data, int64_t request, int whence)
{
struct read_fd_data *mine = (struct read_fd_data *)client_data;
off_t seek = (off_t)request;
la_seek_t seek = (la_seek_t)request;
int64_t r;
int seek_bits = sizeof(seek) * 8 - 1; /* off_t is a signed type. */
/* We use off_t here because lseek() is declared that way. */
/* Reduce a request that would overflow the 'seek' variable. */
/* Do not perform a seek which cannot be fulfilled. */
if (sizeof(request) > sizeof(seek)) {
const int64_t max_seek =
(((int64_t)1 << (seek_bits - 1)) - 1) * 2 + 1;
const int64_t min_seek = ~max_seek;
if (request > max_seek)
seek = (off_t)max_seek;
else if (request < min_seek)
seek = (off_t)min_seek;
if (request < min_seek || request > max_seek) {
errno = EOVERFLOW;
goto err;
}
}
r = lseek(mine->fd, seek, whence);
if (r >= 0)
return r;
err:
if (errno == ESPIPE) {
archive_set_error(a, errno,
"A file descriptor(%d) is not seekable(PIPE)", mine->fd);
+9 -7
View File
@@ -48,6 +48,7 @@
#endif
#include "archive.h"
#include "archive_platform_stat.h"
struct read_FILE_data {
FILE *f;
@@ -65,7 +66,7 @@ static int64_t FILE_skip(struct archive *, void *, int64_t);
int
archive_read_open_FILE(struct archive *a, FILE *f)
{
struct stat st;
la_seek_stat_t st;
struct read_FILE_data *mine;
size_t block_size = 128 * 1024;
void *b;
@@ -88,7 +89,7 @@ archive_read_open_FILE(struct archive *a, FILE *f)
* streams that don't support fileno()). As a result, fileno()
* should be used cautiously.)
*/
if (fstat(fileno(mine->f), &st) == 0 && S_ISREG(st.st_mode)) {
if (la_seek_fstat(fileno(mine->f), &st) == 0 && S_ISREG(st.st_mode)) {
archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
/* Enable the seek optimization only for regular files. */
mine->can_skip = 1;
@@ -205,15 +206,15 @@ FILE_seek(struct archive *a, void *client_data, int64_t request, int whence)
int seek_bits = sizeof(seek) * 8 - 1;
(void)a; /* UNUSED */
/* Reduce a request that would overflow the 'seek' variable. */
/* Do not perform a seek which cannot be fulfilled. */
if (sizeof(request) > sizeof(seek)) {
const int64_t max_seek =
(((int64_t)1 << (seek_bits - 1)) - 1) * 2 + 1;
const int64_t min_seek = ~max_seek;
if (request > max_seek)
seek = max_seek;
else if (request < min_seek)
seek = min_seek;
if (request < min_seek || request > max_seek) {
errno = EOVERFLOW;
goto err;
}
}
#ifdef __ANDROID__
@@ -236,6 +237,7 @@ FILE_seek(struct archive *a, void *client_data, int64_t request, int whence)
}
#endif
/* If we arrive here, the input is corrupted or truncated so fail. */
err:
archive_set_error(a, errno, "Error seeking in FILE* pointer");
return (ARCHIVE_FATAL);
}
+19 -12
View File
@@ -59,6 +59,7 @@
#endif
#include "archive.h"
#include "archive_platform_stat.h"
#include "archive_private.h"
#include "archive_string.h"
@@ -136,8 +137,10 @@ archive_read_open_filenames(struct archive *a, const char **filenames,
mine->filename_type = FNT_STDIN;
} else
mine->filename_type = FNT_MBS;
if (archive_read_append_callback_data(a, mine) != (ARCHIVE_OK))
if (archive_read_append_callback_data(a, mine) != (ARCHIVE_OK)) {
free(mine);
return (ARCHIVE_FATAL);
}
if (filenames == NULL)
break;
filename = *(filenames++);
@@ -216,8 +219,10 @@ archive_read_open_filenames_w(struct archive *a, const wchar_t **wfilenames,
archive_string_free(&fn);
#endif
}
if (archive_read_append_callback_data(a, mine) != (ARCHIVE_OK))
if (archive_read_append_callback_data(a, mine) != (ARCHIVE_OK)) {
free(mine);
return (ARCHIVE_FATAL);
}
if (wfilenames == NULL)
break;
wfilename = *(wfilenames++);
@@ -248,7 +253,7 @@ archive_read_open_filename_w(struct archive *a, const wchar_t *wfilename,
static int
file_open(struct archive *a, void *client_data)
{
struct stat st;
la_seek_stat_t st;
struct read_file_data *mine = (struct read_file_data *)client_data;
void *buffer;
const char *filename = NULL;
@@ -313,7 +318,7 @@ file_open(struct archive *a, void *client_data)
goto fail;
#endif
}
if (fstat(fd, &st) != 0) {
if (la_seek_fstat(fd, &st) != 0) {
#if defined(_WIN32) && !defined(__CYGWIN__)
if (mine->filename_type == FNT_WCS)
archive_set_error(a, errno, "Can't stat '%ls'",
@@ -482,10 +487,11 @@ file_skip_lseek(struct archive *a, void *client_data, int64_t request)
struct read_file_data *mine = (struct read_file_data *)client_data;
#if defined(_WIN32) && !defined(__CYGWIN__)
/* We use _lseeki64() on Windows. */
int64_t old_offset, new_offset, skip = request;
int64_t old_offset, new_offset;
#else
off_t old_offset, new_offset, skip = (off_t)request;
off_t old_offset, new_offset;
#endif
la_seek_t skip = (la_seek_t)request;
int skip_bits = sizeof(skip) * 8 - 1;
/* We use off_t here because lseek() is declared that way. */
@@ -552,21 +558,21 @@ static int64_t
file_seek(struct archive *a, void *client_data, int64_t request, int whence)
{
struct read_file_data *mine = (struct read_file_data *)client_data;
off_t seek = (off_t)request;
la_seek_t seek = (la_seek_t)request;
int64_t r;
int seek_bits = sizeof(seek) * 8 - 1;
/* We use off_t here because lseek() is declared that way. */
/* Reduce a request that would overflow the 'seek' variable. */
/* Do not perform a seek which cannot be fulfilled. */
if (sizeof(request) > sizeof(seek)) {
const int64_t max_seek =
(((int64_t)1 << (seek_bits - 1)) - 1) * 2 + 1;
const int64_t min_seek = ~max_seek;
if (request > max_seek)
seek = (off_t)max_seek;
else if (request < min_seek)
seek = (off_t)min_seek;
if (request < min_seek || request > max_seek) {
errno = EOVERFLOW;
goto err;
}
}
r = lseek(mine->fd, seek, whence);
@@ -574,6 +580,7 @@ file_seek(struct archive *a, void *client_data, int64_t request, int whence)
return r;
/* If the input is corrupted or truncated, fail. */
err:
if (mine->filename_type == FNT_STDIN)
archive_set_error(a, errno, "Error seeking in stdin");
else if (mine->filename_type == FNT_MBS)
+16 -16
View File
@@ -37,7 +37,7 @@ int
archive_read_set_format(struct archive *_a, int code)
{
int r1, r2, slots, i;
char str[10];
const char *str;
struct archive_read *a = (struct archive_read *)_a;
if ((r1 = archive_read_support_format_by_code(_a, code)) < (ARCHIVE_OK))
@@ -49,49 +49,49 @@ archive_read_set_format(struct archive *_a, int code)
switch (code & ARCHIVE_FORMAT_BASE_MASK)
{
case ARCHIVE_FORMAT_7ZIP:
strcpy(str, "7zip");
str = "7zip";
break;
case ARCHIVE_FORMAT_AR:
strcpy(str, "ar");
str = "ar";
break;
case ARCHIVE_FORMAT_CAB:
strcpy(str, "cab");
str = "cab";
break;
case ARCHIVE_FORMAT_CPIO:
strcpy(str, "cpio");
str = "cpio";
break;
case ARCHIVE_FORMAT_EMPTY:
strcpy(str, "empty");
str = "empty";
break;
case ARCHIVE_FORMAT_ISO9660:
strcpy(str, "iso9660");
str = "iso9660";
break;
case ARCHIVE_FORMAT_LHA:
strcpy(str, "lha");
str = "lha";
break;
case ARCHIVE_FORMAT_MTREE:
strcpy(str, "mtree");
str = "mtree";
break;
case ARCHIVE_FORMAT_RAR:
strcpy(str, "rar");
str = "rar";
break;
case ARCHIVE_FORMAT_RAR_V5:
strcpy(str, "rar5");
str = "rar5";
break;
case ARCHIVE_FORMAT_RAW:
strcpy(str, "raw");
str = "raw";
break;
case ARCHIVE_FORMAT_TAR:
strcpy(str, "tar");
str = "tar";
break;
case ARCHIVE_FORMAT_WARC:
strcpy(str, "warc");
str = "warc";
break;
case ARCHIVE_FORMAT_XAR:
strcpy(str, "xar");
str = "xar";
break;
case ARCHIVE_FORMAT_ZIP:
strcpy(str, "zip");
str = "zip";
break;
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
@@ -110,7 +110,7 @@ struct program_filter {
pid_t child;
#endif
int exit_status;
int waitpid_return;
pid_t waitpid_return;
int child_stdin, child_stdout;
char *out_buf;
@@ -242,16 +242,13 @@ child_stop(struct archive_read_filter *self, struct program_filter *state)
state->waitpid_return
= waitpid(state->child, &state->exit_status, 0);
} while (state->waitpid_return == -1 && errno == EINTR);
#if defined(_WIN32) && !defined(__CYGWIN__)
CloseHandle(state->child);
#endif
state->child = 0;
}
if (state->waitpid_return < 0) {
/* waitpid() failed? This is ugly. */
archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
"Child process exited badly");
"Error closing child process");
return (ARCHIVE_WARN);
}
@@ -80,7 +80,7 @@
/*
* ELF format
*/
#define ELF_HDR_MIN_LEN 0x34
#define ELF_HDR_MIN_LEN 0x3f
#define ELF_HDR_EI_CLASS_OFFSET 0x04
#define ELF_HDR_EI_DATA_OFFSET 0x05
@@ -811,6 +811,8 @@ find_elf_data_sec(struct archive_read *a)
strtab_size = (*dec32)(
h + e_shstrndx * e_shentsize + 0x14);
}
if (strtab_size < 6 || strtab_size > SIZE_MAX)
break;
/*
* Read the STRTAB section to find the .data offset
@@ -1391,7 +1393,8 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
* size to liblzma when using lzma_raw_decoder() liblzma
* could correctly deal with BCJ+LZMA. But unfortunately
* there is no way to do that.
* Discussion about this can be found at XZ Utils forum.
*
* Reference: https://web.archive.org/web/20240405171610/https://www.mail-archive.com/xz-devel@tukaani.org/msg00373.html
*/
if (coder2 != NULL) {
zip->codec2 = coder2->codec;
+19 -4
View File
@@ -51,6 +51,7 @@
#include "archive.h"
#include "archive_entry.h"
#include "archive_entry_private.h"
#include "archive_platform_stat.h"
#include "archive_private.h"
#include "archive_rb.h"
#include "archive_read_private.h"
@@ -1073,6 +1074,8 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
/* Non-printable characters are not allowed */
for (s = p;s < p + len - 1; s++) {
if (!isprint((unsigned char)*s) && *s != '\t') {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Non-printable character 0x%02X", (unsigned char)(*s));
r = ARCHIVE_FATAL;
break;
}
@@ -1175,7 +1178,7 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
struct mtree *mtree, struct mtree_entry *mentry, int *use_next)
{
const char *path;
struct stat st_storage, *st;
la_seek_stat_t st_storage, *st;
struct mtree_entry *mp;
struct archive_entry *sparse_entry;
int r = ARCHIVE_OK, r1, parsed_kws;
@@ -1251,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 == -1 && (
if (mtree->fd < 0 && (
#if defined(_WIN32) && !defined(__CYGWIN__)
/*
* On Windows, attempting to open a file with an
@@ -1270,7 +1273,7 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
st = &st_storage;
if (mtree->fd >= 0) {
if (fstat(mtree->fd, st) == -1) {
if (la_seek_fstat(mtree->fd, st) == -1) {
archive_set_error(&a->archive, errno,
"Could not fstat %s", path);
r = ARCHIVE_WARN;
@@ -1283,7 +1286,7 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
#ifdef HAVE_LSTAT
else if (lstat(path, st) == -1)
#else
else if (la_stat(path, st) == -1)
else if (la_seek_stat(path, st) == -1)
#endif
{
st = NULL;
@@ -2130,6 +2133,13 @@ readline(struct archive_read *a, struct mtree *mtree, char **start,
for (u = mtree->line.s + find_off; *u; ++u) {
if (u[0] == '\n') {
/* Ends with unescaped newline. */
/* Check if preceded by '\r' for CRLF handling */
if (u > mtree->line.s && u[-1] == '\r') {
/* CRLF ending - remove the '\r' */
u[-1] = '\n';
u[0] = '\0';
total_size--;
}
*start = mtree->line.s;
return total_size;
} else if (u[0] == '#') {
@@ -2144,6 +2154,11 @@ readline(struct archive_read *a, struct mtree *mtree, char **start,
total_size -= 2;
mtree->line.s[total_size] = '\0';
break;
} else if (u[1] == '\r' && u[2] == '\n') {
/* Trim escaped CRLF. */
total_size -= 3;
mtree->line.s[total_size] = '\0';
break;
} else if (u[1] != '\0') {
/* Skip the two-char escape sequence */
++u;
+3 -5
View File
@@ -1117,8 +1117,6 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff,
if (rar->entry_eof || rar->offset_seek >= rar->unp_size) {
*size = 0;
*offset = rar->offset;
if (*offset < rar->unp_size)
*offset = rar->unp_size;
return (ARCHIVE_EOF);
}
@@ -1455,7 +1453,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
return (ARCHIVE_FATAL);
#endif
}
/* If no CRC error, Go on parsing File Header. */
/* If no CRC error, go on parsing File Header. */
p = h;
endp = p + header_size - 7;
memcpy(&file_header, p, sizeof(file_header));
@@ -2368,8 +2366,8 @@ parse_codes(struct archive_read *a)
return (ARCHIVE_FATAL);
}
/* Make sure ppmd7_contest is freed before Ppmd7_Construct
* because reading a broken file cause this abnormal sequence. */
/* Make sure ppmd7_context is freed before Ppmd7_Construct
* because reading a broken file causes this abnormal sequence. */
__archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
rar->bytein.a = a;
+57 -9
View File
@@ -1619,10 +1619,13 @@ static int process_head_file_extra(struct archive_read* a,
{
uint64_t extra_field_size;
uint64_t extra_field_id = 0;
int ret = ARCHIVE_FATAL;
uint64_t var_size;
while(extra_data_size > 0) {
/* Make sure we won't fail if the file declares only unsupported
attributes. */
int ret = ARCHIVE_OK;
if(!read_var(a, &extra_field_size, &var_size))
return ARCHIVE_EOF;
@@ -1675,12 +1678,53 @@ static int process_head_file_extra(struct archive_read* a,
if (ARCHIVE_OK != consume(a, extra_field_size)) {
return ARCHIVE_EOF;
}
/* Don't fail on unsupported attribute -- we've handled it
by skipping over it. */
ret = ARCHIVE_OK;
}
if (ret != ARCHIVE_OK) {
/* Forward any errors signalled by the attribute parsing
functions. */
return ret;
}
}
if(ret != ARCHIVE_OK) {
/* Attribute not implemented. */
return ret;
if (extra_data_size != 0) {
/* We didn't skip everything, or we skipped too much; either way,
there's an error in this parsing function. */
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
"unsupported structure of file header extra data");
return ARCHIVE_FATAL;
}
return ARCHIVE_OK;
}
static int file_entry_sanity_checks(struct archive_read* a,
size_t block_flags, uint8_t is_dir, uint64_t unpacked_size,
size_t packed_size)
{
if (is_dir) {
const int declares_data_size =
(int) (unpacked_size != 0 || packed_size != 0);
/* FILE entries for directories still declare HFL_DATA in block flags,
even though attaching data to such blocks doesn't make much sense. */
if (declares_data_size) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"directory entries cannot have any data");
return ARCHIVE_FATAL;
}
} else {
const int declares_hfl_data = (int) ((block_flags & HFL_DATA) != 0);
if (!declares_hfl_data) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"no data found in file/service block");
return ARCHIVE_FATAL;
}
}
return ARCHIVE_OK;
@@ -1701,6 +1745,7 @@ static int process_head_file(struct archive_read* a, struct rar5* rar,
int c_method = 0, c_version = 0;
char name_utf8_buf[MAX_NAME_IN_BYTES];
const uint8_t* p;
int sanity_ret;
enum FILE_FLAGS {
DIRECTORY = 0x0001, UTIME = 0x0002, CRC32 = 0x0004,
@@ -1744,10 +1789,6 @@ static int process_head_file(struct archive_read* a, struct rar5* rar,
rar->file.bytes_remaining = data_size;
} else {
rar->file.bytes_remaining = 0;
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"no data found in file/service block");
return ARCHIVE_FATAL;
}
if(!read_var_sized(a, &file_flags, NULL))
@@ -1764,6 +1805,13 @@ static int process_head_file(struct archive_read* a, struct rar5* rar,
rar->file.dir = (uint8_t) ((file_flags & DIRECTORY) > 0);
sanity_ret = file_entry_sanity_checks(a, block_flags, rar->file.dir,
unpacked_size, data_size);
if (sanity_ret != ARCHIVE_OK) {
return sanity_ret;
}
if(!read_var_sized(a, &file_attr, NULL))
return ARCHIVE_EOF;
@@ -4163,7 +4211,7 @@ static int rar5_read_data(struct archive_read *a, const void **buff,
* it's impossible to perform any decompression. */
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Can't decompress an entry marked as a directory");
return ARCHIVE_FAILED;
return ARCHIVE_FATAL;
}
if(!rar->skip_mode && (rar->cstate.last_write_ptr > rar->file.unpacked_size)) {
+50 -20
View File
@@ -233,7 +233,7 @@ static int tar_read_header(struct archive_read *, struct tar *,
struct archive_entry *, int64_t *);
static int tohex(int c);
static char *url_decode(const char *, size_t);
static void tar_flush_unconsumed(struct archive_read *, int64_t *);
static int tar_flush_unconsumed(struct archive_read *, int64_t *);
/* Sanity limits: These numbers should be low enough to
* prevent a maliciously-crafted archive from forcing us to
@@ -477,7 +477,7 @@ archive_read_format_tar_options(struct archive_read *a,
* how much unconsumed data we have floating around, and to consume
* anything outstanding since we're going to do read_aheads
*/
static void
static int
tar_flush_unconsumed(struct archive_read *a, int64_t *unconsumed)
{
if (*unconsumed) {
@@ -490,9 +490,13 @@ tar_flush_unconsumed(struct archive_read *a, int64_t *unconsumed)
memset(data, 0xff, *unconsumed);
}
*/
__archive_read_consume(a, *unconsumed);
int64_t consumed = __archive_read_consume(a, *unconsumed);
if (consumed != *unconsumed) {
return (ARCHIVE_FATAL);
}
*unconsumed = 0;
}
return (ARCHIVE_OK);
}
/*
@@ -750,7 +754,9 @@ tar_read_header(struct archive_read *a, struct tar *tar,
/* Find the next valid header record. */
while (1) {
tar_flush_unconsumed(a, unconsumed);
if (tar_flush_unconsumed(a, unconsumed) != ARCHIVE_OK) {
return (ARCHIVE_FATAL);
}
/* Read 512-byte header record */
h = __archive_read_ahead(a, 512, &bytes);
@@ -796,7 +802,9 @@ tar_read_header(struct archive_read *a, struct tar *tar,
/* This is NOT a null block, so it must be a valid header. */
if (!checksum(a, h)) {
tar_flush_unconsumed(a, unconsumed);
if (tar_flush_unconsumed(a, unconsumed) != ARCHIVE_OK) {
return (ARCHIVE_FATAL);
}
archive_set_error(&a->archive, EINVAL,
"Damaged tar archive (bad header checksum)");
/* If we've read some critical information (pax headers, etc)
@@ -1236,7 +1244,7 @@ header_volume(struct archive_read *a, struct tar *tar,
header = (const struct archive_entry_header_ustar *)h;
size = tar_atol(header->size, sizeof(header->size));
if (size > (int64_t)pathname_limit) {
if (size < 0 || size > (int64_t)pathname_limit) {
return (ARCHIVE_FATAL);
}
to_consume = ((size + 511) & ~511);
@@ -1255,13 +1263,15 @@ read_bytes_to_string(struct archive_read *a,
const void *src;
/* Fail if we can't make our buffer big enough. */
if (archive_string_ensure(as, (size_t)size+1) == NULL) {
if (archive_string_ensure(as, size + 1) == NULL) {
archive_set_error(&a->archive, ENOMEM,
"No memory");
return (ARCHIVE_FATAL);
}
tar_flush_unconsumed(a, unconsumed);
if (tar_flush_unconsumed(a, unconsumed) != ARCHIVE_OK) {
return (ARCHIVE_FATAL);
}
/* Read the body into the string. */
src = __archive_read_ahead(a, size, NULL);
@@ -1272,9 +1282,9 @@ read_bytes_to_string(struct archive_read *a,
*unconsumed = 0;
return (ARCHIVE_FATAL);
}
memcpy(as->s, src, (size_t)size);
memcpy(as->s, src, size);
as->s[size] = '\0';
as->length = (size_t)size;
as->length = size;
*unconsumed += size;
return (ARCHIVE_OK);
}
@@ -1715,7 +1725,9 @@ read_mac_metadata_blob(struct archive_read *a,
* Q: Is the above idea really possible? Even
* when there are GNU or pax extension entries?
*/
tar_flush_unconsumed(a, unconsumed);
if (tar_flush_unconsumed(a, unconsumed) != ARCHIVE_OK) {
return (ARCHIVE_FATAL);
}
data = __archive_read_ahead(a, msize, NULL);
if (data == NULL) {
archive_set_error(&a->archive, EINVAL,
@@ -1900,7 +1912,9 @@ header_pax_extension(struct archive_read *a, struct tar *tar,
(long long)ext_size, (long long)ext_size_limit);
return (ARCHIVE_WARN);
}
tar_flush_unconsumed(a, unconsumed);
if (tar_flush_unconsumed(a, unconsumed) != ARCHIVE_OK) {
return (ARCHIVE_FATAL);
}
/* Parse the size/name of each pax attribute in the body */
archive_string_init(&attr_name);
@@ -1994,7 +2008,9 @@ header_pax_extension(struct archive_read *a, struct tar *tar,
/* Consume size, name, and `=` */
*unconsumed += p - attr_start;
tar_flush_unconsumed(a, unconsumed);
if (tar_flush_unconsumed(a, unconsumed) != ARCHIVE_OK) {
return (ARCHIVE_FATAL);
}
if (value_length == 0) {
archive_set_error(&a->archive, EINVAL,
@@ -2017,7 +2033,9 @@ header_pax_extension(struct archive_read *a, struct tar *tar,
err = err_combine(err, r);
/* Consume the `\n` that follows the pax attribute value. */
tar_flush_unconsumed(a, unconsumed);
if (tar_flush_unconsumed(a, unconsumed) != ARCHIVE_OK) {
return (ARCHIVE_FATAL);
}
p = __archive_read_ahead(a, 1, &did_read);
if (p == NULL) {
archive_set_error(&a->archive, EINVAL,
@@ -2033,7 +2051,9 @@ header_pax_extension(struct archive_read *a, struct tar *tar,
}
ext_size -= 1;
*unconsumed += 1;
tar_flush_unconsumed(a, unconsumed);
if (tar_flush_unconsumed(a, unconsumed) != ARCHIVE_OK) {
return (ARCHIVE_FATAL);
}
}
*unconsumed += ext_size + ext_padding;
@@ -2290,7 +2310,9 @@ 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);
tar_flush_unconsumed(a, &unconsumed);
if (tar_flush_unconsumed(a, &unconsumed) != ARCHIVE_OK) {
return (ARCHIVE_FATAL);
}
if (r < ARCHIVE_OK) {
archive_string_free(&as);
*result = 0;
@@ -2940,7 +2962,9 @@ header_gnutar(struct archive_read *a, struct tar *tar,
/* Copy filename over (to ensure null termination). */
header = (const struct archive_entry_header_gnutar *)h;
const char *existing_pathname = archive_entry_pathname(entry);
if (existing_pathname == NULL || existing_pathname[0] == '\0') {
const wchar_t *existing_wcs_pathname = archive_entry_pathname_w(entry);
if ((existing_pathname == NULL || existing_pathname[0] == '\0')
&& (existing_wcs_pathname == NULL || existing_wcs_pathname[0] == L'\0')) {
if (archive_entry_copy_pathname_l(entry,
header->name, sizeof(header->name), tar->sconv) != 0) {
err = set_conversion_failed_error(a, tar->sconv, "Pathname");
@@ -3093,7 +3117,9 @@ gnu_sparse_old_read(struct archive_read *a, struct tar *tar,
return (ARCHIVE_OK);
do {
tar_flush_unconsumed(a, unconsumed);
if (tar_flush_unconsumed(a, unconsumed) != ARCHIVE_OK) {
return (ARCHIVE_FATAL);
}
data = __archive_read_ahead(a, 512, &bytes_read);
if (data == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
@@ -3283,7 +3309,9 @@ gnu_sparse_10_read(struct archive_read *a, struct tar *tar, int64_t *unconsumed)
return (ARCHIVE_FATAL);
}
/* Skip rest of block... */
tar_flush_unconsumed(a, unconsumed);
if (tar_flush_unconsumed(a, unconsumed) != ARCHIVE_OK) {
return (ARCHIVE_FATAL);
}
bytes_read = tar->entry_bytes_remaining - remaining;
to_skip = 0x1ff & -bytes_read;
/* Fail if tar->entry_bytes_remaing would get negative */
@@ -3509,7 +3537,9 @@ readline(struct archive_read *a, struct tar *tar, const char **start,
const char *s;
void *p;
tar_flush_unconsumed(a, unconsumed);
if (tar_flush_unconsumed(a, unconsumed) != ARCHIVE_OK) {
return (ARCHIVE_FATAL);
}
t = __archive_read_ahead(a, 1, &bytes_read);
if (bytes_read <= 0 || t == NULL)
@@ -405,7 +405,7 @@ _warc_read(struct archive_read *a, const void **buf, size_t *bsz, int64_t *off)
/* it's our lucky day, no work, we can leave early */
*buf = NULL;
*bsz = 0U;
*off = w->cntoff + 4U/*for \r\n\r\n separator*/;
*off = w->cntoff;
w->unconsumed = 0U;
return (ARCHIVE_EOF);
}
+1 -1
View File
@@ -930,7 +930,7 @@ xar_read_data(struct archive_read *a,
abort_read_data:
*buff = NULL;
*size = 0;
*offset = xar->total;
*offset = (int64_t)xar->entry_total;
return (r);
}
+2 -2
View File
@@ -3015,8 +3015,8 @@ init_WinZip_AES_decryption(struct archive_read *a)
p, salt_len, 1000, derived_key, key_len * 2 + 2);
if (r != 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Decryption is unsupported due to lack of "
"crypto library");
r == CRYPTOR_STUB_FUNCTION ? "Decryption is unsupported due "
"to lack of crypto library" : "Failed to process passphrase");
return (ARCHIVE_FAILED);
}
+3 -2
View File
@@ -2015,7 +2015,7 @@ archive_strncat_l(struct archive_string *as, const void *_p, size_t n,
/* We must allocate memory even if there is no data for conversion
* or copy. This simulates archive_string_append behavior. */
if (length == 0) {
int tn = 1;
size_t tn = 1;
if (sc != NULL && (sc->flag & SCONV_TO_UTF16))
tn = 2;
if (archive_string_ensure(as, as->length + tn) == NULL)
@@ -2752,7 +2752,8 @@ archive_string_append_unicode(struct archive_string *as, const void *_p,
char *p, *endp;
uint32_t uc;
size_t w;
int n, ret = 0, ts, tm;
size_t ts, tm;
int n, ret = 0;
int (*parse)(uint32_t *, const char *, size_t);
size_t (*unparse)(char *, size_t, uint32_t);
+1 -1
View File
@@ -146,7 +146,7 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt,
case 'z': s = va_arg(ap, ssize_t); break;
default: s = va_arg(ap, int); break;
}
append_int(as, s, 10);
append_int(as, s, 10);
break;
case 's':
switch(long_flag) {
+33 -5
View File
@@ -445,11 +445,39 @@ __archive_mkstemp(wchar_t *template)
#else
static int
get_tempdir(struct archive_string *temppath)
__archive_issetugid(void)
{
const char *tmp;
#ifdef HAVE_ISSETUGID
return (issetugid());
#elif HAVE_GETRESUID
uid_t ruid, euid, suid;
gid_t rgid, egid, sgid;
if (getresuid(&ruid, &euid, &suid) != 0)
return (-1);
if (ruid != euid || ruid != suid)
return (1);
if (getresgid(&ruid, &egid, &sgid) != 0)
return (-1);
if (rgid != egid || rgid != sgid)
return (1);
#elif HAVE_GETEUID
if (geteuid() != getuid())
return (1);
#if HAVE_GETEGID
if (getegid() != getgid())
return (1);
#endif
#endif
return (0);
}
tmp = getenv("TMPDIR");
int
__archive_get_tempdir(struct archive_string *temppath)
{
const char *tmp = NULL;
if (__archive_issetugid() == 0)
tmp = getenv("TMPDIR");
if (tmp == NULL)
#ifdef _PATH_TMP
tmp = _PATH_TMP;
@@ -476,7 +504,7 @@ __archive_mktemp(const char *tmpdir)
archive_string_init(&temp_name);
if (tmpdir == NULL) {
if (get_tempdir(&temp_name) != ARCHIVE_OK)
if (__archive_get_tempdir(&temp_name) != ARCHIVE_OK)
goto exit_tmpfile;
} else {
archive_strcpy(&temp_name, tmpdir);
@@ -538,7 +566,7 @@ __archive_mktempx(const char *tmpdir, char *template)
if (template == NULL) {
archive_string_init(&temp_name);
if (tmpdir == NULL) {
if (get_tempdir(&temp_name) != ARCHIVE_OK)
if (__archive_get_tempdir(&temp_name) != ARCHIVE_OK)
goto exit_tmpfile;
} else
archive_strcpy(&temp_name, tmpdir);
+145 -3
View File
@@ -45,6 +45,7 @@
#if defined(_WIN32) && !defined(__CYGWIN__)
#include "archive_platform.h"
#include "archive_platform_stat.h"
#include "archive_private.h"
#include "archive_entry.h"
#include "archive_time_private.h"
@@ -313,6 +314,10 @@ __la_open(const char *path, int flags, ...)
pmode = va_arg(ap, int);
va_end(ap);
ws = NULL;
/* _(w)sopen_s fails if we provide any other modes */
pmode = pmode & (_S_IREAD | _S_IWRITE);
if ((flags & ~O_BINARY) == O_RDONLY) {
/*
* When we open a directory, _open function returns
@@ -374,7 +379,7 @@ __la_open(const char *path, int flags, ...)
TODO: Fix mode of new file. */
r = _open(path, flags);
#else
r = _open(path, flags, pmode);
_sopen_s(&r, path, flags, _SH_DENYNO, pmode);
#endif
if (r < 0 && errno == EACCES && (flags & O_CREAT) != 0) {
/* Simulate other POSIX system action to pass our test suite. */
@@ -395,7 +400,7 @@ __la_open(const char *path, int flags, ...)
return (-1);
}
}
r = _wopen(ws, flags, pmode);
_wsopen_s(&r, ws, flags, _SH_DENYNO, pmode);
if (r < 0 && errno == EACCES && (flags & O_CREAT) != 0) {
/* Simulate other POSIX system action to pass our test suite. */
attr = GetFileAttributesW(ws);
@@ -410,6 +415,93 @@ __la_open(const char *path, int flags, ...)
return (r);
}
int
__la_wopen(const wchar_t *path, int flags, ...)
{
va_list ap;
wchar_t *fullpath;
int r, pmode;
DWORD attr;
va_start(ap, flags);
pmode = va_arg(ap, int);
va_end(ap);
fullpath = NULL;
/* _(w)sopen_s fails if we provide any other modes */
pmode = pmode & (_S_IREAD | _S_IWRITE);
if ((flags & ~O_BINARY) == O_RDONLY) {
/*
* When we open a directory, _open function returns
* "Permission denied" error.
*/
attr = GetFileAttributesW(path);
#if !defined(WINAPI_FAMILY_PARTITION) || WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP)
if (attr == (DWORD)-1 && GetLastError() == ERROR_PATH_NOT_FOUND)
#endif
{
fullpath = __la_win_permissive_name_w(path);
if (fullpath == NULL) {
errno = EINVAL;
return (-1);
}
path = fullpath;
attr = GetFileAttributesW(fullpath);
}
if (attr == (DWORD)-1) {
la_dosmaperr(GetLastError());
free(fullpath);
return (-1);
}
if (attr & FILE_ATTRIBUTE_DIRECTORY) {
HANDLE handle;
#if !defined(WINAPI_FAMILY_PARTITION) || WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP)
if (fullpath != NULL)
handle = CreateFileW(fullpath, 0, 0, NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS |
FILE_ATTRIBUTE_READONLY,
NULL);
else
handle = CreateFileW(path, 0, 0, NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS |
FILE_ATTRIBUTE_READONLY,
NULL);
#else /* !WINAPI_PARTITION_DESKTOP */
CREATEFILE2_EXTENDED_PARAMETERS createExParams;
ZeroMemory(&createExParams, sizeof(createExParams));
createExParams.dwSize = sizeof(createExParams);
createExParams.dwFileAttributes = FILE_ATTRIBUTE_READONLY;
createExParams.dwFileFlags = FILE_FLAG_BACKUP_SEMANTICS;
handle = CreateFile2(fullpath, 0, 0,
OPEN_EXISTING, &createExParams);
#endif /* !WINAPI_PARTITION_DESKTOP */
free(fullpath);
if (handle == INVALID_HANDLE_VALUE) {
la_dosmaperr(GetLastError());
return (-1);
}
r = _open_osfhandle((intptr_t)handle, _O_RDONLY);
return (r);
}
}
_wsopen_s(&r, path, flags, _SH_DENYNO, pmode);
if (r < 0 && errno == EACCES && (flags & O_CREAT) != 0) {
/* Simulate other POSIX system action to pass our test suite. */
attr = GetFileAttributesW(path);
if (attr == (DWORD)-1)
la_dosmaperr(GetLastError());
else if (attr & FILE_ATTRIBUTE_DIRECTORY)
errno = EISDIR;
else
errno = EACCES;
}
free(fullpath);
return (r);
}
ssize_t
__la_read(int fd, void *buf, size_t nbytes)
{
@@ -561,6 +653,8 @@ copy_stat(struct stat *st, struct ustat *us)
st->st_mode = us->st_mode;
st->st_nlink = us->st_nlink;
st->st_size = (off_t)us->st_size;
if (st->st_size < 0 || (uint64_t)st->st_size != us->st_size)
st->st_size = 0;
st->st_uid = us->st_uid;
st->st_dev = us->st_dev;
st->st_rdev = us->st_rdev;
@@ -630,6 +724,53 @@ __la_stat(const char *path, struct stat *st)
return (ret);
}
static void
copy_seek_stat(la_seek_stat_t *st, struct ustat *us)
{
st->st_mtime = us->st_mtime;
st->st_gid = us->st_gid;
st->st_ino = getino(us);
st->st_mode = us->st_mode;
st->st_nlink = us->st_nlink;
st->st_size = (la_seek_t)us->st_size;
if (st->st_size < 0 || (uint64_t)st->st_size != us->st_size)
st->st_size = -1;
st->st_uid = us->st_uid;
st->st_dev = us->st_dev;
st->st_rdev = us->st_rdev;
}
int
__la_seek_fstat(int fd, la_seek_stat_t *st)
{
struct ustat u;
int ret;
ret = __hstat((HANDLE)_get_osfhandle(fd), &u);
copy_seek_stat(st, &u);
return (ret);
}
int
__la_seek_stat(const char *path, la_seek_stat_t *st)
{
HANDLE handle;
struct ustat u;
int ret;
handle = la_CreateFile(path, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
if (handle == INVALID_HANDLE_VALUE) {
la_dosmaperr(GetLastError());
return (-1);
}
ret = __hstat(handle, &u);
CloseHandle(handle);
copy_seek_stat(st, &u);
return (ret);
}
/*
* This waitpid is limited implementation.
*/
@@ -641,13 +782,14 @@ __la_waitpid(HANDLE child, int *status, int option)
(void)option;/* UNUSED */
do {
if (GetExitCodeProcess(child, &cs) == 0) {
CloseHandle(child);
la_dosmaperr(GetLastError());
CloseHandle(child);
*status = 0;
return (-1);
}
} while (cs == STILL_ACTIVE);
CloseHandle(child);
*status = (int)(cs & 0xff);
return (0);
}
+7
View File
@@ -72,6 +72,8 @@
#include <windows.h>
//#define EFTYPE 7
#include "archive_platform_stat.h"
#if defined(__BORLANDC__)
#pragma warn -8068 /* Constant out of range in comparison. */
#pragma warn -8072 /* Suspicious pointer arithmetic. */
@@ -106,6 +108,7 @@
#endif
#define lstat __la_stat
#define open __la_open
#define _wopen __la_wopen
#define read __la_read
#if !defined(__BORLANDC__) && !defined(__WATCOMC__)
#define setmode _setmode
@@ -261,6 +264,9 @@
#define F_OK 0 /* Test for existence of file */
#endif
/* Functions to circumvent off_t limitations */
int __la_seek_fstat(int fd, la_seek_stat_t *st);
int __la_seek_stat(const char *path, la_seek_stat_t *st);
/* Replacement POSIX function */
extern int __la_fstat(int fd, struct stat *st);
@@ -269,6 +275,7 @@ extern int __la_lstat(const char *path, struct stat *st);
extern __int64 __la_lseek(int fd, __int64 offset, int whence);
#endif
extern int __la_open(const char *path, int flags, ...);
extern int __la_wopen(const wchar_t *path, int flags, ...);
extern ssize_t __la_read(int fd, void *buf, size_t nbytes);
extern int __la_stat(const char *path, struct stat *st);
extern pid_t __la_waitpid(HANDLE child, int *status, int option);
+18 -12
View File
@@ -360,7 +360,6 @@ archive_write_client_open(struct archive_write_filter *f)
struct archive_none *state;
void *buffer;
size_t buffer_size;
int ret;
f->bytes_per_block = archive_write_get_bytes_per_block(f->archive);
f->bytes_in_last_block =
@@ -385,13 +384,7 @@ archive_write_client_open(struct archive_write_filter *f)
if (a->client_opener == NULL)
return (ARCHIVE_OK);
ret = a->client_opener(f->archive, a->client_data);
if (ret != ARCHIVE_OK) {
free(state->buffer);
free(state);
f->data = NULL;
}
return (ret);
return (a->client_opener(f->archive, a->client_data));
}
static int
@@ -480,6 +473,7 @@ static int
archive_write_client_free(struct archive_write_filter *f)
{
struct archive_write *a = (struct archive_write *)f->archive;
struct archive_none *state = (struct archive_none *)f->data;
if (a->client_freer)
(*a->client_freer)(&a->archive, a->client_data);
@@ -492,6 +486,13 @@ archive_write_client_free(struct archive_write_filter *f)
a->passphrase = NULL;
}
/* Free state. */
if (state != NULL) {
free(state->buffer);
free(state);
f->data = NULL;
}
return (ARCHIVE_OK);
}
@@ -548,8 +549,6 @@ archive_write_client_close(struct archive_write_filter *f)
}
if (a->client_closer)
(*a->client_closer)(&a->archive, a->client_data);
free(state->buffer);
free(state);
/* Clear the close handler myself not to be called again. */
f->state = ARCHIVE_WRITE_FILTER_STATE_CLOSED;
@@ -807,7 +806,10 @@ _archive_write_finish_entry(struct archive *_a)
if (a->archive.state & ARCHIVE_STATE_DATA
&& a->format_finish_entry != NULL)
ret = (a->format_finish_entry)(a);
a->archive.state = ARCHIVE_STATE_HEADER;
if (ret == ARCHIVE_FATAL)
a->archive.state = ARCHIVE_STATE_FATAL;
else
a->archive.state = ARCHIVE_STATE_HEADER;
return (ret);
}
@@ -819,6 +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;
archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_DATA, "archive_write_data");
@@ -826,7 +829,10 @@ _archive_write_data(struct archive *_a, const void *buff, size_t s)
if (s > max_write)
s = max_write;
archive_clear_error(&a->archive);
return ((a->format_write_data)(a, buff, s));
ret = (a->format_write_data)(a, buff, s);
if (ret == ARCHIVE_FATAL)
a->archive.state = ARCHIVE_STATE_FATAL;
return (ret);
}
static struct archive_write_filter *
@@ -281,6 +281,10 @@ static int
archive_compressor_bzip2_free(struct archive_write_filter *f)
{
struct private_data *data = (struct private_data *)f->data;
/* May already have been called, but not necessarily. */
(void)BZ2_bzCompressEnd(&(data->stream));
free(data->compressed);
free(data);
f->data = NULL;
+39 -16
View File
@@ -191,7 +191,8 @@ static int
archive_compressor_gzip_open(struct archive_write_filter *f)
{
struct private_data *data = (struct private_data *)f->data;
int ret;
int ret = ARCHIVE_OK;
int init_success;
if (data->compressed == NULL) {
size_t bs = 65536, bpb;
@@ -221,44 +222,66 @@ archive_compressor_gzip_open(struct archive_write_filter *f)
data->compressed[0] = 0x1f; /* GZip signature bytes */
data->compressed[1] = 0x8b;
data->compressed[2] = 0x08; /* "Deflate" compression */
data->compressed[3] = data->original_filename == NULL ? 0 : 0x8;
data->compressed[3] = 0x00; /* Flags */
if (data->timestamp >= 0) {
time_t t = time(NULL);
data->compressed[4] = (uint8_t)(t)&0xff; /* Timestamp */
data->compressed[5] = (uint8_t)(t>>8)&0xff;
data->compressed[6] = (uint8_t)(t>>16)&0xff;
data->compressed[7] = (uint8_t)(t>>24)&0xff;
} else
} else {
memset(&data->compressed[4], 0, 4);
if (data->compression_level == 9)
data->compressed[8] = 2;
else if(data->compression_level == 1)
data->compressed[8] = 4;
else
data->compressed[8] = 0;
}
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;
if (data->original_filename != NULL) {
strcpy((char*)data->compressed + 10, data->original_filename);
data->stream.next_out += strlen(data->original_filename) + 1;
data->stream.avail_out -= strlen(data->original_filename) + 1;
/* Limit "original filename" to 32k or the
* remaining space in the buffer, whichever is smaller.
*/
int ofn_length = strlen(data->original_filename);
int ofn_max_length = 32768;
int ofn_space_available = data->compressed
+ data->compressed_buffer_size
- data->stream.next_out
- 1;
if (ofn_max_length > ofn_space_available) {
ofn_max_length = ofn_space_available;
}
if (ofn_length < ofn_max_length) {
data->compressed[3] |= 0x8;
strcpy((char*)data->compressed + 10,
data->original_filename);
data->stream.next_out += ofn_length + 1;
data->stream.avail_out -= ofn_length + 1;
} else {
archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"Gzip 'Original Filename' ignored because it is too long");
ret = ARCHIVE_WARN;
}
}
f->write = archive_compressor_gzip_write;
/* Initialize compression library. */
ret = deflateInit2(&(data->stream),
init_success = deflateInit2(&(data->stream),
data->compression_level,
Z_DEFLATED,
-15 /* < 0 to suppress zlib header */,
8,
Z_DEFAULT_STRATEGY);
if (ret == Z_OK) {
if (init_success == Z_OK) {
f->data = data;
return (ARCHIVE_OK);
return (ret);
}
/* Library setup failed: clean up. */
@@ -266,7 +289,7 @@ archive_compressor_gzip_open(struct archive_write_filter *f)
"initializing compression library");
/* Override the error message if we know what really went wrong. */
switch (ret) {
switch (init_success) {
case Z_STREAM_ERROR:
archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"Internal error initializing "
@@ -330,6 +330,7 @@ __archive_write_program_close(struct archive_write_filter *f,
struct archive_write_program_data *data)
{
int ret, status;
pid_t pid;
ssize_t bytes_read;
if (data->child == 0)
@@ -373,14 +374,12 @@ cleanup:
close(data->child_stdin);
if (data->child_stdout != -1)
close(data->child_stdout);
while (waitpid(data->child, &status, 0) == -1 && errno == EINTR)
continue;
#if defined(_WIN32) && !defined(__CYGWIN__)
CloseHandle(data->child);
#endif
do {
pid = waitpid(data->child, &status, 0);
} while (pid == -1 && errno == EINTR);
data->child = 0;
if (status != 0) {
if (pid < 0 || status != 0) {
archive_set_error(f->archive, EIO,
"Error closing program: %s", data->program_name);
ret = ARCHIVE_FATAL;
@@ -391,6 +391,8 @@ archive_compressor_zstd_open(struct archive_write_filter *f)
ZSTD_CCtx_setParameter(data->cstream, ZSTD_c_nbWorkers, data->threads);
ZSTD_CCtx_setParameter(data->cstream, ZSTD_c_checksumFlag, 1);
#if ZSTD_VERSION_NUMBER >= MINVER_LONG
ZSTD_CCtx_setParameter(data->cstream, ZSTD_c_windowLog, data->long_distance);
#endif
+10 -6
View File
@@ -2204,7 +2204,7 @@ restore_entry(struct archive_write_disk *a)
(void)clear_nochange_fflags(a);
if ((a->flags & ARCHIVE_EXTRACT_SAFE_WRITES) &&
S_ISREG(a->st.st_mode)) {
S_ISREG(a->mode)) {
/* Use a temporary file to extract */
if ((a->fd = la_mktemp(a)) == -1) {
archive_set_error(&a->archive, errno,
@@ -2559,9 +2559,9 @@ _archive_write_disk_close(struct archive *_a)
* for directories. For other file types
* we need to verify via fstat() or lstat()
*/
if (fd == -1 || p->filetype != AE_IFDIR) {
if (fd < 0 || 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)) {
@@ -3930,10 +3930,14 @@ clear_nochange_fflags(struct archive_write_disk *a)
#ifdef UF_APPEND
| UF_APPEND
#endif
#ifdef EXT2_APPEND_FL
#if defined(FS_APPEND_FL)
| FS_APPEND_FL
#elif defined(EXT2_APPEND_FL)
| EXT2_APPEND_FL
#endif
#ifdef EXT2_IMMUTABLE_FL
#if defined(FS_IMMUTABLE_FL)
| FS_IMMUTABLE_FL
#elif defined(EXT2_IMMUTABLE_FL)
| EXT2_IMMUTABLE_FL
#endif
;
@@ -4437,7 +4441,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 == -1) {
if (fd < 0) {
archive_set_error(&a->archive, errno,
"Failed to open a restoring file");
ret = ARCHIVE_WARN;
+1 -1
View File
@@ -1618,7 +1618,7 @@ restore_entry(struct archive_write_disk *a)
(void)clear_nochange_fflags(a);
}
if ((a->flags & ARCHIVE_EXTRACT_SAFE_WRITES) &&
S_ISREG(st_mode)) {
S_ISREG(a->mode)) {
int fd = la_mktemp(a);
if (fd == -1) {
+1 -1
View File
@@ -122,7 +122,7 @@ file_write(struct archive *a, void *client_data, const void *buff, size_t length
mine = (struct write_fd_data *)client_data;
for (;;) {
bytesWritten = write(mine->fd, buff, length);
if (bytesWritten <= 0) {
if (bytesWritten < 0) {
if (errno == EINTR)
continue;
archive_set_error(a, errno, "Write error");
+5 -9
View File
@@ -85,16 +85,12 @@ file_write(struct archive *a, void *client_data, const void *buff, size_t length
size_t bytesWritten;
mine = client_data;
for (;;) {
bytesWritten = fwrite(buff, 1, length, mine->f);
if (bytesWritten <= 0) {
if (errno == EINTR)
continue;
archive_set_error(a, errno, "Write error");
return (-1);
}
return (bytesWritten);
bytesWritten = fwrite(buff, 1, length, mine->f);
if (bytesWritten != length) {
archive_set_error(a, errno, "Write error");
return (-1);
}
return (bytesWritten);
}
static int
+2 -1
View File
@@ -108,6 +108,7 @@ open_filename(struct archive *a, int mbs_fn, const void *filename)
else
r = archive_mstring_copy_wcs(&mine->filename, filename);
if (r < 0) {
free(mine);
if (errno == ENOMEM) {
archive_set_error(a, ENOMEM, "No memory");
return (ARCHIVE_FATAL);
@@ -227,7 +228,7 @@ file_write(struct archive *a, void *client_data, const void *buff,
mine = (struct write_file_data *)client_data;
for (;;) {
bytesWritten = write(mine->fd, buff, length);
if (bytesWritten <= 0) {
if (bytesWritten < 0) {
if (errno == EINTR)
continue;
archive_set_error(a, errno, "Write error");
+1 -1
View File
@@ -686,7 +686,7 @@ write_to_temp(struct archive_write *a, const void *buff, size_t s)
ws = write(zip->temp_fd, p, s);
if (ws < 0) {
archive_set_error(&(a->archive), errno,
"fwrite function failed");
"write function failed");
return (ARCHIVE_FATAL);
}
s -= ws;
+8 -11
View File
@@ -1927,7 +1927,7 @@ mtree_entry_setup_filenames(struct archive_write *a, struct mtree_entry *file,
}
/*
* Find out the position which points the last position of
* Find out the position which points to the last position of
* path separator('/').
*/
slash = NULL;
@@ -2024,7 +2024,7 @@ mtree_entry_add_child_tail(struct mtree_entry *parent,
}
/*
* Find a entry from a parent entry with the name.
* Find an entry from a parent entry with given name.
*/
static struct mtree_entry *
mtree_entry_find_child(struct mtree_entry *parent, const char *child_name)
@@ -2148,10 +2148,10 @@ mtree_entry_tree_add(struct archive_write *a, struct mtree_entry **filep)
/* Find next sub directory. */
if (!np->dir_info) {
/* NOT Directory! */
/* NOT a directory! */
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"`%s' is not directory, we cannot insert `%s' ",
"`%s' is not a directory, we cannot insert `%s' ",
np->pathname.s, file->pathname.s);
return (ARCHIVE_FAILED);
}
@@ -2243,10 +2243,7 @@ mtree_entry_tree_add(struct archive_write *a, struct mtree_entry **filep)
}
same_entry:
/*
* We have already has the entry the filename of which is
* the same.
*/
/* We already have an entry with same filename. */
r = mtree_entry_exchange_same_entry(a, np, file);
if (r < ARCHIVE_WARN)
return (r);
@@ -2264,13 +2261,13 @@ mtree_entry_exchange_same_entry(struct archive_write *a, struct mtree_entry *np,
if ((np->mode & AE_IFMT) != (file->mode & AE_IFMT)) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Found duplicate entries `%s' and its file type is "
"different",
"Found duplicate entries for `%s' with "
"differing file types.",
np->pathname.s);
return (ARCHIVE_FAILED);
}
/* Update the existent mtree entry's attributes by the new one's. */
/* Update the existing mtree entry's attributes by the new one's. */
archive_string_empty(&np->symlink);
archive_string_concat(&np->symlink, &file->symlink);
archive_string_empty(&np->uname);
+3 -3
View File
@@ -689,7 +689,7 @@ write_to_temp(struct archive_write *a, const void *buff, size_t s)
ws = write(xar->temp_fd, p, s);
if (ws < 0) {
archive_set_error(&(a->archive), errno,
"fwrite function failed");
"write function failed");
return (ARCHIVE_FATAL);
}
s -= ws;
@@ -3418,8 +3418,8 @@ static int
xml_writer_get_final_content_and_length(struct xml_writer *ctx,
const char **out, size_t *size)
{
*out = (const char*)ctx->bp->content;
*size = (size_t)ctx->bp->use;
*out = (const char*)xmlBufferContent(ctx->bp);
*size = (size_t)xmlBufferLength(ctx->bp);
return (0);
}
+22 -3
View File
@@ -1856,7 +1856,10 @@ archive_write_zip_finish_entry(struct archive_write *a)
}
ret = __archive_write_output(a, zip->buf, remainder);
if (ret != ARCHIVE_OK)
{
deflateEnd(&zip->stream.deflate);
return (ret);
}
zip->entry_compressed_written += remainder;
zip->written_bytes += remainder;
zip->stream.deflate.next_out = zip->buf;
@@ -1898,7 +1901,10 @@ archive_write_zip_finish_entry(struct archive_write *a)
}
ret = __archive_write_output(a, zip->buf, remainder);
if (ret != ARCHIVE_OK)
{
BZ2_bzCompressEnd(&zip->stream.bzip2);
return (ret);
}
zip->entry_compressed_written += remainder;
zip->written_bytes += remainder;
zip->stream.bzip2.next_out = (char*)zip->buf;
@@ -1940,13 +1946,17 @@ archive_write_zip_finish_entry(struct archive_write *a)
}
ret = __archive_write_output(a, zip->buf, remainder);
if (ret != ARCHIVE_OK)
{
ZSTD_freeCStream(zip->stream.zstd.context);
return (ret);
}
zip->entry_compressed_written += remainder;
zip->written_bytes += remainder;
zip->stream.zstd.out.dst = zip->buf;
if (zip->stream.zstd.out.pos != zip->stream.zstd.out.size)
finishing = 0;
zip->stream.zstd.out.dst = zip->buf;
zip->stream.zstd.out.size = zip->len_buf;
zip->stream.zstd.out.pos = 0;
} while (finishing);
ZSTD_freeCStream(zip->stream.zstd.context);
break;
@@ -1984,7 +1994,10 @@ archive_write_zip_finish_entry(struct archive_write *a)
}
ret = __archive_write_output(a, zip->buf, remainder);
if (ret != ARCHIVE_OK)
{
lzma_end(&zip->stream.lzma.context);
return (ret);
}
zip->entry_compressed_written += remainder;
zip->written_bytes += remainder;
zip->stream.lzma.context.next_out = zip->buf;
@@ -2434,13 +2447,19 @@ init_winzip_aes_encryption(struct archive_write *a)
"Can't generate random number for encryption");
return (ARCHIVE_FATAL);
}
archive_pbkdf2_sha1(passphrase, strlen(passphrase),
ret = archive_pbkdf2_sha1(passphrase, strlen(passphrase),
salt, salt_len, 1000, derived_key, key_len * 2 + 2);
if (ret != 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
ret == CRYPTOR_STUB_FUNCTION ? "Encryption is unsupported due to "
"lack of crypto library" : "Failed to process passphrase");
return (ARCHIVE_FAILED);
}
ret = archive_encrypto_aes_ctr_init(&zip->cctx, derived_key, key_len);
if (ret != 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Decryption is unsupported due to lack of crypto library");
"Failed to initialize AES CTR mode");
return (ARCHIVE_FAILED);
}
ret = archive_hmac_sha1_init(&zip->hctx, derived_key + key_len,
+34 -3
View File
@@ -1,6 +1,6 @@
/*-
* Copyright (c) 2007 Joerg Sonnenberger
* Copyright (c) 2012 Michihiro NAKAJIMA
* Copyright (c) 2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -76,7 +76,15 @@ __archive_create_child(const char *cmd, int *child_stdin, int *child_stdout,
{
pid_t child = -1;
int stdin_pipe[2], stdout_pipe[2], tmp;
#if !defined(POSIX_SPAWN_CLOEXEC_DEFAULT) && \
(HAVE_FORK || HAVE_VFORK) && \
(HAVE_CLOSEFROM || HAVE_CLOSE_RANGE || defined(_SC_OPEN_MAX))
#undef HAVE_POSIX_SPAWNP
#endif
#if HAVE_POSIX_SPAWNP
posix_spawnattr_t attr;
posix_spawn_file_actions_t actions;
int r;
#endif
@@ -107,11 +115,21 @@ __archive_create_child(const char *cmd, int *child_stdin, int *child_stdout,
#if HAVE_POSIX_SPAWNP
r = posix_spawn_file_actions_init(&actions);
r = posix_spawnattr_init(&attr);
if (r != 0) {
errno = r;
goto stdout_opened;
}
r = posix_spawn_file_actions_init(&actions);
if (r != 0) {
errno = r;
goto attr_inited;
}
#ifdef POSIX_SPAWN_CLOEXEC_DEFAULT
r = posix_spawnattr_setflags(&attr, POSIX_SPAWN_CLOEXEC_DEFAULT);
if (r != 0)
goto actions_inited;
#endif
r = posix_spawn_file_actions_addclose(&actions, stdin_pipe[1]);
if (r != 0)
goto actions_inited;
@@ -136,11 +154,12 @@ __archive_create_child(const char *cmd, int *child_stdin, int *child_stdout,
if (r != 0)
goto actions_inited;
}
r = posix_spawnp(&child, cmdline->path, &actions, NULL,
r = posix_spawnp(&child, cmdline->path, &actions, &attr,
cmdline->argv, NULL);
if (r != 0)
goto actions_inited;
posix_spawn_file_actions_destroy(&actions);
posix_spawnattr_destroy(&attr);
#else /* HAVE_POSIX_SPAWNP */
@@ -162,6 +181,16 @@ __archive_create_child(const char *cmd, int *child_stdin, int *child_stdout,
_exit(254);
if (stdout_pipe[1] != 1 /* stdout */)
close(stdout_pipe[1]);
#if HAVE_CLOSEFROM
closefrom(3);
#elif HAVE_CLOSE_RANGE
close_range(3, ~0U, 0);
#elif defined(_SC_OPEN_MAX)
for (int i = sysconf(_SC_OPEN_MAX); i > 3;)
close(--i);
#endif
execvp(cmdline->path, cmdline->argv);
_exit(254);
}
@@ -183,6 +212,8 @@ __archive_create_child(const char *cmd, int *child_stdin, int *child_stdout,
actions_inited:
errno = r;
posix_spawn_file_actions_destroy(&actions);
attr_inited:
posix_spawnattr_destroy(&attr);
#endif
stdout_opened:
close(stdout_pipe[0]);