mirror of
https://github.com/Kitware/CMake.git
synced 2026-11-06 05:16:58 +00:00
Merge branch 'upstream-LibArchive' into update-libarchive
* upstream-LibArchive: LibArchive 2026-10-30 (03036ffa)
This commit is contained in:
commit
e34b57cfa3
35 files changed
+463
-273
No files matched your search
@@ -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 @@
|
||||
3008010
|
||||
3008011
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user