Merge branch 'upstream-LibArchive' into update-libarchive

* upstream-LibArchive:
  LibArchive 2026-10-30 (03036ffa)
This commit is contained in:
Brad King committed 2026-10-30 17:39:33 -04:00
commit e34b57cfa3
35 files changed
+463 -273

No files matched your search

-1
View File
@@ -811,7 +811,6 @@ LA_CHECK_INCLUDE_FILE("intsafe.h" HAVE_INTSAFE_H)
LA_CHECK_INCLUDE_FILE("linux/magic.h" HAVE_LINUX_MAGIC_H)
LA_CHECK_INCLUDE_FILE("locale.h" HAVE_LOCALE_H)
LA_CHECK_INCLUDE_FILE("membership.h" HAVE_MEMBERSHIP_H)
LA_CHECK_INCLUDE_FILE("memory.h" HAVE_MEMORY_H)
LA_CHECK_INCLUDE_FILE("paths.h" HAVE_PATHS_H)
LA_CHECK_INCLUDE_FILE("poll.h" HAVE_POLL_H)
LA_CHECK_INCLUDE_FILE("process.h" HAVE_PROCESS_H)
@@ -1,5 +1,4 @@
/* config.h. Generated from build/cmake/config.h.in by cmake configure */
#define __LIBARCHIVE_CONFIG_H_INCLUDED 1
#if defined(__osf__)
# define _OSF_SOURCE
#endif
@@ -709,9 +708,6 @@
/* Define to 1 if you have the 'memset_explicit' function. */
#cmakedefine HAVE_MEMSET_EXPLICIT 1
/* Define to 1 if you have the <memory.h> header file. */
#cmakedefine HAVE_MEMORY_H 1
/* Define to 1 if you have the 'mkdir' function. */
#cmakedefine HAVE_MKDIR 1
+1 -1
View File
@@ -1 +1 @@
3008010
3008011
+4 -2
View File
@@ -34,7 +34,7 @@
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
*/
/* Note: Compiler will complain if this does not match archive_entry.h! */
#define ARCHIVE_VERSION_NUMBER 3008010
#define ARCHIVE_VERSION_NUMBER 3008011
#include <sys/stat.h>
#include <stddef.h> /* for wchar_t */
@@ -174,7 +174,7 @@ __LA_DECL int archive_version_number(void);
/*
* Textual name/version of the library, useful for version displays.
*/
#define ARCHIVE_VERSION_ONLY_STRING "3.8.10"
#define ARCHIVE_VERSION_ONLY_STRING "3.8.11"
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
__LA_DECL const char * archive_version_string(void);
@@ -320,6 +320,7 @@ typedef const char *archive_passphrase_callback(struct archive *,
#define ARCHIVE_FILTER_GRZIP 12
#define ARCHIVE_FILTER_LZ4 13
#define ARCHIVE_FILTER_ZSTD 14
#define ARCHIVE_FILTER_B64 15
#if ARCHIVE_VERSION_NUMBER < 4000000
#define ARCHIVE_COMPRESSION_NONE ARCHIVE_FILTER_NONE
@@ -333,6 +334,7 @@ typedef const char *archive_passphrase_callback(struct archive *,
#define ARCHIVE_COMPRESSION_RPM ARCHIVE_FILTER_RPM
#define ARCHIVE_COMPRESSION_LZIP ARCHIVE_FILTER_LZIP
#define ARCHIVE_COMPRESSION_LRZIP ARCHIVE_FILTER_LRZIP
#define ARCHIVE_COMPRESSION_B64 ARCHIVE_FILTER_B64
#endif
/*
@@ -30,9 +30,6 @@
#ifndef __LIBARCHIVE_BUILD
#error This header is only to be used internally to libarchive.
#endif
#ifndef __LIBARCHIVE_CONFIG_H_INCLUDED
#error "Should have include config.h first!"
#endif
/*
* Crypto support in various Operating Systems:
@@ -28,7 +28,7 @@
#define ARCHIVE_ENTRY_H_INCLUDED
/* Note: Compiler will complain if this does not match archive.h! */
#define ARCHIVE_VERSION_NUMBER 3008010
#define ARCHIVE_VERSION_NUMBER 3008011
/*
* Note: archive_entry.h is for use outside of libarchive; the
@@ -378,7 +378,7 @@ archive_read_set_callback_data2(struct archive *_a, void *client_data,
return ARCHIVE_FATAL;
}
a->client.dataset[iindex].data = client_data;
a->client.dataset[iindex].begin_position = -1;
a->client.dataset[iindex].begin_position = 0;
a->client.dataset[iindex].total_size = -1;
return ARCHIVE_OK;
}
@@ -422,11 +422,11 @@ archive_read_add_callback_data(struct archive *_a, void *client_data,
for (i = a->client.nodes - 1; i > iindex; i--) {
a->client.dataset[i].data = a->client.dataset[i-1].data;
a->client.dataset[i].begin_position = -1;
a->client.dataset[i].begin_position = 0;
a->client.dataset[i].total_size = -1;
}
a->client.dataset[iindex].data = client_data;
a->client.dataset[iindex].begin_position = -1;
a->client.dataset[iindex].begin_position = 0;
a->client.dataset[iindex].total_size = -1;
return ARCHIVE_OK;
}
@@ -454,7 +454,7 @@ int
archive_read_open1(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
struct archive_read_filter *f, *tmp;
struct archive_read_filter *f;
int slot, e = ARCHIVE_OK;
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
@@ -510,11 +510,41 @@ archive_read_open1(struct archive *_a)
}
else
{
size_t count;
struct archive_read_filter *f2;
/* Need to add "NONE" type filter at the end of the filter chain */
tmp = a->filter;
while (tmp->upstream)
tmp = tmp->upstream;
tmp->upstream = f;
count = 1;
for (f2 = a->filter; f2->upstream != NULL; f2 = f2->upstream)
count++;
f2->upstream = f;
while (count-- > 0) {
struct archive_read_filter_bidder *bidder;
size_t i;
int r;
f2 = a->filter;
for (i = 0; i < count; i++)
f2 = f2->upstream;
bidder = f2->bidder;
r = (bidder->vtable->bid)(bidder, f2->upstream);
if (r < 0) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Registered filter does not match");
close_filters(a);
a->archive.state = ARCHIVE_STATE_FATAL;
return (ARCHIVE_FATAL);
}
r = (bidder->vtable->init)(f2);
if (r != ARCHIVE_OK) {
close_filters(a);
a->archive.state = ARCHIVE_STATE_FATAL;
return (ARCHIVE_FATAL);
}
}
}
if (!a->format)
@@ -541,8 +571,6 @@ archive_read_open1(struct archive *_a)
a->archive.state = ARCHIVE_STATE_HEADER;
/* Ensure libarchive starts from the first node in a multivolume set */
client_switch_proxy(f, 0);
return (e);
}
@@ -1692,6 +1720,44 @@ advance_file_pointer(struct archive_read_filter *f, int64_t request)
}
}
static int64_t
get_archive_size(struct archive_read_filter *f)
{
struct archive_read_client *client = &(f->archive->client);
int64_t size;
unsigned int cursor;
/* Try to calculate size without switching client objects. */
size = 0;
for (cursor = 0; cursor < client->nodes; cursor++) {
int64_t total_size = client->dataset[cursor].total_size;
if (total_size < 0)
break;
if (archive_ckd_add_i64(&size, size, total_size))
return (ARCHIVE_FATAL);
}
/* Seek through remaining client objects to calculate size. */
for (; cursor < client->nodes; cursor++) {
int64_t r;
client->dataset[cursor].begin_position = size;
r = client_switch_proxy(f, cursor);
if (r != ARCHIVE_OK)
return (r);
r = client_seek_proxy(f, 0, SEEK_END);
if (r < 0)
return (r);
client->dataset[cursor].total_size = r;
if (archive_ckd_add_i64(&size, size, r))
return (ARCHIVE_FATAL);
f->position = size;
}
return (size);
}
/**
* Returns ARCHIVE_FAILED if seeking isn't supported.
*/
@@ -1706,9 +1772,8 @@ __archive_read_filter_seek(struct archive_read_filter *f, int64_t offset,
int whence)
{
struct archive_read_client *client;
int64_t r;
int64_t old_position, r;
unsigned int cursor, old_cursor;
int sought = 0;
if (f->closed || f->fatal)
return (ARCHIVE_FATAL);
@@ -1717,6 +1782,7 @@ __archive_read_filter_seek(struct archive_read_filter *f, int64_t offset,
client = &(f->archive->client);
old_cursor = client->cursor;
old_position = f->position;
switch (whence) {
case SEEK_CUR:
@@ -1727,8 +1793,7 @@ __archive_read_filter_seek(struct archive_read_filter *f, int64_t offset,
cursor = 0;
while (1)
{
if (client->dataset[cursor].begin_position < 0 ||
client->dataset[cursor].total_size < 0 ||
if (client->dataset[cursor].total_size < 0 ||
client->dataset[cursor].begin_position +
client->dataset[cursor].total_size > offset ||
cursor + 1 >= client->nodes)
@@ -1741,10 +1806,14 @@ __archive_read_filter_seek(struct archive_read_filter *f, int64_t offset,
r = client_switch_proxy(f, cursor);
if (r != ARCHIVE_OK)
goto clear_buffer;
if ((r = client_seek_proxy(f, 0, SEEK_END)) < 0)
goto clear_buffer;
sought = 1;
client->dataset[cursor].total_size = r;
if (client->dataset[cursor].total_size < 0) {
if ((r = client_seek_proxy(f,
0, SEEK_END)) < 0)
goto clear_buffer;
client->dataset[cursor].total_size = r;
f->position = r +
client->dataset[cursor].begin_position;
}
if (client->dataset[cursor].begin_position +
client->dataset[cursor].total_size > offset ||
cursor + 1 >= client->nodes)
@@ -1761,34 +1830,13 @@ __archive_read_filter_seek(struct archive_read_filter *f, int64_t offset,
}
if ((r = client_seek_proxy(f, offset, SEEK_SET)) < 0)
goto clear_buffer;
sought = 1;
break;
case SEEK_END:
cursor = 0;
while (1) {
if (client->dataset[cursor].begin_position < 0 ||
client->dataset[cursor].total_size < 0 ||
cursor + 1 >= client->nodes)
break;
r = client->dataset[cursor].begin_position +
client->dataset[cursor].total_size;
client->dataset[++cursor].begin_position = r;
}
while (1) {
r = client_switch_proxy(f, cursor);
if (r != ARCHIVE_OK)
goto clear_buffer;
if ((r = client_seek_proxy(f, 0, SEEK_END)) < 0)
goto clear_buffer;
sought = 1;
client->dataset[cursor].total_size = r;
r = client->dataset[cursor].begin_position +
client->dataset[cursor].total_size;
if (cursor + 1 >= client->nodes)
break;
client->dataset[++cursor].begin_position = r;
}
r = get_archive_size(f);
if (r < 0)
goto clear_buffer;
cursor = client->nodes - 1;
while (1) {
if (r + offset >=
client->dataset[cursor].begin_position)
@@ -1806,16 +1854,17 @@ __archive_read_filter_seek(struct archive_read_filter *f, int64_t offset,
r = client_seek_proxy(f, offset, SEEK_SET);
if (r < ARCHIVE_OK)
goto clear_buffer;
sought = 1;
break;
default:
return (ARCHIVE_FATAL);
}
r += client->dataset[cursor].begin_position;
f->position = r;
clear_buffer:
if (r == ARCHIVE_FAILED && !sought && old_cursor == client->cursor) {
if (r == ARCHIVE_FAILED &&
old_cursor == client->cursor && old_position == f->position) {
/* Seek failed without moving position: keep buffer */
return (r);
}
@@ -1839,11 +1888,12 @@ clear_buffer:
*/
f->avail = f->client_avail = 0;
f->next = f->buffer;
if (r >= 0) {
f->position = r;
if (r >= 0)
f->end_of_file = 0;
} else
else {
f->position = -1;
f->fatal = 1;
}
return r;
}
@@ -47,6 +47,28 @@ get_last_bidder(struct archive_read *a)
return a->bidders + (i - 1);
}
static int
archive_read_append_filter_last_bidder(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
struct archive_read_filter_bidder *b;
struct archive_read_filter *f;
f = calloc(1, sizeof(*f));
if (f == NULL)
{
archive_set_error(&a->archive, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
b = get_last_bidder(a);
f->bidder = b;
f->archive = a;
f->upstream = a->filter;
a->filter = f;
a->bypass_filter_bidding = 1;
return (ARCHIVE_OK);
}
int
archive_read_append_filter(struct archive *_a, int code)
{
@@ -82,6 +104,7 @@ archive_read_append_filter(struct archive *_a, int code)
case ARCHIVE_FILTER_XZ:
r1 = archive_read_support_filter_xz(_a);
break;
case ARCHIVE_FILTER_B64:
case ARCHIVE_FILTER_UU:
r1 = archive_read_support_filter_uu(_a);
break;
@@ -114,28 +137,9 @@ archive_read_append_filter(struct archive *_a, int code)
if (r1 > ARCHIVE_FATAL && code != ARCHIVE_FILTER_NONE)
{
struct archive_read_filter_bidder *b;
struct archive_read_filter *f;
f = calloc(1, sizeof(*f));
if (f == NULL)
{
archive_set_error(&a->archive, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
b = get_last_bidder(a);
f->bidder = b;
f->archive = a;
f->upstream = a->filter;
a->filter = f;
r2 = (b->vtable->init)(a->filter);
if (r2 != ARCHIVE_OK) {
__archive_read_free_filters(a);
return (ARCHIVE_FATAL);
}
r2 = archive_read_append_filter_last_bidder(_a);
}
a->bypass_filter_bidding = 1;
return (r1 < r2) ? r1 : r2;
}
@@ -149,32 +153,9 @@ int
archive_read_append_filter_program_signature(struct archive *_a,
const char *cmd, const void *signature, size_t signature_len)
{
struct archive_read *a = (struct archive_read *)_a;
struct archive_read_filter_bidder *b;
struct archive_read_filter *f;
int r;
if (archive_read_support_filter_program_signature(_a, cmd, signature,
signature_len) != (ARCHIVE_OK))
return (ARCHIVE_FATAL);
f = calloc(1, sizeof(*f));
if (f == NULL)
{
archive_set_error(&a->archive, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
b = get_last_bidder(a);
f->bidder = b;
f->archive = a;
f->upstream = a->filter;
a->filter = f;
r = (b->vtable->init)(a->filter);
if (r != ARCHIVE_OK) {
__archive_read_free_filters(a);
return (ARCHIVE_FATAL);
}
a->bypass_filter_bidding = 1;
return r;
return (archive_read_append_filter_last_bidder(_a));
}
@@ -31,6 +31,9 @@
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -86,11 +89,30 @@ pad_to(struct archive *a, int fd, int can_lseek,
return (ARCHIVE_OK);
}
static int
lseek_available(int fd)
{
struct stat st;
int ret;
/* Support holes only with regular files. */
ret = (fstat(fd, &st) == 0) && S_ISREG(st.st_mode);
#ifdef HAVE_FCNTL
if (ret) {
int flags = fcntl(fd, F_GETFL);
/* O_APPEND defeats lseek's sparse file purpose. */
if (flags != -1 && flags & O_APPEND)
ret = 0;
}
#endif
return (ret);
}
int
archive_read_data_into_fd(struct archive *a, int fd)
{
struct stat st;
int r, r2;
const void *buff;
size_t size, bytes_to_write;
@@ -107,7 +129,7 @@ archive_read_data_into_fd(struct archive *a, int fd)
declared_size = ((struct archive_read *)a)->entry_bytes_declared;
can_lseek = (fstat(fd, &st) == 0) && S_ISREG(st.st_mode);
can_lseek = lseek_available(fd);
if (can_lseek) {
fd_offset = lseek(fd, 0, SEEK_CUR);
if (fd_offset == -1)
@@ -486,7 +486,17 @@ setup_xattr(struct archive_read_disk *a,
return (ARCHIVE_WARN);
}
if (size > 0 && (value = malloc(size)) == NULL) {
/*
* Do not query an empty value again: if it has grown in the
* meantime, the second call would return the new size without
* storing anything.
*/
if (size == 0) {
archive_entry_xattr_add_entry(entry, name, "", 0);
return (ARCHIVE_OK);
}
if ((value = malloc(size)) == NULL) {
archive_set_error(&a->archive, errno, "Out of memory");
return (ARCHIVE_FATAL);
}
@@ -682,7 +692,17 @@ setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
return (ARCHIVE_WARN);
}
if (size > 0 && (value = malloc(size)) == NULL) {
/*
* Do not query an empty value again: if it has grown in the
* meantime, the second call would return the new size without
* storing anything.
*/
if (size == 0) {
archive_entry_xattr_add_entry(entry, fullname, "", 0);
return (ARCHIVE_OK);
}
if ((value = malloc(size)) == NULL) {
archive_set_error(&a->archive, errno, "Out of memory");
return (ARCHIVE_FATAL);
}
@@ -583,7 +583,6 @@ file_seek(struct archive *a, void *client_data, int64_t request, int whence)
if (r >= 0)
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");
@@ -593,7 +592,7 @@ err:
else
archive_set_error(a, errno, "Error seeking in '%ls'",
mine->filename.w);
return (ARCHIVE_FATAL);
return (ARCHIVE_FAILED);
}
static int
@@ -47,6 +47,7 @@ archive_read_support_filter_by_code(struct archive *a, int filter_code)
return archive_read_support_filter_lzma(a);
case ARCHIVE_FILTER_XZ:
return archive_read_support_filter_xz(a);
case ARCHIVE_FILTER_B64:
case ARCHIVE_FILTER_UU:
return archive_read_support_filter_uu(a);
case ARCHIVE_FILTER_RPM:
@@ -44,6 +44,11 @@
/* Maximum lookahead during bid phase */
#define MAX_LINE_LENGTH 128*1024 /* in bytes */
struct uu_bidder {
int code;
const char *name;
};
struct uu {
unsigned char *out_buff;
#define OUT_BUFF_SIZE (64 * 1024)
@@ -61,6 +66,7 @@ struct uu {
static int uudecode_bidder_bid(struct archive_read_filter_bidder *,
struct archive_read_filter *f);
static int uudecode_bidder_init(struct archive_read_filter *);
static void uudecode_bidder_free(struct archive_read_filter_bidder *);
static int uudecode_read_header(struct archive_read_filter *,
struct archive_entry *entry);
@@ -81,15 +87,27 @@ static const struct archive_read_filter_bidder_vtable
uudecode_bidder_vtable = {
.bid = uudecode_bidder_bid,
.init = uudecode_bidder_init,
.free = uudecode_bidder_free
};
int
archive_read_support_filter_uu(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
struct uu_bidder *data;
return __archive_read_register_bidder(a, NULL,
&uudecode_bidder_vtable);
data = calloc(1, sizeof(*data));
if (data == NULL) {
archive_set_error(_a, ENOMEM, "Can't allocate memory");
return ARCHIVE_FATAL;
}
if (__archive_read_register_bidder(a, data,
&uudecode_bidder_vtable) != ARCHIVE_OK) {
free(data);
return (ARCHIVE_FATAL);
}
return (ARCHIVE_OK);
}
static const unsigned char uuchar[256] = {
@@ -214,6 +232,17 @@ read_line_ahead(struct archive_read_filter *f, ssize_t parsed,
line = b + start;
*len = p - line;
*unconsumed = *len + nl;
/* Only ASCII lines are valid. */
while (p > line) {
unsigned char c = *--p;
if (c < 0x20 || c > 0x7F) {
*len = 0;
*unconsumed = 0;
return (NULL);
}
}
} else {
/* Keep offset for check of possibly missing \n in \r\n. */
if (step != 1)
@@ -276,6 +305,7 @@ static int
uudecode_bidder_bid(struct archive_read_filter_bidder *b,
struct archive_read_filter *f)
{
struct uu_bidder *data = b->data;
const unsigned char *p;
size_t l;
int firstline;
@@ -329,9 +359,14 @@ uudecode_bidder_bid(struct archive_read_filter_bidder *b,
}
offset += unconsumed;
p = read_line_ahead(f, 0, offset, &len, &unconsumed);
if (p != NULL && uuchar[*p])
if (p != NULL && uuchar[*p]) {
data->code = ARCHIVE_FILTER_UU;
data->name = "uu";
return (firstline+30);
}
} else if (l == 13) {
int bid = 0;
/* "begin-base64 " */
while (len > 0) {
if (!base64[*p++])
@@ -339,9 +374,19 @@ uudecode_bidder_bid(struct archive_read_filter_bidder *b,
len--;
}
if (len == 0)
return (firstline+30);
bid = firstline + 30;
if (len == 4 && memcmp(p, "====", 4) == 0)
return (firstline+40);
bid = firstline + 40;
if (bid > 0) {
#if ARCHIVE_VERSION_NUMBER < 4000000
data->code = ARCHIVE_FILTER_UU;
data->name = "uu";
#else
data->code = ARCHIVE_FILTER_B64;
data->name = "b64";
#endif
return (bid);
}
}
return (0);
@@ -357,11 +402,12 @@ uudecode_reader_vtable = {
static int
uudecode_bidder_init(struct archive_read_filter *f)
{
struct uu_bidder *data = f->bidder->data;
struct uu *uu;
void *out_buff;
f->code = ARCHIVE_FILTER_UU;
f->name = "uu";
f->code = data->code;
f->name = data->name;
uu = calloc(1, sizeof(*uu));
out_buff = malloc(OUT_BUFF_SIZE);
@@ -383,6 +429,13 @@ uudecode_bidder_init(struct archive_read_filter *f)
return (ARCHIVE_OK);
}
static void
uudecode_bidder_free(struct archive_read_filter_bidder *b)
{
free(b->data);
b->data = NULL;
}
static int
uudecode_read_header(struct archive_read_filter *f, struct archive_entry *entry)
{
@@ -3954,6 +3954,22 @@ read_stream(struct archive_read *a, const void **buff, size_t size,
return (get_uncompressed_data(a, buff, size, minimum));
}
/* Returns the name of a compressor codec, or NULL if not a compressor. */
static const char *
compressor_name(int64_t codec)
{
switch (codec) {
case _7Z_COPY: return ("Copy");
case _7Z_LZMA: return ("LZMA");
case _7Z_LZMA2: return ("LZMA2");
case _7Z_DEFLATE: return ("Deflate");
case _7Z_BZ2: return ("BZip2");
case _7Z_PPMD: return ("PPMd");
case _7Z_ZSTD: return ("Zstd");
default: return (NULL);
}
}
static int
setup_decode_folder(struct archive_read *a, struct _7z_folder *folder,
int header)
@@ -4016,6 +4032,24 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder,
return (header ? ARCHIVE_FATAL : ARCHIVE_FAILED);
}
/*
* 7-Zip can be asked to chain two compressors in one folder
* (e.g. -m0=LZMA2 -m1=LZMA2). This is slow and gains nothing.
* Our decoder intentionally only supports a compressor
* followed by an optional filter.
*/
if (folder->numCoders == 2 && !found_bcj2 &&
compressor_name(folder->coders[0].codec) != NULL &&
compressor_name(folder->coders[1].codec) != NULL) {
archive_set_error(&(a->archive),
ARCHIVE_ERRNO_MISC,
"The %s is compressed twice with chained compressors "
"(%s and %s), which is not supported", cname,
compressor_name(folder->coders[0].codec),
compressor_name(folder->coders[1].codec));
return (header ? ARCHIVE_FATAL : ARCHIVE_FAILED);
}
/*
* Initialize a stream reader.
*/
@@ -581,6 +581,10 @@ find_newc_header(struct archive_read *a)
}
p += 2;
break;
case '7':
/* A header may start two bytes on. */
p += 2;
break;
case '0':
p++;
break;
@@ -388,9 +388,9 @@ static int archive_read_format_iso9660_read_data(struct archive_read *,
static int archive_read_format_iso9660_read_data_skip(struct archive_read *);
static int archive_read_format_iso9660_read_header(struct archive_read *,
struct archive_entry *);
static const char *build_pathname(struct archive_string *, struct file_info *, int);
static int build_pathname(struct archive_string *, struct file_info *, int);
static int build_pathname_utf16be(unsigned char *, size_t, size_t *,
struct file_info *);
struct file_info *, int);
#if DEBUG
static void dump_isodirrec(FILE *, const unsigned char *isodirrec);
#endif
@@ -432,6 +432,7 @@ static void parse_rockridge_TF1(struct file_info *,
static void parse_rockridge_ZF1(struct file_info *,
const unsigned char *, int);
static void register_file(struct iso9660 *, struct file_info *);
static void release_file(struct file_info *);
static void release_files(struct iso9660 *);
static inline void re_add_entry(struct iso9660 *, struct file_info *);
static inline struct file_info * re_get_entry(struct iso9660 *);
@@ -1280,8 +1281,9 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
}
iso9660->utf16be_path_len = 0;
if (build_pathname_utf16be(iso9660->utf16be_path,
UTF16_NAME_MAX, &(iso9660->utf16be_path_len), file) != 0) {
r = build_pathname_utf16be(iso9660->utf16be_path,
UTF16_NAME_MAX, &(iso9660->utf16be_path_len), file, 0);
if (r != ARCHIVE_OK) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Pathname is too long");
@@ -1308,16 +1310,15 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
rd_r = ARCHIVE_WARN;
}
} else {
const char *path = build_pathname(&iso9660->pathname, file, 0);
if (path == NULL) {
archive_string_empty(&iso9660->pathname);
r = build_pathname(&iso9660->pathname, file, 0);
if (r != ARCHIVE_OK) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Pathname is too long");
return (ARCHIVE_FATAL);
} else {
archive_string_empty(&iso9660->pathname);
archive_entry_set_pathname(entry, path);
}
archive_entry_set_pathname(entry, iso9660->pathname.s);
}
iso9660->entry_bytes_remaining = file->size;
@@ -1901,12 +1902,12 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
if (iso9660->seenJoliet) {
/* Joliet names are max 64 chars (128 bytes) according to spec,
* but genisoimage/mkisofs allows recording longer Joliet
* names which are 103 UCS2 characters(206 bytes) by their
* option '-joliet-long'.
* but authoring tools record longer ones: genisoimage/mkisofs
* up to 103 UCS2 characters (206 bytes) with '-joliet-long',
* Windows tools up to what the directory record holds. The
* record already bounds name_len (checked above), so the
* whole name is kept.
*/
if (name_len > 206)
name_len = 206;
name_len &= ~1;
/* trim trailing first version and dot from filename.
@@ -2154,8 +2155,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
register_file(iso9660, file);
return (file);
fail:
archive_string_free(&file->name);
free(file);
release_file(file);
return (NULL);
}
@@ -2758,25 +2758,31 @@ register_file(struct iso9660 *iso9660, struct file_info *file)
}
static void
release_files(struct iso9660 *iso9660)
release_file(struct file_info *file)
{
struct content *con, *connext;
archive_string_free(&file->name);
archive_string_free(&file->symlink);
free(file->utf16be_name);
con = file->contents.first;
while (con != NULL) {
connext = con->next;
free(con);
con = connext;
}
free(file);
}
static void
release_files(struct iso9660 *iso9660)
{
struct file_info *file;
file = iso9660->use_files;
while (file != NULL) {
struct file_info *next = file->use_next;
archive_string_free(&file->name);
archive_string_free(&file->symlink);
free(file->utf16be_name);
con = file->contents.first;
while (con != NULL) {
connext = con->next;
free(con);
con = connext;
}
free(file);
release_file(file);
file = next;
}
}
@@ -3448,53 +3454,64 @@ time_from_tm(struct tm *t)
#endif
}
static const char *
static int
build_pathname(struct archive_string *as, struct file_info *file, int depth)
{
// Plain ISO9660 only allows 8 dir levels; if we get
// to 1000, then something is very, very wrong.
if (depth > 1000) {
return NULL;
}
if (depth > 1000)
return (ARCHIVE_FATAL);
if (file->parent != NULL && archive_strlen(&file->parent->name) > 0) {
if (build_pathname(as, file->parent, depth + 1) == NULL) {
return NULL;
}
int r = build_pathname(as, file->parent, depth + 1);
if (r != ARCHIVE_OK)
return (r);
archive_strcat(as, "/");
}
if (archive_strlen(&file->name) == 0)
archive_strcat(as, ".");
else
archive_string_concat(as, &file->name);
return (as->s);
return (ARCHIVE_OK);
}
static int
build_pathname_utf16be(unsigned char *p, size_t max, size_t *len,
struct file_info *file)
struct file_info *file, int depth)
{
/*
* Plain ISO9660 only allows 8 dir levels; if we get
* to 1000, then something is very, very wrong. A malformed
* image can also form a cycle in the parent chain via Rock
* Ridge "CL"/"RE" relocation, which without this limit would
* recurse until the stack is exhausted. Mirrors the cap in
* build_pathname().
*/
if (depth > 1000)
return (ARCHIVE_FATAL);
if (file->parent != NULL && file->parent->utf16be_bytes > 0) {
if (build_pathname_utf16be(p, max, len, file->parent) != 0)
return (-1);
if (build_pathname_utf16be(p, max, len, file->parent,
depth + 1) != ARCHIVE_OK)
return (ARCHIVE_FATAL);
if (*len + 2 > max)
return (-1);/* Path is too long! */
return (ARCHIVE_FATAL);/* Path is too long! */
p[*len] = 0;
p[*len + 1] = '/';
*len += 2;
}
if (file->utf16be_bytes == 0) {
if (*len + 2 > max)
return (-1);/* Path is too long! */
return (ARCHIVE_FATAL);/* Path is too long! */
p[*len] = 0;
p[*len + 1] = '.';
*len += 2;
} else {
if (*len + file->utf16be_bytes > max)
return (-1);/* Path is too long! */
return (ARCHIVE_FATAL);/* Path is too long! */
memcpy(p + *len, file->utf16be_name, file->utf16be_bytes);
*len += file->utf16be_bytes;
}
return (0);
return (ARCHIVE_OK);
}
#if DEBUG
@@ -2050,10 +2050,23 @@ readline(struct archive_read *a, struct mtree *mtree, char **start,
for (;;) {
/* Read some more. */
t = __archive_read_ahead(a, 1, &bytes_read);
if (t == NULL)
return (0);
if (bytes_read < 0)
return (ARCHIVE_FATAL);
if (t == NULL) {
if (total_size == 0)
return (0);
/* Last line lacks a newline; add one. */
if (archive_string_ensure(&mtree->line,
total_size + 2) == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate working buffer");
return (ARCHIVE_FATAL);
}
mtree->line.s[total_size++] = '\n';
mtree->line.s[total_size] = '\0';
*start = mtree->line.s;
return total_size;
}
nl = memchr(t, '\n', bytes_read);
/* If we found '\n', trim the read to end exactly there. */
if (nl != NULL) {
@@ -91,6 +91,8 @@
#define FHD_EXTTIME 0x1000
#define FHD_EXTFLAGS 0x2000
#define RAR_MAX_SYMLINK_SIZE (1024 * 1024)
/* File dictionary sizes */
#define DICTIONARY_SIZE_64 0x00
#define DICTIONARY_SIZE_128 0x20
@@ -1971,7 +1973,7 @@ read_symlink_stored(struct archive_read *a, struct archive_entry *entry,
const char *p;
int ret = (ARCHIVE_OK);
if ((uintmax_t)rar->packed_size > SIZE_MAX)
if (rar->packed_size > RAR_MAX_SYMLINK_SIZE)
{
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Unable to read link");
@@ -3247,6 +3247,10 @@ gnu_add_sparse_entry(struct archive_read *a, struct tar *tar,
if (remaining == 0)
return (ARCHIVE_OK);
if (remaining < 0 || offset < 0 || offset > INT64_MAX - remaining) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Malformed sparse map data");
return (ARCHIVE_FATAL);
}
p = calloc(1, sizeof(*p));
if (p == NULL) {
archive_set_error(&a->archive, ENOMEM, "Out of memory");
@@ -3257,10 +3261,6 @@ gnu_add_sparse_entry(struct archive_read *a, struct tar *tar,
else
tar->sparse_list = p;
tar->sparse_last = p;
if (remaining < 0 || offset < 0 || offset > INT64_MAX - remaining) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Malformed sparse map data");
return (ARCHIVE_FATAL);
}
p->offset = offset;
p->remaining = remaining;
return (ARCHIVE_OK);
@@ -3380,18 +3380,18 @@ gnu_sparse_01_parse(struct archive_read *a, struct tar *tar, const char *p, size
e = p;
while (length > 0 && *e != ',') {
if (*e < '0' || *e > '9')
return (ARCHIVE_WARN);
goto malformed;
e++;
length--;
}
if (offset < 0) {
offset = tar_atol10(p, e - p);
if (offset < 0)
return (ARCHIVE_WARN);
goto malformed;
} else {
size = tar_atol10(p, e - p);
if (size < 0)
return (ARCHIVE_WARN);
goto malformed;
if (gnu_add_sparse_entry(a, tar, offset, size)
!= ARCHIVE_OK)
return (ARCHIVE_FATAL);
@@ -3402,6 +3402,10 @@ gnu_sparse_01_parse(struct archive_read *a, struct tar *tar, const char *p, size
p = e + 1;
length--;
}
malformed:
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Malformed sparse map data");
return (ARCHIVE_WARN);
}
/*
@@ -1001,14 +1001,22 @@ move_reading_point(struct archive_read *a, uint64_t offset)
return ((int)step);
xar->offset += step;
} else {
int64_t pos = __archive_read_seek(a, xar->h_base + offset, SEEK_SET);
if (pos == ARCHIVE_FAILED) {
if (archive_ckd_add_u64(&offset, offset, xar->h_base) ||
(int64_t)offset < 0) {
archive_set_error(&(a->archive),
ARCHIVE_ERRNO_FILE_FORMAT,
"Too many bytes to skip");
return (ARCHIVE_FATAL);
}
int64_t r = __archive_read_seek(a, offset, SEEK_SET);
if (r < ARCHIVE_OK) {
archive_set_error(&(a->archive),
ARCHIVE_ERRNO_MISC,
"Cannot seek");
return (ARCHIVE_FAILED);
return ((int)r);
}
xar->offset = pos;
xar->offset = r;
}
}
return (ARCHIVE_OK);
@@ -3294,7 +3302,6 @@ xml2_read_toc(struct archive_read *a)
xmlattr_cleanup(&list);
if (r != ARCHIVE_OK) {
xmlFreeTextReader(reader);
xmlCleanupParser();
return (r);
}
if (empty)
@@ -3308,7 +3315,6 @@ xml2_read_toc(struct archive_read *a)
r = xml_data(a, value, strlen(value));
if (r != ARCHIVE_OK) {
xmlFreeTextReader(reader);
xmlCleanupParser();
return (r);
}
break;
@@ -3320,7 +3326,6 @@ xml2_read_toc(struct archive_read *a)
break;
}
xmlFreeTextReader(reader);
xmlCleanupParser();
return ((r == 0)?ARCHIVE_OK:ARCHIVE_FATAL);
}
@@ -3975,69 +3975,20 @@ archive_read_format_zip_read_data_skip_streamable(struct archive_read *a)
return (ARCHIVE_OK);
}
if (zip->init_decryption) {
/* Validate the descriptor against decoded CRC and sizes. */
while (!zip->end_of_entry) {
int64_t offset = 0;
const void *buff = NULL;
size_t size = 0;
int r;
zip->has_encrypted_entries = 1;
if (zip->entry->zip_flags & ZIP_STRONG_ENCRYPTED)
r = read_decryption_header(a);
else if (zip->entry->compression == WINZIP_AES_ENCRYPTION)
r = init_WinZip_AES_decryption(a);
else
r = init_traditional_PKWARE_decryption(a);
r = archive_read_format_zip_read_data(a, &buff, &size, &offset);
if (r == ARCHIVE_EOF)
return (ARCHIVE_OK);
if (r != ARCHIVE_OK)
return (r);
zip->init_decryption = 0;
}
/* We're streaming and we don't know the length. */
/* If the body is compressed and we know the format, we can
* find an exact end-of-entry by decompressing it. */
switch (zip->entry->compression) {
#ifdef HAVE_ZLIB_H
case 8: /* Deflate compression. */
while (!zip->end_of_entry) {
int64_t offset = 0;
const void *buff = NULL;
size_t size = 0;
int r;
r = zip_read_data_deflate(a, &buff, &size, &offset);
if (r != ARCHIVE_OK)
return (r);
}
return ARCHIVE_OK;
#endif
default: /* Uncompressed or unknown. */
/* Scan for a PK\007\010 signature. */
for (;;) {
const char *p, *buff;
ssize_t bytes_avail;
buff = __archive_read_ahead(a, 16, &bytes_avail);
if (bytes_avail < 16) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated ZIP file data");
return (ARCHIVE_FATAL);
}
p = buff;
while (p <= buff + bytes_avail - 16) {
if (p[3] == 'P') { p += 3; }
else if (p[3] == 'K') { p += 2; }
else if (p[3] == '\007') { p += 1; }
else if (p[3] == '\010' && p[2] == '\007'
&& p[1] == 'K' && p[0] == 'P') {
if (zip->entry->flags & LA_USED_ZIP64)
__archive_read_consume(a,
p - buff + 24);
else
__archive_read_consume(a,
p - buff + 16);
return ARCHIVE_OK;
} else { p += 4; }
}
__archive_read_consume(a, p - buff);
}
}
return (ARCHIVE_OK);
}
int
@@ -288,9 +288,17 @@ archive_wstring_free(struct archive_wstring *as)
struct archive_wstring *
archive_wstring_ensure(struct archive_wstring *as, size_t s)
{
size_t ws;
if (archive_ckd_mul_size(&ws, s, sizeof(wchar_t))) {
/* On failure, wipe the string and return NULL. */
archive_wstring_free(as);
errno = ENOMEM;/* Make sure errno has ENOMEM. */
return (NULL);
}
return (struct archive_wstring *)
archive_string_ensure((struct archive_string *)as,
s * sizeof(wchar_t));
archive_string_ensure((struct archive_string *)as, ws);
}
/* Returns NULL on any allocation failure. */
@@ -710,7 +718,6 @@ static int
archive_string_append_from_wcs_in_codepage(struct archive_string *as,
const wchar_t *ws, size_t len, struct archive_string_conv *sc)
{
BOOL defchar_used, *dp;
int ret = 0;
UINT to_cp;
size_t count, wslen = len;
@@ -732,12 +739,12 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as,
return (-1);
p = as->s + as->length;
count = 0;
defchar_used = 0;
while (count < wslen && *wp) {
if (*wp > 255) {
*p++ = '?';
wp++;
defchar_used = 1;
errno = EILSEQ;
ret = -1;
} else
*p++ = (char)*wp++;
count++;
@@ -750,7 +757,6 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as,
return (-1);
u16 = (uint16_t *)(as->s + as->length);
count = 0;
defchar_used = 0;
if (sc->flag & SCONV_TO_UTF16BE) {
while (count < len && *ws) {
archive_be16enc(u16+count, *ws);
@@ -772,6 +778,7 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as,
return (-1);
do {
int r;
BOOL defchar_used, *dp;
defchar_used = 0;
if (to_cp == CP_UTF8)
@@ -797,15 +804,17 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as,
return (-1);
continue;
}
if (r == 0)
if (r == 0 || defchar_used) {
errno = EILSEQ;
ret = -1;
}
count = (size_t)r;
break;
} while (1);
}
as->length += count;
as->s[as->length] = '\0';
return (defchar_used?-1:ret);
return (ret);
}
#elif defined(HAVE_WCTOMB) || defined(HAVE_WCRTOMB)
@@ -528,7 +528,7 @@ archive_write_client_close(struct archive_write_filter *f)
ssize_t bytes_written;
size_t to_write;
char *p;
int ret = ARCHIVE_OK;
int ret = ARCHIVE_OK, ret1;
/* If there's pending data, pad and write the last block */
if (client->next != client->buffer) {
@@ -569,8 +569,11 @@ archive_write_client_close(struct archive_write_filter *f)
to_write -= bytes_written;
}
}
if (a->client_closer)
(*a->client_closer)(&a->archive, a->client_data);
if (a->client_closer) {
ret1 = (*a->client_closer)(&a->archive, a->client_data);
if (ret1 < ret)
ret = ret1;
}
/* Clear the close handler myself not to be called again. */
f->state = ARCHIVE_WRITE_FILTER_STATE_CLOSED;
@@ -50,6 +50,7 @@ struct { int code; int (*setter)(struct archive *); } codes[] =
{ ARCHIVE_FILTER_LZIP, archive_write_add_filter_lzip },
{ ARCHIVE_FILTER_LZMA, archive_write_add_filter_lzma },
{ ARCHIVE_FILTER_LZOP, archive_write_add_filter_lzop },
{ ARCHIVE_FILTER_B64, archive_write_add_filter_b64encode },
{ ARCHIVE_FILTER_UU, archive_write_add_filter_uuencode },
{ ARCHIVE_FILTER_XZ, archive_write_add_filter_xz },
{ ARCHIVE_FILTER_ZSTD, archive_write_add_filter_zstd },
@@ -99,7 +99,11 @@ archive_write_add_filter_b64encode(struct archive *a)
if (f == NULL)
goto memerr;
f->name = "b64encode";
#if ARCHIVE_VERSION_NUMBER < 4000000
f->code = ARCHIVE_FILTER_UU;
#else
f->code = ARCHIVE_FILTER_B64;
#endif
f->data = b64encode;
f->options = archive_filter_b64encode_options;
f->open = archive_filter_b64encode_open;
@@ -231,7 +235,7 @@ archive_filter_b64encode_write(struct archive_write_filter *f, const void *buff,
{
struct b64encode *b64encode = f->data;
const unsigned char *p = buff;
int ret = ARCHIVE_OK;
int r, ret = ARCHIVE_OK;
if (length == 0)
return (ret);
@@ -256,12 +260,16 @@ archive_filter_b64encode_write(struct archive_write_filter *f, const void *buff,
b64encode->hold_len = length;
}
while (archive_strlen(&b64encode->encoded_buff) >= b64encode->bs) {
ret = __archive_write_filter(f->next_filter,
r = __archive_write_filter(f->next_filter,
b64encode->encoded_buff.s, b64encode->bs);
memmove(b64encode->encoded_buff.s,
b64encode->encoded_buff.s + b64encode->bs,
b64encode->encoded_buff.length - b64encode->bs);
b64encode->encoded_buff.length -= b64encode->bs;
if (r < ret)
ret = r;
if (ret < ARCHIVE_WARN)
break;
}
return (ret);
@@ -222,7 +222,7 @@ archive_filter_uuencode_write(struct archive_write_filter *f, const void *buff,
{
struct uuencode *uuencode = f->data;
const unsigned char *p = buff;
int ret = ARCHIVE_OK;
int r, ret = ARCHIVE_OK;
if (length == 0)
return (ret);
@@ -247,12 +247,16 @@ archive_filter_uuencode_write(struct archive_write_filter *f, const void *buff,
uuencode->hold_len = length;
}
while (archive_strlen(&uuencode->encoded_buff) >= uuencode->bs) {
ret = __archive_write_filter(f->next_filter,
r = __archive_write_filter(f->next_filter,
uuencode->encoded_buff.s, uuencode->bs);
memmove(uuencode->encoded_buff.s,
uuencode->encoded_buff.s + uuencode->bs,
uuencode->encoded_buff.length - uuencode->bs);
uuencode->encoded_buff.length -= uuencode->bs;
if (r < ret)
ret = r;
if (ret < ARCHIVE_WARN)
break;
}
return (ret);
@@ -184,8 +184,9 @@ string_to_number(const char *string, intmax_t *numberp)
if (string == NULL || *string == '\0')
return (ARCHIVE_WARN);
errno = 0;
*numberp = strtoimax(string, &end, 10);
if (end == string || *end != '\0' || errno == EOVERFLOW) {
if (end == string || *end != '\0' || errno == ERANGE) {
*numberp = 0;
return (ARCHIVE_WARN);
}
@@ -202,6 +203,7 @@ string_to_size(const char *string, size_t *numberp)
if (string == NULL || *string == '\0' || *string == '-')
return (ARCHIVE_WARN);
errno = 0;
number = strtoumax(string, &end, 10);
if (end > string) {
if (*end == 'K' || *end == 'k') {
@@ -218,7 +220,7 @@ string_to_size(const char *string, size_t *numberp)
end++;
}
}
if (end == string || *end != '\0' || errno == EOVERFLOW) {
if (end == string || *end != '\0' || errno == ERANGE) {
return (ARCHIVE_WARN);
}
if (number > (uintmax_t)SIZE_MAX >> shift) {
@@ -348,13 +350,13 @@ archive_compressor_zstd_options(struct archive_write_filter *f, const char *key,
ZSTD_bounds bounds = ZSTD_cParam_getBounds(ZSTD_c_windowLog);
if (ZSTD_isError(bounds.error)) {
int max_distance = ((int)(sizeof(size_t) == 4 ? 30 : 31));
if (((int)long_distance) < 10 || (int)long_distance > max_distance) {
if (long_distance < 10 || long_distance > max_distance) {
archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"long out of range");
return (ARCHIVE_FAILED);
}
} else {
if ((int)long_distance < bounds.lowerBound || (int)long_distance > bounds.upperBound) {
if (long_distance < bounds.lowerBound || long_distance > bounds.upperBound) {
archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"long out of range");
return (ARCHIVE_FAILED);
@@ -362,7 +364,7 @@ archive_compressor_zstd_options(struct archive_write_filter *f, const char *key,
}
#else
int max_distance = ((int)(sizeof(size_t) == 4 ? 30 : 31));
if (((int)long_distance) < 10 || (int)long_distance > max_distance)
if (long_distance < 10 || long_distance > max_distance)
return (ARCHIVE_FAILED);
#endif
zstd->long_distance = (int)long_distance;
@@ -1581,7 +1581,7 @@ hfs_write_decmpfs_block(struct archive_write_disk *a, const char *buff,
memcpy(a->uncompressed_buffer +
MAX_DECMPFS_BLOCK_SIZE - a->block_remaining_bytes,
buff, bytes_to_write);
buffer_to_write = a->uncompressed_buffer;
buffer_to_write = (const char *)a->uncompressed_buffer;
}
a->block_remaining_bytes -= bytes_to_write;
a->file_remaining_bytes -= bytes_to_write;
@@ -334,7 +334,7 @@ string_to_number(const char *string, intmax_t *numberp)
return (ARCHIVE_WARN);
errno = 0;
*numberp = strtoimax(string, &end, 10);
if (end == string || *end != '\0' || errno == EOVERFLOW) {
if (end == string || *end != '\0' || errno == ERANGE) {
*numberp = 0;
return (ARCHIVE_WARN);
}
@@ -479,7 +479,7 @@ _7z_options(struct archive_write *a, const char *key, const char *value)
if (strcmp(key, "compression-level") == 0) {
if (value == NULL || *value == '\0') {
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
"Invalid compression-level option value `%s'", value);
"Option 'compression-level' requires an argument");
return (ARCHIVE_FAILED);
}
@@ -1243,16 +1243,16 @@ get_num_opt(struct archive_write *a, int *num, int high, int low,
"option ``%s''", high, key);
return (ARCHIVE_FATAL);
}
if (data < low) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Invalid value(under %d) for "
"option ``%s''", low, key);
return (ARCHIVE_FATAL);
}
p++;
}
if (neg)
data *= -1;
if (data < low) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Invalid value(under %d) for "
"option ``%s''", low, key);
return (ARCHIVE_FATAL);
}
*num = data;
return (ARCHIVE_OK);
@@ -864,13 +864,15 @@ archive_write_pax_header(struct archive_write *a,
const char *oname;
char *name, *bname;
size_t name_length;
ssize_t written;
struct archive_entry *extra = archive_entry_new2(&a->archive);
oname = archive_entry_pathname(entry_original);
name_length = strlen(oname);
name = malloc(name_length + 3);
if (name == NULL || extra == NULL) {
/* XXX error message */
archive_set_error(&a->archive, ENOMEM,
"Can't allocate pax data");
archive_entry_free(extra);
free(name);
return (ARCHIVE_FAILED);
@@ -882,6 +884,14 @@ archive_write_pax_header(struct archive_write *a,
*bname = '\0';
bname = strrchr(name, '/');
}
if (*name == '\0') {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Can't set mac metadata for empty pathname");
archive_entry_free(extra);
free(name);
return (ARCHIVE_FAILED);
}
if (bname == NULL) {
memmove(name + 2, name, name_length + 1);
memmove(name, "._", 2);
@@ -916,8 +926,9 @@ archive_write_pax_header(struct archive_write *a,
return (r);
if (r < ret)
ret = r;
r = (int)archive_write_pax_data(a, mac_metadata,
written = archive_write_pax_data(a, mac_metadata,
mac_metadata_size);
r = written < 0 ? (int)written : ARCHIVE_OK;
if (r < ARCHIVE_WARN)
return (r);
if (r < ret)
@@ -551,8 +551,11 @@ xar_options(struct archive_write *a, const char *key, const char *value)
char *endptr;
unsigned long val;
if (value == NULL)
if (value == NULL) {
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
"Option 'threads' requires an argument");
return (ARCHIVE_FAILED);
}
errno = 0;
val = strtoul(value, &endptr, 10);
if (errno != 0 || *endptr != '\0' || val > (unsigned)INT_MAX) {
@@ -571,6 +574,7 @@ xar_options(struct archive_write *a, const char *key, const char *value)
xar->opt_threads = 1;
#endif
}
return (ARCHIVE_OK);
}
/* Note: The "warn" return is just to inform the options
@@ -435,8 +435,11 @@ archive_write_zip_options(struct archive_write *a, const char *key,
char *endptr;
unsigned long v;
if (val == NULL)
if (val == NULL) {
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
"Option 'threads' requires an argument");
return (ARCHIVE_FAILED);
}
errno = 0;
v = strtoul(val, &endptr, 10);
if (errno != 0 || *endptr != '\0' || v > SHRT_MAX) {
@@ -29,9 +29,6 @@
#ifndef __LIBARCHIVE_BUILD
#error This header is only to be used internally to libarchive.
#endif
#ifndef __LIBARCHIVE_CONFIG_H_INCLUDED
#error "Should have include config.h first!"
#endif
/*
* Choose XML support from third party libraries in this order of preference:
@@ -22,7 +22,6 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define __LIBARCHIVE_CONFIG_H_INCLUDED 1
#include <osreldate.h>
@@ -148,7 +147,6 @@
#define HAVE_LUTIMES 1
#define HAVE_MBRTOWC 1
#define HAVE_MEMMOVE 1
#define HAVE_MEMORY_H 1
#define HAVE_MEMSET 1
#define HAVE_MKDIR 1
#define HAVE_MKFIFO 1