mirror of
https://git.freebsd.org/src.git
synced 2026-01-11 19:57:22 +00:00
libarchive: merge from vendor branch
Update vendor/libarchive to 3.8.2 Important bugfixes: #2477 tar writer: fix replacing a regular file with a dir for ARCHIVE_EXTRACT_SAFE_WRITES #2659 lib: improve filter process handling #2664 zip writer: fix a memory leak if write callback error early #2665 lib: archive_read_data: handle sparse holes at end of file correctly #2668 7zip: Fix out of boundary access #2670 zip writer: fix writing with ZSTD compression #2672 lib: fix error checking in writing files #2678 zstd write filter: enable Zstandard's checksum feature #2679 lib: handle possible errors from system calls #2707 lib: avoid leaking file descriptors into subprocesses #2713 RAR5 reader: fix multiple issues in extra field parsing function #2716 RAR5 reader: early fail when file declares data for a dir entry #2717 bsdtar: Allow filename to have CRLF endings #2719 tar reader: fix checking the result of the strftime (CVE-2025-25724) #2737 tar reader: fix an infinite loop when parsing V headers #2742 lib: parse_date: handle dates in 2038 and beyond if time_t is big enough Obtained from: libarchive Vendor commit: 7f53fce04e4e672230f4eb80b219af17975e4f83 Security: CVE-2025-25724 PR: 290303 (exp-run) MFC after: 1 week
This commit is contained in:
commit
401026e482
112 changed files with 1122 additions and 548 deletions
|
|
@ -1,3 +1,5 @@
|
|||
Oct 15, 2026: libarchive 3.8.2 released
|
||||
|
||||
Jun 01, 2026: libarchive 3.8.1 released
|
||||
|
||||
May 20, 2025: libarchive 3.8.0 released
|
||||
|
|
|
|||
|
|
@ -16,4 +16,4 @@ Please provide the following information in your report:
|
|||
- How to reproduce the issue
|
||||
|
||||
This project is maintained by volunteers on a reasonable-effort basis. As such, we ask
|
||||
that you give me 90 days to work on a fix before public exposure.
|
||||
that you give us 90 days to work on a fix before public exposure.
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@ set -eux
|
|||
#brew update > /dev/null
|
||||
#brew upgrade > /dev/null
|
||||
|
||||
# Workaround for cmake in local/pinned tap issue
|
||||
brew uninstall cmake
|
||||
|
||||
# This does an upgrade if the package is already installed
|
||||
brew install \
|
||||
autoconf \
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@
|
|||
|
||||
#include "bsdcat_platform.h"
|
||||
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
|
|
@ -22,7 +25,7 @@
|
|||
#include <archive_entry.h>
|
||||
|
||||
#include "bsdcat.h"
|
||||
#include "err.h"
|
||||
#include "lafe_err.h"
|
||||
|
||||
#define BYTES_PER_BLOCK (20*512)
|
||||
|
||||
|
|
@ -105,6 +108,16 @@ main(int argc, char **argv)
|
|||
bsdcat = &bsdcat_storage;
|
||||
memset(bsdcat, 0, sizeof(*bsdcat));
|
||||
|
||||
#if defined(HAVE_SIGACTION) && defined(SIGCHLD)
|
||||
{ /* Do not ignore SIGCHLD. */
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = SIG_DFL;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
sigaction(SIGCHLD, &sa, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
lafe_setprogname(*argv, "bsdcat");
|
||||
|
||||
bsdcat->argv = argv;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
#endif
|
||||
|
||||
#include "bsdcat.h"
|
||||
#include "err.h"
|
||||
#include "lafe_err.h"
|
||||
|
||||
/*
|
||||
* Short options for bsdcat. Please keep this sorted.
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
#endif
|
||||
|
||||
#include "cpio.h"
|
||||
#include "err.h"
|
||||
#include "lafe_err.h"
|
||||
|
||||
/*
|
||||
* Short options for cpio. Please keep this sorted.
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@
|
|||
#endif
|
||||
|
||||
#include "cpio.h"
|
||||
#include "err.h"
|
||||
#include "lafe_err.h"
|
||||
#include "line_reader.h"
|
||||
#include "passphrase.h"
|
||||
|
||||
|
|
@ -124,13 +124,21 @@ main(int argc, char *argv[])
|
|||
cpio->buff_size = sizeof(buff);
|
||||
|
||||
|
||||
#if defined(HAVE_SIGACTION) && defined(SIGPIPE)
|
||||
{ /* Ignore SIGPIPE signals. */
|
||||
#if defined(HAVE_SIGACTION)
|
||||
{
|
||||
struct sigaction sa;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
#ifdef SIGPIPE
|
||||
/* Ignore SIGPIPE signals. */
|
||||
sa.sa_handler = SIG_IGN;
|
||||
sigaction(SIGPIPE, &sa, NULL);
|
||||
#endif
|
||||
#ifdef SIGCHLD
|
||||
/* Do not ignore SIGCHLD. */
|
||||
sa.sa_handler = SIG_DFL;
|
||||
sigaction(SIGCHLD, &sa, NULL);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
#include "test.h"
|
||||
|
||||
#include "../cpio.h"
|
||||
#include "err.h"
|
||||
#include "lafe_err.h"
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#define ROOT "root"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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
contrib/libarchive/libarchive/archive_platform_stat.h
Normal file
45
contrib/libarchive/libarchive/archive_platform_stat.h
Normal 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 */
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
|
|
|
|||
|
|
@ -145,6 +145,13 @@ static struct archive_test_acl_t acls_bad[] = {
|
|||
ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" },
|
||||
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE,
|
||||
ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" },
|
||||
|
||||
/* Multiple types */
|
||||
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW | ARCHIVE_ENTRY_ACL_TYPE_AUDIT,
|
||||
ARCHIVE_ENTRY_ACL_EXECUTE,
|
||||
ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" },
|
||||
{ ARCHIVE_ENTRY_ACL_TYPE_NFS4, ARCHIVE_ENTRY_ACL_EXECUTE,
|
||||
ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" },
|
||||
};
|
||||
|
||||
DEFINE_TEST(test_acl_nfs4)
|
||||
|
|
|
|||
|
|
@ -94,6 +94,11 @@ static struct archive_test_acl_t acls_nfs4[] = {
|
|||
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
|
||||
ARCHIVE_ENTRY_ACL_READ | ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT,
|
||||
ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
|
||||
|
||||
/* Invalid type codes */
|
||||
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS | ARCHIVE_ENTRY_ACL_TYPE_DEFAULT,
|
||||
ARCHIVE_ENTRY_ACL_READ,
|
||||
ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
|
||||
};
|
||||
|
||||
DEFINE_TEST(test_acl_posix1e)
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ DEFINE_TEST(test_archive_parse_date)
|
|||
assertEqualInt(get_date(now, "Jan 1, 1970 UTC"), 0);
|
||||
assertEqualInt(get_date(now, "7:12:18-0530 4 May 1983"), 420900138);
|
||||
assertEqualInt(get_date(now, "2004/01/29 513 mest"), 1075345980);
|
||||
assertEqualInt(get_date(now, "2038-06-01 00:01:02 UTC"),
|
||||
sizeof(time_t) <= 4 ? -1 : 2158963262);
|
||||
assertEqualInt(get_date(now, "99/02/17 7pm utc"), 919278000);
|
||||
assertEqualInt(get_date(now, "02/17/99 7:11am est"), 919253460);
|
||||
assertEqualInt(get_date(now, "now - 2 hours"),
|
||||
|
|
|
|||
|
|
@ -991,6 +991,7 @@ DEFINE_TEST(test_archive_string_update_utf8_koi8)
|
|||
static const char koi8_string[] = "\xD0\xD2\xC9";
|
||||
static const wchar_t wcs_string[] = L"\U0000043f\U00000440\U00000438";
|
||||
struct archive_mstring mstr;
|
||||
struct archive *a;
|
||||
int r;
|
||||
|
||||
memset(&mstr, 0, sizeof(mstr));
|
||||
|
|
@ -999,6 +1000,15 @@ DEFINE_TEST(test_archive_string_update_utf8_koi8)
|
|||
skipping("KOI8-R locale not available on this system.");
|
||||
return;
|
||||
}
|
||||
a = archive_write_new();
|
||||
assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a));
|
||||
if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) {
|
||||
skipping("This system cannot convert character-set"
|
||||
" from KOI8-R to UTF-8.");
|
||||
archive_write_free(a);
|
||||
return;
|
||||
}
|
||||
archive_write_free(a);
|
||||
|
||||
r = archive_mstring_update_utf8(NULL, &mstr, utf8_string);
|
||||
|
||||
|
|
|
|||
|
|
@ -880,6 +880,17 @@ DEFINE_TEST(test_entry)
|
|||
if (pst == NULL)
|
||||
return;
|
||||
assertEqualInt(pst->st_uid, 22);
|
||||
|
||||
/* Check behavior with large sizes. */
|
||||
archive_entry_set_size(e, INT64_MAX - 1);
|
||||
assert((pst = archive_entry_stat(e)) != NULL);
|
||||
if (pst == NULL)
|
||||
return;
|
||||
if (sizeof(pst->st_size) < sizeof(int64_t))
|
||||
assertEqualInt(pst->st_size, 0);
|
||||
else
|
||||
assertEqualInt(pst->st_size, INT64_MAX - 1);
|
||||
|
||||
/* We don't need to check high-res fields here. */
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@ DEFINE_TEST(test_read_filter_gzip_recursive)
|
|||
const char *name = "test_read_filter_gzip_recursive.gz";
|
||||
struct archive *a;
|
||||
|
||||
if (!canGzip()) {
|
||||
skipping("gzip not available");
|
||||
if (archive_zlib_version() == NULL) {
|
||||
skipping("zlib not available");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1285,19 +1285,26 @@ DEFINE_TEST(test_read_format_7zip_sfx_pe)
|
|||
const char test_txt[] = "123";
|
||||
int size = sizeof(test_txt) - 1;
|
||||
|
||||
extract_reference_file(reffile);
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertA(0 == archive_read_support_filter_all(a));
|
||||
assertA(0 == archive_read_support_format_all(a));
|
||||
assertA(0 == archive_read_open_filename(a, reffile, bs));
|
||||
|
||||
assertA(0 == archive_read_next_header(a, &ae));
|
||||
assertEqualString("test.txt.txt", archive_entry_pathname(ae));
|
||||
if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) {
|
||||
skipping(
|
||||
"7zip:lzma decoding is not supported on this platform");
|
||||
} else {
|
||||
extract_reference_file(reffile);
|
||||
assertA(0 == archive_read_support_filter_all(a));
|
||||
assertA(0 == archive_read_support_format_all(a));
|
||||
assertA(0 == archive_read_open_filename(a, reffile, bs));
|
||||
|
||||
assertA(size == archive_read_data(a, buff, size));
|
||||
assertEqualMem(buff, test_txt, size);
|
||||
assertA(0 == archive_read_next_header(a, &ae));
|
||||
assertEqualString("test.txt.txt", archive_entry_pathname(ae));
|
||||
|
||||
assertA(size == archive_read_data(a, buff, size));
|
||||
assertEqualMem(buff, test_txt, size);
|
||||
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
|
||||
}
|
||||
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
||||
}
|
||||
|
||||
|
|
@ -1316,19 +1323,26 @@ DEFINE_TEST(test_read_format_7zip_sfx_modified_pe)
|
|||
const char test_txt[] = "123";
|
||||
int size = sizeof(test_txt) - 1;
|
||||
|
||||
extract_reference_file(reffile);
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertA(0 == archive_read_support_filter_all(a));
|
||||
assertA(0 == archive_read_support_format_all(a));
|
||||
assertA(0 == archive_read_open_filename(a, reffile, bs));
|
||||
|
||||
assertA(0 == archive_read_next_header(a, &ae));
|
||||
assertEqualString("test.txt.txt", archive_entry_pathname(ae));
|
||||
if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) {
|
||||
skipping(
|
||||
"7zip:lzma decoding is not supported on this platform");
|
||||
} else {
|
||||
extract_reference_file(reffile);
|
||||
assertA(0 == archive_read_support_filter_all(a));
|
||||
assertA(0 == archive_read_support_format_all(a));
|
||||
assertA(0 == archive_read_open_filename(a, reffile, bs));
|
||||
|
||||
assertA(size == archive_read_data(a, buff, size));
|
||||
assertEqualMem(buff, test_txt, size);
|
||||
assertA(0 == archive_read_next_header(a, &ae));
|
||||
assertEqualString("test.txt.txt", archive_entry_pathname(ae));
|
||||
|
||||
assertA(size == archive_read_data(a, buff, size));
|
||||
assertEqualMem(buff, test_txt, size);
|
||||
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
|
||||
}
|
||||
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
||||
}
|
||||
|
||||
|
|
@ -1346,20 +1360,27 @@ DEFINE_TEST(test_read_format_7zip_sfx_elf)
|
|||
const char test_txt[] = "123";
|
||||
int size = sizeof(test_txt) - 1;
|
||||
|
||||
extract_reference_file(reffile);
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertA(0 == archive_read_support_filter_all(a));
|
||||
assertA(0 == archive_read_support_format_all(a));
|
||||
assertA(0 == archive_read_open_filename(a, reffile, bs));
|
||||
|
||||
assertA(0 == archive_read_next_header(a, &ae));
|
||||
assertEqualString("test.txt.txt", archive_entry_pathname(ae));
|
||||
if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) {
|
||||
skipping(
|
||||
"7zip:lzma decoding is not supported on this platform");
|
||||
} else {
|
||||
extract_reference_file(reffile);
|
||||
assertA(0 == archive_read_support_filter_all(a));
|
||||
assertA(0 == archive_read_support_format_all(a));
|
||||
assertA(0 == archive_read_open_filename(a, reffile, bs));
|
||||
|
||||
assertA(size == archive_read_data(a, buff, size));
|
||||
assertEqualMem(buff, test_txt, size);
|
||||
assertA(0 == archive_read_next_header(a, &ae));
|
||||
assertEqualString("test.txt.txt", archive_entry_pathname(ae));
|
||||
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
||||
assertA(size == archive_read_data(a, buff, size));
|
||||
assertEqualMem(buff, test_txt, size);
|
||||
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
|
||||
}
|
||||
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_read_format_7zip_extract_second)
|
||||
|
|
@ -1597,9 +1618,9 @@ DEFINE_TEST(test_read_format_7zip_lzma2_powerpc)
|
|||
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
|
||||
if (ARCHIVE_OK != archive_read_support_filter_gzip(a)) {
|
||||
if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) {
|
||||
skipping(
|
||||
"7zip:deflate decoding is not supported on this platform");
|
||||
"7zip:lzma decoding is not supported on this platform");
|
||||
} else {
|
||||
test_powerpc_filter("test_read_format_7zip_lzma2_powerpc.7z");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1111,6 +1111,18 @@ DEFINE_TEST(test_read_format_rar5_nonempty_dir_stream)
|
|||
EPILOGUE();
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_read_format_rar5_nonempty_dir_data)
|
||||
{
|
||||
PROLOGUE("test_read_format_rar5_dirdata.rar");
|
||||
|
||||
/* This archive is invalid. It declares a directory entry with nonzero
|
||||
data size. */
|
||||
|
||||
assertA(archive_read_next_header(a, &ae) == ARCHIVE_FATAL);
|
||||
|
||||
EPILOGUE();
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_read_format_rar5_fileattr)
|
||||
{
|
||||
unsigned long set, clear, flag;
|
||||
|
|
@ -1428,3 +1440,57 @@ DEFINE_TEST(test_read_format_rar5_data_ready_pointer_leak)
|
|||
|
||||
EPILOGUE();
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_read_format_rar5_only_crypt_exfld)
|
||||
{
|
||||
/* GH #2711 */
|
||||
|
||||
char buf[4096];
|
||||
PROLOGUE("test_read_format_rar5_only_crypt_exfld.rar");
|
||||
|
||||
/* The reader should allow iteration through files, but should fail
|
||||
during data extraction. */
|
||||
|
||||
assertA(archive_read_next_header(a, &ae) == ARCHIVE_OK);
|
||||
assertA(archive_read_data(a, buf, sizeof(buf)) == ARCHIVE_FATAL);
|
||||
|
||||
/* The reader should also provide a valid error message. */
|
||||
assertA(archive_error_string(a) != NULL);
|
||||
|
||||
EPILOGUE();
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_read_format_rar5_only_unsupported_exfld)
|
||||
{
|
||||
/* GH #2711 */
|
||||
|
||||
char buf[4096];
|
||||
PROLOGUE("test_read_format_rar5_unsupported_exfld.rar");
|
||||
|
||||
/* The reader should allow iteration through files, and it should
|
||||
succeed with data extraction. */
|
||||
|
||||
assertA(archive_read_next_header(a, &ae) == ARCHIVE_OK);
|
||||
|
||||
/* 48 is the expected number of bytes that should be extracted */
|
||||
assertA(archive_read_data(a, buf, sizeof(buf)) == 48);
|
||||
|
||||
EPILOGUE();
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_read_format_rar5_invalidhash_and_validhtime_exfld)
|
||||
{
|
||||
/* GH #2711 */
|
||||
|
||||
char buf[4096];
|
||||
PROLOGUE("test_read_format_rar5_invalid_hash_valid_htime_exfld.rar");
|
||||
|
||||
/* The reader should report an error when trying to process this data.
|
||||
Returning EOF here means that the reader has failed to identify
|
||||
malformed structure. */
|
||||
|
||||
assertA(archive_read_next_header(a, &ae) < 0);
|
||||
assertA(archive_read_data(a, buf, sizeof(buf)) < 0);
|
||||
|
||||
EPILOGUE();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
begin 644 -
|
||||
M4F%R(1H'`0`BD'[;,`$%,#8P`0&`@("``B?GD;$U`@(+@X``"_C5%:2#``(`
|
||||
M`#"``S`P,#`P,#`P,#!);S#6KA',@]:N$?*IN;YV[8"1S>?4^`,#`R,#`P,#
|
||||
-`P,#1)'C@XX*4`O.^P``
|
||||
`
|
||||
end
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
begin 644 -
|
||||
M4F%R(1H'`0`SDK7E"@$%!@`%`0&`@`#^T/5L)`(###$$,>V#`D840I@``0AF
|
||||
M:6QE+G1X=`@"OX0]``$"`P(#`&EN=F%L:60@2$%32"!E>'1R82P@86YD(&QA
|
||||
>=&5R(&$@=F%L:60@2%1)344@97AT<F$@/=^&`@4$
|
||||
`
|
||||
end
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
begin 644 -
|
||||
M4F%R(1H'`0`SDK7E"@$%!@`%`0&`@`"!0_"Y/0(#)2X$+NV#`IB>)!,``0AF
|
||||
M:6QE+G1X="0!```&``````````````````````````````````````````!R
|
||||
M87(U('-T;W)E9"!F:6QE('=I=&@@;VYL>2!A($-265!4(&5X=')A(&9I96QD
|
||||
'(#W?A@(%!```
|
||||
`
|
||||
end
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
begin 644 -
|
||||
M4F%R(1H'`0`SDK7E"@$%!@`%`0&`@`#>[JDS)@(##C`$,.V#`BX6Z[0``0AF
|
||||
M:6QE+G1X=`W_____#WA6-!(`````<F%R-2!S=&]R960@9FEL92!W:71H(&%N
|
||||
?('5N<W5P<&]R=&5D(&5X=')A(&9I96QD(#W?A@(%!```
|
||||
`
|
||||
end
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/*-
|
||||
* Copyright (c) 2025 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
|
||||
DEFINE_TEST(test_read_format_tar_V_negative_size)
|
||||
{
|
||||
/*
|
||||
* An archive that contains a `V` volume header with a negative body size
|
||||
*
|
||||
* This used to lead to an infinite loop: the tar reader would "advance"
|
||||
* by the size of the body to skip it, which would in this case end up
|
||||
* reversing back to the beginning of the same header.
|
||||
*/
|
||||
struct archive_entry *ae;
|
||||
struct archive *a;
|
||||
const char *refname = "test_read_format_tar_V_negative_size.tar";
|
||||
|
||||
extract_reference_file(refname);
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_support_filter_all(a));
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_support_format_all(a));
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240));
|
||||
assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae));
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
Tar archive with a single `V` header that has a negative size.
|
||||
This used to result in an infinite loop -- the tar reader would
|
||||
"advance" by the size of the header, which in this case just backed
|
||||
up to re-read the same header again.
|
||||
|
||||
begin 644 test_read_format_tar_V_negative_size.tar
|
||||
M`#(VXP```````````````````-Z;@"E&LOX^\@````````````!7````'```
|
||||
M````````````````````````````````````````````````````````````
|
||||
M``````````````````````````````````````````#___\````````@````
|
||||
M````````````````````````````5H%ZL#X]SH\-``":SN#[C4;Z5OOW-&']
|
||||
M?HHQ%WRG?Z$Q>^E#_1.OY96VEI*Z<U[)$TR502_;F$;9FU"/F'!`V:0`````
|
||||
M`````````````````````````````````````````````````````0``````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M`````````````````````````````0``````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
1````````````````````````
|
||||
`
|
||||
end
|
||||
|
|
@ -138,7 +138,10 @@ DEFINE_TEST(test_read_append_filter)
|
|||
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
||||
return;
|
||||
}
|
||||
assertEqualIntA(a, ARCHIVE_OK, r);
|
||||
if (r == ARCHIVE_WARN && canGzip())
|
||||
assertEqualString(archive_error_string(a), "Using external gzip program");
|
||||
else
|
||||
assertEqualIntA(a, ARCHIVE_OK, r);
|
||||
assertEqualInt(ARCHIVE_OK,
|
||||
archive_read_open_memory(a, archive, sizeof(archive)));
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_next_header(a, &ae));
|
||||
|
|
@ -210,7 +213,7 @@ DEFINE_TEST(test_read_append_filter_wrong_program)
|
|||
/*
|
||||
* If we have "bunzip2 -q", try using that.
|
||||
*/
|
||||
if (!canRunCommand("bunzip2 -h")) {
|
||||
if (!canRunCommand("bunzip2 -h", NULL)) {
|
||||
skipping("Can't run bunzip2 program on this platform");
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -267,6 +267,35 @@ DEFINE_TEST(test_write_filter_bzip2)
|
|||
assertEqualInt(ARCHIVE_OK, archive_write_close(a));
|
||||
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
|
||||
|
||||
/*
|
||||
* Test behavior after a fatal error (triggered by giving
|
||||
* archive_write_open_memory() a very small buffer).
|
||||
*/
|
||||
if (!use_prog) {
|
||||
used1 = 0;
|
||||
assert((a = archive_write_new()) != NULL);
|
||||
assertEqualIntA(a, ARCHIVE_OK,
|
||||
archive_write_set_format_ustar(a));
|
||||
assertEqualIntA(a, ARCHIVE_OK,
|
||||
archive_write_add_filter_bzip2(a));
|
||||
assertEqualIntA(a, ARCHIVE_OK,
|
||||
archive_write_open_memory(a, buff, 100, &used1));
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_set_filetype(ae, AE_IFREG);
|
||||
archive_entry_set_size(ae, 4000000);
|
||||
archive_entry_copy_pathname(ae, "file");
|
||||
assertEqualIntA(a, ARCHIVE_OK,
|
||||
archive_write_header(a, ae));
|
||||
for (i = 0; i < 1000000; i++) {
|
||||
r = archive_write_data(a, &i, 4);
|
||||
if (r == ARCHIVE_FATAL)
|
||||
break;
|
||||
}
|
||||
assertEqualIntA(a, ARCHIVE_FATAL, r);
|
||||
archive_entry_free(ae);
|
||||
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -166,9 +166,15 @@ DEFINE_TEST(test_write_filter_gzip)
|
|||
assertEqualInt(rbuff[0], 0x1f);
|
||||
assertEqualInt(rbuff[1], 0x8b);
|
||||
assertEqualInt(rbuff[2], 0x08);
|
||||
assertEqualInt(rbuff[3], 0x08);
|
||||
assertEqualInt(rbuff[8], 2); /* RFC 1952 flag for compression level 9 */
|
||||
assertEqualString((const char*)rbuff+10, "testorgfilename");
|
||||
/* RFC 1952 flag for compression level 9 */
|
||||
assertEqualInt(rbuff[8], 2);
|
||||
/* External gzip program might not save filename */
|
||||
if (!use_prog || rbuff[3] == 0x08) {
|
||||
assertEqualInt(rbuff[3], 0x08);
|
||||
assertEqualString((const char*)rbuff+10, "testorgfilename");
|
||||
} else {
|
||||
assertEqualInt(rbuff[3], 0x00);
|
||||
}
|
||||
|
||||
/* Curiously, this test fails; the test data above compresses
|
||||
* better at default compression than at level 9. */
|
||||
|
|
|
|||
|
|
@ -81,8 +81,11 @@ DEFINE_TEST(test_write_filter_gzip_timestamp)
|
|||
archive_entry_free(ae);
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
|
||||
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
|
||||
failure("Timestamp should be recorded");
|
||||
assert(memcmp(buff + 4, "\x00\x00\x00\x00", 4) != 0);
|
||||
/* External gzip program might not save timestamp */
|
||||
if (!use_prog) {
|
||||
failure("Timestamp should be recorded");
|
||||
assert(memcmp(buff + 4, "\x00\x00\x00\x00", 4) != 0);
|
||||
}
|
||||
|
||||
/* Test2: set "gzip:!timestamp" option. */
|
||||
assert((a = archive_write_new()) != NULL);
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "err.h"
|
||||
#include "lafe_err.h"
|
||||
|
||||
static void lafe_vwarnc(int, const char *, va_list) __LA_PRINTFLIKE(2, 0);
|
||||
|
||||
|
|
@ -31,7 +31,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "err.h"
|
||||
#include "lafe_err.h"
|
||||
#include "line_reader.h"
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__BORLANDC__)
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@
|
|||
#include <readpassphrase.h>
|
||||
#endif
|
||||
|
||||
#include "err.h"
|
||||
#include "lafe_err.h"
|
||||
#include "passphrase.h"
|
||||
|
||||
#ifndef HAVE_READPASSPHRASE
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@
|
|||
#endif
|
||||
|
||||
#include "bsdtar.h"
|
||||
#include "err.h"
|
||||
#include "lafe_err.h"
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000 && !defined(_PATH_DEFTAPE)
|
||||
// Libarchive 4.0 and later will NOT define _PATH_DEFTAPE
|
||||
|
|
@ -182,6 +182,11 @@ main(int argc, char **argv)
|
|||
/* Ignore SIGPIPE signals. */
|
||||
sa.sa_handler = SIG_IGN;
|
||||
sigaction(SIGPIPE, &sa, NULL);
|
||||
#endif
|
||||
#ifdef SIGCHLD
|
||||
/* Do not ignore SIGCHLD. */
|
||||
sa.sa_handler = SIG_DFL;
|
||||
sigaction(SIGCHLD, &sa, NULL);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -16,6 +16,12 @@
|
|||
#define ENV_WRITER_OPTIONS "TAR_WRITER_OPTIONS"
|
||||
#define IGNORE_WRONG_MODULE_NAME "__ignore_wrong_module_name__,"
|
||||
|
||||
#if defined(_MSC_VER ) && (_MSC_VER < 1927 ) /* Check if compiler pre-dated Visual Studio 2019 Release 16.8 */
|
||||
#define ARCHIVE_RESTRICT
|
||||
#else
|
||||
#define ARCHIVE_RESTRICT restrict
|
||||
#endif
|
||||
|
||||
struct creation_set;
|
||||
/*
|
||||
* The internal state for the "bsdtar" program.
|
||||
|
|
@ -188,7 +194,7 @@ int edit_pathname(struct bsdtar *, struct archive_entry *);
|
|||
void edit_mtime(struct bsdtar *, struct archive_entry *);
|
||||
int need_report(void);
|
||||
int pathcmp(const char *a, const char *b);
|
||||
void safe_fprintf(FILE * restrict, const char * restrict fmt, ...) __LA_PRINTF(2, 3);
|
||||
void safe_fprintf(FILE * ARCHIVE_RESTRICT, const char * ARCHIVE_RESTRICT fmt, ...) __LA_PRINTF(2, 3);
|
||||
void set_chdir(struct bsdtar *, const char *newdir);
|
||||
const char *tar_i64toa(int64_t);
|
||||
void tar_mode_c(struct bsdtar *bsdtar);
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
#endif
|
||||
|
||||
#include "bsdtar.h"
|
||||
#include "err.h"
|
||||
#include "lafe_err.h"
|
||||
|
||||
/*
|
||||
* Short options for tar. Please keep this sorted.
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
#endif
|
||||
|
||||
#include "bsdtar.h"
|
||||
#include "err.h"
|
||||
#include "lafe_err.h"
|
||||
|
||||
struct creation_set {
|
||||
char *create_format;
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@
|
|||
#endif
|
||||
|
||||
#include "bsdtar.h"
|
||||
#include "err.h"
|
||||
#include "lafe_err.h"
|
||||
|
||||
struct progress_data {
|
||||
struct bsdtar *bsdtar;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
#define REG_BASIC 0
|
||||
#endif
|
||||
|
||||
#include "err.h"
|
||||
#include "lafe_err.h"
|
||||
|
||||
struct subst_rule {
|
||||
struct subst_rule *next;
|
||||
|
|
|
|||
74
contrib/libarchive/tar/test/test_crlf_mtree.c
Normal file
74
contrib/libarchive/tar/test/test_crlf_mtree.c
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2018 The FreeBSD Foundation
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by Arshan Khanifar <arshankhanifar@gmail.com>
|
||||
* under sponsorship from the FreeBSD Foundation.
|
||||
*/
|
||||
#include "test.h"
|
||||
|
||||
DEFINE_TEST(test_crlf_mtree)
|
||||
{
|
||||
char *p0;
|
||||
size_t s;
|
||||
int r;
|
||||
p0 = NULL;
|
||||
char *content = "#mtree\r\n"
|
||||
"f type=file uname=\\\r\n"
|
||||
"root gname=root mode=0755 content=bar/foo\r\n"
|
||||
"g type=file uname=root gname=root mode=0755 content=bar/goo\r\n";
|
||||
char *filename = "output.tar";
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
char *p;
|
||||
#endif
|
||||
|
||||
/* an absolute path to mtree file */
|
||||
char *mtree_file = "/METALOG.mtree";
|
||||
char *absolute_path = malloc(strlen(testworkdir) + strlen(mtree_file) + 1);
|
||||
strcpy(absolute_path, testworkdir);
|
||||
strcat(absolute_path, mtree_file );
|
||||
|
||||
/* Create an archive using an mtree file. */
|
||||
assertMakeFile(absolute_path, 0777, content);
|
||||
assertMakeDir("bar", 0775);
|
||||
assertMakeFile("bar/foo", 0777, "abc");
|
||||
assertMakeFile("bar/goo", 0777, "abc");
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
p = absolute_path;
|
||||
while(*p != '\0') {
|
||||
if (*p == '/')
|
||||
*p = '\\';
|
||||
p++;
|
||||
}
|
||||
|
||||
r = systemf("%s -cf %s @%s >step1.out 2>step1.err", testprog, filename, absolute_path);
|
||||
failure("Error invoking %s -cf %s -C bar @%s", testprog, filename, absolute_path);
|
||||
#else
|
||||
r = systemf("%s -cf %s \"@%s\" >step1.out 2>step1.err", testprog, filename, absolute_path);
|
||||
failure("Error invoking %s -cf %s -C bar \"@%s\"", testprog, filename, absolute_path);
|
||||
#endif
|
||||
|
||||
assertEqualInt(r, 0);
|
||||
assertEmptyFile("step1.out");
|
||||
assertEmptyFile("step1.err");
|
||||
|
||||
/* Do validation of the constructed archive. */
|
||||
|
||||
p0 = slurpfile(&s, "output.tar");
|
||||
if (!assert(p0 != NULL))
|
||||
goto done;
|
||||
if (!assert(s >= 2048))
|
||||
goto done;
|
||||
assertEqualMem(p0 + 0, "f", 2);
|
||||
assertEqualMem(p0 + 512, "abc", 4);
|
||||
assertEqualMem(p0 + 1024, "g", 2);
|
||||
assertEqualMem(p0 + 1536, "abc", 4);
|
||||
done:
|
||||
free(p0);
|
||||
free(absolute_path);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -16,11 +16,12 @@ DEFINE_TEST(test_option_safe_writes)
|
|||
assertMakeFile("d", 0644, "c");
|
||||
assertMakeFile("fs", 0644, "d");
|
||||
assertMakeFile("ds", 0644, "e");
|
||||
assertMakeDir("fd", 0755);
|
||||
assertEqualInt(0, chdir(".."));
|
||||
|
||||
/* Tar files up */
|
||||
assertEqualInt(0,
|
||||
systemf("%s -c -C in -f t.tar f fh d fs ds "
|
||||
systemf("%s -c -C in -f t.tar f fh d fs ds fd "
|
||||
">pack.out 2>pack.err", testprog));
|
||||
|
||||
/* Verify that nothing went to stdout or stderr. */
|
||||
|
|
@ -32,6 +33,7 @@ DEFINE_TEST(test_option_safe_writes)
|
|||
assertEqualInt(0, chdir("out"));
|
||||
assertMakeFile("f", 0644, "a");
|
||||
assertMakeHardlink("fh", "f");
|
||||
assertMakeFile("fd", 0644, "b");
|
||||
assertMakeDir("d", 0755);
|
||||
if (canSymlink()) {
|
||||
assertMakeSymlink("fs", "f", 0);
|
||||
|
|
@ -55,4 +57,5 @@ DEFINE_TEST(test_option_safe_writes)
|
|||
assertTextFileContents("c","d");
|
||||
assertTextFileContents("d","fs");
|
||||
assertTextFileContents("e","ds");
|
||||
assertIsDir("fd", 0755);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
#endif
|
||||
|
||||
#include "bsdtar.h"
|
||||
#include "err.h"
|
||||
#include "lafe_err.h"
|
||||
#include "passphrase.h"
|
||||
|
||||
static size_t bsdtar_expand_char(char *, size_t, size_t, char);
|
||||
|
|
@ -682,6 +682,7 @@ list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry)
|
|||
{
|
||||
char tmp[100];
|
||||
size_t w;
|
||||
size_t sw;
|
||||
const char *p;
|
||||
const char *fmt;
|
||||
time_t tim;
|
||||
|
|
@ -769,8 +770,8 @@ list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry)
|
|||
ltime = localtime(&tim);
|
||||
#endif
|
||||
if (ltime)
|
||||
strftime(tmp, sizeof(tmp), fmt, ltime);
|
||||
else
|
||||
sw = strftime(tmp, sizeof(tmp), fmt, ltime);
|
||||
if (!ltime || !sw)
|
||||
sprintf(tmp, "-- -- ----");
|
||||
fprintf(out, " %s ", tmp);
|
||||
safe_fprintf(out, "%s", archive_entry_pathname(entry));
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@
|
|||
#endif
|
||||
|
||||
#include "bsdtar.h"
|
||||
#include "err.h"
|
||||
#include "lafe_err.h"
|
||||
#include "line_reader.h"
|
||||
|
||||
#ifndef O_BINARY
|
||||
|
|
@ -111,7 +111,32 @@ seek_file(int fd, int64_t offset, int whence)
|
|||
return (SetFilePointerEx((HANDLE)_get_osfhandle(fd),
|
||||
distance, NULL, FILE_BEGIN) ? 1 : -1);
|
||||
}
|
||||
#define open _open
|
||||
|
||||
static int
|
||||
_open_wrap_sopen(char const *const path, int const oflag, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int r, pmode;
|
||||
|
||||
pmode = 0;
|
||||
if (oflag & _O_CREAT)
|
||||
{
|
||||
va_start(ap, oflag);
|
||||
pmode = va_arg(ap, int);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
_sopen_s(&r, path, oflag, _SH_DENYNO, pmode & 0600);
|
||||
if (r < 0)
|
||||
{
|
||||
/* _sopen_s populates errno */
|
||||
return -1;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
#define open _open_wrap_sopen
|
||||
#define close _close
|
||||
#define read _read
|
||||
#ifdef lseek
|
||||
|
|
|
|||
|
|
@ -340,8 +340,14 @@ int canGrzip(void);
|
|||
/* Return true if this platform can run the "gzip" program. */
|
||||
int canGzip(void);
|
||||
|
||||
/* Return true if this platform can run the specified command. */
|
||||
int canRunCommand(const char *);
|
||||
/* Return true if this platform can run the specified command.
|
||||
*
|
||||
* Result can be optionally cached with `*tested`:
|
||||
* - 0 if not tested yet
|
||||
* - <0 if already tested negative
|
||||
* - >0 if already tested positive
|
||||
*/
|
||||
int canRunCommand(const char *cmd, int *tested);
|
||||
|
||||
/* Return true if this platform can run the "lrzip" program. */
|
||||
int canLrzip(void);
|
||||
|
|
|
|||
|
|
@ -2523,167 +2523,77 @@ static const char *redirectArgs = ">NUL 2>NUL"; /* Win32 cmd.exe */
|
|||
#else
|
||||
static const char *redirectArgs = ">/dev/null 2>/dev/null"; /* POSIX 'sh' */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Can this platform run the specified command?
|
||||
*/
|
||||
int
|
||||
canRunCommand(const char *cmd, int *tested)
|
||||
{
|
||||
int value = tested ? *tested : 0;
|
||||
if (!value) {
|
||||
value = systemf("%s %s", cmd, redirectArgs) ? -1 : +1;
|
||||
if (tested)
|
||||
*tested = value;
|
||||
}
|
||||
return (value > 0);
|
||||
}
|
||||
|
||||
#define CAN_RUN_FUNC(Program, Command) \
|
||||
int can##Program(void) { \
|
||||
static int tested = 0; \
|
||||
return canRunCommand((Command), &tested); \
|
||||
}
|
||||
|
||||
/*
|
||||
* Can this platform run the bzip2 program?
|
||||
*/
|
||||
int
|
||||
canBzip2(void)
|
||||
{
|
||||
static int tested = 0, value = 0;
|
||||
if (!tested) {
|
||||
tested = 1;
|
||||
if (systemf("bzip2 --help %s", redirectArgs) == 0)
|
||||
value = 1;
|
||||
}
|
||||
return (value);
|
||||
}
|
||||
CAN_RUN_FUNC(Bzip2, "bzip2 --help")
|
||||
|
||||
/*
|
||||
* Can this platform run the grzip program?
|
||||
*/
|
||||
int
|
||||
canGrzip(void)
|
||||
{
|
||||
static int tested = 0, value = 0;
|
||||
if (!tested) {
|
||||
tested = 1;
|
||||
if (systemf("grzip -V %s", redirectArgs) == 0)
|
||||
value = 1;
|
||||
}
|
||||
return (value);
|
||||
}
|
||||
CAN_RUN_FUNC(Grzip, "grzip -V")
|
||||
|
||||
/*
|
||||
* Can this platform run the gzip program?
|
||||
*/
|
||||
int
|
||||
canGzip(void)
|
||||
{
|
||||
static int tested = 0, value = 0;
|
||||
if (!tested) {
|
||||
tested = 1;
|
||||
if (systemf("gzip --help %s", redirectArgs) == 0)
|
||||
value = 1;
|
||||
}
|
||||
return (value);
|
||||
}
|
||||
CAN_RUN_FUNC(Gzip, "gzip --help")
|
||||
|
||||
/*
|
||||
* Can this platform run the lrzip program?
|
||||
*/
|
||||
int
|
||||
canRunCommand(const char *cmd)
|
||||
{
|
||||
static int tested = 0, value = 0;
|
||||
if (!tested) {
|
||||
tested = 1;
|
||||
if (systemf("%s %s", cmd, redirectArgs) == 0)
|
||||
value = 1;
|
||||
}
|
||||
return (value);
|
||||
}
|
||||
|
||||
int
|
||||
canLrzip(void)
|
||||
{
|
||||
static int tested = 0, value = 0;
|
||||
if (!tested) {
|
||||
tested = 1;
|
||||
if (systemf("lrzip -V %s", redirectArgs) == 0)
|
||||
value = 1;
|
||||
}
|
||||
return (value);
|
||||
}
|
||||
CAN_RUN_FUNC(Lrzip, "lrzip -V")
|
||||
|
||||
/*
|
||||
* Can this platform run the lz4 program?
|
||||
*/
|
||||
int
|
||||
canLz4(void)
|
||||
{
|
||||
static int tested = 0, value = 0;
|
||||
if (!tested) {
|
||||
tested = 1;
|
||||
if (systemf("lz4 --help %s", redirectArgs) == 0)
|
||||
value = 1;
|
||||
}
|
||||
return (value);
|
||||
}
|
||||
CAN_RUN_FUNC(Lz4, "lz4 --help")
|
||||
|
||||
/*
|
||||
* Can this platform run the zstd program?
|
||||
*/
|
||||
int
|
||||
canZstd(void)
|
||||
{
|
||||
static int tested = 0, value = 0;
|
||||
if (!tested) {
|
||||
tested = 1;
|
||||
if (systemf("zstd --help %s", redirectArgs) == 0)
|
||||
value = 1;
|
||||
}
|
||||
return (value);
|
||||
}
|
||||
CAN_RUN_FUNC(Zstd, "zstd --help")
|
||||
|
||||
/*
|
||||
* Can this platform run the lzip program?
|
||||
*/
|
||||
int
|
||||
canLzip(void)
|
||||
{
|
||||
static int tested = 0, value = 0;
|
||||
if (!tested) {
|
||||
tested = 1;
|
||||
if (systemf("lzip --help %s", redirectArgs) == 0)
|
||||
value = 1;
|
||||
}
|
||||
return (value);
|
||||
}
|
||||
CAN_RUN_FUNC(Lzip, "lzip --help")
|
||||
|
||||
/*
|
||||
* Can this platform run the lzma program?
|
||||
*/
|
||||
int
|
||||
canLzma(void)
|
||||
{
|
||||
static int tested = 0, value = 0;
|
||||
if (!tested) {
|
||||
tested = 1;
|
||||
if (systemf("lzma --help %s", redirectArgs) == 0)
|
||||
value = 1;
|
||||
}
|
||||
return (value);
|
||||
}
|
||||
CAN_RUN_FUNC(Lzma, "lzma --help")
|
||||
|
||||
/*
|
||||
* Can this platform run the lzop program?
|
||||
*/
|
||||
int
|
||||
canLzop(void)
|
||||
{
|
||||
static int tested = 0, value = 0;
|
||||
if (!tested) {
|
||||
tested = 1;
|
||||
if (systemf("lzop --help %s", redirectArgs) == 0)
|
||||
value = 1;
|
||||
}
|
||||
return (value);
|
||||
}
|
||||
CAN_RUN_FUNC(Lzop, "lzop --help")
|
||||
|
||||
/*
|
||||
* Can this platform run the xz program?
|
||||
*/
|
||||
int
|
||||
canXz(void)
|
||||
{
|
||||
static int tested = 0, value = 0;
|
||||
if (!tested) {
|
||||
tested = 1;
|
||||
if (systemf("xz --help %s", redirectArgs) == 0)
|
||||
value = 1;
|
||||
}
|
||||
return (value);
|
||||
}
|
||||
CAN_RUN_FUNC(Xz, "xz --help")
|
||||
|
||||
/*
|
||||
* Can this filesystem handle nodump flags.
|
||||
|
|
@ -4184,6 +4094,9 @@ main(int argc, char **argv)
|
|||
if (testprogfile == NULL)
|
||||
{
|
||||
tmp2_len = strlen(testprogdir) + 1 + strlen(PROGRAM) + 1;
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
tmp2_len += 4;
|
||||
#endif
|
||||
if ((tmp2 = malloc(tmp2_len)) == NULL)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Out of memory.");
|
||||
|
|
@ -4192,6 +4105,9 @@ main(int argc, char **argv)
|
|||
strncpy(tmp2, testprogdir, tmp2_len);
|
||||
strncat(tmp2, "/", tmp2_len);
|
||||
strncat(tmp2, PROGRAM, tmp2_len);
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
strncat(tmp2, ".exe", tmp2_len);
|
||||
#endif
|
||||
testprogfile = tmp2;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@
|
|||
#ifdef HAVE_LOCALE_H
|
||||
#include <locale.h>
|
||||
#endif
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDARG_H
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
|
|
@ -54,7 +57,7 @@
|
|||
|
||||
#include "bsdunzip.h"
|
||||
#include "passphrase.h"
|
||||
#include "err.h"
|
||||
#include "lafe_err.h"
|
||||
|
||||
/* command-line options */
|
||||
static int a_opt; /* convert EOL */
|
||||
|
|
@ -1187,6 +1190,16 @@ main(int argc, char *argv[])
|
|||
const char *zipfile;
|
||||
int nopts;
|
||||
|
||||
#if defined(HAVE_SIGACTION) && defined(SIGCHLD)
|
||||
{ /* Do not ignore SIGCHLD. */
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = SIG_DFL;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
sigaction(SIGCHLD, &sa, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
lafe_setprogname(*argv, "bsdunzip");
|
||||
|
||||
#if HAVE_SETLOCALE
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
#endif
|
||||
|
||||
#include "bsdunzip.h"
|
||||
#include "err.h"
|
||||
#include "lafe_err.h"
|
||||
|
||||
/*
|
||||
* Short options for bsdunzip. Please keep this sorted.
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
/* Test C arg - match case-insensitive */
|
||||
DEFINE_TEST(test_C)
|
||||
{
|
||||
#ifdef HAVE_LIBZ
|
||||
const char *reffile = "test_basic.zip";
|
||||
int r;
|
||||
|
||||
|
|
@ -19,4 +20,7 @@ DEFINE_TEST(test_C)
|
|||
assertEmptyFile("test.err");
|
||||
|
||||
assertTextFileContents("contents CAPS\n", "test_basic/CAPS");
|
||||
#else
|
||||
skipping("zlib not available");
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
/* Test L arg - make names lowercase */
|
||||
DEFINE_TEST(test_L)
|
||||
{
|
||||
#ifdef HAVE_LIBZ
|
||||
const char *reffile = "test_basic.zip";
|
||||
int r;
|
||||
|
||||
|
|
@ -22,4 +23,7 @@ DEFINE_TEST(test_L)
|
|||
assertTextFileContents("contents b\n", "test_basic/b");
|
||||
assertTextFileContents("contents c\n", "test_basic/c");
|
||||
assertTextFileContents("contents CAPS\n", "test_basic/caps");
|
||||
#else
|
||||
skipping("zlib not available");
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,9 +14,13 @@ DEFINE_TEST(test_P_encryption)
|
|||
|
||||
extract_reference_file(reffile);
|
||||
r = systemf("%s -P password %s >test.out 2>test.err", testprog, reffile);
|
||||
assertEqualInt(0, r);
|
||||
assertNonEmptyFile("test.out");
|
||||
assertEmptyFile("test.err");
|
||||
if (r == 256) {
|
||||
assertTextFileContents("unzip: Decryption is unsupported due to lack of crypto library\n", "test.err");
|
||||
} else {
|
||||
assertEqualInt(0, r);
|
||||
assertNonEmptyFile("test.out");
|
||||
assertEmptyFile("test.err");
|
||||
|
||||
assertTextFileContents("plaintext\n", "encrypted/file.txt");
|
||||
assertTextFileContents("plaintext\n", "encrypted/file.txt");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
/* This test just does a basic zip decompression */
|
||||
DEFINE_TEST(test_basic)
|
||||
{
|
||||
#ifdef HAVE_LIBZ
|
||||
const char *reffile = "test_basic.zip";
|
||||
int r;
|
||||
|
||||
|
|
@ -22,4 +23,7 @@ DEFINE_TEST(test_basic)
|
|||
assertTextFileContents("contents b\n", "test_basic/b");
|
||||
assertTextFileContents("contents c\n", "test_basic/c");
|
||||
assertTextFileContents("contents CAPS\n", "test_basic/CAPS");
|
||||
#else
|
||||
skipping("zlib not available");
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
/* Test d arg - extract to target dir - before zipfile argument */
|
||||
DEFINE_TEST(test_d_before_zipfile)
|
||||
{
|
||||
#ifdef HAVE_LIBZ
|
||||
const char *reffile = "test_basic.zip";
|
||||
int r;
|
||||
|
||||
|
|
@ -22,11 +23,15 @@ DEFINE_TEST(test_d_before_zipfile)
|
|||
assertTextFileContents("contents b\n", "foobar/test_basic/b");
|
||||
assertTextFileContents("contents c\n", "foobar/test_basic/c");
|
||||
assertTextFileContents("contents CAPS\n", "foobar/test_basic/CAPS");
|
||||
#else
|
||||
skipping("zlib not available");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Test d arg - extract to target dir - after zipfile argument */
|
||||
DEFINE_TEST(test_d_after_zipfile)
|
||||
{
|
||||
#ifdef HAVE_LIBZ
|
||||
const char *reffile = "test_basic.zip";
|
||||
int r;
|
||||
|
||||
|
|
@ -40,4 +45,7 @@ DEFINE_TEST(test_d_after_zipfile)
|
|||
assertTextFileContents("contents b\n", "foobar/test_basic/b");
|
||||
assertTextFileContents("contents c\n", "foobar/test_basic/c");
|
||||
assertTextFileContents("contents CAPS\n", "foobar/test_basic/CAPS");
|
||||
#else
|
||||
skipping("zlib not available");
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
/* Test double dash arg - swallow "--" and use next argument as file name */
|
||||
DEFINE_TEST(test_doubledash)
|
||||
{
|
||||
#ifdef HAVE_LIBZ
|
||||
const char *reffile = "test_basic.zip";
|
||||
int r;
|
||||
|
||||
|
|
@ -22,4 +23,7 @@ DEFINE_TEST(test_doubledash)
|
|||
assertTextFileContents("contents b\n", "test_basic/b");
|
||||
assertTextFileContents("contents c\n", "test_basic/c");
|
||||
assertTextFileContents("contents CAPS\n", "test_basic/CAPS");
|
||||
#else
|
||||
skipping("zlib not available");
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
/* Test that the glob works */
|
||||
DEFINE_TEST(test_glob)
|
||||
{
|
||||
#ifdef HAVE_LIBZ
|
||||
const char *reffile = "test_basic.zip";
|
||||
int r;
|
||||
|
||||
|
|
@ -22,4 +23,7 @@ DEFINE_TEST(test_glob)
|
|||
assertTextFileContents("contents b\n", "test_basic/b");
|
||||
assertFileNotExists("test_basic/c");
|
||||
assertFileNotExists("test_basic/CAPS");
|
||||
#else
|
||||
skipping("zlib not available");
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
/* Test j arg - don't make directories */
|
||||
DEFINE_TEST(test_j)
|
||||
{
|
||||
#ifdef HAVE_LIBZ
|
||||
const char *reffile = "test_basic.zip";
|
||||
int r;
|
||||
|
||||
|
|
@ -22,4 +23,7 @@ DEFINE_TEST(test_j)
|
|||
assertTextFileContents("contents b\n", "b");
|
||||
assertTextFileContents("contents c\n", "c");
|
||||
assertTextFileContents("contents CAPS\n", "CAPS");
|
||||
#else
|
||||
skipping("zlib not available");
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
/* Test n arg - don't overwrite existing files */
|
||||
DEFINE_TEST(test_n)
|
||||
{
|
||||
#ifdef HAVE_LIBZ
|
||||
const char *reffile = "test_basic.zip";
|
||||
int r;
|
||||
|
||||
|
|
@ -26,4 +27,7 @@ DEFINE_TEST(test_n)
|
|||
assertTextFileContents("orig b\n", "test_basic/b");
|
||||
assertTextFileContents("contents c\n", "test_basic/c");
|
||||
assertTextFileContents("contents CAPS\n", "test_basic/CAPS");
|
||||
#else
|
||||
skipping("zlib not available");
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
/* Test o arg - overwrite existing files */
|
||||
DEFINE_TEST(test_o)
|
||||
{
|
||||
#ifdef HAVE_LIBZ
|
||||
const char *reffile = "test_basic.zip";
|
||||
int r;
|
||||
|
||||
|
|
@ -25,4 +26,7 @@ DEFINE_TEST(test_o)
|
|||
assertTextFileContents("contents b\n", "test_basic/b");
|
||||
assertTextFileContents("contents c\n", "test_basic/c");
|
||||
assertTextFileContents("contents CAPS\n", "test_basic/CAPS");
|
||||
#else
|
||||
skipping("zlib not available");
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
/* Test p arg - Print to stdout */
|
||||
DEFINE_TEST(test_p)
|
||||
{
|
||||
#ifdef HAVE_LIBZ
|
||||
const char *reffile = "test_basic.zip";
|
||||
int r;
|
||||
|
||||
|
|
@ -17,4 +18,7 @@ DEFINE_TEST(test_p)
|
|||
assertEqualInt(0, r);
|
||||
assertTextFileContents("contents a\ncontents b\ncontents c\ncontents CAPS\n", "test.out");
|
||||
assertEmptyFile("test.err");
|
||||
#else
|
||||
skipping("zlib not available");
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue