MFV r248590,248594:
Update libarchive to 3.1.2 Some of new features: - support for lrzip and grzip compression - support for writing tar v7 format - b64encode and uuencode filters - support for __MACOSX directory in Zip archives - support for lzop compresion (external utility)
This commit is contained in:
commit
5ee0a7b76c
@ -1,3 +1,30 @@
|
||||
Feb 09, 2013: libarchive 3.1.2 released
|
||||
|
||||
Jan 28, 2013: libarchive's new website moved to http://www.libarchive.org.
|
||||
|
||||
Jan 13, 2013: libarchive 3.1.1 released
|
||||
|
||||
Jan 13, 2013: libarchive 3.1.0 released
|
||||
|
||||
Dec 07, 2012: Implement functions to manually set the format and filters used.
|
||||
|
||||
Nov 11, 2012: Add support for __MACOSX directory in Zip archives, which resource
|
||||
forks are stored in.
|
||||
|
||||
Oct 20, 2012: Add support for writing v7 tar format.
|
||||
|
||||
Oct 09, 2012: Add support for grzip compression.
|
||||
|
||||
Oct 07, 2012: Introduce b64encode filter.
|
||||
Oct 07, 2012: Introduce uuencode filter.
|
||||
|
||||
Oct 06, 2012: Add support for lzop.
|
||||
|
||||
Sep 27, 2012: Implement function used to seek within data blocks.
|
||||
(Currently only supported for uncompressed RAR archives).
|
||||
|
||||
Apr 22, 2012: Add basic archive read and write filter support for lrzip.
|
||||
|
||||
Mar 27, 2012: libarchive 3.0.4 released
|
||||
|
||||
Feb 05, 2012: libarchive development now hosted at GitHub.
|
||||
|
@ -1,7 +1,7 @@
|
||||
README for libarchive bundle.
|
||||
|
||||
Questions? Issues?
|
||||
* http://libarchive.github.com/ is the home for ongoing
|
||||
* http://www.libarchive.org is the home for ongoing
|
||||
libarchive development, including documentation, and
|
||||
links to the libarchive mailing lists.
|
||||
* To report an issue, use the issue tracker at
|
||||
|
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd December 24, 2011
|
||||
.Dd October 7, 2012
|
||||
.Dt CPIO 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -176,11 +176,21 @@ With this option, the target of the link will be archived or copied instead.
|
||||
(p mode only)
|
||||
Create links from the target directory to the original files,
|
||||
instead of copying.
|
||||
.It Fl Fl lrzip
|
||||
(o mode only)
|
||||
Compress the resulting archive with
|
||||
.Xr lrzip 1 .
|
||||
In input mode, this option is ignored.
|
||||
.It Fl Fl lzma
|
||||
(o mode only)
|
||||
Compress the file with lzma-compatible compression before writing it.
|
||||
In input mode, this option is ignored; lzma compression is recognized
|
||||
automatically on input.
|
||||
.It Fl Fl lzop
|
||||
(o mode only)
|
||||
Compress the resulting archive with
|
||||
.Xr lzop 1 .
|
||||
In input mode, this option is ignored.
|
||||
.It Fl m , Fl Fl preserve-modification-time
|
||||
(i and p modes)
|
||||
Set file modification time on created files to match
|
||||
|
@ -61,16 +61,20 @@ static const struct option {
|
||||
int required; /* 1 if this option requires an argument */
|
||||
int equivalent; /* Equivalent short option. */
|
||||
} cpio_longopts[] = {
|
||||
{ "b64encode", 0, OPTION_B64ENCODE },
|
||||
{ "create", 0, 'o' },
|
||||
{ "dot", 0, 'V' },
|
||||
{ "extract", 0, 'i' },
|
||||
{ "file", 1, 'F' },
|
||||
{ "format", 1, 'H' },
|
||||
{ "grzip", 0, OPTION_GRZIP },
|
||||
{ "help", 0, 'h' },
|
||||
{ "insecure", 0, OPTION_INSECURE },
|
||||
{ "link", 0, 'l' },
|
||||
{ "list", 0, 't' },
|
||||
{ "lrzip", 0, OPTION_LRZIP },
|
||||
{ "lzma", 0, OPTION_LZMA },
|
||||
{ "lzop", 0, OPTION_LZOP },
|
||||
{ "make-directories", 0, 'd' },
|
||||
{ "no-preserve-owner", 0, OPTION_NO_PRESERVE_OWNER },
|
||||
{ "null", 0, '0' },
|
||||
@ -81,6 +85,7 @@ static const struct option {
|
||||
{ "preserve-owner", 0, OPTION_PRESERVE_OWNER },
|
||||
{ "quiet", 0, OPTION_QUIET },
|
||||
{ "unconditional", 0, 'u' },
|
||||
{ "uuencode", 0, OPTION_UUENCODE },
|
||||
{ "verbose", 0, 'v' },
|
||||
{ "version", 0, OPTION_VERSION },
|
||||
{ "xz", 0, 'J' },
|
||||
|
@ -207,6 +207,9 @@ main(int argc, char *argv[])
|
||||
case 'B': /* POSIX 1997 */
|
||||
cpio->bytes_per_block = 5120;
|
||||
break;
|
||||
case OPTION_B64ENCODE:
|
||||
cpio->add_filter = opt;
|
||||
break;
|
||||
case 'C': /* NetBSD/OpenBSD */
|
||||
cpio->bytes_per_block = atoi(cpio->argument);
|
||||
if (cpio->bytes_per_block <= 0)
|
||||
@ -234,6 +237,9 @@ main(int argc, char *argv[])
|
||||
lafe_errc(1, 0, "Error : %s",
|
||||
archive_error_string(cpio->matching));
|
||||
break;
|
||||
case OPTION_GRZIP:
|
||||
cpio->compress = opt;
|
||||
break;
|
||||
case 'H': /* GNU cpio (also --format) */
|
||||
cpio->format = cpio->argument;
|
||||
break;
|
||||
@ -265,7 +271,9 @@ main(int argc, char *argv[])
|
||||
case 'l': /* POSIX 1997 */
|
||||
cpio->option_link = 1;
|
||||
break;
|
||||
case OPTION_LRZIP:
|
||||
case OPTION_LZMA: /* GNU tar, others */
|
||||
case OPTION_LZOP: /* GNU tar, others */
|
||||
cpio->compress = opt;
|
||||
break;
|
||||
case 'm': /* POSIX 1997 */
|
||||
@ -326,6 +334,9 @@ main(int argc, char *argv[])
|
||||
cpio->extract_flags
|
||||
&= ~ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER;
|
||||
break;
|
||||
case OPTION_UUENCODE:
|
||||
cpio->add_filter = opt;
|
||||
break;
|
||||
case 'v': /* POSIX 1997 */
|
||||
cpio->verbose++;
|
||||
break;
|
||||
@ -417,6 +428,7 @@ main(int argc, char *argv[])
|
||||
archive_match_free(cpio->matching);
|
||||
free_cache(cpio->gname_cache);
|
||||
free_cache(cpio->uname_cache);
|
||||
free(cpio->destdir);
|
||||
return (cpio->return_value);
|
||||
}
|
||||
|
||||
@ -516,27 +528,49 @@ mode_out(struct cpio *cpio)
|
||||
if (cpio->archive == NULL)
|
||||
lafe_errc(1, 0, "Failed to allocate archive object");
|
||||
switch (cpio->compress) {
|
||||
case OPTION_GRZIP:
|
||||
r = archive_write_add_filter_grzip(cpio->archive);
|
||||
break;
|
||||
case 'J':
|
||||
r = archive_write_set_compression_xz(cpio->archive);
|
||||
r = archive_write_add_filter_xz(cpio->archive);
|
||||
break;
|
||||
case OPTION_LRZIP:
|
||||
r = archive_write_add_filter_lrzip(cpio->archive);
|
||||
break;
|
||||
case OPTION_LZMA:
|
||||
r = archive_write_set_compression_lzma(cpio->archive);
|
||||
r = archive_write_add_filter_lzma(cpio->archive);
|
||||
break;
|
||||
case OPTION_LZOP:
|
||||
r = archive_write_add_filter_lzop(cpio->archive);
|
||||
break;
|
||||
case 'j': case 'y':
|
||||
r = archive_write_set_compression_bzip2(cpio->archive);
|
||||
r = archive_write_add_filter_bzip2(cpio->archive);
|
||||
break;
|
||||
case 'z':
|
||||
r = archive_write_set_compression_gzip(cpio->archive);
|
||||
r = archive_write_add_filter_gzip(cpio->archive);
|
||||
break;
|
||||
case 'Z':
|
||||
r = archive_write_set_compression_compress(cpio->archive);
|
||||
r = archive_write_add_filter_compress(cpio->archive);
|
||||
break;
|
||||
default:
|
||||
r = archive_write_set_compression_none(cpio->archive);
|
||||
r = archive_write_add_filter_none(cpio->archive);
|
||||
break;
|
||||
}
|
||||
if (r < ARCHIVE_WARN)
|
||||
lafe_errc(1, 0, "Requested compression not available");
|
||||
switch (cpio->add_filter) {
|
||||
case 0:
|
||||
r = ARCHIVE_OK;
|
||||
break;
|
||||
case OPTION_B64ENCODE:
|
||||
r = archive_write_add_filter_b64encode(cpio->archive);
|
||||
break;
|
||||
case OPTION_UUENCODE:
|
||||
r = archive_write_add_filter_uuencode(cpio->archive);
|
||||
break;
|
||||
}
|
||||
if (r < ARCHIVE_WARN)
|
||||
lafe_errc(1, 0, "Requested filter not available");
|
||||
r = archive_write_set_format_by_name(cpio->archive, cpio->format);
|
||||
if (r != ARCHIVE_OK)
|
||||
lafe_errc(1, 0, "%s", archive_error_string(cpio->archive));
|
||||
@ -548,7 +582,7 @@ mode_out(struct cpio *cpio)
|
||||
/*
|
||||
* The main loop: Copy each file into the output archive.
|
||||
*/
|
||||
r = archive_write_open_file(cpio->archive, cpio->filename);
|
||||
r = archive_write_open_filename(cpio->archive, cpio->filename);
|
||||
if (r != ARCHIVE_OK)
|
||||
lafe_errc(1, 0, "%s", archive_error_string(cpio->archive));
|
||||
lr = lafe_line_reader("-", cpio->option_null);
|
||||
@ -577,7 +611,7 @@ mode_out(struct cpio *cpio)
|
||||
|
||||
if (!cpio->quiet) {
|
||||
int64_t blocks =
|
||||
(archive_position_uncompressed(cpio->archive) + 511)
|
||||
(archive_filter_bytes(cpio->archive, 0) + 511)
|
||||
/ 512;
|
||||
fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
|
||||
blocks == 1 ? "block" : "blocks");
|
||||
@ -806,18 +840,21 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
|
||||
exit(1);
|
||||
|
||||
if (r >= ARCHIVE_WARN && archive_entry_size(entry) > 0 && fd >= 0) {
|
||||
bytes_read = read(fd, cpio->buff, cpio->buff_size);
|
||||
bytes_read = read(fd, cpio->buff, (unsigned)cpio->buff_size);
|
||||
while (bytes_read > 0) {
|
||||
r = archive_write_data(cpio->archive,
|
||||
ssize_t bytes_write;
|
||||
bytes_write = archive_write_data(cpio->archive,
|
||||
cpio->buff, bytes_read);
|
||||
if (r < 0)
|
||||
if (bytes_write < 0)
|
||||
lafe_errc(1, archive_errno(cpio->archive),
|
||||
"%s", archive_error_string(cpio->archive));
|
||||
if (r < bytes_read) {
|
||||
if (bytes_write < bytes_read) {
|
||||
lafe_warnc(0,
|
||||
"Truncated write; file may have grown while being archived.");
|
||||
"Truncated write; file may have "
|
||||
"grown while being archived.");
|
||||
}
|
||||
bytes_read = read(fd, cpio->buff, cpio->buff_size);
|
||||
bytes_read = read(fd, cpio->buff,
|
||||
(unsigned)cpio->buff_size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -908,7 +945,8 @@ mode_in(struct cpio *cpio)
|
||||
archive_read_support_filter_all(a);
|
||||
archive_read_support_format_all(a);
|
||||
|
||||
if (archive_read_open_file(a, cpio->filename, cpio->bytes_per_block))
|
||||
if (archive_read_open_filename(a, cpio->filename,
|
||||
cpio->bytes_per_block))
|
||||
lafe_errc(1, archive_errno(a),
|
||||
"%s", archive_error_string(a));
|
||||
for (;;) {
|
||||
@ -957,7 +995,7 @@ mode_in(struct cpio *cpio)
|
||||
if (r != ARCHIVE_OK)
|
||||
lafe_errc(1, 0, "%s", archive_error_string(ext));
|
||||
if (!cpio->quiet) {
|
||||
int64_t blocks = (archive_position_uncompressed(a) + 511)
|
||||
int64_t blocks = (archive_filter_bytes(a, 0) + 511)
|
||||
/ 512;
|
||||
fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
|
||||
blocks == 1 ? "block" : "blocks");
|
||||
@ -988,7 +1026,7 @@ extract_data(struct archive *ar, struct archive *aw)
|
||||
"%s", archive_error_string(ar));
|
||||
exit(1);
|
||||
}
|
||||
r = archive_write_data_block(aw, block, size, offset);
|
||||
r = (int)archive_write_data_block(aw, block, size, offset);
|
||||
if (r != ARCHIVE_OK) {
|
||||
lafe_warnc(archive_errno(aw),
|
||||
"%s", archive_error_string(aw));
|
||||
@ -1010,7 +1048,8 @@ mode_list(struct cpio *cpio)
|
||||
archive_read_support_filter_all(a);
|
||||
archive_read_support_format_all(a);
|
||||
|
||||
if (archive_read_open_file(a, cpio->filename, cpio->bytes_per_block))
|
||||
if (archive_read_open_filename(a, cpio->filename,
|
||||
cpio->bytes_per_block))
|
||||
lafe_errc(1, archive_errno(a),
|
||||
"%s", archive_error_string(a));
|
||||
for (;;) {
|
||||
@ -1032,7 +1071,7 @@ mode_list(struct cpio *cpio)
|
||||
if (r != ARCHIVE_OK)
|
||||
lafe_errc(1, 0, "%s", archive_error_string(a));
|
||||
if (!cpio->quiet) {
|
||||
int64_t blocks = (archive_position_uncompressed(a) + 511)
|
||||
int64_t blocks = (archive_filter_bytes(a, 0) + 511)
|
||||
/ 512;
|
||||
fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
|
||||
blocks == 1 ? "block" : "blocks");
|
||||
@ -1167,7 +1206,7 @@ mode_pass(struct cpio *cpio, const char *destdir)
|
||||
|
||||
if (!cpio->quiet) {
|
||||
int64_t blocks =
|
||||
(archive_position_uncompressed(cpio->archive) + 511)
|
||||
(archive_filter_bytes(cpio->archive, 0) + 511)
|
||||
/ 512;
|
||||
fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
|
||||
blocks == 1 ? "block" : "blocks");
|
||||
|
@ -44,6 +44,7 @@ struct cpio {
|
||||
const char *argument;
|
||||
|
||||
/* Options */
|
||||
int add_filter; /* --uuencode */
|
||||
const char *filename;
|
||||
int mode; /* -i -o -p */
|
||||
int compress; /* -j, -y, or -z */
|
||||
@ -96,11 +97,16 @@ const char *owner_parse(const char *, int *, int *);
|
||||
|
||||
/* Fake short equivalents for long options that otherwise lack them. */
|
||||
enum {
|
||||
OPTION_INSECURE = 1,
|
||||
OPTION_B64ENCODE = 1,
|
||||
OPTION_GRZIP,
|
||||
OPTION_INSECURE,
|
||||
OPTION_LRZIP,
|
||||
OPTION_LZMA,
|
||||
OPTION_LZOP,
|
||||
OPTION_NO_PRESERVE_OWNER,
|
||||
OPTION_PRESERVE_OWNER,
|
||||
OPTION_QUIET,
|
||||
OPTION_UUENCODE,
|
||||
OPTION_VERSION
|
||||
};
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
*/
|
||||
|
||||
#include "test.h"
|
||||
#include "test_utils.h"
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
@ -91,6 +92,7 @@ __FBSDID("$FreeBSD$");
|
||||
*/
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#include <io.h>
|
||||
#include <direct.h>
|
||||
#include <windows.h>
|
||||
#ifndef F_OK
|
||||
#define F_OK (0)
|
||||
@ -389,7 +391,6 @@ failure_finish(void *extra)
|
||||
fprintf(stderr,
|
||||
" *** forcing core dump so failure can be debugged ***\n");
|
||||
abort();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -622,8 +623,8 @@ assertion_equal_string(const char *file, int line,
|
||||
if (v1 == v2 || (v1 != NULL && v2 != NULL && strcmp(v1, v2) == 0))
|
||||
return (1);
|
||||
failure_start(file, line, "%s != %s", e1, e2);
|
||||
l1 = strlen(e1);
|
||||
l2 = strlen(e2);
|
||||
l1 = (int)strlen(e1);
|
||||
l2 = (int)strlen(e2);
|
||||
if (l1 < l2)
|
||||
l1 = l2;
|
||||
strdump(e1, v1, l1, utf8);
|
||||
@ -746,6 +747,8 @@ assertion_equal_mem(const char *file, int line,
|
||||
assertion_count(file, line);
|
||||
if (v1 == v2 || (v1 != NULL && v2 != NULL && memcmp(v1, v2, l) == 0))
|
||||
return (1);
|
||||
if (v1 == NULL || v2 == NULL)
|
||||
return (0);
|
||||
|
||||
failure_start(file, line, "%s != %s", e1, e2);
|
||||
logprintf(" size %s = %d\n", ld, (int)l);
|
||||
@ -839,9 +842,14 @@ assertion_equal_file(const char *filename, int line, const char *fn1, const char
|
||||
|
||||
f1 = fopen(fn1, "rb");
|
||||
f2 = fopen(fn2, "rb");
|
||||
if (f1 == NULL || f2 == NULL) {
|
||||
if (f1) fclose(f1);
|
||||
if (f2) fclose(f2);
|
||||
return (0);
|
||||
}
|
||||
for (;;) {
|
||||
n1 = fread(buff1, 1, sizeof(buff1), f1);
|
||||
n2 = fread(buff2, 1, sizeof(buff2), f2);
|
||||
n1 = (int)fread(buff1, 1, sizeof(buff1), f1);
|
||||
n2 = (int)fread(buff2, 1, sizeof(buff2), f2);
|
||||
if (n1 != n2)
|
||||
break;
|
||||
if (n1 == 0 && n2 == 0) {
|
||||
@ -915,7 +923,7 @@ assertion_file_contents(const char *filename, int line, const void *buff, int s,
|
||||
return (0);
|
||||
}
|
||||
contents = malloc(s * 2);
|
||||
n = fread(contents, 1, s * 2, f);
|
||||
n = (int)fread(contents, 1, s * 2, f);
|
||||
fclose(f);
|
||||
if (n == s && memcmp(buff, contents, s) == 0) {
|
||||
free(contents);
|
||||
@ -951,9 +959,9 @@ assertion_text_file_contents(const char *filename, int line, const char *buff, c
|
||||
failure_finish(NULL);
|
||||
return (0);
|
||||
}
|
||||
s = strlen(buff);
|
||||
s = (int)strlen(buff);
|
||||
contents = malloc(s * 2 + 128);
|
||||
n = fread(contents, 1, s * 2 + 128 - 1, f);
|
||||
n = (int)fread(contents, 1, s * 2 + 128 - 1, f);
|
||||
if (n >= 0)
|
||||
contents[n] = '\0';
|
||||
fclose(f);
|
||||
@ -1004,8 +1012,8 @@ assertion_file_contains_lines_any_order(const char *file, int line,
|
||||
char *buff;
|
||||
size_t buff_size;
|
||||
size_t expected_count, actual_count, i, j;
|
||||
char **expected;
|
||||
char *p, **actual;
|
||||
char **expected = NULL;
|
||||
char *p, **actual = NULL;
|
||||
char c;
|
||||
int expected_failure = 0, actual_failure = 0;
|
||||
|
||||
@ -1018,14 +1026,21 @@ assertion_file_contains_lines_any_order(const char *file, int line,
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Make a copy of the provided lines and count up the expected file size. */
|
||||
expected_count = 0;
|
||||
/* Make a copy of the provided lines and count up the expected
|
||||
* file size. */
|
||||
for (i = 0; lines[i] != NULL; ++i) {
|
||||
}
|
||||
expected_count = i;
|
||||
expected = malloc(sizeof(char *) * expected_count);
|
||||
for (i = 0; lines[i] != NULL; ++i) {
|
||||
expected[i] = strdup(lines[i]);
|
||||
if (expected_count) {
|
||||
expected = malloc(sizeof(char *) * expected_count);
|
||||
if (expected == NULL) {
|
||||
failure_start(pathname, line, "Can't allocate memory");
|
||||
failure_finish(NULL);
|
||||
return (0);
|
||||
}
|
||||
for (i = 0; lines[i] != NULL; ++i) {
|
||||
expected[i] = strdup(lines[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Break the file into lines */
|
||||
@ -1037,11 +1052,19 @@ assertion_file_contains_lines_any_order(const char *file, int line,
|
||||
++actual_count;
|
||||
c = *p;
|
||||
}
|
||||
actual = malloc(sizeof(char *) * actual_count);
|
||||
for (j = 0, p = buff; p < buff + buff_size; p += 1 + strlen(p)) {
|
||||
if (*p != '\0') {
|
||||
actual[j] = p;
|
||||
++j;
|
||||
if (actual_count) {
|
||||
actual = calloc(sizeof(char *), actual_count);
|
||||
if (actual == NULL) {
|
||||
failure_start(pathname, line, "Can't allocate memory");
|
||||
failure_finish(NULL);
|
||||
free(expected);
|
||||
return (0);
|
||||
}
|
||||
for (j = 0, p = buff; p < buff + buff_size; p += 1 + strlen(p)) {
|
||||
if (*p != '\0') {
|
||||
actual[j] = p;
|
||||
++j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1176,11 +1199,11 @@ assertion_file_time(const char *file, int line,
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#define EPOC_TIME (116444736000000000ULL)
|
||||
FILETIME ftime, fbirthtime, fatime, fmtime;
|
||||
FILETIME fxtime, fbirthtime, fatime, fmtime;
|
||||
ULARGE_INTEGER wintm;
|
||||
HANDLE h;
|
||||
ftime.dwLowDateTime = 0;
|
||||
ftime.dwHighDateTime = 0;
|
||||
fxtime.dwLowDateTime = 0;
|
||||
fxtime.dwHighDateTime = 0;
|
||||
|
||||
assertion_count(file, line);
|
||||
/* Note: FILE_FLAG_BACKUP_SEMANTICS applies to open
|
||||
@ -1195,9 +1218,9 @@ assertion_file_time(const char *file, int line,
|
||||
}
|
||||
r = GetFileTime(h, &fbirthtime, &fatime, &fmtime);
|
||||
switch (type) {
|
||||
case 'a': ftime = fatime; break;
|
||||
case 'b': ftime = fbirthtime; break;
|
||||
case 'm': ftime = fmtime; break;
|
||||
case 'a': fxtime = fatime; break;
|
||||
case 'b': fxtime = fbirthtime; break;
|
||||
case 'm': fxtime = fmtime; break;
|
||||
}
|
||||
CloseHandle(h);
|
||||
if (r == 0) {
|
||||
@ -1205,8 +1228,8 @@ assertion_file_time(const char *file, int line,
|
||||
failure_finish(NULL);
|
||||
return (0);
|
||||
}
|
||||
wintm.LowPart = ftime.dwLowDateTime;
|
||||
wintm.HighPart = ftime.dwHighDateTime;
|
||||
wintm.LowPart = fxtime.dwLowDateTime;
|
||||
wintm.HighPart = fxtime.dwHighDateTime;
|
||||
filet = (wintm.QuadPart - EPOC_TIME) / 10000000;
|
||||
filet_nsec = ((wintm.QuadPart - EPOC_TIME) % 10000000) * 100;
|
||||
nsec = (nsec / 100) * 100; /* Round the request */
|
||||
@ -1834,15 +1857,45 @@ canSymlink(void)
|
||||
return (value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Can this platform run the gzip program?
|
||||
*/
|
||||
/* Platform-dependent options for hiding the output of a subcommand. */
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
static const char *redirectArgs = ">NUL 2>NUL"; /* Win32 cmd.exe */
|
||||
#else
|
||||
static const char *redirectArgs = ">/dev/null 2>/dev/null"; /* POSIX 'sh' */
|
||||
#endif
|
||||
/*
|
||||
* Can this platform run the bzip2 program?
|
||||
*/
|
||||
int
|
||||
canBzip2(void)
|
||||
{
|
||||
static int tested = 0, value = 0;
|
||||
if (!tested) {
|
||||
tested = 1;
|
||||
if (systemf("bzip2 -d -V %s", redirectArgs) == 0)
|
||||
value = 1;
|
||||
}
|
||||
return (value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Can this platform run the grzip program?
|
||||
*/
|
||||
int
|
||||
canGrzip(void)
|
||||
{
|
||||
static int tested = 0, value = 0;
|
||||
if (!tested) {
|
||||
tested = 1;
|
||||
if (systemf("grzip -V %s", redirectArgs) == 0)
|
||||
value = 1;
|
||||
}
|
||||
return (value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Can this platform run the gzip program?
|
||||
*/
|
||||
int
|
||||
canGzip(void)
|
||||
{
|
||||
@ -1856,15 +1909,75 @@ canGzip(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* Can this platform run the gunzip program?
|
||||
* Can this platform run the lrzip program?
|
||||
*/
|
||||
int
|
||||
canGunzip(void)
|
||||
canLrzip(void)
|
||||
{
|
||||
static int tested = 0, value = 0;
|
||||
if (!tested) {
|
||||
tested = 1;
|
||||
if (systemf("gunzip -V %s", redirectArgs) == 0)
|
||||
if (systemf("lrzip -V %s", redirectArgs) == 0)
|
||||
value = 1;
|
||||
}
|
||||
return (value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Can this platform run the lzip program?
|
||||
*/
|
||||
int
|
||||
canLzip(void)
|
||||
{
|
||||
static int tested = 0, value = 0;
|
||||
if (!tested) {
|
||||
tested = 1;
|
||||
if (systemf("lzip -V %s", redirectArgs) == 0)
|
||||
value = 1;
|
||||
}
|
||||
return (value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Can this platform run the lzma program?
|
||||
*/
|
||||
int
|
||||
canLzma(void)
|
||||
{
|
||||
static int tested = 0, value = 0;
|
||||
if (!tested) {
|
||||
tested = 1;
|
||||
if (systemf("lzma -V %s", redirectArgs) == 0)
|
||||
value = 1;
|
||||
}
|
||||
return (value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Can this platform run the lzop program?
|
||||
*/
|
||||
int
|
||||
canLzop(void)
|
||||
{
|
||||
static int tested = 0, value = 0;
|
||||
if (!tested) {
|
||||
tested = 1;
|
||||
if (systemf("lzop -V %s", redirectArgs) == 0)
|
||||
value = 1;
|
||||
}
|
||||
return (value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Can this platform run the xz program?
|
||||
*/
|
||||
int
|
||||
canXz(void)
|
||||
{
|
||||
static int tested = 0, value = 0;
|
||||
if (!tested) {
|
||||
tested = 1;
|
||||
if (systemf("xz -V %s", redirectArgs) == 0)
|
||||
value = 1;
|
||||
}
|
||||
return (value);
|
||||
@ -2124,7 +2237,7 @@ is_LargeInode(const char *file)
|
||||
/* Use "list.h" to create a list of all tests (functions and names). */
|
||||
#undef DEFINE_TEST
|
||||
#define DEFINE_TEST(n) { n, #n, 0 },
|
||||
struct { void (*func)(void); const char *name; int failures; } tests[] = {
|
||||
struct test_list_t tests[] = {
|
||||
#include "list.h"
|
||||
};
|
||||
|
||||
@ -2377,65 +2490,6 @@ get_refdir(const char *d)
|
||||
return strdup(buff);
|
||||
}
|
||||
|
||||
static int
|
||||
get_test_set(int *test_set, int limit, const char *test)
|
||||
{
|
||||
int start, end;
|
||||
int idx = 0;
|
||||
|
||||
if (test == NULL) {
|
||||
/* Default: Run all tests. */
|
||||
for (;idx < limit; idx++)
|
||||
test_set[idx] = idx;
|
||||
return (limit);
|
||||
}
|
||||
if (*test >= '0' && *test <= '9') {
|
||||
const char *vp = test;
|
||||
start = 0;
|
||||
while (*vp >= '0' && *vp <= '9') {
|
||||
start *= 10;
|
||||
start += *vp - '0';
|
||||
++vp;
|
||||
}
|
||||
if (*vp == '\0') {
|
||||
end = start;
|
||||
} else if (*vp == '-') {
|
||||
++vp;
|
||||
if (*vp == '\0') {
|
||||
end = limit - 1;
|
||||
} else {
|
||||
end = 0;
|
||||
while (*vp >= '0' && *vp <= '9') {
|
||||
end *= 10;
|
||||
end += *vp - '0';
|
||||
++vp;
|
||||
}
|
||||
}
|
||||
} else
|
||||
return (-1);
|
||||
if (start < 0 || end >= limit || start > end)
|
||||
return (-1);
|
||||
while (start <= end)
|
||||
test_set[idx++] = start++;
|
||||
} else {
|
||||
size_t len = strlen(test);
|
||||
for (start = 0; start < limit; ++start) {
|
||||
const char *name = tests[start].name;
|
||||
const char *p;
|
||||
|
||||
while ((p = strchr(name, test[0])) != NULL) {
|
||||
if (strncmp(p, test, len) == 0) {
|
||||
test_set[idx++] = start;
|
||||
break;
|
||||
} else
|
||||
name = p + 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return ((idx == 0)?-1:idx);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@ -2720,10 +2774,11 @@ main(int argc, char **argv)
|
||||
do {
|
||||
int test_num;
|
||||
|
||||
test_num = get_test_set(test_set, limit, *argv);
|
||||
test_num = get_test_set(test_set, limit, *argv, tests);
|
||||
if (test_num < 0) {
|
||||
printf("*** INVALID Test %s\n", *argv);
|
||||
free(refdir_alloc);
|
||||
free(testprogdir);
|
||||
usage(progname);
|
||||
return (1);
|
||||
}
|
||||
|
@ -266,11 +266,29 @@ void sleepUntilAfter(time_t);
|
||||
/* Return true if this platform can create symlinks. */
|
||||
int canSymlink(void);
|
||||
|
||||
/* Return true if this platform can run the "bzip2" program. */
|
||||
int canBzip2(void);
|
||||
|
||||
/* Return true if this platform can run the "grzip" program. */
|
||||
int canGrzip(void);
|
||||
|
||||
/* Return true if this platform can run the "gzip" program. */
|
||||
int canGzip(void);
|
||||
|
||||
/* Return true if this platform can run the "gunzip" program. */
|
||||
int canGunzip(void);
|
||||
/* Return true if this platform can run the "lrzip" program. */
|
||||
int canLrzip(void);
|
||||
|
||||
/* Return true if this platform can run the "lzip" program. */
|
||||
int canLzip(void);
|
||||
|
||||
/* Return true if this platform can run the "lzma" program. */
|
||||
int canLzma(void);
|
||||
|
||||
/* Return true if this platform can run the "lzop" program. */
|
||||
int canLzop(void);
|
||||
|
||||
/* Return true if this platform can run the "xz" program. */
|
||||
int canXz(void);
|
||||
|
||||
/* Return true if this filesystem can handle nodump flags. */
|
||||
int canNodump(void);
|
||||
|
@ -148,7 +148,7 @@ DEFINE_TEST(test_basic)
|
||||
strncat(result,
|
||||
"bsdcpio: file: large inode number truncated: "
|
||||
"Numerical result out of range\n",
|
||||
sizeof(result) - strlen(result));
|
||||
sizeof(result) - strlen(result) -1);
|
||||
|
||||
/* hardlink to above file. */
|
||||
assertMakeHardlink("linkfile", "file");
|
||||
@ -157,7 +157,7 @@ DEFINE_TEST(test_basic)
|
||||
strncat(result,
|
||||
"bsdcpio: linkfile: large inode number truncated: "
|
||||
"Numerical result out of range\n",
|
||||
sizeof(result) - strlen(result));
|
||||
sizeof(result) - strlen(result) -1);
|
||||
|
||||
/* Symlink to above file. */
|
||||
if (canSymlink()) {
|
||||
@ -167,7 +167,7 @@ DEFINE_TEST(test_basic)
|
||||
strncat(result,
|
||||
"bsdcpio: symlink: large inode number truncated: "
|
||||
"Numerical result out of range\n",
|
||||
sizeof(result) - strlen(result));
|
||||
sizeof(result) - strlen(result) -1);
|
||||
}
|
||||
|
||||
/* Another file with different permissions. */
|
||||
@ -177,7 +177,7 @@ DEFINE_TEST(test_basic)
|
||||
strncat(result,
|
||||
"bsdcpio: file2: large inode number truncated: "
|
||||
"Numerical result out of range\n",
|
||||
sizeof(result) - strlen(result));
|
||||
sizeof(result) - strlen(result) -1);
|
||||
|
||||
/* Directory. */
|
||||
assertMakeDir("dir", 0775);
|
||||
@ -186,8 +186,8 @@ DEFINE_TEST(test_basic)
|
||||
strncat(result,
|
||||
"bsdcpio: dir: large inode number truncated: "
|
||||
"Numerical result out of range\n",
|
||||
sizeof(result) - strlen(result));
|
||||
strncat(result, "2 blocks\n", sizeof(result) - strlen(result));
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result, "2 blocks\n", sizeof(result) - strlen(result) -1);
|
||||
|
||||
/* All done. */
|
||||
fclose(filelist);
|
||||
|
7
contrib/libarchive/cpio/test/test_extract.cpio.Z.uu
Normal file
7
contrib/libarchive/cpio/test/test_extract.cpio.Z.uu
Normal file
@ -0,0 +1,7 @@
|
||||
begin 664 test_extract.cpio.Z
|
||||
M'YV0,&X$'`B#!@P8,0XJC)$0A@T;!A'>J+%PHL*%%P_&D`%CAHP;!F7,B*C0
|
||||
M1L:+(LVD85,F!H`Q;]S0*2-S#H@W9D"H9!G#A8*!`@46U)A11L.'$6-8U+CT
|
||||
M8D.G'#V"A"&#!L6+)D\>3+FRC(R7,6?6O)ESIU>?0`EJ7<N6[=.V:V/,@$M%
|
||||
A2I`D3(I("<$7@-^_@`,+'DRXL.'#B!,K7LRXL>/'D!4#
|
||||
`
|
||||
end
|
7
contrib/libarchive/cpio/test/test_extract.cpio.bz2.uu
Normal file
7
contrib/libarchive/cpio/test/test_extract.cpio.bz2.uu
Normal file
@ -0,0 +1,7 @@
|
||||
begin 664 test_extract.cpio.bz2
|
||||
M0EIH.3%!629365?=.4@``#G_@G*0(`#@`7^`(B04``LEC```!"``E`E(>I,H
|
||||
M::'J&@_4C3:@E$AD#0&@&@%"E;V/1!XIP>#C9T[41`4PQ1A`@S*4F&BD@B0T
|
||||
MBA$$-:\/@BQGNKU1G@%#`G+N0R%$JTHG(XBRB%1$V8F4#F_IWT=S4+ERVL(?
|
||||
40V!'@1L4+AO_B[DBG"A(*^Z<I```
|
||||
`
|
||||
end
|
7
contrib/libarchive/cpio/test/test_extract.cpio.grz.uu
Normal file
7
contrib/libarchive/cpio/test/test_extract.cpio.grz.uu
Normal file
@ -0,0 +1,7 @@
|
||||
begin 644 test_extract.cpio.grz
|
||||
M1U)::7!)20`"!#HI``(``*P-```&`0``"````&X````B%2.02C`PK`#__..F
|
||||
MI;8=99?N!6`:IQJ:XU/T"`W`B"?N/D9-0K6VN/D\.2>0,#J&)3G"\^YE?X_'
|
||||
M_K._F':0[`DL%IQ=<,Z-JH>V$S,?.[`&42C7]J^XQ@9OY!Z$!$^JLQPKZU[:
|
||||
/!M,+.$MY:Y(HS<<]U`&`
|
||||
`
|
||||
end
|
7
contrib/libarchive/cpio/test/test_extract.cpio.gz.uu
Normal file
7
contrib/libarchive/cpio/test/test_extract.cpio.gz.uu
Normal file
@ -0,0 +1,7 @@
|
||||
begin 664 test_extract.cpio.gz
|
||||
M'XL("`5X<E```W1E<W1?97AT<F%C="YC<&EO`#,P-P!!`Q,#`T,#$#`$4F9F
|
||||
M(*ZYJ0&,-(#)&A@:&1@;F9L8&!F;@/EF!C!@9)R6F9-JR)"<GU>2FE=2K)"?
|
||||
MI@`6T>,R0+?$B$A+3$RQ6F*$88D1PA*"P!"[J#$2)R3(T=/'-4A149%AF`,`
|
||||
(305ZBP`"````
|
||||
`
|
||||
end
|
8
contrib/libarchive/cpio/test/test_extract.cpio.lrz.uu
Normal file
8
contrib/libarchive/cpio/test/test_extract.cpio.lrz.uu
Normal file
@ -0,0 +1,8 @@
|
||||
begin 664 test_extract.cpio.lrz
|
||||
M3%):20`&``(``````````%T````!`0```@$`$`,`````#@`#`````"\``QH`
|
||||
M&@````!W``$G`&4``#,``2(``0``#0$````U<-`Y!F$`MP$````8#=\$8#<1
|
||||
MR/BL39$D4M>["H7&@4%L/4*_(*VGB*YU>?RX.9]HL86'.A)H@Y;Z\^$?M^8_
|
||||
M!/-;62G.*7*A&A!_ENZ8$7]O-M7_.FTRC%BCGC95:6'9ZH3)QSCR4RX42P!`
|
||||
/-E>/7"L[:OY"/A924S4$
|
||||
`
|
||||
end
|
6
contrib/libarchive/cpio/test/test_extract.cpio.lz.uu
Normal file
6
contrib/libarchive/cpio/test/test_extract.cpio.lz.uu
Normal file
@ -0,0 +1,6 @@
|
||||
begin 664 test_extract.cpio.lz
|
||||
M3%I)4`$,`!@-WP1@-Q'(^*Q-D212U[L*A<:!06P]0K\@K:>(KG5Y_+@YGVBQ
|
||||
MA8<Z$FB#EOKSX1^WYC\$\UM9*<XI<J$:$'^B>;_>8N3MLP="$0SJ#QKYB?@8
|
||||
G]@'$$7\&W^T*+9?6B=?__M$G@$T%>HL``@```````($`````````
|
||||
`
|
||||
end
|
6
contrib/libarchive/cpio/test/test_extract.cpio.lzma.uu
Normal file
6
contrib/libarchive/cpio/test/test_extract.cpio.lzma.uu
Normal file
@ -0,0 +1,6 @@
|
||||
begin 664 test_extract.cpio.lzma
|
||||
M70``@`#__________P`8#=\$8#<1R/BL39$D4M>["H7&@4%L/4*_(*VGB*YU
|
||||
M>?RX.9]HL86'.A)H@Y;Z\^$?M^8_!/-;62G.*7*A&A!_HGF_WF+D[;.+!OW3
|
||||
:T_2I)V(;K[FNL#'W%T+L;ATS`A*3__[1Z```
|
||||
`
|
||||
end
|
9
contrib/libarchive/cpio/test/test_extract.cpio.lzo.uu
Normal file
9
contrib/libarchive/cpio/test/test_extract.cpio.lzo.uu
Normal file
@ -0,0 +1,9 @@
|
||||
begin 664 test_extract.cpio.lzo
|
||||
MB4Q:3P`-"AH*$#`@8`E``04#```!``"!M%!R>-T`````$71E<W1?97AT<F%C
|
||||
M="YC<&EOOH$+9````@````"DIR,^[`HP-S`W,#<P,#0P,#$P8``#,3$P,#8V
|
||||
M>`$#-S4P,#`QE`!@`7`#"C`P,3(P,S(W-#`R,S2!`C:4`'````(R,V9I;&4Q
|
||||
M`&-O;G1E;G1S(&]F((8"+@HOD0$R(`:1`31J$#`P+I$!,B^1`3(HD`%L$3L,
|
||||
M`+P<+HH`,3,I1``(5%)!24Q%4B$A(0`@JP````$`````````````````````
|
||||
*````$0``````````
|
||||
`
|
||||
end
|
7
contrib/libarchive/cpio/test/test_extract.cpio.xz.uu
Normal file
7
contrib/libarchive/cpio/test/test_extract.cpio.xz.uu
Normal file
@ -0,0 +1,7 @@
|
||||
begin 664 test_extract.cpio.xz
|
||||
M_3=Z6%H```3FUK1&`@`A`18```!T+^6CX`'_`&%=`!@-WP1@-Q'(^*Q-D212
|
||||
MU[L*A<:!06P]0K\@K:>(KG5Y_+@YGVBQA8<Z$FB#EOKSX1^WYC\$\UM9*<XI
|
||||
M<J$:$'^B>;_>8N3MLXL&_=/3]*DG8ANON:ZP,?<70NQN'3"CP@``````J9FA
|
||||
=#1$]4L<``7V`!`````?M;4JQQ&?[`@`````$65H`
|
||||
`
|
||||
end
|
42
contrib/libarchive/cpio/test/test_extract_cpio_Z.c
Normal file
42
contrib/libarchive/cpio/test/test_extract_cpio_Z.c
Normal file
@ -0,0 +1,42 @@
|
||||
/*-
|
||||
* Copyright (c) 2012 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
DEFINE_TEST(test_extract_cpio_Z)
|
||||
{
|
||||
const char *reffile = "test_extract.cpio.Z";
|
||||
|
||||
extract_reference_file(reffile);
|
||||
assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err",
|
||||
testprog, reffile));
|
||||
|
||||
assertFileExists("file1");
|
||||
assertTextFileContents("contents of file1.\n", "file1");
|
||||
assertFileExists("file2");
|
||||
assertTextFileContents("contents of file2.\n", "file2");
|
||||
assertEmptyFile("test.out");
|
||||
assertTextFileContents("1 block\n", "test.err");
|
||||
}
|
48
contrib/libarchive/cpio/test/test_extract_cpio_bz2.c
Normal file
48
contrib/libarchive/cpio/test/test_extract_cpio_bz2.c
Normal file
@ -0,0 +1,48 @@
|
||||
/*-
|
||||
* Copyright (c) 2012 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
DEFINE_TEST(test_extract_cpio_bz2)
|
||||
{
|
||||
const char *reffile = "test_extract.cpio.bz2";
|
||||
int f;
|
||||
|
||||
extract_reference_file(reffile);
|
||||
f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile);
|
||||
if (f == 0 || canBzip2()) {
|
||||
assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err",
|
||||
testprog, reffile));
|
||||
|
||||
assertFileExists("file1");
|
||||
assertTextFileContents("contents of file1.\n", "file1");
|
||||
assertFileExists("file2");
|
||||
assertTextFileContents("contents of file2.\n", "file2");
|
||||
assertEmptyFile("test.out");
|
||||
assertTextFileContents("1 block\n", "test.err");
|
||||
} else {
|
||||
skipping("It seems bzip2 is not supported on this platform");
|
||||
}
|
||||
}
|
48
contrib/libarchive/cpio/test/test_extract_cpio_grz.c
Normal file
48
contrib/libarchive/cpio/test/test_extract_cpio_grz.c
Normal file
@ -0,0 +1,48 @@
|
||||
/*-
|
||||
* Copyright (c) 2012 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
DEFINE_TEST(test_extract_cpio_grz)
|
||||
{
|
||||
const char *reffile = "test_extract.cpio.grz";
|
||||
int f;
|
||||
|
||||
extract_reference_file(reffile);
|
||||
f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile);
|
||||
if (f == 0 || canGrzip()) {
|
||||
assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err",
|
||||
testprog, reffile));
|
||||
|
||||
assertFileExists("file1");
|
||||
assertTextFileContents("contents of file1.\n", "file1");
|
||||
assertFileExists("file2");
|
||||
assertTextFileContents("contents of file2.\n", "file2");
|
||||
assertEmptyFile("test.out");
|
||||
assertTextFileContents("1 block\n", "test.err");
|
||||
} else {
|
||||
skipping("It seems grzip is not supported on this platform");
|
||||
}
|
||||
}
|
48
contrib/libarchive/cpio/test/test_extract_cpio_gz.c
Normal file
48
contrib/libarchive/cpio/test/test_extract_cpio_gz.c
Normal file
@ -0,0 +1,48 @@
|
||||
/*-
|
||||
* Copyright (c) 2012 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
DEFINE_TEST(test_extract_cpio_gz)
|
||||
{
|
||||
const char *reffile = "test_extract.cpio.gz";
|
||||
int f;
|
||||
|
||||
extract_reference_file(reffile);
|
||||
f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile);
|
||||
if (f == 0 || canGzip()) {
|
||||
assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err",
|
||||
testprog, reffile));
|
||||
|
||||
assertFileExists("file1");
|
||||
assertTextFileContents("contents of file1.\n", "file1");
|
||||
assertFileExists("file2");
|
||||
assertTextFileContents("contents of file2.\n", "file2");
|
||||
assertEmptyFile("test.out");
|
||||
assertTextFileContents("1 block\n", "test.err");
|
||||
} else {
|
||||
skipping("It seems gzip is not supported on this platform");
|
||||
}
|
||||
}
|
48
contrib/libarchive/cpio/test/test_extract_cpio_lrz.c
Normal file
48
contrib/libarchive/cpio/test/test_extract_cpio_lrz.c
Normal file
@ -0,0 +1,48 @@
|
||||
/*-
|
||||
* Copyright (c) 2012 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
DEFINE_TEST(test_extract_cpio_lrz)
|
||||
{
|
||||
const char *reffile = "test_extract.cpio.lrz";
|
||||
int f;
|
||||
|
||||
extract_reference_file(reffile);
|
||||
f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile);
|
||||
if (f == 0 || canLrzip()) {
|
||||
assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err",
|
||||
testprog, reffile));
|
||||
|
||||
assertFileExists("file1");
|
||||
assertTextFileContents("contents of file1.\n", "file1");
|
||||
assertFileExists("file2");
|
||||
assertTextFileContents("contents of file2.\n", "file2");
|
||||
assertEmptyFile("test.out");
|
||||
assertTextFileContents("1 block\n", "test.err");
|
||||
} else {
|
||||
skipping("It seems lrzip is not supported on this platform");
|
||||
}
|
||||
}
|
48
contrib/libarchive/cpio/test/test_extract_cpio_lz.c
Normal file
48
contrib/libarchive/cpio/test/test_extract_cpio_lz.c
Normal file
@ -0,0 +1,48 @@
|
||||
/*-
|
||||
* Copyright (c) 2012 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
DEFINE_TEST(test_extract_cpio_lz)
|
||||
{
|
||||
const char *reffile = "test_extract.cpio.lz";
|
||||
int f;
|
||||
|
||||
extract_reference_file(reffile);
|
||||
f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile);
|
||||
if (f == 0 || canLzip()) {
|
||||
assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err",
|
||||
testprog, reffile));
|
||||
|
||||
assertFileExists("file1");
|
||||
assertTextFileContents("contents of file1.\n", "file1");
|
||||
assertFileExists("file2");
|
||||
assertTextFileContents("contents of file2.\n", "file2");
|
||||
assertEmptyFile("test.out");
|
||||
assertTextFileContents("1 block\n", "test.err");
|
||||
} else {
|
||||
skipping("It seems lzip is not supported on this platform");
|
||||
}
|
||||
}
|
48
contrib/libarchive/cpio/test/test_extract_cpio_lzma.c
Normal file
48
contrib/libarchive/cpio/test/test_extract_cpio_lzma.c
Normal file
@ -0,0 +1,48 @@
|
||||
/*-
|
||||
* Copyright (c) 2012 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
DEFINE_TEST(test_extract_cpio_lzma)
|
||||
{
|
||||
const char *reffile = "test_extract.cpio.lzma";
|
||||
int f;
|
||||
|
||||
extract_reference_file(reffile);
|
||||
f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile);
|
||||
if (f == 0 || canLzma()) {
|
||||
assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err",
|
||||
testprog, reffile));
|
||||
|
||||
assertFileExists("file1");
|
||||
assertTextFileContents("contents of file1.\n", "file1");
|
||||
assertFileExists("file2");
|
||||
assertTextFileContents("contents of file2.\n", "file2");
|
||||
assertEmptyFile("test.out");
|
||||
assertTextFileContents("1 block\n", "test.err");
|
||||
} else {
|
||||
skipping("It seems lzma is not supported on this platform");
|
||||
}
|
||||
}
|
48
contrib/libarchive/cpio/test/test_extract_cpio_lzo.c
Normal file
48
contrib/libarchive/cpio/test/test_extract_cpio_lzo.c
Normal file
@ -0,0 +1,48 @@
|
||||
/*-
|
||||
* Copyright (c) 2012 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
DEFINE_TEST(test_extract_cpio_lzo)
|
||||
{
|
||||
const char *reffile = "test_extract.cpio.lrz";
|
||||
int f;
|
||||
|
||||
extract_reference_file(reffile);
|
||||
f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile);
|
||||
if (f == 0 || canLzop()) {
|
||||
assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err",
|
||||
testprog, reffile));
|
||||
|
||||
assertFileExists("file1");
|
||||
assertTextFileContents("contents of file1.\n", "file1");
|
||||
assertFileExists("file2");
|
||||
assertTextFileContents("contents of file2.\n", "file2");
|
||||
assertEmptyFile("test.out");
|
||||
assertTextFileContents("1 block\n", "test.err");
|
||||
} else {
|
||||
skipping("It seems lzop is not supported on this platform");
|
||||
}
|
||||
}
|
48
contrib/libarchive/cpio/test/test_extract_cpio_xz.c
Normal file
48
contrib/libarchive/cpio/test/test_extract_cpio_xz.c
Normal file
@ -0,0 +1,48 @@
|
||||
/*-
|
||||
* Copyright (c) 2012 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
DEFINE_TEST(test_extract_cpio_xz)
|
||||
{
|
||||
const char *reffile = "test_extract.cpio.xz";
|
||||
int f;
|
||||
|
||||
extract_reference_file(reffile);
|
||||
f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile);
|
||||
if (f == 0 || canXz()) {
|
||||
assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err",
|
||||
testprog, reffile));
|
||||
|
||||
assertFileExists("file1");
|
||||
assertTextFileContents("contents of file1.\n", "file1");
|
||||
assertFileExists("file2");
|
||||
assertTextFileContents("contents of file2.\n", "file2");
|
||||
assertEmptyFile("test.out");
|
||||
assertTextFileContents("1 block\n", "test.err");
|
||||
} else {
|
||||
skipping("It seems xz is not supported on this platform");
|
||||
}
|
||||
}
|
@ -157,9 +157,9 @@ DEFINE_TEST(test_format_newc)
|
||||
|
||||
/* Verify that nothing went to stderr. */
|
||||
if (canSymlink()) {
|
||||
strncat(result, "2 blocks\n", sizeof(result) - strlen(result));
|
||||
strncat(result, "2 blocks\n", sizeof(result) - strlen(result) -1);
|
||||
} else {
|
||||
strncat(result, "1 block\n", sizeof(result) - strlen(result));
|
||||
strncat(result, "1 block\n", sizeof(result) - strlen(result) -1);
|
||||
}
|
||||
assertTextFileContents(result, "newc.err");
|
||||
|
||||
|
54
contrib/libarchive/cpio/test/test_option_b64encode.c
Normal file
54
contrib/libarchive/cpio/test/test_option_b64encode.c
Normal file
@ -0,0 +1,54 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* Copyright (c) 2012 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
DEFINE_TEST(test_option_b64encode)
|
||||
{
|
||||
char *p;
|
||||
size_t s;
|
||||
|
||||
/* Create a file. */
|
||||
assertMakeFile("f", 0644, "a");
|
||||
|
||||
/* Archive it with compress compression and uuencode. */
|
||||
assertEqualInt(0,
|
||||
systemf("echo f | %s -o -Z --b64encode >archive.out 2>archive.err",
|
||||
testprog));
|
||||
/* Check that the archive file has an uuencode signature. */
|
||||
p = slurpfile(&s, "archive.out");
|
||||
assert(s > 2);
|
||||
assertEqualMem(p, "begin-base64 644", 16);
|
||||
|
||||
/* Archive it with uuencode only. */
|
||||
assertEqualInt(0,
|
||||
systemf("echo f | %s -o --b64encode >archive.out 2>archive.err",
|
||||
testprog));
|
||||
/* Check that the archive file has an uuencode signature. */
|
||||
p = slurpfile(&s, "archive.out");
|
||||
assert(s > 2);
|
||||
assertEqualMem(p, "begin-base64 644", 16);
|
||||
}
|
52
contrib/libarchive/cpio/test/test_option_grzip.c
Normal file
52
contrib/libarchive/cpio/test/test_option_grzip.c
Normal file
@ -0,0 +1,52 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* Copyright (c) 2012 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
DEFINE_TEST(test_option_grzip)
|
||||
{
|
||||
char *p;
|
||||
size_t s;
|
||||
|
||||
if (!canGrzip()) {
|
||||
skipping("grzip is not supported on this platform");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create a file. */
|
||||
assertMakeFile("f", 0644, "a");
|
||||
|
||||
/* Archive it with grzip compression. */
|
||||
assertEqualInt(0,
|
||||
systemf("echo f | %s -o --grzip >archive.out 2>archive.err",
|
||||
testprog));
|
||||
p = slurpfile(&s, "archive.err");
|
||||
p[s] = '\0';
|
||||
/* Check that the archive file has an grzip signature. */
|
||||
p = slurpfile(&s, "archive.out");
|
||||
assert(s > 2);
|
||||
assertEqualMem(p, "GRZipII\x00\x02\x04:)", 12);
|
||||
}
|
52
contrib/libarchive/cpio/test/test_option_lrzip.c
Normal file
52
contrib/libarchive/cpio/test/test_option_lrzip.c
Normal file
@ -0,0 +1,52 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* Copyright (c) 2012 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
DEFINE_TEST(test_option_lrzip)
|
||||
{
|
||||
char *p;
|
||||
size_t s;
|
||||
|
||||
if (!canLrzip()) {
|
||||
skipping("lrzip is not supported on this platform");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create a file. */
|
||||
assertMakeFile("f", 0644, "a");
|
||||
|
||||
/* Archive it with lrzip compression. */
|
||||
assertEqualInt(0,
|
||||
systemf("echo f | %s -o --lrzip >archive.out 2>archive.err",
|
||||
testprog));
|
||||
p = slurpfile(&s, "archive.err");
|
||||
p[s] = '\0';
|
||||
/* Check that the archive file has an lzma signature. */
|
||||
p = slurpfile(&s, "archive.out");
|
||||
assert(s > 2);
|
||||
assertEqualMem(p, "LRZI\x00", 5);
|
||||
}
|
56
contrib/libarchive/cpio/test/test_option_lzop.c
Normal file
56
contrib/libarchive/cpio/test/test_option_lzop.c
Normal file
@ -0,0 +1,56 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* Copyright (c) 2012 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
DEFINE_TEST(test_option_lzop)
|
||||
{
|
||||
char *p;
|
||||
int r;
|
||||
size_t s;
|
||||
|
||||
/* Create a file. */
|
||||
assertMakeFile("f", 0644, "a");
|
||||
|
||||
/* Archive it with lzop compression. */
|
||||
r = systemf("echo f | %s -o --lzop >archive.out 2>archive.err",
|
||||
testprog);
|
||||
p = slurpfile(&s, "archive.err");
|
||||
p[s] = '\0';
|
||||
if (r != 0) {
|
||||
if (!canLzop()) {
|
||||
skipping("lzop is not supported on this platform");
|
||||
return;
|
||||
}
|
||||
failure("--lzop option is broken");
|
||||
assertEqualInt(r, 0);
|
||||
return;
|
||||
}
|
||||
/* Check that the archive file has an lzma signature. */
|
||||
p = slurpfile(&s, "archive.out");
|
||||
assert(s > 2);
|
||||
assertEqualMem(p, "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a", 9);
|
||||
}
|
54
contrib/libarchive/cpio/test/test_option_uuencode.c
Normal file
54
contrib/libarchive/cpio/test/test_option_uuencode.c
Normal file
@ -0,0 +1,54 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* Copyright (c) 2012 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
DEFINE_TEST(test_option_uuencode)
|
||||
{
|
||||
char *p;
|
||||
size_t s;
|
||||
|
||||
/* Create a file. */
|
||||
assertMakeFile("f", 0644, "a");
|
||||
|
||||
/* Archive it with compress compression and uuencode. */
|
||||
assertEqualInt(0,
|
||||
systemf("echo f | %s -o -Z --uuencode >archive.out 2>archive.err",
|
||||
testprog));
|
||||
/* Check that the archive file has an uuencode signature. */
|
||||
p = slurpfile(&s, "archive.out");
|
||||
assert(s > 2);
|
||||
assertEqualMem(p, "begin 644", 9);
|
||||
|
||||
/* Archive it with uuencode only. */
|
||||
assertEqualInt(0,
|
||||
systemf("echo f | %s -o --uuencode >archive.out 2>archive.err",
|
||||
testprog));
|
||||
/* Check that the archive file has an uuencode signature. */
|
||||
p = slurpfile(&s, "archive.out");
|
||||
assert(s > 2);
|
||||
assertEqualMem(p, "begin 644", 9);
|
||||
}
|
57
contrib/libarchive/cpio/test/test_option_xz.c
Normal file
57
contrib/libarchive/cpio/test/test_option_xz.c
Normal file
@ -0,0 +1,57 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* Copyright (c) 2012 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
DEFINE_TEST(test_option_xz)
|
||||
{
|
||||
char *p;
|
||||
int r;
|
||||
size_t s;
|
||||
|
||||
/* Create a file. */
|
||||
assertMakeFile("f", 0644, "a");
|
||||
|
||||
/* Archive it with xz compression. */
|
||||
r = systemf("echo f | %s -o --xz >archive.out 2>archive.err",
|
||||
testprog);
|
||||
p = slurpfile(&s, "archive.err");
|
||||
p[s] = '\0';
|
||||
if (r != 0) {
|
||||
if (strstr(p, "compression not available") != NULL) {
|
||||
skipping("This version of bsdcpio was compiled "
|
||||
"without xz support");
|
||||
return;
|
||||
}
|
||||
failure("--xz option is broken");
|
||||
assertEqualInt(r, 0);
|
||||
return;
|
||||
}
|
||||
/* Check that the archive file has an xz signature. */
|
||||
p = slurpfile(&s, "archive.out");
|
||||
assert(s > 2);
|
||||
assertEqualMem(p, "\xFD\x37\x7A\x58\x5A\x00", 6);
|
||||
}
|
@ -40,9 +40,8 @@ DEFINE_TEST(test_option_y)
|
||||
p = slurpfile(&s, "archive.err");
|
||||
p[s] = '\0';
|
||||
if (r != 0) {
|
||||
if (strstr(p, "compression not available") != NULL) {
|
||||
skipping("This version of bsdcpio was compiled "
|
||||
"without bzip2 support");
|
||||
if (!canBzip2()) {
|
||||
skipping("bzip2 is not supported on this platform");
|
||||
return;
|
||||
}
|
||||
failure("-y option is broken");
|
||||
|
@ -40,9 +40,8 @@ DEFINE_TEST(test_option_z)
|
||||
p = slurpfile(&s, "archive.err");
|
||||
p[s] = '\0';
|
||||
if (r != 0) {
|
||||
if (strstr(p, "compression not available") != NULL) {
|
||||
skipping("This version of bsdcpio was compiled "
|
||||
"without gzip support");
|
||||
if (!canGzip()) {
|
||||
skipping("gzip is not supported on this platform");
|
||||
return;
|
||||
}
|
||||
failure("-z option is broken");
|
||||
|
@ -97,6 +97,12 @@
|
||||
#define __LA_PRINTF(fmtarg, firstvararg) /* nothing */
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ >= 3 && __GNUC_MINOR__ >= 1
|
||||
# define __LA_DEPRECATED __attribute__((deprecated))
|
||||
#else
|
||||
# define __LA_DEPRECATED
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -118,13 +124,13 @@ extern "C" {
|
||||
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
|
||||
*/
|
||||
/* Note: Compiler will complain if this does not match archive_entry.h! */
|
||||
#define ARCHIVE_VERSION_NUMBER 3000004
|
||||
#define ARCHIVE_VERSION_NUMBER 3001002
|
||||
__LA_DECL int archive_version_number(void);
|
||||
|
||||
/*
|
||||
* Textual name/version of the library, useful for version displays.
|
||||
*/
|
||||
#define ARCHIVE_VERSION_STRING "libarchive 3.0.4"
|
||||
#define ARCHIVE_VERSION_STRING "libarchive 3.1.2"
|
||||
__LA_DECL const char * archive_version_string(void);
|
||||
|
||||
/* Declare our basic types. */
|
||||
@ -194,6 +200,13 @@ typedef int archive_open_callback(struct archive *, void *_client_data);
|
||||
|
||||
typedef int archive_close_callback(struct archive *, void *_client_data);
|
||||
|
||||
/* Switches from one client data object to the next/prev client data object.
|
||||
* This is useful for reading from different data blocks such as a set of files
|
||||
* that make up one large file.
|
||||
*/
|
||||
typedef int archive_switch_callback(struct archive *, void *_client_data1,
|
||||
void *_client_data2);
|
||||
|
||||
/*
|
||||
* Codes to identify various stream filters.
|
||||
*/
|
||||
@ -207,6 +220,9 @@ typedef int archive_close_callback(struct archive *, void *_client_data);
|
||||
#define ARCHIVE_FILTER_UU 7
|
||||
#define ARCHIVE_FILTER_RPM 8
|
||||
#define ARCHIVE_FILTER_LZIP 9
|
||||
#define ARCHIVE_FILTER_LRZIP 10
|
||||
#define ARCHIVE_FILTER_LZOP 11
|
||||
#define ARCHIVE_FILTER_GRZIP 12
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
#define ARCHIVE_COMPRESSION_NONE ARCHIVE_FILTER_NONE
|
||||
@ -219,6 +235,7 @@ typedef int archive_close_callback(struct archive *, void *_client_data);
|
||||
#define ARCHIVE_COMPRESSION_UU ARCHIVE_FILTER_UU
|
||||
#define ARCHIVE_COMPRESSION_RPM ARCHIVE_FILTER_RPM
|
||||
#define ARCHIVE_COMPRESSION_LZIP ARCHIVE_FILTER_LZIP
|
||||
#define ARCHIVE_COMPRESSION_LRZIP ARCHIVE_FILTER_LRZIP
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -291,37 +308,49 @@ __LA_DECL struct archive *archive_read_new(void);
|
||||
*/
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
__LA_DECL int archive_read_support_compression_all(struct archive *);
|
||||
__LA_DECL int archive_read_support_compression_bzip2(struct archive *);
|
||||
__LA_DECL int archive_read_support_compression_compress(struct archive *);
|
||||
__LA_DECL int archive_read_support_compression_gzip(struct archive *);
|
||||
__LA_DECL int archive_read_support_compression_lzip(struct archive *);
|
||||
__LA_DECL int archive_read_support_compression_lzma(struct archive *);
|
||||
__LA_DECL int archive_read_support_compression_none(struct archive *);
|
||||
__LA_DECL int archive_read_support_compression_all(struct archive *)
|
||||
__LA_DEPRECATED;
|
||||
__LA_DECL int archive_read_support_compression_bzip2(struct archive *)
|
||||
__LA_DEPRECATED;
|
||||
__LA_DECL int archive_read_support_compression_compress(struct archive *)
|
||||
__LA_DEPRECATED;
|
||||
__LA_DECL int archive_read_support_compression_gzip(struct archive *)
|
||||
__LA_DEPRECATED;
|
||||
__LA_DECL int archive_read_support_compression_lzip(struct archive *)
|
||||
__LA_DEPRECATED;
|
||||
__LA_DECL int archive_read_support_compression_lzma(struct archive *)
|
||||
__LA_DEPRECATED;
|
||||
__LA_DECL int archive_read_support_compression_none(struct archive *)
|
||||
__LA_DEPRECATED;
|
||||
__LA_DECL int archive_read_support_compression_program(struct archive *,
|
||||
const char *command);
|
||||
const char *command) __LA_DEPRECATED;
|
||||
__LA_DECL int archive_read_support_compression_program_signature
|
||||
(struct archive *, const char *,
|
||||
const void * /* match */, size_t);
|
||||
const void * /* match */, size_t) __LA_DEPRECATED;
|
||||
|
||||
__LA_DECL int archive_read_support_compression_rpm(struct archive *);
|
||||
__LA_DECL int archive_read_support_compression_uu(struct archive *);
|
||||
__LA_DECL int archive_read_support_compression_xz(struct archive *);
|
||||
__LA_DECL int archive_read_support_compression_rpm(struct archive *)
|
||||
__LA_DEPRECATED;
|
||||
__LA_DECL int archive_read_support_compression_uu(struct archive *)
|
||||
__LA_DEPRECATED;
|
||||
__LA_DECL int archive_read_support_compression_xz(struct archive *)
|
||||
__LA_DEPRECATED;
|
||||
#endif
|
||||
|
||||
__LA_DECL int archive_read_support_filter_all(struct archive *);
|
||||
__LA_DECL int archive_read_support_filter_bzip2(struct archive *);
|
||||
__LA_DECL int archive_read_support_filter_compress(struct archive *);
|
||||
__LA_DECL int archive_read_support_filter_gzip(struct archive *);
|
||||
__LA_DECL int archive_read_support_filter_grzip(struct archive *);
|
||||
__LA_DECL int archive_read_support_filter_lrzip(struct archive *);
|
||||
__LA_DECL int archive_read_support_filter_lzip(struct archive *);
|
||||
__LA_DECL int archive_read_support_filter_lzma(struct archive *);
|
||||
__LA_DECL int archive_read_support_filter_lzop(struct archive *);
|
||||
__LA_DECL int archive_read_support_filter_none(struct archive *);
|
||||
__LA_DECL int archive_read_support_filter_program(struct archive *,
|
||||
const char *command);
|
||||
__LA_DECL int archive_read_support_filter_program_signature
|
||||
(struct archive *, const char *,
|
||||
(struct archive *, const char * /* cmd */,
|
||||
const void * /* match */, size_t);
|
||||
|
||||
__LA_DECL int archive_read_support_filter_rpm(struct archive *);
|
||||
__LA_DECL int archive_read_support_filter_uu(struct archive *);
|
||||
__LA_DECL int archive_read_support_filter_xz(struct archive *);
|
||||
@ -343,6 +372,17 @@ __LA_DECL int archive_read_support_format_tar(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_xar(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_zip(struct archive *);
|
||||
|
||||
/* Functions to manually set the format and filters to be used. This is
|
||||
* useful to bypass the bidding process when the format and filters to use
|
||||
* is known in advance.
|
||||
*/
|
||||
__LA_DECL int archive_read_set_format(struct archive *, int);
|
||||
__LA_DECL int archive_read_append_filter(struct archive *, int);
|
||||
__LA_DECL int archive_read_append_filter_program(struct archive *,
|
||||
const char *);
|
||||
__LA_DECL int archive_read_append_filter_program_signature
|
||||
(struct archive *, const char *, const void * /* match */, size_t);
|
||||
|
||||
/* Set various callbacks. */
|
||||
__LA_DECL int archive_read_set_open_callback(struct archive *,
|
||||
archive_open_callback *);
|
||||
@ -354,8 +394,23 @@ __LA_DECL int archive_read_set_skip_callback(struct archive *,
|
||||
archive_skip_callback *);
|
||||
__LA_DECL int archive_read_set_close_callback(struct archive *,
|
||||
archive_close_callback *);
|
||||
/* The callback data is provided to all of the callbacks above. */
|
||||
/* Callback used to switch between one data object to the next */
|
||||
__LA_DECL int archive_read_set_switch_callback(struct archive *,
|
||||
archive_switch_callback *);
|
||||
|
||||
/* This sets the first data object. */
|
||||
__LA_DECL int archive_read_set_callback_data(struct archive *, void *);
|
||||
/* This sets data object at specified index */
|
||||
__LA_DECL int archive_read_set_callback_data2(struct archive *, void *,
|
||||
unsigned int);
|
||||
/* This adds a data object at the specified index. */
|
||||
__LA_DECL int archive_read_add_callback_data(struct archive *, void *,
|
||||
unsigned int);
|
||||
/* This appends a data object to the end of list */
|
||||
__LA_DECL int archive_read_append_callback_data(struct archive *, void *);
|
||||
/* This prepends a data object to the beginning of list */
|
||||
__LA_DECL int archive_read_prepend_callback_data(struct archive *, void *);
|
||||
|
||||
/* Opening freezes the callbacks. */
|
||||
__LA_DECL int archive_read_open1(struct archive *);
|
||||
|
||||
@ -375,11 +430,15 @@ __LA_DECL int archive_read_open2(struct archive *, void *_client_data,
|
||||
/* Use this if you know the filename. Note: NULL indicates stdin. */
|
||||
__LA_DECL int archive_read_open_filename(struct archive *,
|
||||
const char *_filename, size_t _block_size);
|
||||
/* Use this for reading multivolume files by filenames.
|
||||
* NOTE: Must be NULL terminated. Sorting is NOT done. */
|
||||
__LA_DECL int archive_read_open_filenames(struct archive *,
|
||||
const char **_filenames, size_t _block_size);
|
||||
__LA_DECL int archive_read_open_filename_w(struct archive *,
|
||||
const wchar_t *_filename, size_t _block_size);
|
||||
/* archive_read_open_file() is a deprecated synonym for ..._open_filename(). */
|
||||
__LA_DECL int archive_read_open_file(struct archive *,
|
||||
const char *_filename, size_t _block_size);
|
||||
const char *_filename, size_t _block_size) __LA_DEPRECATED;
|
||||
/* Read an archive that's stored in memory. */
|
||||
__LA_DECL int archive_read_open_memory(struct archive *,
|
||||
void * buff, size_t size);
|
||||
@ -411,6 +470,9 @@ __LA_DECL __LA_INT64_T archive_read_header_position(struct archive *);
|
||||
__LA_DECL __LA_SSIZE_T archive_read_data(struct archive *,
|
||||
void *, size_t);
|
||||
|
||||
/* Seek within the body of an entry. Similar to lseek(2). */
|
||||
__LA_DECL __LA_INT64_T archive_seek_data(struct archive *, __LA_INT64_T, int);
|
||||
|
||||
/*
|
||||
* A zero-copy version of archive_read_data that also exposes the file offset
|
||||
* of each returned block. Note that the client has no way to specify
|
||||
@ -494,6 +556,12 @@ __LA_DECL int archive_read_set_options(struct archive *_a,
|
||||
/* Default: Do not restore Mac extended metadata. */
|
||||
/* This has no effect except on Mac OS. */
|
||||
#define ARCHIVE_EXTRACT_MAC_METADATA (0x2000)
|
||||
/* Default: Use HFS+ compression if it was compressed. */
|
||||
/* This has no effect except on Mac OS v10.6 or later. */
|
||||
#define ARCHIVE_EXTRACT_NO_HFS_COMPRESSION (0x4000)
|
||||
/* Default: Do not use HFS+ compression if it was not compressed. */
|
||||
/* This has no effect except on Mac OS v10.6 or later. */
|
||||
#define ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED (0x8000)
|
||||
|
||||
__LA_DECL int archive_read_extract(struct archive *, struct archive_entry *,
|
||||
int flags);
|
||||
@ -514,7 +582,7 @@ __LA_DECL int archive_read_close(struct archive *);
|
||||
__LA_DECL int archive_read_free(struct archive *);
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* Synonym for archive_read_free() for backwards compatibility. */
|
||||
__LA_DECL int archive_read_finish(struct archive *);
|
||||
__LA_DECL int archive_read_finish(struct archive *) __LA_DEPRECATED;
|
||||
#endif
|
||||
|
||||
/*-
|
||||
@ -547,27 +615,41 @@ __LA_DECL int archive_write_set_skip_file(struct archive *,
|
||||
__LA_INT64_T, __LA_INT64_T);
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
__LA_DECL int archive_write_set_compression_bzip2(struct archive *);
|
||||
__LA_DECL int archive_write_set_compression_compress(struct archive *);
|
||||
__LA_DECL int archive_write_set_compression_gzip(struct archive *);
|
||||
__LA_DECL int archive_write_set_compression_lzip(struct archive *);
|
||||
__LA_DECL int archive_write_set_compression_lzma(struct archive *);
|
||||
__LA_DECL int archive_write_set_compression_none(struct archive *);
|
||||
__LA_DECL int archive_write_set_compression_bzip2(struct archive *)
|
||||
__LA_DEPRECATED;
|
||||
__LA_DECL int archive_write_set_compression_compress(struct archive *)
|
||||
__LA_DEPRECATED;
|
||||
__LA_DECL int archive_write_set_compression_gzip(struct archive *)
|
||||
__LA_DEPRECATED;
|
||||
__LA_DECL int archive_write_set_compression_lzip(struct archive *)
|
||||
__LA_DEPRECATED;
|
||||
__LA_DECL int archive_write_set_compression_lzma(struct archive *)
|
||||
__LA_DEPRECATED;
|
||||
__LA_DECL int archive_write_set_compression_none(struct archive *)
|
||||
__LA_DEPRECATED;
|
||||
__LA_DECL int archive_write_set_compression_program(struct archive *,
|
||||
const char *cmd);
|
||||
__LA_DECL int archive_write_set_compression_xz(struct archive *);
|
||||
const char *cmd) __LA_DEPRECATED;
|
||||
__LA_DECL int archive_write_set_compression_xz(struct archive *)
|
||||
__LA_DEPRECATED;
|
||||
#endif
|
||||
|
||||
/* A convenience function to set the filter based on the code. */
|
||||
__LA_DECL int archive_write_add_filter(struct archive *, int filter_code);
|
||||
__LA_DECL int archive_write_add_filter_by_name(struct archive *,
|
||||
const char *name);
|
||||
__LA_DECL int archive_write_add_filter_b64encode(struct archive *);
|
||||
__LA_DECL int archive_write_add_filter_bzip2(struct archive *);
|
||||
__LA_DECL int archive_write_add_filter_compress(struct archive *);
|
||||
__LA_DECL int archive_write_add_filter_grzip(struct archive *);
|
||||
__LA_DECL int archive_write_add_filter_gzip(struct archive *);
|
||||
__LA_DECL int archive_write_add_filter_lrzip(struct archive *);
|
||||
__LA_DECL int archive_write_add_filter_lzip(struct archive *);
|
||||
__LA_DECL int archive_write_add_filter_lzma(struct archive *);
|
||||
__LA_DECL int archive_write_add_filter_lzop(struct archive *);
|
||||
__LA_DECL int archive_write_add_filter_none(struct archive *);
|
||||
__LA_DECL int archive_write_add_filter_program(struct archive *,
|
||||
const char *cmd);
|
||||
__LA_DECL int archive_write_add_filter_uuencode(struct archive *);
|
||||
__LA_DECL int archive_write_add_filter_xz(struct archive *);
|
||||
|
||||
|
||||
@ -584,14 +666,18 @@ __LA_DECL int archive_write_set_format_cpio_newc(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_gnutar(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_iso9660(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_mtree(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_mtree_classic(struct archive *);
|
||||
/* TODO: int archive_write_set_format_old_tar(struct archive *); */
|
||||
__LA_DECL int archive_write_set_format_pax(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_pax_restricted(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_shar(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_shar_dump(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_ustar(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_v7tar(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_xar(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_zip(struct archive *);
|
||||
__LA_DECL int archive_write_zip_set_compression_deflate(struct archive *);
|
||||
__LA_DECL int archive_write_zip_set_compression_store(struct archive *);
|
||||
__LA_DECL int archive_write_open(struct archive *, void *,
|
||||
archive_open_callback *, archive_write_callback *,
|
||||
archive_close_callback *);
|
||||
@ -600,7 +686,8 @@ __LA_DECL int archive_write_open_filename(struct archive *, const char *_file);
|
||||
__LA_DECL int archive_write_open_filename_w(struct archive *,
|
||||
const wchar_t *_file);
|
||||
/* A deprecated synonym for archive_write_open_filename() */
|
||||
__LA_DECL int archive_write_open_file(struct archive *, const char *_file);
|
||||
__LA_DECL int archive_write_open_file(struct archive *, const char *_file)
|
||||
__LA_DEPRECATED;
|
||||
__LA_DECL int archive_write_open_FILE(struct archive *, FILE *);
|
||||
/* _buffSize is the size of the buffer, _used refers to a variable that
|
||||
* will be updated after each write into the buffer. */
|
||||
@ -622,12 +709,16 @@ __LA_DECL __LA_SSIZE_T archive_write_data_block(struct archive *,
|
||||
|
||||
__LA_DECL int archive_write_finish_entry(struct archive *);
|
||||
__LA_DECL int archive_write_close(struct archive *);
|
||||
/* Marks the archive as FATAL so that a subsequent free() operation
|
||||
* won't try to close() cleanly. Provides a fast abort capability
|
||||
* when the client discovers that things have gone wrong. */
|
||||
__LA_DECL int archive_write_fail(struct archive *);
|
||||
/* This can fail if the archive wasn't already closed, in which case
|
||||
* archive_write_free() will implicitly call archive_write_close(). */
|
||||
__LA_DECL int archive_write_free(struct archive *);
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* Synonym for archive_write_free() for backwards compatibility. */
|
||||
__LA_DECL int archive_write_finish(struct archive *);
|
||||
__LA_DECL int archive_write_finish(struct archive *) __LA_DEPRECATED;
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -806,13 +897,17 @@ __LA_DECL const char * archive_filter_name(struct archive *, int);
|
||||
/* These don't properly handle multiple filters, so are deprecated and
|
||||
* will eventually be removed. */
|
||||
/* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, -1); */
|
||||
__LA_DECL __LA_INT64_T archive_position_compressed(struct archive *);
|
||||
__LA_DECL __LA_INT64_T archive_position_compressed(struct archive *)
|
||||
__LA_DEPRECATED;
|
||||
/* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, 0); */
|
||||
__LA_DECL __LA_INT64_T archive_position_uncompressed(struct archive *);
|
||||
__LA_DECL __LA_INT64_T archive_position_uncompressed(struct archive *)
|
||||
__LA_DEPRECATED;
|
||||
/* As of libarchive 3.0, this is an alias for archive_filter_name(a, 0); */
|
||||
__LA_DECL const char *archive_compression_name(struct archive *);
|
||||
__LA_DECL const char *archive_compression_name(struct archive *)
|
||||
__LA_DEPRECATED;
|
||||
/* As of libarchive 3.0, this is an alias for archive_filter_code(a, 0); */
|
||||
__LA_DECL int archive_compression(struct archive *);
|
||||
__LA_DECL int archive_compression(struct archive *)
|
||||
__LA_DEPRECATED;
|
||||
#endif
|
||||
|
||||
__LA_DECL int archive_errno(struct archive *);
|
||||
|
227
contrib/libarchive/libarchive/archive_cmdline.c
Normal file
227
contrib/libarchive/libarchive/archive_cmdline.c
Normal file
@ -0,0 +1,227 @@
|
||||
/*-
|
||||
* Copyright (c) 2012 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_cmdline_private.h"
|
||||
#include "archive_string.h"
|
||||
|
||||
static int cmdline_set_path(struct archive_cmdline *, const char *);
|
||||
static int cmdline_add_arg(struct archive_cmdline *, const char *);
|
||||
|
||||
static ssize_t
|
||||
extract_quotation(struct archive_string *as, const char *p)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
for (s = p + 1; *s;) {
|
||||
if (*s == '\\') {
|
||||
if (s[1] != '\0') {
|
||||
archive_strappend_char(as, s[1]);
|
||||
s += 2;
|
||||
} else
|
||||
s++;
|
||||
} else if (*s == '"')
|
||||
break;
|
||||
else {
|
||||
archive_strappend_char(as, s[0]);
|
||||
s++;
|
||||
}
|
||||
}
|
||||
if (*s != '"')
|
||||
return (ARCHIVE_FAILED);/* Invalid sequence. */
|
||||
return ((ssize_t)(s + 1 - p));
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
get_argument(struct archive_string *as, const char *p)
|
||||
{
|
||||
const char *s = p;
|
||||
|
||||
archive_string_empty(as);
|
||||
|
||||
/* Skip beginning space characters. */
|
||||
while (*s != '\0' && *s == ' ')
|
||||
s++;
|
||||
/* Copy non-space characters. */
|
||||
while (*s != '\0' && *s != ' ') {
|
||||
if (*s == '\\') {
|
||||
if (s[1] != '\0') {
|
||||
archive_strappend_char(as, s[1]);
|
||||
s += 2;
|
||||
} else {
|
||||
s++;/* Ignore this character.*/
|
||||
break;
|
||||
}
|
||||
} else if (*s == '"') {
|
||||
ssize_t q = extract_quotation(as, s);
|
||||
if (q < 0)
|
||||
return (ARCHIVE_FAILED);/* Invalid sequence. */
|
||||
s += q;
|
||||
} else {
|
||||
archive_strappend_char(as, s[0]);
|
||||
s++;
|
||||
}
|
||||
}
|
||||
return ((ssize_t)(s - p));
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up command line arguments.
|
||||
* Returns ARChIVE_OK if everything okey.
|
||||
* Returns ARChIVE_FAILED if there is a lack of the `"' terminator or an
|
||||
* empty command line.
|
||||
* Returns ARChIVE_FATAL if no memory.
|
||||
*/
|
||||
int
|
||||
__archive_cmdline_parse(struct archive_cmdline *data, const char *cmd)
|
||||
{
|
||||
struct archive_string as;
|
||||
const char *p;
|
||||
ssize_t al;
|
||||
int r;
|
||||
|
||||
archive_string_init(&as);
|
||||
|
||||
/* Get first argument as a command path. */
|
||||
al = get_argument(&as, cmd);
|
||||
if (al < 0) {
|
||||
r = ARCHIVE_FAILED;/* Invalid sequence. */
|
||||
goto exit_function;
|
||||
}
|
||||
if (archive_strlen(&as) == 0) {
|
||||
r = ARCHIVE_FAILED;/* An empty command path. */
|
||||
goto exit_function;
|
||||
}
|
||||
r = cmdline_set_path(data, as.s);
|
||||
if (r != ARCHIVE_OK)
|
||||
goto exit_function;
|
||||
p = strrchr(as.s, '/');
|
||||
if (p == NULL)
|
||||
p = as.s;
|
||||
else
|
||||
p++;
|
||||
r = cmdline_add_arg(data, p);
|
||||
if (r != ARCHIVE_OK)
|
||||
goto exit_function;
|
||||
cmd += al;
|
||||
|
||||
for (;;) {
|
||||
al = get_argument(&as, cmd);
|
||||
if (al < 0) {
|
||||
r = ARCHIVE_FAILED;/* Invalid sequence. */
|
||||
goto exit_function;
|
||||
}
|
||||
if (al == 0)
|
||||
break;
|
||||
cmd += al;
|
||||
if (archive_strlen(&as) == 0 && *cmd == '\0')
|
||||
break;
|
||||
r = cmdline_add_arg(data, as.s);
|
||||
if (r != ARCHIVE_OK)
|
||||
goto exit_function;
|
||||
}
|
||||
r = ARCHIVE_OK;
|
||||
exit_function:
|
||||
archive_string_free(&as);
|
||||
return (r);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the program path.
|
||||
*/
|
||||
static int
|
||||
cmdline_set_path(struct archive_cmdline *data, const char *path)
|
||||
{
|
||||
char *newptr;
|
||||
|
||||
newptr = realloc(data->path, strlen(path) + 1);
|
||||
if (newptr == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
data->path = newptr;
|
||||
strcpy(data->path, path);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a argument for the program.
|
||||
*/
|
||||
static int
|
||||
cmdline_add_arg(struct archive_cmdline *data, const char *arg)
|
||||
{
|
||||
char **newargv;
|
||||
|
||||
if (data->path == NULL)
|
||||
return (ARCHIVE_FAILED);
|
||||
|
||||
newargv = realloc(data->argv, (data->argc + 2) * sizeof(char *));
|
||||
if (newargv == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
data->argv = newargv;
|
||||
data->argv[data->argc] = strdup(arg);
|
||||
if (data->argv[data->argc] == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
/* Set the terminator of argv. */
|
||||
data->argv[++data->argc] = NULL;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
struct archive_cmdline *
|
||||
__archive_cmdline_allocate(void)
|
||||
{
|
||||
return (struct archive_cmdline *)
|
||||
calloc(1, sizeof(struct archive_cmdline));
|
||||
}
|
||||
|
||||
/*
|
||||
* Release the resources.
|
||||
*/
|
||||
int
|
||||
__archive_cmdline_free(struct archive_cmdline *data)
|
||||
{
|
||||
|
||||
if (data) {
|
||||
free(data->path);
|
||||
if (data->argv != NULL) {
|
||||
int i;
|
||||
for (i = 0; data->argv[i] != NULL; i++)
|
||||
free(data->argv[i]);
|
||||
free(data->argv);
|
||||
}
|
||||
free(data);
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
47
contrib/libarchive/libarchive/archive_cmdline_private.h
Normal file
47
contrib/libarchive/libarchive/archive_cmdline_private.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*-
|
||||
* Copyright (c) 2012 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef __LIBARCHIVE_BUILD
|
||||
#ifndef __LIBARCHIVE_TEST
|
||||
#error This header is only to be used internally to libarchive.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ARCHIVE_CMDLINE_PRIVATE_H
|
||||
#define ARCHIVE_CMDLINE_PRIVATE_H
|
||||
|
||||
struct archive_cmdline {
|
||||
char *path;
|
||||
char **argv;
|
||||
int argc;
|
||||
};
|
||||
|
||||
struct archive_cmdline *__archive_cmdline_allocate(void);
|
||||
int __archive_cmdline_parse(struct archive_cmdline *, const char *);
|
||||
int __archive_cmdline_free(struct archive_cmdline *);
|
||||
|
||||
#endif
|
@ -90,7 +90,7 @@ win_crypto_Update(Digest_CTX *ctx, const unsigned char *buf, size_t len)
|
||||
static int
|
||||
win_crypto_Final(unsigned char *buf, size_t bufsize, Digest_CTX *ctx)
|
||||
{
|
||||
DWORD siglen = bufsize;
|
||||
DWORD siglen = (DWORD)bufsize;
|
||||
|
||||
if (!ctx->valid)
|
||||
return (ARCHIVE_FAILED);
|
||||
@ -1222,8 +1222,10 @@ __archive_stub_sha512final(archive_sha512_ctx *ctx, void *md)
|
||||
* 2. libc2
|
||||
* 3. libc3
|
||||
* 4. libSystem
|
||||
* 5. OpenSSL
|
||||
* 6. Windows API
|
||||
* 5. Nettle
|
||||
* 6. OpenSSL
|
||||
* 7. libmd
|
||||
* 8. Windows API
|
||||
*/
|
||||
const struct archive_crypto __archive_crypto =
|
||||
{
|
||||
|
@ -1449,6 +1449,9 @@ static struct flag {
|
||||
{ "nouunlnk", L"nouunlnk", UF_NOUNLINK, 0 },
|
||||
{ "nouunlink", L"nouunlink", UF_NOUNLINK, 0 },
|
||||
#endif
|
||||
#ifdef UF_COMPRESSED
|
||||
{ "nocompressed",L"nocompressed", UF_COMPRESSED, 0 },
|
||||
#endif
|
||||
#ifdef EXT2_UNRM_FL
|
||||
{ "nouunlink", L"nouunlink", EXT2_UNRM_FL, 0},
|
||||
#endif
|
||||
|
@ -29,7 +29,7 @@
|
||||
#define ARCHIVE_ENTRY_H_INCLUDED
|
||||
|
||||
/* Note: Compiler will complain if this does not match archive.h! */
|
||||
#define ARCHIVE_VERSION_NUMBER 3000004
|
||||
#define ARCHIVE_VERSION_NUMBER 3001002
|
||||
|
||||
/*
|
||||
* Note: archive_entry.h is for use outside of libarchive; the
|
||||
|
@ -244,6 +244,9 @@ archive_entry_linkify(struct archive_entry_linkresolver *res,
|
||||
* for future use.
|
||||
*/
|
||||
le = insert_entry(res, *e);
|
||||
if (le == NULL)
|
||||
/* XXX We should return an error code XXX */
|
||||
return;
|
||||
le->entry = *e;
|
||||
*e = NULL;
|
||||
}
|
||||
|
@ -1376,6 +1376,7 @@ add_entry(struct archive_match *a, int flag,
|
||||
archive_mstring_copy_wcs(&(f->pathname), pathname);
|
||||
a->exclusion_tree.rbt_ops = &rb_ops_wcs;
|
||||
#else
|
||||
(void)rb_ops_wcs;
|
||||
pathname = archive_entry_pathname(entry);
|
||||
if (pathname == NULL) {
|
||||
free(f);
|
||||
@ -1515,6 +1516,7 @@ time_excluded(struct archive_match *a, struct archive_entry *entry)
|
||||
pathname = archive_entry_pathname_w(entry);
|
||||
a->exclusion_tree.rbt_ops = &rb_ops_wcs;
|
||||
#else
|
||||
(void)rb_ops_wcs;
|
||||
pathname = archive_entry_pathname(entry);
|
||||
a->exclusion_tree.rbt_ops = &rb_ops_mbs;
|
||||
#endif
|
||||
@ -1675,13 +1677,16 @@ add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id)
|
||||
unsigned i;
|
||||
|
||||
if (ids->count + 1 >= ids->size) {
|
||||
void *p;
|
||||
|
||||
if (ids->size == 0)
|
||||
ids->size = 8;
|
||||
else
|
||||
ids->size *= 2;
|
||||
ids->ids = realloc(ids->ids, sizeof(*ids->ids) * ids->size);
|
||||
if (ids->ids == NULL)
|
||||
p = realloc(ids->ids, sizeof(*ids->ids) * ids->size);
|
||||
if (p == NULL)
|
||||
return (error_nomem(a));
|
||||
ids->ids = (int64_t *)p;
|
||||
}
|
||||
|
||||
/* Find an insert point. */
|
||||
@ -1709,7 +1714,7 @@ match_owner_id(struct id_array *ids, int64_t id)
|
||||
unsigned b, m, t;
|
||||
|
||||
t = 0;
|
||||
b = ids->count;
|
||||
b = (unsigned)ids->count;
|
||||
while (t < b) {
|
||||
m = (t + b)>>1;
|
||||
if (ids->ids[m] == id)
|
||||
|
@ -87,6 +87,8 @@ _archive_set_either_option(struct archive *a, const char *m, const char *o, cons
|
||||
if (r2 == ARCHIVE_FATAL)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
if (r2 == ARCHIVE_WARN - 1)
|
||||
return r1;
|
||||
return r1 > r2 ? r1 : r2;
|
||||
}
|
||||
|
||||
@ -94,7 +96,7 @@ int
|
||||
_archive_set_options(struct archive *a, const char *options,
|
||||
int magic, const char *fn, option_handler use_option)
|
||||
{
|
||||
int allok = 1, anyok = 0, r;
|
||||
int allok = 1, anyok = 0, ignore_mod_err = 0, r;
|
||||
char *data;
|
||||
const char *s, *mod, *opt, *val;
|
||||
|
||||
@ -111,6 +113,15 @@ _archive_set_options(struct archive *a, const char *options,
|
||||
mod = opt = val = NULL;
|
||||
|
||||
parse_option(&s, &mod, &opt, &val);
|
||||
if (mod == NULL && opt != NULL &&
|
||||
strcmp("__ignore_wrong_module_name__", opt) == 0) {
|
||||
/* Ignore module name error */
|
||||
if (val != NULL) {
|
||||
ignore_mod_err = 1;
|
||||
anyok = 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
r = use_option(a, mod, opt, val);
|
||||
if (r == ARCHIVE_FATAL) {
|
||||
@ -122,6 +133,8 @@ _archive_set_options(struct archive *a, const char *options,
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
if (r == ARCHIVE_WARN - 1) {
|
||||
if (ignore_mod_err)
|
||||
continue;
|
||||
/* The module name is wrong. */
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
"Unknown module name: `%s'", mod);
|
||||
|
@ -990,7 +990,7 @@ static void RangeEnc_ShiftLow(CPpmd7z_RangeEnc *p)
|
||||
p->Cache = (Byte)((UInt32)p->Low >> 24);
|
||||
}
|
||||
p->CacheSize++;
|
||||
p->Low = (UInt32)p->Low << 8;
|
||||
p->Low = ((UInt32)p->Low << 8) & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
static void RangeEnc_Encode(CPpmd7z_RangeEnc *p, UInt32 start, UInt32 size, UInt32 total)
|
||||
|
@ -134,6 +134,7 @@ int __archive_check_magic(struct archive *, unsigned int magic,
|
||||
|
||||
void __archive_errx(int retvalue, const char *msg) __LA_DEAD;
|
||||
|
||||
void __archive_ensure_cloexec_flag(int fd);
|
||||
int __archive_mktemp(const char *tmpdir);
|
||||
|
||||
int __archive_clean(struct archive *);
|
||||
|
@ -237,6 +237,8 @@ __archive_rb_tree_reparent_nodes(
|
||||
struct archive_rb_node * const new_father = old_child;
|
||||
struct archive_rb_node * const new_child = old_father;
|
||||
|
||||
if (new_father == NULL)
|
||||
return;
|
||||
/*
|
||||
* Exchange descendant linkages.
|
||||
*/
|
||||
@ -552,6 +554,8 @@ __archive_rb_tree_removal_rebalance(struct archive_rb_tree *rbt,
|
||||
unsigned int other = which ^ RB_DIR_OTHER;
|
||||
struct archive_rb_node *brother = parent->rb_nodes[other];
|
||||
|
||||
if (brother == NULL)
|
||||
return;/* The tree may be broken. */
|
||||
/*
|
||||
* For cases 1, 2a, and 2b, our brother's children must
|
||||
* be black and our father must be black
|
||||
@ -573,6 +577,8 @@ __archive_rb_tree_removal_rebalance(struct archive_rb_tree *rbt,
|
||||
*/
|
||||
__archive_rb_tree_reparent_nodes(parent, other);
|
||||
brother = parent->rb_nodes[other];
|
||||
if (brother == NULL)
|
||||
return;/* The tree may be broken. */
|
||||
} else {
|
||||
/*
|
||||
* Both our parent and brother are black.
|
||||
@ -656,6 +662,8 @@ __archive_rb_tree_removal_rebalance(struct archive_rb_tree *rbt,
|
||||
* If we had two red nephews, then after the swap,
|
||||
* our former father would have a red grandson.
|
||||
*/
|
||||
if (brother->rb_nodes[other] == NULL)
|
||||
return;/* The tree may be broken. */
|
||||
RB_MARK_BLACK(brother->rb_nodes[other]);
|
||||
__archive_rb_tree_reparent_nodes(parent, other);
|
||||
break; /* We're done! */
|
||||
|
@ -57,8 +57,6 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
static int choose_filters(struct archive_read *);
|
||||
static int choose_format(struct archive_read *);
|
||||
static void free_filters(struct archive_read *);
|
||||
static int close_filters(struct archive_read *);
|
||||
static struct archive_vtable *archive_read_vtable(void);
|
||||
static int64_t _archive_filter_bytes(struct archive *, int);
|
||||
static int _archive_filter_code(struct archive *, int);
|
||||
@ -194,8 +192,8 @@ client_skip_proxy(struct archive_read_filter *self, int64_t request)
|
||||
int64_t get, ask = request;
|
||||
if (ask > skip_limit)
|
||||
ask = skip_limit;
|
||||
get = (self->archive->client.skipper)(&self->archive->archive,
|
||||
self->data, ask);
|
||||
get = (self->archive->client.skipper)
|
||||
(&self->archive->archive, self->data, ask);
|
||||
if (get == 0)
|
||||
return (total);
|
||||
request -= get;
|
||||
@ -215,8 +213,8 @@ client_skip_proxy(struct archive_read_filter *self, int64_t request)
|
||||
* only do this for skips of over 64k.
|
||||
*/
|
||||
int64_t before = self->position;
|
||||
int64_t after = (self->archive->client.seeker)(&self->archive->archive,
|
||||
self->data, request, SEEK_CUR);
|
||||
int64_t after = (self->archive->client.seeker)
|
||||
(&self->archive->archive, self->data, request, SEEK_CUR);
|
||||
if (after != before + request)
|
||||
return ARCHIVE_FATAL;
|
||||
return after - before;
|
||||
@ -241,14 +239,64 @@ client_seek_proxy(struct archive_read_filter *self, int64_t offset, int whence)
|
||||
static int
|
||||
client_close_proxy(struct archive_read_filter *self)
|
||||
{
|
||||
int r = ARCHIVE_OK;
|
||||
int r = ARCHIVE_OK, r2;
|
||||
unsigned int i;
|
||||
|
||||
if (self->archive->client.closer != NULL)
|
||||
r = (self->archive->client.closer)((struct archive *)self->archive,
|
||||
self->data);
|
||||
if (self->archive->client.closer == NULL)
|
||||
return (r);
|
||||
for (i = 0; i < self->archive->client.nodes; i++)
|
||||
{
|
||||
r2 = (self->archive->client.closer)
|
||||
((struct archive *)self->archive,
|
||||
self->archive->client.dataset[i].data);
|
||||
if (r > r2)
|
||||
r = r2;
|
||||
}
|
||||
return (r);
|
||||
}
|
||||
|
||||
static int
|
||||
client_open_proxy(struct archive_read_filter *self)
|
||||
{
|
||||
int r = ARCHIVE_OK;
|
||||
if (self->archive->client.opener != NULL)
|
||||
r = (self->archive->client.opener)(
|
||||
(struct archive *)self->archive, self->data);
|
||||
return (r);
|
||||
}
|
||||
|
||||
static int
|
||||
client_switch_proxy(struct archive_read_filter *self, unsigned int iindex)
|
||||
{
|
||||
int r1 = ARCHIVE_OK, r2 = ARCHIVE_OK;
|
||||
void *data2 = NULL;
|
||||
|
||||
/* Don't do anything if already in the specified data node */
|
||||
if (self->archive->client.cursor == iindex)
|
||||
return (ARCHIVE_OK);
|
||||
|
||||
self->archive->client.cursor = iindex;
|
||||
data2 = self->archive->client.dataset[self->archive->client.cursor].data;
|
||||
if (self->archive->client.switcher != NULL)
|
||||
{
|
||||
r1 = r2 = (self->archive->client.switcher)
|
||||
((struct archive *)self->archive, self->data, data2);
|
||||
self->data = data2;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Attempt to call close and open instead */
|
||||
if (self->archive->client.closer != NULL)
|
||||
r1 = (self->archive->client.closer)
|
||||
((struct archive *)self->archive, self->data);
|
||||
self->data = data2;
|
||||
if (self->archive->client.opener != NULL)
|
||||
r2 = (self->archive->client.opener)
|
||||
((struct archive *)self->archive, self->data);
|
||||
}
|
||||
return (r1 < r2) ? r1 : r2;
|
||||
}
|
||||
|
||||
int
|
||||
archive_read_set_open_callback(struct archive *_a,
|
||||
archive_open_callback *client_opener)
|
||||
@ -305,21 +353,110 @@ archive_read_set_close_callback(struct archive *_a,
|
||||
}
|
||||
|
||||
int
|
||||
archive_read_set_callback_data(struct archive *_a, void *client_data)
|
||||
archive_read_set_switch_callback(struct archive *_a,
|
||||
archive_switch_callback *client_switcher)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
|
||||
"archive_read_set_callback_data");
|
||||
a->client.data = client_data;
|
||||
"archive_read_set_switch_callback");
|
||||
a->client.switcher = client_switcher;
|
||||
return ARCHIVE_OK;
|
||||
}
|
||||
|
||||
int
|
||||
archive_read_set_callback_data(struct archive *_a, void *client_data)
|
||||
{
|
||||
return archive_read_set_callback_data2(_a, client_data, 0);
|
||||
}
|
||||
|
||||
int
|
||||
archive_read_set_callback_data2(struct archive *_a, void *client_data,
|
||||
unsigned int iindex)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
|
||||
"archive_read_set_callback_data2");
|
||||
|
||||
if (a->client.nodes == 0)
|
||||
{
|
||||
a->client.dataset = (struct archive_read_data_node *)
|
||||
calloc(1, sizeof(*a->client.dataset));
|
||||
if (a->client.dataset == NULL)
|
||||
{
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"No memory.");
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
a->client.nodes = 1;
|
||||
}
|
||||
|
||||
if (iindex > a->client.nodes - 1)
|
||||
{
|
||||
archive_set_error(&a->archive, EINVAL,
|
||||
"Invalid index specified.");
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
a->client.dataset[iindex].data = client_data;
|
||||
a->client.dataset[iindex].begin_position = -1;
|
||||
a->client.dataset[iindex].total_size = -1;
|
||||
return ARCHIVE_OK;
|
||||
}
|
||||
|
||||
int
|
||||
archive_read_add_callback_data(struct archive *_a, void *client_data,
|
||||
unsigned int iindex)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
void *p;
|
||||
unsigned int i;
|
||||
|
||||
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
|
||||
"archive_read_add_callback_data");
|
||||
if (iindex > a->client.nodes) {
|
||||
archive_set_error(&a->archive, EINVAL,
|
||||
"Invalid index specified.");
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
p = realloc(a->client.dataset, sizeof(*a->client.dataset)
|
||||
* (++(a->client.nodes)));
|
||||
if (p == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"No memory.");
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
a->client.dataset = (struct archive_read_data_node *)p;
|
||||
for (i = a->client.nodes - 1; i > iindex && i > 0; i--) {
|
||||
a->client.dataset[i].data = a->client.dataset[i-1].data;
|
||||
a->client.dataset[i].begin_position = -1;
|
||||
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].total_size = -1;
|
||||
return ARCHIVE_OK;
|
||||
}
|
||||
|
||||
int
|
||||
archive_read_append_callback_data(struct archive *_a, void *client_data)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
return archive_read_add_callback_data(_a, client_data, a->client.nodes);
|
||||
}
|
||||
|
||||
int
|
||||
archive_read_prepend_callback_data(struct archive *_a, void *client_data)
|
||||
{
|
||||
return archive_read_add_callback_data(_a, client_data, 0);
|
||||
}
|
||||
|
||||
int
|
||||
archive_read_open1(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
struct archive_read_filter *filter;
|
||||
int slot, e;
|
||||
struct archive_read_filter *filter, *tmp;
|
||||
int slot;
|
||||
int e = 0;
|
||||
unsigned int i;
|
||||
|
||||
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
|
||||
"archive_read_open");
|
||||
@ -334,11 +471,14 @@ archive_read_open1(struct archive *_a)
|
||||
|
||||
/* Open data source. */
|
||||
if (a->client.opener != NULL) {
|
||||
e =(a->client.opener)(&a->archive, a->client.data);
|
||||
e = (a->client.opener)(&a->archive, a->client.dataset[0].data);
|
||||
if (e != 0) {
|
||||
/* If the open failed, call the closer to clean up. */
|
||||
if (a->client.closer)
|
||||
(a->client.closer)(&a->archive, a->client.data);
|
||||
if (a->client.closer) {
|
||||
for (i = 0; i < a->client.nodes; i++)
|
||||
(a->client.closer)(&a->archive,
|
||||
a->client.dataset[i].data);
|
||||
}
|
||||
return (e);
|
||||
}
|
||||
}
|
||||
@ -349,31 +489,51 @@ archive_read_open1(struct archive *_a)
|
||||
filter->bidder = NULL;
|
||||
filter->upstream = NULL;
|
||||
filter->archive = a;
|
||||
filter->data = a->client.data;
|
||||
filter->data = a->client.dataset[0].data;
|
||||
filter->open = client_open_proxy;
|
||||
filter->read = client_read_proxy;
|
||||
filter->skip = client_skip_proxy;
|
||||
filter->seek = client_seek_proxy;
|
||||
filter->close = client_close_proxy;
|
||||
filter->sswitch = client_switch_proxy;
|
||||
filter->name = "none";
|
||||
filter->code = ARCHIVE_COMPRESSION_NONE;
|
||||
a->filter = filter;
|
||||
filter->code = ARCHIVE_FILTER_NONE;
|
||||
|
||||
/* Build out the input pipeline. */
|
||||
e = choose_filters(a);
|
||||
if (e < ARCHIVE_WARN) {
|
||||
a->archive.state = ARCHIVE_STATE_FATAL;
|
||||
return (ARCHIVE_FATAL);
|
||||
a->client.dataset[0].begin_position = 0;
|
||||
if (!a->filter || !a->bypass_filter_bidding)
|
||||
{
|
||||
a->filter = filter;
|
||||
/* Build out the input pipeline. */
|
||||
e = choose_filters(a);
|
||||
if (e < ARCHIVE_WARN) {
|
||||
a->archive.state = ARCHIVE_STATE_FATAL;
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Need to add "NONE" type filter at the end of the filter chain */
|
||||
tmp = a->filter;
|
||||
while (tmp->upstream)
|
||||
tmp = tmp->upstream;
|
||||
tmp->upstream = filter;
|
||||
}
|
||||
|
||||
slot = choose_format(a);
|
||||
if (slot < 0) {
|
||||
close_filters(a);
|
||||
a->archive.state = ARCHIVE_STATE_FATAL;
|
||||
return (ARCHIVE_FATAL);
|
||||
if (!a->format)
|
||||
{
|
||||
slot = choose_format(a);
|
||||
if (slot < 0) {
|
||||
__archive_read_close_filters(a);
|
||||
a->archive.state = ARCHIVE_STATE_FATAL;
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
a->format = &(a->formats[slot]);
|
||||
}
|
||||
a->format = &(a->formats[slot]);
|
||||
|
||||
a->archive.state = ARCHIVE_STATE_HEADER;
|
||||
|
||||
/* Ensure libarchive starts from the first node in a multivolume set */
|
||||
client_switch_proxy(a->filter, 0);
|
||||
return (e);
|
||||
}
|
||||
|
||||
@ -413,8 +573,8 @@ choose_filters(struct archive_read *a)
|
||||
/* Verify the filter by asking it for some data. */
|
||||
__archive_read_filter_ahead(a->filter, 1, &avail);
|
||||
if (avail < 0) {
|
||||
close_filters(a);
|
||||
free_filters(a);
|
||||
__archive_read_close_filters(a);
|
||||
__archive_read_free_filters(a);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
a->archive.compression_name = a->filter->name;
|
||||
@ -432,8 +592,8 @@ choose_filters(struct archive_read *a)
|
||||
a->filter = filter;
|
||||
r = (best_bidder->init)(a->filter);
|
||||
if (r != ARCHIVE_OK) {
|
||||
close_filters(a);
|
||||
free_filters(a);
|
||||
__archive_read_close_filters(a);
|
||||
__archive_read_free_filters(a);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
}
|
||||
@ -501,6 +661,9 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
|
||||
|
||||
a->read_data_output_offset = 0;
|
||||
a->read_data_remaining = 0;
|
||||
a->read_data_is_posix_read = 0;
|
||||
a->read_data_requested = 0;
|
||||
a->data_start_node = a->client.cursor;
|
||||
/* EOF always wins; otherwise return the worst error. */
|
||||
return (r2 < r1 || r2 == ARCHIVE_EOF) ? r2 : r1;
|
||||
}
|
||||
@ -611,6 +774,8 @@ archive_read_data(struct archive *_a, void *buff, size_t s)
|
||||
while (s > 0) {
|
||||
if (a->read_data_remaining == 0) {
|
||||
read_buf = a->read_data_block;
|
||||
a->read_data_is_posix_read = 1;
|
||||
a->read_data_requested = s;
|
||||
r = _archive_read_data_block(&a->archive, &read_buf,
|
||||
&a->read_data_remaining, &a->read_data_offset);
|
||||
a->read_data_block = read_buf;
|
||||
@ -664,6 +829,8 @@ archive_read_data(struct archive *_a, void *buff, size_t s)
|
||||
bytes_read += len;
|
||||
}
|
||||
}
|
||||
a->read_data_is_posix_read = 0;
|
||||
a->read_data_requested = 0;
|
||||
return (bytes_read);
|
||||
}
|
||||
|
||||
@ -698,6 +865,23 @@ archive_read_data_skip(struct archive *_a)
|
||||
return (r);
|
||||
}
|
||||
|
||||
int64_t
|
||||
archive_seek_data(struct archive *_a, int64_t offset, int whence)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA,
|
||||
"archive_seek_data_block");
|
||||
|
||||
if (a->format->seek_data == NULL) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
"Internal error: "
|
||||
"No format_seek_data_block function registered");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
return (a->format->seek_data)(a, offset, whence);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the next block of entry data from the archive.
|
||||
* This is a zero-copy interface; the client receives a pointer,
|
||||
@ -724,8 +908,8 @@ _archive_read_data_block(struct archive *_a,
|
||||
return (a->format->read_data)(a, buff, size, offset);
|
||||
}
|
||||
|
||||
static int
|
||||
close_filters(struct archive_read *a)
|
||||
int
|
||||
__archive_read_close_filters(struct archive_read *a)
|
||||
{
|
||||
struct archive_read_filter *f = a->filter;
|
||||
int r = ARCHIVE_OK;
|
||||
@ -745,8 +929,8 @@ close_filters(struct archive_read *a)
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
free_filters(struct archive_read *a)
|
||||
void
|
||||
__archive_read_free_filters(struct archive_read *a)
|
||||
{
|
||||
while (a->filter != NULL) {
|
||||
struct archive_read_filter *t = a->filter->upstream;
|
||||
@ -790,7 +974,7 @@ _archive_read_close(struct archive *_a)
|
||||
/* TODO: Clean up the formatters. */
|
||||
|
||||
/* Release the filter objects. */
|
||||
r1 = close_filters(a);
|
||||
r1 = __archive_read_close_filters(a);
|
||||
if (r1 < r)
|
||||
r = r1;
|
||||
|
||||
@ -829,7 +1013,7 @@ _archive_read_free(struct archive *_a)
|
||||
}
|
||||
|
||||
/* Free the filters */
|
||||
free_filters(a);
|
||||
__archive_read_free_filters(a);
|
||||
|
||||
/* Release the bidder objects. */
|
||||
n = sizeof(a->bidders)/sizeof(a->bidders[0]);
|
||||
@ -846,6 +1030,7 @@ _archive_read_free(struct archive *_a)
|
||||
archive_entry_free(a->entry);
|
||||
a->archive.magic = 0;
|
||||
__archive_clean(&a->archive);
|
||||
free(a->client.dataset);
|
||||
free(a);
|
||||
return (r);
|
||||
}
|
||||
@ -855,7 +1040,8 @@ get_filter(struct archive *_a, int n)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
struct archive_read_filter *f = a->filter;
|
||||
/* We use n == -1 for 'the last filter', which is always the client proxy. */
|
||||
/* We use n == -1 for 'the last filter', which is always the
|
||||
* client proxy. */
|
||||
if (n == -1 && f != NULL) {
|
||||
struct archive_read_filter *last = f;
|
||||
f = f->upstream;
|
||||
@ -908,6 +1094,7 @@ __archive_read_register_format(struct archive_read *a,
|
||||
int (*read_header)(struct archive_read *, struct archive_entry *),
|
||||
int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *),
|
||||
int (*read_data_skip)(struct archive_read *),
|
||||
int64_t (*seek_data)(struct archive_read *, int64_t, int),
|
||||
int (*cleanup)(struct archive_read *))
|
||||
{
|
||||
int i, number_slots;
|
||||
@ -927,6 +1114,7 @@ __archive_read_register_format(struct archive_read *a,
|
||||
a->formats[i].read_header = read_header;
|
||||
a->formats[i].read_data = read_data;
|
||||
a->formats[i].read_data_skip = read_data_skip;
|
||||
a->formats[i].seek_data = seek_data;
|
||||
a->formats[i].cleanup = cleanup;
|
||||
a->formats[i].data = format_data;
|
||||
a->formats[i].name = name;
|
||||
@ -1073,7 +1261,8 @@ __archive_read_filter_ahead(struct archive_read_filter *filter,
|
||||
if (filter->next > filter->buffer &&
|
||||
filter->next + min > filter->buffer + filter->buffer_size) {
|
||||
if (filter->avail > 0)
|
||||
memmove(filter->buffer, filter->next, filter->avail);
|
||||
memmove(filter->buffer, filter->next,
|
||||
filter->avail);
|
||||
filter->next = filter->buffer;
|
||||
}
|
||||
|
||||
@ -1088,15 +1277,26 @@ __archive_read_filter_ahead(struct archive_read_filter *filter,
|
||||
&filter->client_buff);
|
||||
if (bytes_read < 0) { /* Read error. */
|
||||
filter->client_total = filter->client_avail = 0;
|
||||
filter->client_next = filter->client_buff = NULL;
|
||||
filter->client_next =
|
||||
filter->client_buff = NULL;
|
||||
filter->fatal = 1;
|
||||
if (avail != NULL)
|
||||
*avail = ARCHIVE_FATAL;
|
||||
return (NULL);
|
||||
}
|
||||
if (bytes_read == 0) { /* Premature end-of-file. */
|
||||
if (bytes_read == 0) {
|
||||
/* Check for another client object first */
|
||||
if (filter->archive->client.cursor !=
|
||||
filter->archive->client.nodes - 1) {
|
||||
if (client_switch_proxy(filter,
|
||||
filter->archive->client.cursor + 1)
|
||||
== ARCHIVE_OK)
|
||||
continue;
|
||||
}
|
||||
/* Premature end-of-file. */
|
||||
filter->client_total = filter->client_avail = 0;
|
||||
filter->client_next = filter->client_buff = NULL;
|
||||
filter->client_next =
|
||||
filter->client_buff = NULL;
|
||||
filter->end_of_file = 1;
|
||||
/* Return whatever we do have. */
|
||||
if (avail != NULL)
|
||||
@ -1106,9 +1306,7 @@ __archive_read_filter_ahead(struct archive_read_filter *filter,
|
||||
filter->client_total = bytes_read;
|
||||
filter->client_avail = filter->client_total;
|
||||
filter->client_next = filter->client_buff;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
/*
|
||||
* We can't satisfy the request from the copy
|
||||
* buffer or the existing client data, so we
|
||||
@ -1129,9 +1327,10 @@ __archive_read_filter_ahead(struct archive_read_filter *filter,
|
||||
t *= 2;
|
||||
if (t <= s) { /* Integer overflow! */
|
||||
archive_set_error(
|
||||
&filter->archive->archive,
|
||||
ENOMEM,
|
||||
"Unable to allocate copy buffer");
|
||||
&filter->archive->archive,
|
||||
ENOMEM,
|
||||
"Unable to allocate copy"
|
||||
" buffer");
|
||||
filter->fatal = 1;
|
||||
if (avail != NULL)
|
||||
*avail = ARCHIVE_FATAL;
|
||||
@ -1170,8 +1369,8 @@ __archive_read_filter_ahead(struct archive_read_filter *filter,
|
||||
if (tocopy > filter->client_avail)
|
||||
tocopy = filter->client_avail;
|
||||
|
||||
memcpy(filter->next + filter->avail, filter->client_next,
|
||||
tocopy);
|
||||
memcpy(filter->next + filter->avail,
|
||||
filter->client_next, tocopy);
|
||||
/* Remove this data from client buffer. */
|
||||
filter->client_next += tocopy;
|
||||
filter->client_avail -= tocopy;
|
||||
@ -1274,6 +1473,13 @@ advance_file_pointer(struct archive_read_filter *filter, int64_t request)
|
||||
}
|
||||
|
||||
if (bytes_read == 0) {
|
||||
if (filter->archive->client.cursor !=
|
||||
filter->archive->client.nodes - 1) {
|
||||
if (client_switch_proxy(filter,
|
||||
filter->archive->client.cursor + 1)
|
||||
== ARCHIVE_OK)
|
||||
continue;
|
||||
}
|
||||
filter->client_buff = NULL;
|
||||
filter->end_of_file = 1;
|
||||
return (total_bytes_skipped);
|
||||
@ -1305,15 +1511,109 @@ __archive_read_seek(struct archive_read *a, int64_t offset, int whence)
|
||||
}
|
||||
|
||||
int64_t
|
||||
__archive_read_filter_seek(struct archive_read_filter *filter, int64_t offset, int whence)
|
||||
__archive_read_filter_seek(struct archive_read_filter *filter, int64_t offset,
|
||||
int whence)
|
||||
{
|
||||
struct archive_read_client *client;
|
||||
int64_t r;
|
||||
unsigned int cursor;
|
||||
|
||||
if (filter->closed || filter->fatal)
|
||||
return (ARCHIVE_FATAL);
|
||||
if (filter->seek == NULL)
|
||||
return (ARCHIVE_FAILED);
|
||||
r = filter->seek(filter, offset, whence);
|
||||
|
||||
client = &(filter->archive->client);
|
||||
switch (whence) {
|
||||
case SEEK_CUR:
|
||||
/* Adjust the offset and use SEEK_SET instead */
|
||||
offset += filter->position;
|
||||
case SEEK_SET:
|
||||
cursor = 0;
|
||||
while (1)
|
||||
{
|
||||
if (client->dataset[cursor].begin_position < 0 ||
|
||||
client->dataset[cursor].total_size < 0 ||
|
||||
client->dataset[cursor].begin_position +
|
||||
client->dataset[cursor].total_size - 1 > offset ||
|
||||
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(filter, cursor);
|
||||
if (r != ARCHIVE_OK)
|
||||
return r;
|
||||
if ((r = client_seek_proxy(filter, 0, SEEK_END)) < 0)
|
||||
return r;
|
||||
client->dataset[cursor].total_size = r;
|
||||
if (client->dataset[cursor].begin_position +
|
||||
client->dataset[cursor].total_size - 1 > offset ||
|
||||
cursor + 1 >= client->nodes)
|
||||
break;
|
||||
r = client->dataset[cursor].begin_position +
|
||||
client->dataset[cursor].total_size;
|
||||
client->dataset[++cursor].begin_position = r;
|
||||
}
|
||||
offset -= client->dataset[cursor].begin_position;
|
||||
if (offset < 0)
|
||||
offset = 0;
|
||||
else if (offset > client->dataset[cursor].total_size - 1)
|
||||
offset = client->dataset[cursor].total_size - 1;
|
||||
if ((r = client_seek_proxy(filter, offset, SEEK_SET)) < 0)
|
||||
return r;
|
||||
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(filter, cursor);
|
||||
if (r != ARCHIVE_OK)
|
||||
return r;
|
||||
if ((r = client_seek_proxy(filter, 0, SEEK_END)) < 0)
|
||||
return r;
|
||||
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;
|
||||
}
|
||||
while (1) {
|
||||
if (r + offset >=
|
||||
client->dataset[cursor].begin_position)
|
||||
break;
|
||||
offset += client->dataset[cursor].total_size;
|
||||
if (cursor == 0)
|
||||
break;
|
||||
cursor--;
|
||||
r = client->dataset[cursor].begin_position +
|
||||
client->dataset[cursor].total_size;
|
||||
}
|
||||
offset = (r + offset) - client->dataset[cursor].begin_position;
|
||||
if ((r = client_switch_proxy(filter, cursor)) != ARCHIVE_OK)
|
||||
return r;
|
||||
r = client_seek_proxy(filter, offset, SEEK_SET);
|
||||
if (r < ARCHIVE_OK)
|
||||
return r;
|
||||
break;
|
||||
|
||||
default:
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
r += client->dataset[cursor].begin_position;
|
||||
|
||||
if (r >= 0) {
|
||||
/*
|
||||
* Ouch. Clearing the buffer like this hurts, especially
|
||||
|
198
contrib/libarchive/libarchive/archive_read_append_filter.c
Normal file
198
contrib/libarchive/libarchive/archive_read_append_filter.c
Normal file
@ -0,0 +1,198 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2012 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
|
||||
int
|
||||
archive_read_append_filter(struct archive *_a, int code)
|
||||
{
|
||||
int r1, r2, number_bidders, i;
|
||||
char str[20];
|
||||
struct archive_read_filter_bidder *bidder;
|
||||
struct archive_read_filter *filter;
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
|
||||
r1 = r2 = (ARCHIVE_OK);
|
||||
switch (code)
|
||||
{
|
||||
case ARCHIVE_FILTER_NONE:
|
||||
/* No filter to add, so do nothing.
|
||||
* NOTE: An initial "NONE" type filter is always set at the end of the
|
||||
* filter chain.
|
||||
*/
|
||||
r1 = (ARCHIVE_OK);
|
||||
break;
|
||||
case ARCHIVE_FILTER_GZIP:
|
||||
strcpy(str, "gzip");
|
||||
r1 = archive_read_support_filter_gzip(_a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_BZIP2:
|
||||
strcpy(str, "bzip2");
|
||||
r1 = archive_read_support_filter_bzip2(_a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_COMPRESS:
|
||||
strcpy(str, "compress (.Z)");
|
||||
r1 = archive_read_support_filter_compress(_a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_PROGRAM:
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
"Cannot append program filter using archive_read_append_filter");
|
||||
return (ARCHIVE_FATAL);
|
||||
case ARCHIVE_FILTER_LZMA:
|
||||
strcpy(str, "lzma");
|
||||
r1 = archive_read_support_filter_lzma(_a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_XZ:
|
||||
strcpy(str, "xz");
|
||||
r1 = archive_read_support_filter_xz(_a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_UU:
|
||||
strcpy(str, "uu");
|
||||
r1 = archive_read_support_filter_uu(_a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_RPM:
|
||||
strcpy(str, "rpm");
|
||||
r1 = archive_read_support_filter_rpm(_a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_LZIP:
|
||||
strcpy(str, "lzip");
|
||||
r1 = archive_read_support_filter_lzip(_a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_LRZIP:
|
||||
strcpy(str, "lrzip");
|
||||
r1 = archive_read_support_filter_lrzip(_a);
|
||||
break;
|
||||
default:
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
"Invalid filter code specified");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
if (code != ARCHIVE_FILTER_NONE)
|
||||
{
|
||||
number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]);
|
||||
|
||||
bidder = a->bidders;
|
||||
for (i = 0; i < number_bidders; i++, bidder++)
|
||||
{
|
||||
if (!bidder->name || !strcmp(bidder->name, str))
|
||||
break;
|
||||
}
|
||||
if (!bidder->name || strcmp(bidder->name, str))
|
||||
{
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
"Internal error: Unable to append filter");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
filter
|
||||
= (struct archive_read_filter *)calloc(1, sizeof(*filter));
|
||||
if (filter == NULL)
|
||||
{
|
||||
archive_set_error(&a->archive, ENOMEM, "Out of memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
filter->bidder = bidder;
|
||||
filter->archive = a;
|
||||
filter->upstream = a->filter;
|
||||
a->filter = filter;
|
||||
r2 = (bidder->init)(a->filter);
|
||||
if (r2 != ARCHIVE_OK) {
|
||||
__archive_read_close_filters(a);
|
||||
__archive_read_free_filters(a);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
}
|
||||
|
||||
a->bypass_filter_bidding = 1;
|
||||
return (r1 < r2) ? r1 : r2;
|
||||
}
|
||||
|
||||
int
|
||||
archive_read_append_filter_program(struct archive *_a, const char *cmd)
|
||||
{
|
||||
return (archive_read_append_filter_program_signature(_a, cmd, NULL, 0));
|
||||
}
|
||||
|
||||
int
|
||||
archive_read_append_filter_program_signature(struct archive *_a,
|
||||
const char *cmd, const void *signature, size_t signature_len)
|
||||
{
|
||||
int r, number_bidders, i;
|
||||
struct archive_read_filter_bidder *bidder;
|
||||
struct archive_read_filter *filter;
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
|
||||
if (archive_read_support_filter_program_signature(_a, cmd, signature,
|
||||
signature_len) != (ARCHIVE_OK))
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]);
|
||||
|
||||
bidder = a->bidders;
|
||||
for (i = 0; i < number_bidders; i++, bidder++)
|
||||
{
|
||||
/* Program bidder name set to filter name after initialization */
|
||||
if (bidder->data && !bidder->name)
|
||||
break;
|
||||
}
|
||||
if (!bidder->data)
|
||||
{
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
"Internal error: Unable to append program filter");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
filter
|
||||
= (struct archive_read_filter *)calloc(1, sizeof(*filter));
|
||||
if (filter == NULL)
|
||||
{
|
||||
archive_set_error(&a->archive, ENOMEM, "Out of memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
filter->bidder = bidder;
|
||||
filter->archive = a;
|
||||
filter->upstream = a->filter;
|
||||
a->filter = filter;
|
||||
r = (bidder->init)(a->filter);
|
||||
if (r != ARCHIVE_OK) {
|
||||
__archive_read_close_filters(a);
|
||||
__archive_read_free_filters(a);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
bidder->name = a->filter->name;
|
||||
|
||||
a->bypass_filter_bidding = 1;
|
||||
return r;
|
||||
}
|
@ -49,8 +49,10 @@ __FBSDID("$FreeBSD$");
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_XATTR_H
|
||||
#if defined(HAVE_SYS_XATTR_H)
|
||||
#include <sys/xattr.h>
|
||||
#elif defined(HAVE_ATTR_XATTR_H)
|
||||
#include <attr/xattr.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_EA_H
|
||||
#include <sys/ea.h>
|
||||
@ -58,9 +60,6 @@ __FBSDID("$FreeBSD$");
|
||||
#ifdef HAVE_ACL_LIBACL_H
|
||||
#include <acl/libacl.h>
|
||||
#endif
|
||||
#ifdef HAVE_ATTR_XATTR_H
|
||||
#include <attr/xattr.h>
|
||||
#endif
|
||||
#ifdef HAVE_COPYFILE_H
|
||||
#include <copyfile.h>
|
||||
#endif
|
||||
@ -104,6 +103,10 @@ __FBSDID("$FreeBSD$");
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_disk_private.h"
|
||||
|
||||
#ifndef O_CLOEXEC
|
||||
#define O_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Linux and FreeBSD plug this obvious hole in POSIX.1e in
|
||||
* different ways.
|
||||
@ -193,12 +196,14 @@ archive_read_disk_entry_from_file(struct archive *_a,
|
||||
if (fd < 0) {
|
||||
if (a->tree != NULL)
|
||||
fd = a->open_on_current_dir(a->tree, path,
|
||||
O_RDONLY | O_NONBLOCK);
|
||||
O_RDONLY | O_NONBLOCK | O_CLOEXEC);
|
||||
else
|
||||
fd = open(path, O_RDONLY | O_NONBLOCK);
|
||||
fd = open(path, O_RDONLY | O_NONBLOCK |
|
||||
O_CLOEXEC);
|
||||
__archive_ensure_cloexec_flag(fd);
|
||||
}
|
||||
if (fd >= 0) {
|
||||
unsigned long stflags;
|
||||
int stflags;
|
||||
r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags);
|
||||
if (r == 0 && stflags != 0)
|
||||
archive_entry_set_fflags(entry, stflags, 0);
|
||||
@ -286,9 +291,10 @@ setup_mac_metadata(struct archive_read_disk *a,
|
||||
int copyfile_flags = COPYFILE_NOFOLLOW | COPYFILE_ACL | COPYFILE_XATTR;
|
||||
struct stat copyfile_stat;
|
||||
int ret = ARCHIVE_OK;
|
||||
void *buff;
|
||||
void *buff = NULL;
|
||||
int have_attrs;
|
||||
const char *name, *tempdir, *tempfile = NULL;
|
||||
const char *name, *tempdir;
|
||||
struct archive_string tempfile;
|
||||
|
||||
(void)fd; /* UNUSED */
|
||||
name = archive_entry_sourcepath(entry);
|
||||
@ -323,25 +329,28 @@ setup_mac_metadata(struct archive_read_disk *a,
|
||||
tempdir = getenv("TMPDIR");
|
||||
if (tempdir == NULL)
|
||||
tempdir = _PATH_TMP;
|
||||
tempfile = tempnam(tempdir, "tar.md.");
|
||||
archive_string_init(&tempfile);
|
||||
archive_strcpy(&tempfile, tempdir);
|
||||
archive_strcat(&tempfile, "tar.md.XXXXXX");
|
||||
tempfd = mkstemp(tempfile.s);
|
||||
if (tempfd < 0) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Could not open extended attribute file");
|
||||
ret = ARCHIVE_WARN;
|
||||
goto cleanup;
|
||||
}
|
||||
__archive_ensure_cloexec_flag(tempfd);
|
||||
|
||||
/* XXX I wish copyfile() could pack directly to a memory
|
||||
* buffer; that would avoid the temp file here. For that
|
||||
* matter, it would be nice if fcopyfile() actually worked,
|
||||
* that would reduce the many open/close races here. */
|
||||
if (copyfile(name, tempfile, 0, copyfile_flags | COPYFILE_PACK)) {
|
||||
if (copyfile(name, tempfile.s, 0, copyfile_flags | COPYFILE_PACK)) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Could not pack extended attributes");
|
||||
ret = ARCHIVE_WARN;
|
||||
goto cleanup;
|
||||
}
|
||||
tempfd = open(tempfile, O_RDONLY);
|
||||
if (tempfd < 0) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Could not open extended attribute file");
|
||||
ret = ARCHIVE_WARN;
|
||||
goto cleanup;
|
||||
}
|
||||
if (fstat(tempfd, ©file_stat)) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Could not check size of extended attributes");
|
||||
@ -364,10 +373,12 @@ setup_mac_metadata(struct archive_read_disk *a,
|
||||
archive_entry_copy_mac_metadata(entry, buff, copyfile_stat.st_size);
|
||||
|
||||
cleanup:
|
||||
if (tempfd >= 0)
|
||||
if (tempfd >= 0) {
|
||||
close(tempfd);
|
||||
if (tempfile != NULL)
|
||||
unlink(tempfile);
|
||||
unlink(tempfile.s);
|
||||
}
|
||||
archive_string_free(&tempfile);
|
||||
free(buff);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
@ -388,7 +399,7 @@ setup_mac_metadata(struct archive_read_disk *a,
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_POSIX_ACL
|
||||
#if defined(HAVE_POSIX_ACL) && defined(ACL_TYPE_NFS4)
|
||||
static int translate_acl(struct archive_read_disk *a,
|
||||
struct archive_entry *entry, acl_t acl, int archive_entry_acl_type);
|
||||
|
||||
@ -398,7 +409,9 @@ setup_acls(struct archive_read_disk *a,
|
||||
{
|
||||
const char *accpath;
|
||||
acl_t acl;
|
||||
#if HAVE_ACL_IS_TRIVIAL_NP
|
||||
int r;
|
||||
#endif
|
||||
|
||||
accpath = archive_entry_sourcepath(entry);
|
||||
if (accpath == NULL)
|
||||
@ -520,7 +533,6 @@ translate_acl(struct archive_read_disk *a,
|
||||
int s, ae_id, ae_tag, ae_perm;
|
||||
const char *ae_name;
|
||||
|
||||
|
||||
// FreeBSD "brands" ACLs as POSIX.1e or NFSv4
|
||||
// Make sure the "brand" on this ACL is consistent
|
||||
// with the default_entry_acl_type bits provided.
|
||||
@ -530,7 +542,6 @@ translate_acl(struct archive_read_disk *a,
|
||||
switch (default_entry_acl_type) {
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
|
||||
entry_acl_type = default_entry_acl_type;
|
||||
break;
|
||||
default:
|
||||
// XXX set warning message?
|
||||
@ -644,7 +655,7 @@ translate_acl(struct archive_read_disk *a,
|
||||
#else
|
||||
static int
|
||||
setup_acls(struct archive_read_disk *a,
|
||||
struct archive_entry *entry, int fd)
|
||||
struct archive_entry *entry, int *fd)
|
||||
{
|
||||
(void)a; /* UNUSED */
|
||||
(void)entry; /* UNUSED */
|
||||
@ -1034,16 +1045,19 @@ setup_sparse(struct archive_read_disk *a,
|
||||
path = archive_entry_pathname(entry);
|
||||
if (a->tree != NULL)
|
||||
*fd = a->open_on_current_dir(a->tree, path,
|
||||
O_RDONLY | O_NONBLOCK);
|
||||
O_RDONLY | O_NONBLOCK | O_CLOEXEC);
|
||||
else
|
||||
*fd = open(path, O_RDONLY | O_NONBLOCK);
|
||||
*fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
|
||||
if (*fd < 0) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Can't open `%s'", path);
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
__archive_ensure_cloexec_flag(*fd);
|
||||
}
|
||||
|
||||
/* Initialize buffer to avoid the error valgrind complains about. */
|
||||
memset(buff, 0, sizeof(buff));
|
||||
count = (sizeof(buff) - sizeof(*fm))/sizeof(*fe);
|
||||
fm = (struct fiemap *)buff;
|
||||
fm->fm_start = 0;
|
||||
@ -1145,12 +1159,13 @@ setup_sparse(struct archive_read_disk *a,
|
||||
|
||||
if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0)
|
||||
return (ARCHIVE_OK);
|
||||
*fd = open(path, O_RDONLY | O_NONBLOCK);
|
||||
*fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
|
||||
if (*fd < 0) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Can't open `%s'", path);
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
__archive_ensure_cloexec_flag(*fd);
|
||||
initial_off = 0;
|
||||
}
|
||||
|
||||
|
@ -105,6 +105,9 @@ __FBSDID("$FreeBSD$");
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
#ifndef O_CLOEXEC
|
||||
#define O_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
/*-
|
||||
* This is a new directory-walking system that addresses a number
|
||||
@ -361,6 +364,7 @@ static int setup_sparse(struct archive_read_disk *, struct archive_entry *);
|
||||
static int close_and_restore_time(int fd, struct tree *,
|
||||
struct restore_time *);
|
||||
static int open_on_current_dir(struct tree *, const char *, int);
|
||||
static int tree_dup(int);
|
||||
|
||||
|
||||
static struct archive_vtable *
|
||||
@ -717,7 +721,7 @@ _archive_read_data_block(struct archive *_a, const void **buff,
|
||||
* Open the current file.
|
||||
*/
|
||||
if (t->entry_fd < 0) {
|
||||
int flags = O_RDONLY | O_BINARY;
|
||||
int flags = O_RDONLY | O_BINARY | O_CLOEXEC;
|
||||
|
||||
/*
|
||||
* Eliminate or reduce cache effects if we can.
|
||||
@ -740,6 +744,7 @@ _archive_read_data_block(struct archive *_a, const void **buff,
|
||||
#endif
|
||||
t->entry_fd = open_on_current_dir(t,
|
||||
tree_current_access_path(t), flags);
|
||||
__archive_ensure_cloexec_flag(t->entry_fd);
|
||||
#if defined(O_NOATIME)
|
||||
/*
|
||||
* When we did open the file with O_NOATIME flag,
|
||||
@ -781,8 +786,8 @@ _archive_read_data_block(struct archive *_a, const void **buff,
|
||||
t->entry_buff_size = t->current_filesystem->buff_size;
|
||||
|
||||
buffbytes = t->entry_buff_size;
|
||||
if (buffbytes > (size_t)t->current_sparse->length)
|
||||
buffbytes = (size_t)t->current_sparse->length;
|
||||
if ((int64_t)buffbytes > t->current_sparse->length)
|
||||
buffbytes = t->current_sparse->length;
|
||||
|
||||
/*
|
||||
* Skip hole.
|
||||
@ -984,10 +989,12 @@ next_entry(struct archive_read_disk *a, struct tree *t,
|
||||
#elif defined(EXT2_IOC_GETFLAGS) && defined(EXT2_NODUMP_FL) &&\
|
||||
defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)
|
||||
if (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode)) {
|
||||
unsigned long stflags;
|
||||
int stflags;
|
||||
|
||||
t->entry_fd = open_on_current_dir(t,
|
||||
tree_current_access_path(t), O_RDONLY | O_NONBLOCK);
|
||||
tree_current_access_path(t),
|
||||
O_RDONLY | O_NONBLOCK | O_CLOEXEC);
|
||||
__archive_ensure_cloexec_flag(t->entry_fd);
|
||||
if (t->entry_fd >= 0) {
|
||||
r = ioctl(t->entry_fd, EXT2_IOC_GETFLAGS,
|
||||
&stflags);
|
||||
@ -1359,15 +1366,17 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
|
||||
fid = t->max_filesystem_id++;
|
||||
if (t->max_filesystem_id > t->allocated_filesytem) {
|
||||
size_t s;
|
||||
void *p;
|
||||
|
||||
s = t->max_filesystem_id * 2;
|
||||
t->filesystem_table = realloc(t->filesystem_table,
|
||||
s * sizeof(*t->filesystem_table));
|
||||
if (t->filesystem_table == NULL) {
|
||||
p = realloc(t->filesystem_table,
|
||||
s * sizeof(*t->filesystem_table));
|
||||
if (p == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate tar data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
t->filesystem_table = (struct filesystem *)p;
|
||||
t->allocated_filesytem = s;
|
||||
}
|
||||
t->current_filesystem_id = fid;
|
||||
@ -1482,7 +1491,8 @@ setup_current_filesystem(struct archive_read_disk *a)
|
||||
* where current is.
|
||||
*/
|
||||
int fd = openat(tree_current_dir_fd(t),
|
||||
tree_current_access_path(t), O_RDONLY);
|
||||
tree_current_access_path(t), O_RDONLY | O_CLOEXEC);
|
||||
__archive_ensure_cloexec_flag(fd);
|
||||
if (fd < 0) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"openat failed");
|
||||
@ -1660,7 +1670,8 @@ setup_current_filesystem(struct archive_read_disk *a)
|
||||
* where current is.
|
||||
*/
|
||||
int fd = openat(tree_current_dir_fd(t),
|
||||
tree_current_access_path(t), O_RDONLY);
|
||||
tree_current_access_path(t), O_RDONLY | O_CLOEXEC);
|
||||
__archive_ensure_cloexec_flag(fd);
|
||||
if (fd < 0) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"openat failed");
|
||||
@ -1768,7 +1779,8 @@ setup_current_filesystem(struct archive_read_disk *a)
|
||||
* where current is.
|
||||
*/
|
||||
int fd = openat(tree_current_dir_fd(t),
|
||||
tree_current_access_path(t), O_RDONLY);
|
||||
tree_current_access_path(t), O_RDONLY | O_CLOEXEC);
|
||||
__archive_ensure_cloexec_flag(fd);
|
||||
if (fd < 0) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"openat failed");
|
||||
@ -1889,7 +1901,8 @@ static int
|
||||
close_and_restore_time(int fd, struct tree *t, struct restore_time *rt)
|
||||
{
|
||||
#ifndef HAVE_UTIMES
|
||||
(void)a; /* UNUSED */
|
||||
(void)t; /* UNUSED */
|
||||
(void)rt; /* UNUSED */
|
||||
return (close(fd));
|
||||
#else
|
||||
#if defined(HAVE_FUTIMENS) && !defined(__CYGWIN__)
|
||||
@ -1952,6 +1965,28 @@ open_on_current_dir(struct tree *t, const char *path, int flags)
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
tree_dup(int fd)
|
||||
{
|
||||
int new_fd;
|
||||
#ifdef F_DUPFD_CLOEXEC
|
||||
static volatile int can_dupfd_cloexec = 1;
|
||||
|
||||
if (can_dupfd_cloexec) {
|
||||
new_fd = fcntl(fd, F_DUPFD_CLOEXEC);
|
||||
if (new_fd != -1)
|
||||
return (new_fd);
|
||||
/* Linux 2.6.18 - 2.6.23 declare F_DUPFD_CLOEXEC,
|
||||
* but it cannot be used. So we have to try dup(). */
|
||||
/* We won't try F_DUPFD_CLOEXEC. */
|
||||
can_dupfd_cloexec = 0;
|
||||
}
|
||||
#endif /* F_DUPFD_CLOEXEC */
|
||||
new_fd = dup(fd);
|
||||
__archive_ensure_cloexec_flag(new_fd);
|
||||
return (new_fd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a directory path to the current stack.
|
||||
*/
|
||||
@ -2052,8 +2087,9 @@ tree_reopen(struct tree *t, const char *path, int restore_time)
|
||||
tree_push(t, path, 0, 0, 0, NULL);
|
||||
t->stack->flags = needsFirstVisit;
|
||||
t->maxOpenCount = t->openCount = 1;
|
||||
t->initial_dir_fd = open(".", O_RDONLY);
|
||||
t->working_dir_fd = dup(t->initial_dir_fd);
|
||||
t->initial_dir_fd = open(".", O_RDONLY | O_CLOEXEC);
|
||||
__archive_ensure_cloexec_flag(t->initial_dir_fd);
|
||||
t->working_dir_fd = tree_dup(t->initial_dir_fd);
|
||||
return (t);
|
||||
}
|
||||
|
||||
@ -2063,11 +2099,12 @@ tree_descent(struct tree *t)
|
||||
int flag, new_fd, r = 0;
|
||||
|
||||
t->dirname_length = archive_strlen(&t->path);
|
||||
flag = O_RDONLY;
|
||||
flag = O_RDONLY | O_CLOEXEC;
|
||||
#if defined(O_DIRECTORY)
|
||||
flag |= O_DIRECTORY;
|
||||
#endif
|
||||
new_fd = open_on_current_dir(t, t->stack->name.s, flag);
|
||||
__archive_ensure_cloexec_flag(new_fd);
|
||||
if (new_fd < 0) {
|
||||
t->tree_errno = errno;
|
||||
r = TREE_ERROR_DIR;
|
||||
@ -2101,8 +2138,10 @@ tree_ascend(struct tree *t)
|
||||
prev_dir_fd = t->working_dir_fd;
|
||||
if (te->flags & isDirLink)
|
||||
new_fd = te->symlink_parent_fd;
|
||||
else
|
||||
new_fd = open_on_current_dir(t, "..", O_RDONLY);
|
||||
else {
|
||||
new_fd = open_on_current_dir(t, "..", O_RDONLY | O_CLOEXEC);
|
||||
__archive_ensure_cloexec_flag(new_fd);
|
||||
}
|
||||
if (new_fd < 0) {
|
||||
t->tree_errno = errno;
|
||||
r = TREE_ERROR_FATAL;
|
||||
@ -2265,11 +2304,16 @@ tree_dir_next_posix(struct tree *t)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_FDOPENDIR)
|
||||
if ((t->d = fdopendir(dup(t->working_dir_fd))) == NULL) {
|
||||
#else
|
||||
if (tree_enter_working_dir(t) != 0 ||
|
||||
(t->d = opendir(".")) == NULL) {
|
||||
t->d = fdopendir(tree_dup(t->working_dir_fd));
|
||||
#else /* HAVE_FDOPENDIR */
|
||||
if (tree_enter_working_dir(t) == 0) {
|
||||
t->d = opendir(".");
|
||||
#if HAVE_DIRFD || defined(dirfd)
|
||||
__archive_ensure_cloexec_flag(dirfd(t->d));
|
||||
#endif
|
||||
}
|
||||
#endif /* HAVE_FDOPENDIR */
|
||||
if (t->d == NULL) {
|
||||
r = tree_ascend(t); /* Undo "chdir" */
|
||||
tree_pop(t);
|
||||
t->tree_errno = errno;
|
||||
@ -2296,11 +2340,21 @@ tree_dir_next_posix(struct tree *t)
|
||||
#endif /* HAVE_READDIR_R */
|
||||
}
|
||||
for (;;) {
|
||||
errno = 0;
|
||||
#if defined(HAVE_READDIR_R)
|
||||
r = readdir_r(t->d, t->dirent, &t->de);
|
||||
#ifdef _AIX
|
||||
/* Note: According to the man page, return value 9 indicates
|
||||
* that the readdir_r was not successful and the error code
|
||||
* is set to the global errno variable. And then if the end
|
||||
* of directory entries was reached, the return value is 9
|
||||
* and the third parameter is set to NULL and errno is
|
||||
* unchanged. */
|
||||
if (r == 9)
|
||||
r = errno;
|
||||
#endif /* _AIX */
|
||||
if (r != 0 || t->de == NULL) {
|
||||
#else
|
||||
errno = 0;
|
||||
t->de = readdir(t->d);
|
||||
if (t->de == NULL) {
|
||||
r = errno;
|
||||
@ -2391,7 +2445,7 @@ tree_current_is_dir(struct tree *t)
|
||||
return 1;
|
||||
/* Not a dir; might be a link to a dir. */
|
||||
/* If it's not a link, then it's not a link to a dir. */
|
||||
if (!S_ISLNK(tree_current_lstat(t)->st_mode))
|
||||
if (!S_ISLNK(st->st_mode))
|
||||
return 0;
|
||||
/*
|
||||
* It's a link, but we don't know what it's a link to,
|
||||
|
@ -154,7 +154,7 @@ copy_data(struct archive *ar, struct archive *aw)
|
||||
return (ARCHIVE_OK);
|
||||
if (r != ARCHIVE_OK)
|
||||
return (r);
|
||||
r = archive_write_data_block(aw, buff, size, offset);
|
||||
r = (int)archive_write_data_block(aw, buff, size, offset);
|
||||
if (r < ARCHIVE_WARN)
|
||||
r = ARCHIVE_WARN;
|
||||
if (r != ARCHIVE_OK) {
|
||||
|
@ -119,7 +119,8 @@ file_read(struct archive *a, void *client_data, const void **buff)
|
||||
if (bytes_read < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
archive_set_error(a, errno, "Error reading fd %d", mine->fd);
|
||||
archive_set_error(a, errno, "Error reading fd %d",
|
||||
mine->fd);
|
||||
}
|
||||
return (bytes_read);
|
||||
}
|
||||
|
@ -108,11 +108,11 @@ static ssize_t
|
||||
file_read(struct archive *a, void *client_data, const void **buff)
|
||||
{
|
||||
struct read_FILE_data *mine = (struct read_FILE_data *)client_data;
|
||||
ssize_t bytes_read;
|
||||
size_t bytes_read;
|
||||
|
||||
*buff = mine->buffer;
|
||||
bytes_read = fread(mine->buffer, 1, mine->block_size, mine->f);
|
||||
if (bytes_read < 0) {
|
||||
if (bytes_read < mine->block_size && ferror(mine->f)) {
|
||||
archive_set_error(a, errno, "Error reading file");
|
||||
}
|
||||
return (bytes_read);
|
||||
|
@ -60,11 +60,15 @@ __FBSDID("$FreeBSD$");
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_string.h"
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
#ifndef O_CLOEXEC
|
||||
#define O_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
struct read_file_data {
|
||||
int fd;
|
||||
@ -79,9 +83,10 @@ struct read_file_data {
|
||||
} filename; /* Must be last! */
|
||||
};
|
||||
|
||||
static int file_open(struct archive *, void *);
|
||||
static int file_close(struct archive *, void *);
|
||||
static int file_open_filename(struct archive *, enum fnt_e, const void *,
|
||||
size_t);
|
||||
static int file_close2(struct archive *, void *);
|
||||
static int file_switch(struct archive *, void *, void *);
|
||||
static ssize_t file_read(struct archive *, void *, const void **buff);
|
||||
static int64_t file_seek(struct archive *, void *, int64_t request, int);
|
||||
static int64_t file_skip(struct archive *, void *, int64_t request);
|
||||
@ -98,26 +103,76 @@ int
|
||||
archive_read_open_filename(struct archive *a, const char *filename,
|
||||
size_t block_size)
|
||||
{
|
||||
enum fnt_e filename_type;
|
||||
const char *filenames[2] = { filename, NULL };
|
||||
return archive_read_open_filenames(a, filenames, block_size);
|
||||
}
|
||||
|
||||
if (filename == NULL || filename[0] == '\0') {
|
||||
filename_type = FNT_STDIN;
|
||||
} else
|
||||
filename_type = FNT_MBS;
|
||||
return (file_open_filename(a, filename_type, filename, block_size));
|
||||
int
|
||||
archive_read_open_filenames(struct archive *a, const char **filenames,
|
||||
size_t block_size)
|
||||
{
|
||||
struct read_file_data *mine;
|
||||
const char *filename = NULL;
|
||||
if (filenames)
|
||||
filename = *(filenames++);
|
||||
|
||||
archive_clear_error(a);
|
||||
do
|
||||
{
|
||||
if (filename == NULL)
|
||||
filename = "";
|
||||
mine = (struct read_file_data *)calloc(1,
|
||||
sizeof(*mine) + strlen(filename));
|
||||
if (mine == NULL)
|
||||
goto no_memory;
|
||||
strcpy(mine->filename.m, filename);
|
||||
mine->block_size = block_size;
|
||||
mine->fd = -1;
|
||||
mine->buffer = NULL;
|
||||
mine->st_mode = mine->use_lseek = 0;
|
||||
if (filename == NULL || filename[0] == '\0') {
|
||||
mine->filename_type = FNT_STDIN;
|
||||
} else
|
||||
mine->filename_type = FNT_MBS;
|
||||
if (archive_read_append_callback_data(a, mine) != (ARCHIVE_OK))
|
||||
return (ARCHIVE_FATAL);
|
||||
if (filenames == NULL)
|
||||
break;
|
||||
filename = *(filenames++);
|
||||
} while (filename != NULL && filename[0] != '\0');
|
||||
archive_read_set_open_callback(a, file_open);
|
||||
archive_read_set_read_callback(a, file_read);
|
||||
archive_read_set_skip_callback(a, file_skip);
|
||||
archive_read_set_close_callback(a, file_close);
|
||||
archive_read_set_switch_callback(a, file_switch);
|
||||
archive_read_set_seek_callback(a, file_seek);
|
||||
|
||||
return (archive_read_open1(a));
|
||||
no_memory:
|
||||
archive_set_error(a, ENOMEM, "No memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
int
|
||||
archive_read_open_filename_w(struct archive *a, const wchar_t *wfilename,
|
||||
size_t block_size)
|
||||
{
|
||||
enum fnt_e filename_type;
|
||||
struct read_file_data *mine = (struct read_file_data *)calloc(1,
|
||||
sizeof(*mine) + wcslen(wfilename) * sizeof(wchar_t));
|
||||
if (!mine)
|
||||
{
|
||||
archive_set_error(a, ENOMEM, "No memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
mine->fd = -1;
|
||||
mine->block_size = block_size;
|
||||
|
||||
if (wfilename == NULL || wfilename[0] == L'\0') {
|
||||
filename_type = FNT_STDIN;
|
||||
mine->filename_type = FNT_STDIN;
|
||||
} else {
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
filename_type = FNT_WCS;
|
||||
mine->filename_type = FNT_WCS;
|
||||
wcscpy(mine->filename.w, wfilename);
|
||||
#else
|
||||
/*
|
||||
* POSIX system does not support a wchar_t interface for
|
||||
@ -125,7 +180,6 @@ archive_read_open_filename_w(struct archive *a, const wchar_t *wfilename,
|
||||
* filename to multi-byte one and use it.
|
||||
*/
|
||||
struct archive_string fn;
|
||||
int r;
|
||||
|
||||
archive_string_init(&fn);
|
||||
if (archive_string_append_from_wcs(&fn, wfilename,
|
||||
@ -138,22 +192,31 @@ archive_read_open_filename_w(struct archive *a, const wchar_t *wfilename,
|
||||
"Failed to convert a wide-character"
|
||||
" filename to a multi-byte filename");
|
||||
archive_string_free(&fn);
|
||||
free(mine);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
r = file_open_filename(a, FNT_MBS, fn.s, block_size);
|
||||
mine->filename_type = FNT_MBS;
|
||||
strcpy(mine->filename.m, fn.s);
|
||||
archive_string_free(&fn);
|
||||
return (r);
|
||||
#endif
|
||||
}
|
||||
return (file_open_filename(a, filename_type, wfilename, block_size));
|
||||
if (archive_read_append_callback_data(a, mine) != (ARCHIVE_OK))
|
||||
return (ARCHIVE_FATAL);
|
||||
archive_read_set_open_callback(a, file_open);
|
||||
archive_read_set_read_callback(a, file_read);
|
||||
archive_read_set_skip_callback(a, file_skip);
|
||||
archive_read_set_close_callback(a, file_close);
|
||||
archive_read_set_switch_callback(a, file_switch);
|
||||
archive_read_set_seek_callback(a, file_seek);
|
||||
|
||||
return (archive_read_open1(a));
|
||||
}
|
||||
|
||||
static int
|
||||
file_open_filename(struct archive *a, enum fnt_e filename_type,
|
||||
const void *_filename, size_t block_size)
|
||||
file_open(struct archive *a, void *client_data)
|
||||
{
|
||||
struct stat st;
|
||||
struct read_file_data *mine;
|
||||
struct read_file_data *mine = (struct read_file_data *)client_data;
|
||||
void *buffer;
|
||||
const char *filename = NULL;
|
||||
const wchar_t *wfilename = NULL;
|
||||
@ -168,7 +231,7 @@ file_open_filename(struct archive *a, enum fnt_e filename_type,
|
||||
#endif
|
||||
|
||||
archive_clear_error(a);
|
||||
if (filename_type == FNT_STDIN) {
|
||||
if (mine->filename_type == FNT_STDIN) {
|
||||
/* We used to delegate stdin support by
|
||||
* directly calling archive_read_open_fd(a,0,block_size)
|
||||
* here, but that doesn't (and shouldn't) handle the
|
||||
@ -183,9 +246,10 @@ file_open_filename(struct archive *a, enum fnt_e filename_type,
|
||||
setmode(0, O_BINARY);
|
||||
#endif
|
||||
filename = "";
|
||||
} else if (filename_type == FNT_MBS) {
|
||||
filename = (const char *)_filename;
|
||||
fd = open(filename, O_RDONLY | O_BINARY);
|
||||
} else if (mine->filename_type == FNT_MBS) {
|
||||
filename = mine->filename.m;
|
||||
fd = open(filename, O_RDONLY | O_BINARY | O_CLOEXEC);
|
||||
__archive_ensure_cloexec_flag(fd);
|
||||
if (fd < 0) {
|
||||
archive_set_error(a, errno,
|
||||
"Failed to open '%s'", filename);
|
||||
@ -193,7 +257,7 @@ file_open_filename(struct archive *a, enum fnt_e filename_type,
|
||||
}
|
||||
} else {
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
wfilename = (const wchar_t *)_filename;
|
||||
wfilename = mine->filename.w;
|
||||
fd = _wopen(wfilename, O_RDONLY | O_BINARY);
|
||||
if (fd < 0 && errno == ENOENT) {
|
||||
wchar_t *fullpath;
|
||||
@ -215,7 +279,7 @@ file_open_filename(struct archive *a, enum fnt_e filename_type,
|
||||
#endif
|
||||
}
|
||||
if (fstat(fd, &st) != 0) {
|
||||
if (filename_type == FNT_WCS)
|
||||
if (mine->filename_type == FNT_WCS)
|
||||
archive_set_error(a, errno, "Can't stat '%S'",
|
||||
wfilename);
|
||||
else
|
||||
@ -280,50 +344,32 @@ file_open_filename(struct archive *a, enum fnt_e filename_type,
|
||||
#endif
|
||||
/* TODO: Add an "is_tape_like" variable and appropriate tests. */
|
||||
|
||||
if (filename_type == FNT_WCS)
|
||||
mine = (struct read_file_data *)calloc(1,
|
||||
sizeof(*mine) + wcslen(wfilename) * sizeof(wchar_t));
|
||||
else
|
||||
mine = (struct read_file_data *)calloc(1,
|
||||
sizeof(*mine) + strlen(filename));
|
||||
/* Disk-like devices prefer power-of-two block sizes. */
|
||||
/* Use provided block_size as a guide so users have some control. */
|
||||
if (is_disk_like) {
|
||||
size_t new_block_size = 64 * 1024;
|
||||
while (new_block_size < block_size
|
||||
while (new_block_size < mine->block_size
|
||||
&& new_block_size < 64 * 1024 * 1024)
|
||||
new_block_size *= 2;
|
||||
block_size = new_block_size;
|
||||
mine->block_size = new_block_size;
|
||||
}
|
||||
buffer = malloc(block_size);
|
||||
buffer = malloc(mine->block_size);
|
||||
if (mine == NULL || buffer == NULL) {
|
||||
archive_set_error(a, ENOMEM, "No memory");
|
||||
free(mine);
|
||||
free(buffer);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (filename_type == FNT_WCS)
|
||||
wcscpy(mine->filename.w, wfilename);
|
||||
else
|
||||
strcpy(mine->filename.m, filename);
|
||||
mine->filename_type = filename_type;
|
||||
mine->block_size = block_size;
|
||||
mine->buffer = buffer;
|
||||
mine->fd = fd;
|
||||
/* Remember mode so close can decide whether to flush. */
|
||||
mine->st_mode = st.st_mode;
|
||||
|
||||
/* Disk-like inputs can use lseek(). */
|
||||
if (is_disk_like) {
|
||||
archive_read_set_seek_callback(a, file_seek);
|
||||
if (is_disk_like)
|
||||
mine->use_lseek = 1;
|
||||
}
|
||||
|
||||
archive_read_set_read_callback(a, file_read);
|
||||
archive_read_set_skip_callback(a, file_skip);
|
||||
archive_read_set_close_callback(a, file_close);
|
||||
archive_read_set_callback_data(a, mine);
|
||||
return (archive_read_open1(a));
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
@ -401,9 +447,7 @@ file_skip_lseek(struct archive *a, void *client_data, int64_t request)
|
||||
/* TODO: Deal with case where off_t isn't 64 bits.
|
||||
* This shouldn't be a problem on Linux or other POSIX
|
||||
* systems, since the configuration logic for libarchive
|
||||
* tries to obtain a 64-bit off_t. It's still an issue
|
||||
* on Windows, though, so it might suffice to just use
|
||||
* _lseeki64() on Windows.
|
||||
* tries to obtain a 64-bit off_t.
|
||||
*/
|
||||
if ((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0 &&
|
||||
(new_offset = lseek(mine->fd, request, SEEK_CUR)) >= 0)
|
||||
@ -475,7 +519,7 @@ file_seek(struct archive *a, void *client_data, int64_t request, int whence)
|
||||
}
|
||||
|
||||
static int
|
||||
file_close(struct archive *a, void *client_data)
|
||||
file_close2(struct archive *a, void *client_data)
|
||||
{
|
||||
struct read_file_data *mine = (struct read_file_data *)client_data;
|
||||
|
||||
@ -508,6 +552,23 @@ file_close(struct archive *a, void *client_data)
|
||||
close(mine->fd);
|
||||
}
|
||||
free(mine->buffer);
|
||||
mine->buffer = NULL;
|
||||
mine->fd = -1;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
file_close(struct archive *a, void *client_data)
|
||||
{
|
||||
struct read_file_data *mine = (struct read_file_data *)client_data;
|
||||
file_close2(a, client_data);
|
||||
free(mine);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
file_switch(struct archive *a, void *client_data1, void *client_data2)
|
||||
{
|
||||
file_close2(a, client_data1);
|
||||
return file_open(a, client_data2);
|
||||
}
|
||||
|
@ -58,6 +58,8 @@ struct archive_read_filter;
|
||||
struct archive_read_filter_bidder {
|
||||
/* Configuration data for the bidder. */
|
||||
void *data;
|
||||
/* Name of the filter */
|
||||
const char *name;
|
||||
/* Taste the upstream filter to see if we handle this. */
|
||||
int (*bid)(struct archive_read_filter_bidder *,
|
||||
struct archive_read_filter *);
|
||||
@ -82,6 +84,8 @@ struct archive_read_filter {
|
||||
struct archive_read_filter_bidder *bidder; /* My bidder. */
|
||||
struct archive_read_filter *upstream; /* Who I read from. */
|
||||
struct archive_read *archive; /* Associated archive. */
|
||||
/* Open a block for reading */
|
||||
int (*open)(struct archive_read_filter *self);
|
||||
/* Return next block. */
|
||||
ssize_t (*read)(struct archive_read_filter *, const void **);
|
||||
/* Skip forward this many bytes. */
|
||||
@ -90,6 +94,8 @@ struct archive_read_filter {
|
||||
int64_t (*seek)(struct archive_read_filter *self, int64_t offset, int whence);
|
||||
/* Close (just this filter) and free(self). */
|
||||
int (*close)(struct archive_read_filter *self);
|
||||
/* Function that handles switching from reading one block to the next/prev */
|
||||
int (*sswitch)(struct archive_read_filter *self, unsigned int iindex);
|
||||
/* My private data. */
|
||||
void *data;
|
||||
|
||||
@ -118,13 +124,22 @@ struct archive_read_filter {
|
||||
* transformation filters. This will probably break the API/ABI and
|
||||
* so should be deferred at least until libarchive 3.0.
|
||||
*/
|
||||
struct archive_read_data_node {
|
||||
int64_t begin_position;
|
||||
int64_t total_size;
|
||||
void *data;
|
||||
};
|
||||
struct archive_read_client {
|
||||
archive_open_callback *opener;
|
||||
archive_read_callback *reader;
|
||||
archive_skip_callback *skipper;
|
||||
archive_seek_callback *seeker;
|
||||
archive_close_callback *closer;
|
||||
void *data;
|
||||
archive_switch_callback *switcher;
|
||||
unsigned int nodes;
|
||||
unsigned int cursor;
|
||||
int64_t position;
|
||||
struct archive_read_data_node *dataset;
|
||||
};
|
||||
|
||||
struct archive_read {
|
||||
@ -146,18 +161,33 @@ struct archive_read {
|
||||
int64_t read_data_output_offset;
|
||||
size_t read_data_remaining;
|
||||
|
||||
/* Callbacks to open/read/write/close client archive stream. */
|
||||
/*
|
||||
* Used by formats/filters to determine the amount of data
|
||||
* requested from a call to archive_read_data(). This is only
|
||||
* useful when the format/filter has seek support.
|
||||
*/
|
||||
char read_data_is_posix_read;
|
||||
size_t read_data_requested;
|
||||
|
||||
/* Callbacks to open/read/write/close client archive streams. */
|
||||
struct archive_read_client client;
|
||||
|
||||
/* Registered filter bidders. */
|
||||
struct archive_read_filter_bidder bidders[9];
|
||||
struct archive_read_filter_bidder bidders[14];
|
||||
|
||||
/* Last filter in chain */
|
||||
struct archive_read_filter *filter;
|
||||
|
||||
/* Whether to bypass filter bidding process */
|
||||
int bypass_filter_bidding;
|
||||
|
||||
/* File offset of beginning of most recently-read header. */
|
||||
int64_t header_position;
|
||||
|
||||
/* Nodes and offsets of compressed data block */
|
||||
unsigned int data_start_node;
|
||||
unsigned int data_end_node;
|
||||
|
||||
/*
|
||||
* Format detection is mostly the same as compression
|
||||
* detection, with one significant difference: The bidders
|
||||
@ -175,6 +205,7 @@ struct archive_read {
|
||||
int (*read_header)(struct archive_read *, struct archive_entry *);
|
||||
int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *);
|
||||
int (*read_data_skip)(struct archive_read *);
|
||||
int64_t (*seek_data)(struct archive_read *, int64_t, int);
|
||||
int (*cleanup)(struct archive_read *);
|
||||
} formats[16];
|
||||
struct archive_format_descriptor *format; /* Active format. */
|
||||
@ -194,6 +225,7 @@ int __archive_read_register_format(struct archive_read *a,
|
||||
int (*read_header)(struct archive_read *, struct archive_entry *),
|
||||
int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *),
|
||||
int (*read_data_skip)(struct archive_read *),
|
||||
int64_t (*seek_data)(struct archive_read *, int64_t, int),
|
||||
int (*cleanup)(struct archive_read *));
|
||||
|
||||
int __archive_read_get_bidder(struct archive_read *a,
|
||||
@ -207,4 +239,6 @@ int64_t __archive_read_filter_seek(struct archive_read_filter *, int64_t, int);
|
||||
int64_t __archive_read_consume(struct archive_read *, int64_t);
|
||||
int64_t __archive_read_filter_consume(struct archive_read_filter *, int64_t);
|
||||
int __archive_read_program(struct archive_read_filter *, const char *);
|
||||
void __archive_read_free_filters(struct archive_read *);
|
||||
int __archive_read_close_filters(struct archive_read *);
|
||||
#endif
|
||||
|
105
contrib/libarchive/libarchive/archive_read_set_format.c
Normal file
105
contrib/libarchive/libarchive/archive_read_set_format.c
Normal file
@ -0,0 +1,105 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2012 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
|
||||
int
|
||||
archive_read_set_format(struct archive *_a, int code)
|
||||
{
|
||||
int r1, r2, slots, i;
|
||||
char str[10];
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
|
||||
if ((r1 = archive_read_support_format_by_code(_a, code)) < (ARCHIVE_OK))
|
||||
return r1;
|
||||
|
||||
r1 = r2 = (ARCHIVE_OK);
|
||||
if (a->format)
|
||||
r2 = (ARCHIVE_WARN);
|
||||
switch (code & ARCHIVE_FORMAT_BASE_MASK)
|
||||
{
|
||||
case ARCHIVE_FORMAT_7ZIP:
|
||||
strcpy(str, "7zip");
|
||||
break;
|
||||
case ARCHIVE_FORMAT_AR:
|
||||
strcpy(str, "ar");
|
||||
break;
|
||||
case ARCHIVE_FORMAT_CAB:
|
||||
strcpy(str, "cab");
|
||||
break;
|
||||
case ARCHIVE_FORMAT_CPIO:
|
||||
strcpy(str, "cpio");
|
||||
break;
|
||||
case ARCHIVE_FORMAT_ISO9660:
|
||||
strcpy(str, "iso9660");
|
||||
break;
|
||||
case ARCHIVE_FORMAT_LHA:
|
||||
strcpy(str, "lha");
|
||||
break;
|
||||
case ARCHIVE_FORMAT_MTREE:
|
||||
strcpy(str, "mtree");
|
||||
break;
|
||||
case ARCHIVE_FORMAT_RAR:
|
||||
strcpy(str, "rar");
|
||||
break;
|
||||
case ARCHIVE_FORMAT_TAR:
|
||||
strcpy(str, "tar");
|
||||
break;
|
||||
case ARCHIVE_FORMAT_XAR:
|
||||
strcpy(str, "xar");
|
||||
break;
|
||||
case ARCHIVE_FORMAT_ZIP:
|
||||
strcpy(str, "zip");
|
||||
break;
|
||||
default:
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
"Invalid format code specified");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
slots = sizeof(a->formats) / sizeof(a->formats[0]);
|
||||
a->format = &(a->formats[0]);
|
||||
for (i = 0; i < slots; i++, a->format++) {
|
||||
if (!a->format->name || !strcmp(a->format->name, str))
|
||||
break;
|
||||
}
|
||||
if (!a->format->name || strcmp(a->format->name, str))
|
||||
{
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
"Internal error: Unable to set format");
|
||||
r1 = (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
return (r1 < r2) ? r1 : r2;
|
||||
}
|
@ -48,7 +48,7 @@ archive_read_support_filter_all(struct archive *a)
|
||||
archive_read_support_filter_bzip2(a);
|
||||
/* The decompress code doesn't use an outside library. */
|
||||
archive_read_support_filter_compress(a);
|
||||
/* Gzip decompress falls back to "gunzip" command-line. */
|
||||
/* Gzip decompress falls back to "gzip -d" command-line. */
|
||||
archive_read_support_filter_gzip(a);
|
||||
/* Lzip falls back to "unlzip" command-line program. */
|
||||
archive_read_support_filter_lzip(a);
|
||||
@ -63,6 +63,12 @@ archive_read_support_filter_all(struct archive *a)
|
||||
archive_read_support_filter_uu(a);
|
||||
/* The decode code doesn't use an outside library. */
|
||||
archive_read_support_filter_rpm(a);
|
||||
/* The decode code always uses "lrzip -q -d" command-line. */
|
||||
archive_read_support_filter_lrzip(a);
|
||||
/* Lzop decompress falls back to "lzop -d" command-line. */
|
||||
archive_read_support_filter_lzop(a);
|
||||
/* The decode code always uses "grzip -d" command-line. */
|
||||
archive_read_support_filter_grzip(a);
|
||||
|
||||
/* Note: We always return ARCHIVE_OK here, even if some of the
|
||||
* above return ARCHIVE_WARN. The intent here is to enable
|
||||
|
@ -94,6 +94,7 @@ archive_read_support_filter_bzip2(struct archive *_a)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
reader->data = NULL;
|
||||
reader->name = "bzip2";
|
||||
reader->bid = bzip2_reader_bid;
|
||||
reader->init = bzip2_reader_init;
|
||||
reader->options = NULL;
|
||||
@ -102,7 +103,7 @@ archive_read_support_filter_bzip2(struct archive *_a)
|
||||
return (ARCHIVE_OK);
|
||||
#else
|
||||
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
|
||||
"Using external bunzip2 program");
|
||||
"Using external bzip2 program");
|
||||
return (ARCHIVE_WARN);
|
||||
#endif
|
||||
}
|
||||
@ -170,11 +171,11 @@ bzip2_reader_init(struct archive_read_filter *self)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = __archive_read_program(self, "bunzip2");
|
||||
r = __archive_read_program(self, "bzip2 -d");
|
||||
/* Note: We set the format here even if __archive_read_program()
|
||||
* above fails. We do, after all, know what the format is
|
||||
* even if we weren't able to read it. */
|
||||
self->code = ARCHIVE_COMPRESSION_BZIP2;
|
||||
self->code = ARCHIVE_FILTER_BZIP2;
|
||||
self->name = "bzip2";
|
||||
return (r);
|
||||
}
|
||||
@ -192,7 +193,7 @@ bzip2_reader_init(struct archive_read_filter *self)
|
||||
void *out_block;
|
||||
struct private_data *state;
|
||||
|
||||
self->code = ARCHIVE_COMPRESSION_BZIP2;
|
||||
self->code = ARCHIVE_FILTER_BZIP2;
|
||||
self->name = "bzip2";
|
||||
|
||||
state = (struct private_data *)calloc(sizeof(*state), 1);
|
||||
|
@ -163,6 +163,7 @@ archive_read_support_filter_compress(struct archive *_a)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
bidder->data = NULL;
|
||||
bidder->name = "compress (.Z)";
|
||||
bidder->bid = compress_bidder_bid;
|
||||
bidder->init = compress_bidder_init;
|
||||
bidder->options = NULL;
|
||||
@ -212,7 +213,7 @@ compress_bidder_init(struct archive_read_filter *self)
|
||||
void *out_block;
|
||||
int code;
|
||||
|
||||
self->code = ARCHIVE_COMPRESSION_COMPRESS;
|
||||
self->code = ARCHIVE_FILTER_COMPRESS;
|
||||
self->name = "compress (.Z)";
|
||||
|
||||
state = (struct private_data *)calloc(sizeof(*state), 1);
|
||||
|
@ -0,0 +1,121 @@
|
||||
/*-
|
||||
* Copyright (c) 2012 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
|
||||
static const unsigned char grzip_magic[] = {
|
||||
0x47, 0x52, 0x5a, 0x69, 0x70, 0x49, 0x49, 0x00,
|
||||
0x02, 0x04, 0x3a, 0x29 };
|
||||
|
||||
static int grzip_bidder_bid(struct archive_read_filter_bidder *,
|
||||
struct archive_read_filter *);
|
||||
static int grzip_bidder_init(struct archive_read_filter *);
|
||||
|
||||
|
||||
static int
|
||||
grzip_reader_free(struct archive_read_filter_bidder *self)
|
||||
{
|
||||
(void)self; /* UNUSED */
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
int
|
||||
archive_read_support_filter_grzip(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
struct archive_read_filter_bidder *reader;
|
||||
|
||||
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_read_support_filter_grzip");
|
||||
|
||||
if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
reader->data = NULL;
|
||||
reader->bid = grzip_bidder_bid;
|
||||
reader->init = grzip_bidder_init;
|
||||
reader->options = NULL;
|
||||
reader->free = grzip_reader_free;
|
||||
/* This filter always uses an external program. */
|
||||
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
|
||||
"Using external grzip program for grzip decompression");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bidder just verifies the header and returns the number of verified bits.
|
||||
*/
|
||||
static int
|
||||
grzip_bidder_bid(struct archive_read_filter_bidder *self,
|
||||
struct archive_read_filter *filter)
|
||||
{
|
||||
const unsigned char *p;
|
||||
ssize_t avail;
|
||||
|
||||
(void)self; /* UNUSED */
|
||||
|
||||
p = __archive_read_filter_ahead(filter, sizeof(grzip_magic), &avail);
|
||||
if (p == NULL || avail == 0)
|
||||
return (0);
|
||||
|
||||
if (memcmp(p, grzip_magic, sizeof(grzip_magic)))
|
||||
return (0);
|
||||
|
||||
return (sizeof(grzip_magic) * 8);
|
||||
}
|
||||
|
||||
static int
|
||||
grzip_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = __archive_read_program(self, "grzip -d");
|
||||
/* Note: We set the format here even if __archive_read_program()
|
||||
* above fails. We do, after all, know what the format is
|
||||
* even if we weren't able to read it. */
|
||||
self->code = ARCHIVE_FILTER_GRZIP;
|
||||
self->name = "grzip";
|
||||
return (r);
|
||||
}
|
@ -72,7 +72,7 @@ static int gzip_filter_close(struct archive_read_filter *);
|
||||
*
|
||||
* TODO: If zlib is unavailable, gzip_bidder_init() should
|
||||
* use the compress_program framework to try to fire up an external
|
||||
* gunzip program.
|
||||
* gzip program.
|
||||
*/
|
||||
static int gzip_bidder_bid(struct archive_read_filter_bidder *,
|
||||
struct archive_read_filter *);
|
||||
@ -100,6 +100,7 @@ archive_read_support_filter_gzip(struct archive *_a)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
bidder->data = NULL;
|
||||
bidder->name = "gzip";
|
||||
bidder->bid = gzip_bidder_bid;
|
||||
bidder->init = gzip_bidder_init;
|
||||
bidder->options = NULL;
|
||||
@ -109,7 +110,7 @@ archive_read_support_filter_gzip(struct archive *_a)
|
||||
return (ARCHIVE_OK);
|
||||
#else
|
||||
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
|
||||
"Using external gunzip program");
|
||||
"Using external gzip program");
|
||||
return (ARCHIVE_WARN);
|
||||
#endif
|
||||
}
|
||||
@ -121,7 +122,7 @@ archive_read_support_filter_gzip(struct archive *_a)
|
||||
* number of bytes in header. If pbits is non-NULL, it receives a
|
||||
* count of bits verified, suitable for use by bidder.
|
||||
*/
|
||||
static int
|
||||
static ssize_t
|
||||
peek_at_header(struct archive_read_filter *filter, int *pbits)
|
||||
{
|
||||
const unsigned char *p;
|
||||
@ -223,7 +224,7 @@ gzip_bidder_bid(struct archive_read_filter_bidder *self,
|
||||
|
||||
/*
|
||||
* If we don't have the library on this system, we can't do the
|
||||
* decompression directly. We can, however, try to run gunzip
|
||||
* decompression directly. We can, however, try to run "gzip -d"
|
||||
* in case that's available.
|
||||
*/
|
||||
static int
|
||||
@ -231,11 +232,11 @@ gzip_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = __archive_read_program(self, "gunzip");
|
||||
r = __archive_read_program(self, "gzip -d");
|
||||
/* Note: We set the format here even if __archive_read_program()
|
||||
* above fails. We do, after all, know what the format is
|
||||
* even if we weren't able to read it. */
|
||||
self->code = ARCHIVE_COMPRESSION_GZIP;
|
||||
self->code = ARCHIVE_FILTER_GZIP;
|
||||
self->name = "gzip";
|
||||
return (r);
|
||||
}
|
||||
@ -252,7 +253,7 @@ gzip_bidder_init(struct archive_read_filter *self)
|
||||
static const size_t out_block_size = 64 * 1024;
|
||||
void *out_block;
|
||||
|
||||
self->code = ARCHIVE_COMPRESSION_GZIP;
|
||||
self->code = ARCHIVE_FILTER_GZIP;
|
||||
self->name = "gzip";
|
||||
|
||||
state = (struct private_data *)calloc(sizeof(*state), 1);
|
||||
@ -299,7 +300,7 @@ consume_header(struct archive_read_filter *self)
|
||||
/* Initialize compression library. */
|
||||
state->stream.next_in = (unsigned char *)(uintptr_t)
|
||||
__archive_read_filter_ahead(self->upstream, 1, &avail);
|
||||
state->stream.avail_in = avail;
|
||||
state->stream.avail_in = (uInt)avail;
|
||||
ret = inflateInit2(&(state->stream),
|
||||
-15 /* Don't check for zlib header */);
|
||||
|
||||
@ -380,7 +381,7 @@ gzip_filter_read(struct archive_read_filter *self, const void **p)
|
||||
|
||||
/* Empty our output buffer. */
|
||||
state->stream.next_out = state->out_block;
|
||||
state->stream.avail_out = state->out_block_size;
|
||||
state->stream.avail_out = (uInt)state->out_block_size;
|
||||
|
||||
/* Try to fill the output buffer. */
|
||||
while (state->stream.avail_out > 0 && !state->eof) {
|
||||
@ -407,7 +408,7 @@ gzip_filter_read(struct archive_read_filter *self, const void **p)
|
||||
"truncated gzip input");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
state->stream.avail_in = avail_in;
|
||||
state->stream.avail_in = (uInt)avail_in;
|
||||
|
||||
/* Decompress and consume some of that data. */
|
||||
ret = inflate(&(state->stream), 0);
|
||||
|
@ -0,0 +1,132 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
|
||||
#define LRZIP_HEADER_MAGIC "LRZI"
|
||||
#define LRZIP_HEADER_MAGIC_LEN 4
|
||||
|
||||
static int lrzip_bidder_bid(struct archive_read_filter_bidder *,
|
||||
struct archive_read_filter *);
|
||||
static int lrzip_bidder_init(struct archive_read_filter *);
|
||||
|
||||
|
||||
static int
|
||||
lrzip_reader_free(struct archive_read_filter_bidder *self)
|
||||
{
|
||||
(void)self; /* UNUSED */
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
int
|
||||
archive_read_support_filter_lrzip(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
struct archive_read_filter_bidder *reader;
|
||||
|
||||
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_read_support_filter_lrzip");
|
||||
|
||||
if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
reader->data = NULL;
|
||||
reader->name = "lrzip";
|
||||
reader->bid = lrzip_bidder_bid;
|
||||
reader->init = lrzip_bidder_init;
|
||||
reader->options = NULL;
|
||||
reader->free = lrzip_reader_free;
|
||||
/* This filter always uses an external program. */
|
||||
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
|
||||
"Using external lrzip program for lrzip decompression");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bidder just verifies the header and returns the number of verified bits.
|
||||
*/
|
||||
static int
|
||||
lrzip_bidder_bid(struct archive_read_filter_bidder *self,
|
||||
struct archive_read_filter *filter)
|
||||
{
|
||||
const unsigned char *p;
|
||||
ssize_t avail, len;
|
||||
int i;
|
||||
|
||||
(void)self; /* UNUSED */
|
||||
/* Start by looking at the first six bytes of the header, which
|
||||
* is all fixed layout. */
|
||||
len = 6;
|
||||
p = __archive_read_filter_ahead(filter, len, &avail);
|
||||
if (p == NULL || avail == 0)
|
||||
return (0);
|
||||
|
||||
if (memcmp(p, LRZIP_HEADER_MAGIC, LRZIP_HEADER_MAGIC_LEN))
|
||||
return (0);
|
||||
|
||||
/* current major version is always 0, verify this */
|
||||
if (p[LRZIP_HEADER_MAGIC_LEN])
|
||||
return 0;
|
||||
/* support only v0.6+ lrzip for sanity */
|
||||
i = p[LRZIP_HEADER_MAGIC_LEN + 1];
|
||||
if ((i < 6) || (i > 10))
|
||||
return 0;
|
||||
|
||||
return (int)len;
|
||||
}
|
||||
|
||||
static int
|
||||
lrzip_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = __archive_read_program(self, "lrzip -d -q");
|
||||
/* Note: We set the format here even if __archive_read_program()
|
||||
* above fails. We do, after all, know what the format is
|
||||
* even if we weren't able to read it. */
|
||||
self->code = ARCHIVE_FILTER_LRZIP;
|
||||
self->name = "lrzip";
|
||||
return (r);
|
||||
}
|
486
contrib/libarchive/libarchive/archive_read_support_filter_lzop.c
Normal file
486
contrib/libarchive/libarchive/archive_read_support_filter_lzop.c
Normal file
@ -0,0 +1,486 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* Copyright (c) 2012 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_LZO_LZOCONF_H
|
||||
#include <lzo/lzoconf.h>
|
||||
#endif
|
||||
#ifdef HAVE_LZO_LZO1X_H
|
||||
#include <lzo/lzo1x.h>
|
||||
#endif
|
||||
#ifdef HAVE_ZLIB_H
|
||||
#include <zlib.h> /* for crc32 and adler32 */
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#if !defined(HAVE_ZLIB_H) &&\
|
||||
defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
|
||||
#include "archive_crc32.h"
|
||||
#endif
|
||||
#include "archive_endian.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
|
||||
#ifndef HAVE_ZLIB_H
|
||||
#define adler32 lzo_adler32
|
||||
#endif
|
||||
|
||||
#define LZOP_HEADER_MAGIC "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a"
|
||||
#define LZOP_HEADER_MAGIC_LEN 9
|
||||
|
||||
#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
|
||||
struct read_lzop {
|
||||
unsigned char *out_block;
|
||||
size_t out_block_size;
|
||||
int64_t total_out;
|
||||
int flags;
|
||||
uint32_t compressed_cksum;
|
||||
uint32_t uncompressed_cksum;
|
||||
size_t compressed_size;
|
||||
size_t uncompressed_size;
|
||||
size_t unconsumed_bytes;
|
||||
char in_stream;
|
||||
char eof; /* True = found end of compressed data. */
|
||||
};
|
||||
|
||||
#define FILTER 0x0800
|
||||
#define CRC32_HEADER 0x1000
|
||||
#define EXTRA_FIELD 0x0040
|
||||
#define ADLER32_UNCOMPRESSED 0x0001
|
||||
#define ADLER32_COMPRESSED 0x0002
|
||||
#define CRC32_UNCOMPRESSED 0x0100
|
||||
#define CRC32_COMPRESSED 0x0200
|
||||
#define MAX_BLOCK_SIZE (64 * 1024 * 1024)
|
||||
|
||||
static ssize_t lzop_filter_read(struct archive_read_filter *, const void **);
|
||||
static int lzop_filter_close(struct archive_read_filter *);
|
||||
#endif
|
||||
|
||||
static int lzop_bidder_bid(struct archive_read_filter_bidder *,
|
||||
struct archive_read_filter *);
|
||||
static int lzop_bidder_init(struct archive_read_filter *);
|
||||
|
||||
int
|
||||
archive_read_support_filter_lzop(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
struct archive_read_filter_bidder *reader;
|
||||
|
||||
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_read_support_filter_lzop");
|
||||
|
||||
if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
reader->data = NULL;
|
||||
reader->bid = lzop_bidder_bid;
|
||||
reader->init = lzop_bidder_init;
|
||||
reader->options = NULL;
|
||||
reader->free = NULL;
|
||||
/* Signal the extent of lzop support with the return value here. */
|
||||
#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
|
||||
return (ARCHIVE_OK);
|
||||
#else
|
||||
/* Return ARCHIVE_WARN since this always uses an external program. */
|
||||
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
|
||||
"Using external lzop program for lzop decompression");
|
||||
return (ARCHIVE_WARN);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Bidder just verifies the header and returns the number of verified bits.
|
||||
*/
|
||||
static int
|
||||
lzop_bidder_bid(struct archive_read_filter_bidder *self,
|
||||
struct archive_read_filter *filter)
|
||||
{
|
||||
const unsigned char *p;
|
||||
ssize_t avail;
|
||||
|
||||
(void)self; /* UNUSED */
|
||||
|
||||
p = __archive_read_filter_ahead(filter, LZOP_HEADER_MAGIC_LEN, &avail);
|
||||
if (p == NULL || avail == 0)
|
||||
return (0);
|
||||
|
||||
if (memcmp(p, LZOP_HEADER_MAGIC, LZOP_HEADER_MAGIC_LEN))
|
||||
return (0);
|
||||
|
||||
return (LZOP_HEADER_MAGIC_LEN * 8);
|
||||
}
|
||||
|
||||
#if !defined(HAVE_LZO_LZOCONF_H) || !defined(HAVE_LZO_LZO1X_H)
|
||||
/*
|
||||
* If we don't have the library on this system, we can't do the
|
||||
* decompression directly. We can, however, try to run "lzop -d"
|
||||
* in case that's available.
|
||||
*/
|
||||
static int
|
||||
lzop_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = __archive_read_program(self, "lzop -d");
|
||||
/* Note: We set the format here even if __archive_read_program()
|
||||
* above fails. We do, after all, know what the format is
|
||||
* even if we weren't able to read it. */
|
||||
self->code = ARCHIVE_FILTER_LZOP;
|
||||
self->name = "lzop";
|
||||
return (r);
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* Initialize the filter object.
|
||||
*/
|
||||
static int
|
||||
lzop_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
struct read_lzop *state;
|
||||
|
||||
self->code = ARCHIVE_FILTER_LZOP;
|
||||
self->name = "lzop";
|
||||
|
||||
state = (struct read_lzop *)calloc(sizeof(*state), 1);
|
||||
if (state == NULL) {
|
||||
archive_set_error(&self->archive->archive, ENOMEM,
|
||||
"Can't allocate data for lzop decompression");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
self->data = state;
|
||||
self->read = lzop_filter_read;
|
||||
self->skip = NULL; /* not supported */
|
||||
self->close = lzop_filter_close;
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
consume_header(struct archive_read_filter *self)
|
||||
{
|
||||
struct read_lzop *state = (struct read_lzop *)self->data;
|
||||
const unsigned char *p, *_p;
|
||||
unsigned checksum, flags, len, method, version;
|
||||
|
||||
/*
|
||||
* Check LZOP magic code.
|
||||
*/
|
||||
p = __archive_read_filter_ahead(self->upstream,
|
||||
LZOP_HEADER_MAGIC_LEN, NULL);
|
||||
if (p == NULL)
|
||||
return (ARCHIVE_EOF);
|
||||
|
||||
if (memcmp(p, LZOP_HEADER_MAGIC, LZOP_HEADER_MAGIC_LEN))
|
||||
return (ARCHIVE_EOF);
|
||||
__archive_read_filter_consume(self->upstream,
|
||||
LZOP_HEADER_MAGIC_LEN);
|
||||
|
||||
p = __archive_read_filter_ahead(self->upstream, 29, NULL);
|
||||
if (p == NULL)
|
||||
goto truncated;
|
||||
_p = p;
|
||||
version = archive_be16dec(p);
|
||||
p += 4;/* version(2 bytes) + library version(2 bytes) */
|
||||
|
||||
if (version >= 0x940) {
|
||||
unsigned reqversion = archive_be16dec(p); p += 2;
|
||||
if (reqversion < 0x900) {
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC, "Invalid required version");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
method = *p++;
|
||||
if (method < 1 || method > 3) {
|
||||
archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Unsupported method");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
|
||||
if (version >= 0x940) {
|
||||
unsigned level = *p++;
|
||||
if (method == 1 && level == 0) level = 3;
|
||||
if (method == 2 && level == 0) level = 1;
|
||||
if (method == 3 && level == 0) level = 9;
|
||||
if (level < 1 && level > 9) {
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC, "Invalid level");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
flags = archive_be32dec(p); p += 4;
|
||||
|
||||
if (flags & FILTER)
|
||||
p += 4; /* Skip filter */
|
||||
p += 4; /* Skip mode */
|
||||
if (version >= 0x940)
|
||||
p += 8; /* Skip mtime */
|
||||
else
|
||||
p += 4; /* Skip mtime */
|
||||
len = *p++; /* Read filename length */
|
||||
len += p - _p;
|
||||
/* Make sure we have all bytes we need to calculate checksum. */
|
||||
p = __archive_read_filter_ahead(self->upstream, len + 4, NULL);
|
||||
if (p == NULL)
|
||||
goto truncated;
|
||||
if (flags & CRC32_HEADER)
|
||||
checksum = crc32(crc32(0, NULL, 0), p, len);
|
||||
else
|
||||
checksum = adler32(adler32(0, NULL, 0), p, len);
|
||||
if (archive_be32dec(p + len) != checksum)
|
||||
goto corrupted;
|
||||
__archive_read_filter_consume(self->upstream, len + 4);
|
||||
if (flags & EXTRA_FIELD) {
|
||||
/* Skip extra field */
|
||||
p = __archive_read_filter_ahead(self->upstream, 4, NULL);
|
||||
if (p == NULL)
|
||||
goto truncated;
|
||||
len = archive_be32dec(p);
|
||||
__archive_read_filter_consume(self->upstream, len + 4 + 4);
|
||||
}
|
||||
state->flags = flags;
|
||||
state->in_stream = 1;
|
||||
return (ARCHIVE_OK);
|
||||
truncated:
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data");
|
||||
return (ARCHIVE_FAILED);
|
||||
corrupted:
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT, "Corrupted lzop header");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
|
||||
static int
|
||||
consume_block_info(struct archive_read_filter *self)
|
||||
{
|
||||
struct read_lzop *state = (struct read_lzop *)self->data;
|
||||
const unsigned char *p;
|
||||
unsigned flags = state->flags;
|
||||
|
||||
p = __archive_read_filter_ahead(self->upstream, 4, NULL);
|
||||
if (p == NULL)
|
||||
goto truncated;
|
||||
state->uncompressed_size = archive_be32dec(p);
|
||||
__archive_read_filter_consume(self->upstream, 4);
|
||||
if (state->uncompressed_size == 0)
|
||||
return (ARCHIVE_EOF);
|
||||
if (state->uncompressed_size > MAX_BLOCK_SIZE)
|
||||
goto corrupted;
|
||||
|
||||
p = __archive_read_filter_ahead(self->upstream, 4, NULL);
|
||||
if (p == NULL)
|
||||
goto truncated;
|
||||
state->compressed_size = archive_be32dec(p);
|
||||
__archive_read_filter_consume(self->upstream, 4);
|
||||
if (state->compressed_size > state->uncompressed_size)
|
||||
goto corrupted;
|
||||
|
||||
if (flags & (CRC32_UNCOMPRESSED | ADLER32_UNCOMPRESSED)) {
|
||||
p = __archive_read_filter_ahead(self->upstream, 4, NULL);
|
||||
if (p == NULL)
|
||||
goto truncated;
|
||||
state->compressed_cksum = state->uncompressed_cksum =
|
||||
archive_be32dec(p);
|
||||
__archive_read_filter_consume(self->upstream, 4);
|
||||
}
|
||||
if ((flags & (CRC32_COMPRESSED | ADLER32_COMPRESSED)) &&
|
||||
state->compressed_size < state->uncompressed_size) {
|
||||
p = __archive_read_filter_ahead(self->upstream, 4, NULL);
|
||||
if (p == NULL)
|
||||
goto truncated;
|
||||
state->compressed_cksum = archive_be32dec(p);
|
||||
__archive_read_filter_consume(self->upstream, 4);
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
truncated:
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data");
|
||||
return (ARCHIVE_FAILED);
|
||||
corrupted:
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT, "Corrupted lzop header");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
lzop_filter_read(struct archive_read_filter *self, const void **p)
|
||||
{
|
||||
struct read_lzop *state = (struct read_lzop *)self->data;
|
||||
const void *b;
|
||||
lzo_uint out_size;
|
||||
uint32_t cksum;
|
||||
int ret, r;
|
||||
|
||||
if (state->unconsumed_bytes) {
|
||||
__archive_read_filter_consume(self->upstream,
|
||||
state->unconsumed_bytes);
|
||||
state->unconsumed_bytes = 0;
|
||||
}
|
||||
if (state->eof)
|
||||
return (0);
|
||||
|
||||
for (;;) {
|
||||
if (!state->in_stream) {
|
||||
ret = consume_header(self);
|
||||
if (ret < ARCHIVE_OK)
|
||||
return (ret);
|
||||
if (ret == ARCHIVE_EOF) {
|
||||
state->eof = 1;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
ret = consume_block_info(self);
|
||||
if (ret < ARCHIVE_OK)
|
||||
return (ret);
|
||||
if (ret == ARCHIVE_EOF)
|
||||
state->in_stream = 0;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (state->out_block == NULL ||
|
||||
state->out_block_size < state->uncompressed_size) {
|
||||
void *new_block;
|
||||
|
||||
new_block = realloc(state->out_block, state->uncompressed_size);
|
||||
if (new_block == NULL) {
|
||||
archive_set_error(&self->archive->archive, ENOMEM,
|
||||
"Can't allocate data for lzop decompression");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
state->out_block = new_block;
|
||||
state->out_block_size = state->uncompressed_size;
|
||||
}
|
||||
|
||||
b = __archive_read_filter_ahead(self->upstream,
|
||||
state->compressed_size, NULL);
|
||||
if (b == NULL) {
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (state->flags & CRC32_COMPRESSED)
|
||||
cksum = crc32(crc32(0, NULL, 0), b, state->compressed_size);
|
||||
else if (state->flags & ADLER32_COMPRESSED)
|
||||
cksum = adler32(adler32(0, NULL, 0), b, state->compressed_size);
|
||||
else
|
||||
cksum = state->compressed_cksum;
|
||||
if (cksum != state->compressed_cksum) {
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC, "Corrupted data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the both uncompressed size and compressed size are the same,
|
||||
* we do not decompress this block.
|
||||
*/
|
||||
if (state->uncompressed_size == state->compressed_size) {
|
||||
*p = b;
|
||||
state->total_out += state->compressed_size;
|
||||
state->unconsumed_bytes = state->compressed_size;
|
||||
return ((ssize_t)state->uncompressed_size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Drive lzo uncompresison.
|
||||
*/
|
||||
out_size = (lzo_uint)state->uncompressed_size;
|
||||
r = lzo1x_decompress_safe(b, (lzo_uint)state->compressed_size,
|
||||
state->out_block, &out_size, NULL);
|
||||
switch (r) {
|
||||
case LZO_E_OK:
|
||||
if (out_size == state->uncompressed_size)
|
||||
break;
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC, "Corrupted data");
|
||||
return (ARCHIVE_FATAL);
|
||||
case LZO_E_OUT_OF_MEMORY:
|
||||
archive_set_error(&self->archive->archive, ENOMEM,
|
||||
"lzop decompression failed: out of memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
default:
|
||||
archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
|
||||
"lzop decompression failed: %d", r);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
if (state->flags & CRC32_UNCOMPRESSED)
|
||||
cksum = crc32(crc32(0, NULL, 0), state->out_block,
|
||||
state->uncompressed_size);
|
||||
else if (state->flags & ADLER32_UNCOMPRESSED)
|
||||
cksum = adler32(adler32(0, NULL, 0), state->out_block,
|
||||
state->uncompressed_size);
|
||||
else
|
||||
cksum = state->uncompressed_cksum;
|
||||
if (cksum != state->uncompressed_cksum) {
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC, "Corrupted data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
__archive_read_filter_consume(self->upstream, state->compressed_size);
|
||||
*p = state->out_block;
|
||||
state->total_out += out_size;
|
||||
return ((ssize_t)out_size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up the decompressor.
|
||||
*/
|
||||
static int
|
||||
lzop_filter_close(struct archive_read_filter *self)
|
||||
{
|
||||
struct read_lzop *state = (struct read_lzop *)self->data;
|
||||
|
||||
free(state->out_block);
|
||||
free(state);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#endif
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2007 Joerg Sonnenberger
|
||||
* Copyright (c) 2012 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -53,7 +54,9 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_string.h"
|
||||
#include "archive_read_private.h"
|
||||
#include "filter_fork.h"
|
||||
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
@ -79,50 +82,13 @@ archive_read_support_filter_program(struct archive *a, const char *cmd)
|
||||
return (archive_read_support_filter_program_signature(a, cmd, NULL, 0));
|
||||
}
|
||||
|
||||
|
||||
/* This capability is only available on POSIX systems. */
|
||||
#if (!defined(HAVE_PIPE) || !defined(HAVE_FCNTL) || \
|
||||
!(defined(HAVE_FORK) || defined(HAVE_VFORK))) && (!defined(_WIN32) || defined(__CYGWIN__))
|
||||
|
||||
/*
|
||||
* On non-Posix systems, allow the program to build, but choke if
|
||||
* this function is actually invoked.
|
||||
*/
|
||||
int
|
||||
archive_read_support_filter_program_signature(struct archive *_a,
|
||||
const char *cmd, const void *signature, size_t signature_len)
|
||||
{
|
||||
(void)_a; /* UNUSED */
|
||||
(void)cmd; /* UNUSED */
|
||||
(void)signature; /* UNUSED */
|
||||
(void)signature_len; /* UNUSED */
|
||||
|
||||
archive_set_error(_a, -1,
|
||||
"External compression programs not supported on this platform");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
int
|
||||
__archive_read_program(struct archive_read_filter *self, const char *cmd)
|
||||
{
|
||||
(void)self; /* UNUSED */
|
||||
(void)cmd; /* UNUSED */
|
||||
|
||||
archive_set_error(&self->archive->archive, -1,
|
||||
"External compression programs not supported on this platform");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include "filter_fork.h"
|
||||
|
||||
/*
|
||||
* The bidder object stores the command and the signature to watch for.
|
||||
* The 'inhibit' entry here is used to ensure that unchecked filters never
|
||||
* bid twice in the same pipeline.
|
||||
*/
|
||||
struct program_bidder {
|
||||
char *description;
|
||||
char *cmd;
|
||||
void *signature;
|
||||
size_t signature_len;
|
||||
@ -138,8 +104,12 @@ static int program_bidder_free(struct archive_read_filter_bidder *);
|
||||
* The actual filter needs to track input and output data.
|
||||
*/
|
||||
struct program_filter {
|
||||
char *description;
|
||||
struct archive_string description;
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
HANDLE child;
|
||||
#else
|
||||
pid_t child;
|
||||
#endif
|
||||
int exit_status;
|
||||
int waitpid_return;
|
||||
int child_stdin, child_stdout;
|
||||
@ -151,6 +121,29 @@ struct program_filter {
|
||||
static ssize_t program_filter_read(struct archive_read_filter *,
|
||||
const void **);
|
||||
static int program_filter_close(struct archive_read_filter *);
|
||||
static void free_state(struct program_bidder *);
|
||||
|
||||
static int
|
||||
set_bidder_signature(struct archive_read_filter_bidder *bidder,
|
||||
struct program_bidder *state, const void *signature, size_t signature_len)
|
||||
{
|
||||
|
||||
if (signature != NULL && signature_len > 0) {
|
||||
state->signature_len = signature_len;
|
||||
state->signature = malloc(signature_len);
|
||||
memcpy(state->signature, signature, signature_len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in the bidder object.
|
||||
*/
|
||||
bidder->data = state;
|
||||
bidder->bid = program_bidder_bid;
|
||||
bidder->init = program_bidder_init;
|
||||
bidder->options = NULL;
|
||||
bidder->free = program_bidder_free;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
int
|
||||
archive_read_support_filter_program_signature(struct archive *_a,
|
||||
@ -169,37 +162,40 @@ archive_read_support_filter_program_signature(struct archive *_a,
|
||||
/*
|
||||
* Allocate our private state.
|
||||
*/
|
||||
state = (struct program_bidder *)calloc(sizeof (*state), 1);
|
||||
state = (struct program_bidder *)calloc(1, sizeof (*state));
|
||||
if (state == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
goto memerr;
|
||||
state->cmd = strdup(cmd);
|
||||
if (signature != NULL && signature_len > 0) {
|
||||
state->signature_len = signature_len;
|
||||
state->signature = malloc(signature_len);
|
||||
memcpy(state->signature, signature, signature_len);
|
||||
}
|
||||
if (state->cmd == NULL)
|
||||
goto memerr;
|
||||
|
||||
/*
|
||||
* Fill in the bidder object.
|
||||
*/
|
||||
bidder->data = state;
|
||||
bidder->bid = program_bidder_bid;
|
||||
bidder->init = program_bidder_init;
|
||||
bidder->options = NULL;
|
||||
bidder->free = program_bidder_free;
|
||||
return (ARCHIVE_OK);
|
||||
return set_bidder_signature(bidder, state, signature, signature_len);
|
||||
memerr:
|
||||
free_state(state);
|
||||
archive_set_error(_a, ENOMEM, "Can't allocate memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
static int
|
||||
program_bidder_free(struct archive_read_filter_bidder *self)
|
||||
{
|
||||
struct program_bidder *state = (struct program_bidder *)self->data;
|
||||
free(state->cmd);
|
||||
free(state->signature);
|
||||
free(self->data);
|
||||
|
||||
free_state(state);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static void
|
||||
free_state(struct program_bidder *state)
|
||||
{
|
||||
|
||||
if (state) {
|
||||
free(state->cmd);
|
||||
free(state->signature);
|
||||
free(state);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we do have a signature, bid only if that matches.
|
||||
*
|
||||
@ -258,6 +254,9 @@ child_stop(struct archive_read_filter *self, struct program_filter *state)
|
||||
state->waitpid_return
|
||||
= waitpid(state->child, &state->exit_status, 0);
|
||||
} while (state->waitpid_return == -1 && errno == EINTR);
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
CloseHandle(state->child);
|
||||
#endif
|
||||
state->child = 0;
|
||||
}
|
||||
|
||||
@ -310,11 +309,35 @@ child_read(struct archive_read_filter *self, char *buf, size_t buf_len)
|
||||
struct program_filter *state = self->data;
|
||||
ssize_t ret, requested, avail;
|
||||
const char *p;
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
HANDLE handle = (HANDLE)_get_osfhandle(state->child_stdout);
|
||||
#endif
|
||||
|
||||
requested = buf_len > SSIZE_MAX ? SSIZE_MAX : buf_len;
|
||||
|
||||
for (;;) {
|
||||
do {
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* Avoid infinity wait.
|
||||
* Note: If there is no data in the pipe, ReadFile()
|
||||
* called in read() never returns and so we won't
|
||||
* write remaining encoded data to the pipe.
|
||||
* Note: This way may cause performance problem.
|
||||
* we are looking forward to great code to resolve
|
||||
* this. */
|
||||
DWORD pipe_avail = -1;
|
||||
int cnt = 2;
|
||||
|
||||
while (PeekNamedPipe(handle, NULL, 0, NULL,
|
||||
&pipe_avail, NULL) != 0 && pipe_avail == 0 &&
|
||||
cnt--)
|
||||
Sleep(5);
|
||||
if (pipe_avail == 0) {
|
||||
ret = -1;
|
||||
errno = EAGAIN;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
ret = read(state->child_stdout, buf, requested);
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
|
||||
@ -376,38 +399,57 @@ __archive_read_program(struct archive_read_filter *self, const char *cmd)
|
||||
struct program_filter *state;
|
||||
static const size_t out_buf_len = 65536;
|
||||
char *out_buf;
|
||||
char *description;
|
||||
const char *prefix = "Program: ";
|
||||
pid_t child;
|
||||
size_t l;
|
||||
|
||||
l = strlen(prefix) + strlen(cmd) + 1;
|
||||
state = (struct program_filter *)calloc(1, sizeof(*state));
|
||||
out_buf = (char *)malloc(out_buf_len);
|
||||
description = (char *)malloc(strlen(prefix) + strlen(cmd) + 1);
|
||||
if (state == NULL || out_buf == NULL || description == NULL) {
|
||||
if (state == NULL || out_buf == NULL ||
|
||||
archive_string_ensure(&state->description, l) == NULL) {
|
||||
archive_set_error(&self->archive->archive, ENOMEM,
|
||||
"Can't allocate input data");
|
||||
free(state);
|
||||
if (state != NULL) {
|
||||
archive_string_free(&state->description);
|
||||
free(state);
|
||||
}
|
||||
free(out_buf);
|
||||
free(description);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
archive_strcpy(&state->description, prefix);
|
||||
archive_strcat(&state->description, cmd);
|
||||
|
||||
self->code = ARCHIVE_COMPRESSION_PROGRAM;
|
||||
state->description = description;
|
||||
strcpy(state->description, prefix);
|
||||
strcat(state->description, cmd);
|
||||
self->name = state->description;
|
||||
self->code = ARCHIVE_FILTER_PROGRAM;
|
||||
self->name = state->description.s;
|
||||
|
||||
state->out_buf = out_buf;
|
||||
state->out_buf_len = out_buf_len;
|
||||
|
||||
if ((state->child = __archive_create_child(cmd,
|
||||
&state->child_stdin, &state->child_stdout)) == -1) {
|
||||
child = __archive_create_child(cmd, &state->child_stdin,
|
||||
&state->child_stdout);
|
||||
if (child == -1) {
|
||||
free(state->out_buf);
|
||||
free(state);
|
||||
archive_set_error(&self->archive->archive, EINVAL,
|
||||
"Can't initialize filter; unable to run program \"%s\"", cmd);
|
||||
"Can't initialize filter; unable to run program \"%s\"",
|
||||
cmd);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
state->child = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, child);
|
||||
if (state->child == NULL) {
|
||||
child_stop(self, state);
|
||||
free(state->out_buf);
|
||||
free(state);
|
||||
archive_set_error(&self->archive->archive, EINVAL,
|
||||
"Can't initialize filter; unable to run program \"%s\"",
|
||||
cmd);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
#else
|
||||
state->child = child;
|
||||
#endif
|
||||
|
||||
self->data = state;
|
||||
self->read = program_filter_read;
|
||||
@ -467,10 +509,8 @@ program_filter_close(struct archive_read_filter *self)
|
||||
|
||||
/* Release our private data. */
|
||||
free(state->out_buf);
|
||||
free(state->description);
|
||||
archive_string_free(&state->description);
|
||||
free(state);
|
||||
|
||||
return (e);
|
||||
}
|
||||
|
||||
#endif /* !defined(HAVE_PIPE) || !defined(HAVE_VFORK) || !defined(HAVE_FCNTL) */
|
||||
|
@ -85,6 +85,7 @@ archive_read_support_filter_rpm(struct archive *_a)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
bidder->data = NULL;
|
||||
bidder->name = "rpm";
|
||||
bidder->bid = rpm_bidder_bid;
|
||||
bidder->init = rpm_bidder_init;
|
||||
bidder->options = NULL;
|
||||
@ -137,7 +138,7 @@ rpm_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
struct rpm *rpm;
|
||||
|
||||
self->code = ARCHIVE_COMPRESSION_RPM;
|
||||
self->code = ARCHIVE_FILTER_RPM;
|
||||
self->name = "rpm";
|
||||
self->read = rpm_filter_read;
|
||||
self->skip = NULL; /* not supported */
|
||||
|
@ -56,6 +56,7 @@ struct uudecode {
|
||||
#define ST_READ_UU 1
|
||||
#define ST_UUEND 2
|
||||
#define ST_READ_BASE64 3
|
||||
#define ST_IGNORE 4
|
||||
};
|
||||
|
||||
static int uudecode_bidder_bid(struct archive_read_filter_bidder *,
|
||||
@ -88,6 +89,7 @@ archive_read_support_filter_uu(struct archive *_a)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
bidder->data = NULL;
|
||||
bidder->name = "uu";
|
||||
bidder->bid = uudecode_bidder_bid;
|
||||
bidder->init = uudecode_bidder_init;
|
||||
bidder->options = NULL;
|
||||
@ -377,7 +379,7 @@ uudecode_bidder_init(struct archive_read_filter *self)
|
||||
void *out_buff;
|
||||
void *in_buff;
|
||||
|
||||
self->code = ARCHIVE_COMPRESSION_UU;
|
||||
self->code = ARCHIVE_FILTER_UU;
|
||||
self->name = "uu";
|
||||
self->read = uudecode_filter_read;
|
||||
self->skip = NULL; /* not supported */
|
||||
@ -470,6 +472,10 @@ uudecode_filter_read(struct archive_read_filter *self, const void **buff)
|
||||
total = 0;
|
||||
out = uudecode->out_buff;
|
||||
ravail = avail_in;
|
||||
if (uudecode->state == ST_IGNORE) {
|
||||
used = avail_in;
|
||||
goto finish;
|
||||
}
|
||||
if (uudecode->in_cnt) {
|
||||
/*
|
||||
* If there is remaining data which is saved by
|
||||
@ -485,12 +491,18 @@ uudecode_filter_read(struct archive_read_filter *self, const void **buff)
|
||||
uudecode->in_cnt = 0;
|
||||
}
|
||||
for (;used < avail_in; d += llen, used += llen) {
|
||||
int l, body;
|
||||
int64_t l, body;
|
||||
|
||||
b = d;
|
||||
len = get_line(b, avail_in - used, &nl);
|
||||
if (len < 0) {
|
||||
/* Non-ascii character is found. */
|
||||
if (uudecode->state == ST_FIND_HEAD &&
|
||||
(uudecode->total > 0 || total > 0)) {
|
||||
uudecode->state = ST_IGNORE;
|
||||
used = avail_in;
|
||||
goto finish;
|
||||
}
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Insufficient compressed data");
|
||||
@ -507,7 +519,7 @@ uudecode_filter_read(struct archive_read_filter *self, const void **buff)
|
||||
return (ARCHIVE_FATAL);
|
||||
if (uudecode->in_buff != b)
|
||||
memmove(uudecode->in_buff, b, len);
|
||||
uudecode->in_cnt = len;
|
||||
uudecode->in_cnt = (int)len;
|
||||
if (total == 0) {
|
||||
/* Do not return 0; it means end-of-file.
|
||||
* We should try to read bytes more. */
|
||||
@ -545,7 +557,7 @@ uudecode_filter_read(struct archive_read_filter *self, const void **buff)
|
||||
break;
|
||||
case ST_READ_UU:
|
||||
if (total + len * 2 > OUT_BUFF_SIZE)
|
||||
break;
|
||||
goto finish;
|
||||
body = len - nl;
|
||||
if (!uuchar[*b] || body <= 0) {
|
||||
archive_set_error(&self->archive->archive,
|
||||
@ -611,7 +623,7 @@ uudecode_filter_read(struct archive_read_filter *self, const void **buff)
|
||||
break;
|
||||
case ST_READ_BASE64:
|
||||
if (total + len * 2 > OUT_BUFF_SIZE)
|
||||
break;
|
||||
goto finish;
|
||||
l = len - nl;
|
||||
if (l >= 3 && b[0] == '=' && b[1] == '=' &&
|
||||
b[2] == '=') {
|
||||
@ -657,8 +669,10 @@ uudecode_filter_read(struct archive_read_filter *self, const void **buff)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
__archive_read_filter_consume(self->upstream, ravail);
|
||||
finish:
|
||||
if (ravail < avail_in)
|
||||
used -= avail_in - ravail;
|
||||
__archive_read_filter_consume(self->upstream, used);
|
||||
|
||||
*buff = uudecode->out_buff;
|
||||
uudecode->total += total;
|
||||
|
@ -136,6 +136,7 @@ archive_read_support_filter_xz(struct archive *_a)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
bidder->data = NULL;
|
||||
bidder->name = "xz";
|
||||
bidder->bid = xz_bidder_bid;
|
||||
bidder->init = xz_bidder_init;
|
||||
bidder->options = NULL;
|
||||
@ -144,7 +145,7 @@ archive_read_support_filter_xz(struct archive *_a)
|
||||
return (ARCHIVE_OK);
|
||||
#else
|
||||
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
|
||||
"Using external unxz program for xz decompression");
|
||||
"Using external xz program for xz decompression");
|
||||
return (ARCHIVE_WARN);
|
||||
#endif
|
||||
}
|
||||
@ -170,6 +171,7 @@ archive_read_support_filter_lzma(struct archive *_a)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
bidder->data = NULL;
|
||||
bidder->name = "lzma";
|
||||
bidder->bid = lzma_bidder_bid;
|
||||
bidder->init = lzma_bidder_init;
|
||||
bidder->options = NULL;
|
||||
@ -180,7 +182,7 @@ archive_read_support_filter_lzma(struct archive *_a)
|
||||
return (ARCHIVE_OK);
|
||||
#else
|
||||
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
|
||||
"Using external unlzma program for lzma decompression");
|
||||
"Using external lzma program for lzma decompression");
|
||||
return (ARCHIVE_WARN);
|
||||
#endif
|
||||
}
|
||||
@ -207,6 +209,7 @@ archive_read_support_filter_lzip(struct archive *_a)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
bidder->data = NULL;
|
||||
bidder->name = "lzip";
|
||||
bidder->bid = lzip_bidder_bid;
|
||||
bidder->init = lzip_bidder_init;
|
||||
bidder->options = NULL;
|
||||
@ -415,7 +418,7 @@ lzip_bidder_bid(struct archive_read_filter_bidder *self,
|
||||
static int
|
||||
xz_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
self->code = ARCHIVE_COMPRESSION_XZ;
|
||||
self->code = ARCHIVE_FILTER_XZ;
|
||||
self->name = "xz";
|
||||
return (xz_lzma_bidder_init(self));
|
||||
}
|
||||
@ -423,7 +426,7 @@ xz_bidder_init(struct archive_read_filter *self)
|
||||
static int
|
||||
lzma_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
self->code = ARCHIVE_COMPRESSION_LZMA;
|
||||
self->code = ARCHIVE_FILTER_LZMA;
|
||||
self->name = "lzma";
|
||||
return (xz_lzma_bidder_init(self));
|
||||
}
|
||||
@ -431,7 +434,7 @@ lzma_bidder_init(struct archive_read_filter *self)
|
||||
static int
|
||||
lzip_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
self->code = ARCHIVE_COMPRESSION_LZIP;
|
||||
self->code = ARCHIVE_FILTER_LZIP;
|
||||
self->name = "lzip";
|
||||
return (xz_lzma_bidder_init(self));
|
||||
}
|
||||
@ -518,7 +521,7 @@ xz_lzma_bidder_init(struct archive_read_filter *self)
|
||||
state->stream.avail_out = state->out_block_size;
|
||||
|
||||
state->crc32 = 0;
|
||||
if (self->code == ARCHIVE_COMPRESSION_LZIP) {
|
||||
if (self->code == ARCHIVE_FILTER_LZIP) {
|
||||
/*
|
||||
* We have to read a lzip header and use it to initialize
|
||||
* compression library, thus we cannot initialize the
|
||||
@ -530,7 +533,7 @@ xz_lzma_bidder_init(struct archive_read_filter *self)
|
||||
state->in_stream = 1;
|
||||
|
||||
/* Initialize compression library. */
|
||||
if (self->code == ARCHIVE_COMPRESSION_XZ)
|
||||
if (self->code == ARCHIVE_FILTER_XZ)
|
||||
ret = lzma_stream_decoder(&(state->stream),
|
||||
LZMA_MEMLIMIT,/* memlimit */
|
||||
LZMA_CONCATENATED);
|
||||
@ -730,7 +733,7 @@ xz_filter_read(struct archive_read_filter *self, const void **p)
|
||||
*p = NULL;
|
||||
else {
|
||||
*p = state->out_block;
|
||||
if (self->code == ARCHIVE_COMPRESSION_LZIP) {
|
||||
if (self->code == ARCHIVE_FILTER_LZIP) {
|
||||
state->crc32 = lzma_crc32(state->out_block,
|
||||
decompressed, state->crc32);
|
||||
if (state->eof) {
|
||||
@ -778,7 +781,7 @@ lzma_bidder_init(struct archive_read_filter *self)
|
||||
struct private_data *state;
|
||||
ssize_t ret, avail_in;
|
||||
|
||||
self->code = ARCHIVE_COMPRESSION_LZMA;
|
||||
self->code = ARCHIVE_FILTER_LZMA;
|
||||
self->name = "lzma";
|
||||
|
||||
state = (struct private_data *)calloc(sizeof(*state), 1);
|
||||
@ -941,11 +944,11 @@ lzma_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = __archive_read_program(self, "unlzma");
|
||||
r = __archive_read_program(self, "lzma -d -qq");
|
||||
/* Note: We set the format here even if __archive_read_program()
|
||||
* above fails. We do, after all, know what the format is
|
||||
* even if we weren't able to read it. */
|
||||
self->code = ARCHIVE_COMPRESSION_LZMA;
|
||||
self->code = ARCHIVE_FILTER_LZMA;
|
||||
self->name = "lzma";
|
||||
return (r);
|
||||
}
|
||||
@ -958,11 +961,11 @@ xz_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = __archive_read_program(self, "unxz");
|
||||
r = __archive_read_program(self, "xz -d -qq");
|
||||
/* Note: We set the format here even if __archive_read_program()
|
||||
* above fails. We do, after all, know what the format is
|
||||
* even if we weren't able to read it. */
|
||||
self->code = ARCHIVE_COMPRESSION_XZ;
|
||||
self->code = ARCHIVE_FILTER_XZ;
|
||||
self->name = "xz";
|
||||
return (r);
|
||||
}
|
||||
@ -972,11 +975,11 @@ lzip_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = __archive_read_program(self, "unlzip");
|
||||
r = __archive_read_program(self, "lzip -d -q");
|
||||
/* Note: We set the format here even if __archive_read_program()
|
||||
* above fails. We do, after all, know what the format is
|
||||
* even if we weren't able to read it. */
|
||||
self->code = ARCHIVE_COMPRESSION_LZIP;
|
||||
self->code = ARCHIVE_FILTER_LZIP;
|
||||
self->name = "lzip";
|
||||
return (r);
|
||||
}
|
||||
|
@ -409,6 +409,7 @@ archive_read_support_format_7zip(struct archive *_a)
|
||||
archive_read_format_7zip_read_header,
|
||||
archive_read_format_7zip_read_data,
|
||||
archive_read_format_7zip_read_data_skip,
|
||||
NULL,
|
||||
archive_read_format_7zip_cleanup);
|
||||
|
||||
if (r != ARCHIVE_OK)
|
||||
@ -684,8 +685,8 @@ archive_read_format_7zip_read_header(struct archive_read *a,
|
||||
symname[symsize] = '\0';
|
||||
archive_entry_copy_symlink(entry,
|
||||
(const char *)symname);
|
||||
free(symname);
|
||||
}
|
||||
free(symname);
|
||||
archive_entry_set_size(entry, 0);
|
||||
}
|
||||
|
||||
@ -709,16 +710,15 @@ archive_read_format_7zip_read_data(struct archive_read *a,
|
||||
if (zip->pack_stream_bytes_unconsumed)
|
||||
read_consume(a);
|
||||
|
||||
*offset = zip->entry_offset;
|
||||
*size = 0;
|
||||
*buff = NULL;
|
||||
/*
|
||||
* If we hit end-of-entry last time, clean up and return
|
||||
* ARCHIVE_EOF this time.
|
||||
*/
|
||||
if (zip->end_of_entry) {
|
||||
*offset = zip->entry_offset;
|
||||
*size = 0;
|
||||
*buff = NULL;
|
||||
if (zip->end_of_entry)
|
||||
return (ARCHIVE_EOF);
|
||||
}
|
||||
|
||||
bytes = read_stream(a, buff,
|
||||
(size_t)zip->entry_bytes_remaining, 0);
|
||||
@ -736,7 +736,8 @@ archive_read_format_7zip_read_data(struct archive_read *a,
|
||||
|
||||
/* Update checksum */
|
||||
if ((zip->entry->flg & CRC32_IS_SET) && bytes)
|
||||
zip->entry_crc32 = crc32(zip->entry_crc32, *buff, bytes);
|
||||
zip->entry_crc32 = crc32(zip->entry_crc32, *buff,
|
||||
(unsigned)bytes);
|
||||
|
||||
/* If we hit the end, swallow any end-of-data marker. */
|
||||
if (zip->end_of_entry) {
|
||||
@ -1363,9 +1364,9 @@ decompress(struct archive_read *a, struct _7zip *zip,
|
||||
#ifdef HAVE_ZLIB_H
|
||||
case _7Z_DEFLATE:
|
||||
zip->stream.next_in = (Bytef *)(uintptr_t)t_next_in;
|
||||
zip->stream.avail_in = t_avail_in;
|
||||
zip->stream.avail_in = (uInt)t_avail_in;
|
||||
zip->stream.next_out = t_next_out;
|
||||
zip->stream.avail_out = t_avail_out;
|
||||
zip->stream.avail_out = (uInt)t_avail_out;
|
||||
r = inflate(&(zip->stream), 0);
|
||||
switch (r) {
|
||||
case Z_STREAM_END: /* Found end of stream. */
|
||||
@ -1607,9 +1608,10 @@ read_Digests(struct archive_read *a, struct _7z_digests *d, size_t num)
|
||||
const unsigned char *p;
|
||||
unsigned i;
|
||||
|
||||
if (num == 0)
|
||||
return (-1);
|
||||
memset(d, 0, sizeof(*d));
|
||||
|
||||
|
||||
d->defineds = malloc(num);
|
||||
if (d->defineds == NULL)
|
||||
return (-1);
|
||||
@ -2687,7 +2689,7 @@ header_bytes(struct archive_read *a, size_t rbytes)
|
||||
}
|
||||
|
||||
/* Update checksum */
|
||||
zip->header_crc32 = crc32(zip->header_crc32, p, rbytes);
|
||||
zip->header_crc32 = crc32(zip->header_crc32, p, (unsigned)rbytes);
|
||||
return (p);
|
||||
}
|
||||
|
||||
@ -2966,16 +2968,19 @@ extract_pack_stream(struct archive_read *a, size_t minimum)
|
||||
* Expand the uncompressed buffer up to
|
||||
* the minimum size.
|
||||
*/
|
||||
zip->uncompressed_buffer_size = minimum + 1023;
|
||||
zip->uncompressed_buffer_size &= ~0x3ff;
|
||||
zip->uncompressed_buffer =
|
||||
realloc(zip->uncompressed_buffer,
|
||||
zip->uncompressed_buffer_size);
|
||||
if (zip->uncompressed_buffer == NULL) {
|
||||
void *p;
|
||||
size_t new_size;
|
||||
|
||||
new_size = minimum + 1023;
|
||||
new_size &= ~0x3ff;
|
||||
p = realloc(zip->uncompressed_buffer, new_size);
|
||||
if (p == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"No memory for 7-Zip decompression");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
zip->uncompressed_buffer = (unsigned char *)p;
|
||||
zip->uncompressed_buffer_size = new_size;
|
||||
}
|
||||
/*
|
||||
* Move unconsumed bytes to the head.
|
||||
@ -3095,7 +3100,7 @@ read_stream(struct archive_read *a, const void **buff, size_t size,
|
||||
{
|
||||
struct _7zip *zip = (struct _7zip *)a->format->data;
|
||||
uint64_t skip_bytes = 0;
|
||||
int r;
|
||||
ssize_t r;
|
||||
|
||||
if (zip->uncompressed_buffer_bytes_remaining == 0) {
|
||||
if (zip->pack_stream_inbytes_remaining > 0) {
|
||||
@ -3346,8 +3351,10 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder,
|
||||
for (i = 0; i < 3; i++) {
|
||||
const struct _7z_coder *coder = scoder[i];
|
||||
|
||||
if ((r = seek_pack(a)) < 0)
|
||||
if ((r = seek_pack(a)) < 0) {
|
||||
free(b[0]); free(b[1]); free(b[2]);
|
||||
return (r);
|
||||
}
|
||||
|
||||
if (sunpack[i] == (uint64_t)-1)
|
||||
zip->folder_outbytes_remaining =
|
||||
@ -3356,13 +3363,16 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder,
|
||||
zip->folder_outbytes_remaining = sunpack[i];
|
||||
|
||||
r = init_decompression(a, zip, coder, NULL);
|
||||
if (r != ARCHIVE_OK)
|
||||
if (r != ARCHIVE_OK) {
|
||||
free(b[0]); free(b[1]); free(b[2]);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
/* Allocate memory for the decorded data of a sub
|
||||
* stream. */
|
||||
b[i] = malloc((size_t)zip->folder_outbytes_remaining);
|
||||
if (b[i] == NULL) {
|
||||
free(b[0]); free(b[1]); free(b[2]);
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"No memory for 7-Zip decompression");
|
||||
return (ARCHIVE_FATAL);
|
||||
@ -3370,14 +3380,18 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder,
|
||||
|
||||
/* Extract a sub stream. */
|
||||
while (zip->pack_stream_inbytes_remaining > 0) {
|
||||
r = extract_pack_stream(a, 0);
|
||||
if (r < 0)
|
||||
r = (int)extract_pack_stream(a, 0);
|
||||
if (r < 0) {
|
||||
free(b[0]); free(b[1]); free(b[2]);
|
||||
return (r);
|
||||
}
|
||||
bytes = get_uncompressed_data(a, &buff,
|
||||
zip->uncompressed_buffer_bytes_remaining,
|
||||
0);
|
||||
if (bytes < 0)
|
||||
if (bytes < 0) {
|
||||
free(b[0]); free(b[1]); free(b[2]);
|
||||
return ((int)bytes);
|
||||
}
|
||||
memcpy(b[i]+s[i], buff, bytes);
|
||||
s[i] += bytes;
|
||||
if (zip->pack_stream_bytes_unconsumed)
|
||||
@ -3557,7 +3571,7 @@ x86_Convert(struct _7zip *zip, uint8_t *data, size_t size)
|
||||
}
|
||||
zip->bcj_prevPosT = prevPosT;
|
||||
zip->bcj_prevMask = prevMask;
|
||||
zip->bcj_ip += bufferPos;
|
||||
zip->bcj_ip += (uint32_t)bufferPos;
|
||||
return (bufferPos);
|
||||
}
|
||||
|
||||
@ -3701,7 +3715,7 @@ Bcj2_Decode(struct _7zip *zip, uint8_t *outBuf, size_t outSize)
|
||||
((uint32_t)v[1] << 16) |
|
||||
((uint32_t)v[2] << 8) |
|
||||
((uint32_t)v[3])) -
|
||||
((uint32_t)zip->bcj2_outPos + outPos + 4);
|
||||
((uint32_t)zip->bcj2_outPos + (uint32_t)outPos + 4);
|
||||
out[0] = (uint8_t)dest;
|
||||
out[1] = (uint8_t)(dest >> 8);
|
||||
out[2] = (uint8_t)(dest >> 16);
|
||||
@ -3716,7 +3730,7 @@ Bcj2_Decode(struct _7zip *zip, uint8_t *outBuf, size_t outSize)
|
||||
*/
|
||||
zip->odd_bcj_size = 4 -i;
|
||||
for (; i < 4; i++) {
|
||||
j = i - 4 + zip->odd_bcj_size;
|
||||
j = i - 4 + (unsigned)zip->odd_bcj_size;
|
||||
zip->odd_bcj[j] = out[i];
|
||||
}
|
||||
break;
|
||||
|
@ -121,6 +121,7 @@ archive_read_support_format_ar(struct archive *_a)
|
||||
archive_read_format_ar_read_header,
|
||||
archive_read_format_ar_read_data,
|
||||
archive_read_format_ar_skip,
|
||||
NULL,
|
||||
archive_read_format_ar_cleanup);
|
||||
|
||||
if (r != ARCHIVE_OK) {
|
||||
|
@ -382,6 +382,7 @@ archive_read_support_format_cab(struct archive *_a)
|
||||
archive_read_format_cab_read_header,
|
||||
archive_read_format_cab_read_data,
|
||||
archive_read_format_cab_read_data_skip,
|
||||
NULL,
|
||||
archive_read_format_cab_cleanup);
|
||||
|
||||
if (r != ARCHIVE_OK)
|
||||
@ -539,7 +540,7 @@ truncated_error(struct archive_read *a)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
static int
|
||||
static ssize_t
|
||||
cab_strnlen(const unsigned char *p, size_t maxlen)
|
||||
{
|
||||
size_t i;
|
||||
@ -550,7 +551,7 @@ cab_strnlen(const unsigned char *p, size_t maxlen)
|
||||
}
|
||||
if (i > maxlen)
|
||||
return (-1);/* invalid */
|
||||
return (i);
|
||||
return ((ssize_t)i);
|
||||
}
|
||||
|
||||
/* Read bytes as much as remaining. */
|
||||
@ -626,8 +627,9 @@ cab_read_header(struct archive_read *a)
|
||||
struct cab *cab;
|
||||
struct cfheader *hd;
|
||||
size_t bytes, used;
|
||||
ssize_t len;
|
||||
int64_t skip;
|
||||
int err, i, len;
|
||||
int err, i;
|
||||
int cur_folder, prev_folder;
|
||||
uint32_t offset32;
|
||||
|
||||
@ -1066,13 +1068,13 @@ static uint32_t
|
||||
cab_checksum_cfdata_4(const void *p, size_t bytes, uint32_t seed)
|
||||
{
|
||||
const unsigned char *b;
|
||||
int u32num;
|
||||
unsigned u32num;
|
||||
uint32_t sum;
|
||||
|
||||
u32num = bytes / 4;
|
||||
u32num = (unsigned)bytes / 4;
|
||||
sum = seed;
|
||||
b = p;
|
||||
while (--u32num >= 0) {
|
||||
for (;u32num > 0; --u32num) {
|
||||
sum ^= archive_le32dec(b);
|
||||
b += 4;
|
||||
}
|
||||
@ -1485,7 +1487,7 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
|
||||
* cast to remove 'const'.
|
||||
*/
|
||||
cab->stream.next_in = (Bytef *)(uintptr_t)d;
|
||||
cab->stream.avail_in = bytes_avail;
|
||||
cab->stream.avail_in = (uInt)bytes_avail;
|
||||
cab->stream.total_in = 0;
|
||||
|
||||
/* Cut out a tow-byte MSZIP signature(0x43, 0x4b). */
|
||||
@ -1506,7 +1508,7 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
|
||||
*avail = ARCHIVE_FATAL;
|
||||
return (NULL);
|
||||
}
|
||||
mszip -= bytes_avail;
|
||||
mszip -= (int)bytes_avail;
|
||||
continue;
|
||||
}
|
||||
if (mszip == 1 && cab->stream.next_in[0] != 0x4b)
|
||||
@ -1935,7 +1937,7 @@ cab_read_data(struct archive_read *a, const void **buff,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT, "Invalid CFDATA");
|
||||
return (ARCHIVE_FATAL);
|
||||
} else
|
||||
return (bytes_avail);
|
||||
return ((int)bytes_avail);
|
||||
}
|
||||
if (bytes_avail > cab->entry_bytes_remaining)
|
||||
bytes_avail = (ssize_t)cab->entry_bytes_remaining;
|
||||
@ -2001,7 +2003,8 @@ archive_read_format_cab_read_data_skip(struct archive_read *a)
|
||||
|
||||
/* If the compression type is none(uncompressed), we've already
|
||||
* consumed data as much as the current entry size. */
|
||||
if (cab->entry_cffolder->comptype == COMPTYPE_NONE)
|
||||
if (cab->entry_cffolder->comptype == COMPTYPE_NONE &&
|
||||
cab->entry_cfdata != NULL)
|
||||
cab->entry_cfdata->unconsumed = 0;
|
||||
|
||||
/* This entry is finished and done. */
|
||||
@ -2198,7 +2201,7 @@ lzx_translation(struct lzx_stream *strm, void *p, size_t size, uint32_t offset)
|
||||
size_t i = b - (unsigned char *)p;
|
||||
int32_t cp, displacement, value;
|
||||
|
||||
cp = offset + i;
|
||||
cp = (int32_t)(offset + (uint32_t)i);
|
||||
value = archive_le32dec(&b[1]);
|
||||
if (value >= -cp && value < (int32_t)ds->translation_size) {
|
||||
if (value >= 0)
|
||||
@ -2584,7 +2587,7 @@ lzx_read_blocks(struct lzx_stream *strm, int last)
|
||||
goto failed;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
l = ds->block_bytes_avail;
|
||||
l = (int)ds->block_bytes_avail;
|
||||
if (l > ds->w_size - ds->w_pos)
|
||||
l = ds->w_size - ds->w_pos;
|
||||
if (l > strm->avail_out)
|
||||
@ -2746,8 +2749,8 @@ lzx_decode_blocks(struct lzx_stream *strm, int last)
|
||||
struct lzx_br bre = ds->br;
|
||||
struct huffman *at = &(ds->at), *lt = &(ds->lt), *mt = &(ds->mt);
|
||||
const struct lzx_pos_tbl *pos_tbl = ds->pos_tbl;
|
||||
unsigned char *outp = strm->next_out;
|
||||
unsigned char *endp = outp + strm->avail_out;
|
||||
unsigned char *noutp = strm->next_out;
|
||||
unsigned char *endp = noutp + strm->avail_out;
|
||||
unsigned char *w_buff = ds->w_buff;
|
||||
unsigned char *at_bitlen = at->bitlen;
|
||||
unsigned char *lt_bitlen = lt->bitlen;
|
||||
@ -2781,10 +2784,10 @@ lzx_decode_blocks(struct lzx_stream *strm, int last)
|
||||
ds->position_slot = position_slot;
|
||||
ds->r0 = r0; ds->r1 = r1; ds->r2 = r2;
|
||||
ds->w_pos = w_pos;
|
||||
strm->avail_out = endp - outp;
|
||||
strm->avail_out = endp - noutp;
|
||||
return (ARCHIVE_EOF);
|
||||
}
|
||||
if (outp >= endp)
|
||||
if (noutp >= endp)
|
||||
/* Output buffer is empty. */
|
||||
goto next_data;
|
||||
|
||||
@ -2818,7 +2821,7 @@ lzx_decode_blocks(struct lzx_stream *strm, int last)
|
||||
w_buff[w_pos] = c;
|
||||
w_pos = (w_pos + 1) & w_mask;
|
||||
/* Store the decoded code to output buffer. */
|
||||
*outp++ = c;
|
||||
*noutp++ = c;
|
||||
block_bytes_avail--;
|
||||
}
|
||||
/*
|
||||
@ -2963,22 +2966,22 @@ lzx_decode_blocks(struct lzx_stream *strm, int last)
|
||||
if (l > w_size - w_pos)
|
||||
l = w_size - w_pos;
|
||||
}
|
||||
if (outp + l >= endp)
|
||||
l = endp - outp;
|
||||
if (noutp + l >= endp)
|
||||
l = (int)(endp - noutp);
|
||||
s = w_buff + copy_pos;
|
||||
if (l >= 8 && ((copy_pos + l < w_pos)
|
||||
|| (w_pos + l < copy_pos))) {
|
||||
memcpy(w_buff + w_pos, s, l);
|
||||
memcpy(outp, s, l);
|
||||
memcpy(noutp, s, l);
|
||||
} else {
|
||||
unsigned char *d;
|
||||
int li;
|
||||
|
||||
d = w_buff + w_pos;
|
||||
for (li = 0; li < l; li++)
|
||||
outp[li] = d[li] = s[li];
|
||||
noutp[li] = d[li] = s[li];
|
||||
}
|
||||
outp += l;
|
||||
noutp += l;
|
||||
copy_pos = (copy_pos + l) & w_mask;
|
||||
w_pos = (w_pos + l) & w_mask;
|
||||
block_bytes_avail -= l;
|
||||
@ -2986,7 +2989,7 @@ lzx_decode_blocks(struct lzx_stream *strm, int last)
|
||||
/* A copy of current pattern ended. */
|
||||
break;
|
||||
copy_len -= l;
|
||||
if (outp >= endp) {
|
||||
if (noutp >= endp) {
|
||||
/* Output buffer is empty. */
|
||||
state = ST_COPY;
|
||||
goto next_data;
|
||||
@ -3009,7 +3012,7 @@ lzx_decode_blocks(struct lzx_stream *strm, int last)
|
||||
ds->r0 = r0; ds->r1 = r1; ds->r2 = r2;
|
||||
ds->state = state;
|
||||
ds->w_pos = w_pos;
|
||||
strm->avail_out = endp - outp;
|
||||
strm->avail_out = endp - noutp;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
@ -3126,7 +3129,7 @@ lzx_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits)
|
||||
hf->bitlen = calloc(len_size, sizeof(hf->bitlen[0]));
|
||||
if (hf->bitlen == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
hf->len_size = len_size;
|
||||
hf->len_size = (int)len_size;
|
||||
} else
|
||||
memset(hf->bitlen, 0, len_size * sizeof(hf->bitlen[0]));
|
||||
if (hf->tbl == NULL) {
|
||||
@ -3134,7 +3137,7 @@ lzx_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits)
|
||||
bits = tbl_bits;
|
||||
else
|
||||
bits = HTBL_BITS;
|
||||
hf->tbl = malloc((1 << bits) * sizeof(hf->tbl[0]));
|
||||
hf->tbl = malloc(((size_t)1 << bits) * sizeof(hf->tbl[0]));
|
||||
if (hf->tbl == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
hf->tbl_bits = tbl_bits;
|
||||
|
@ -242,6 +242,7 @@ archive_read_support_format_cpio(struct archive *_a)
|
||||
archive_read_format_cpio_read_header,
|
||||
archive_read_format_cpio_read_data,
|
||||
archive_read_format_cpio_skip,
|
||||
NULL,
|
||||
archive_read_format_cpio_cleanup);
|
||||
|
||||
if (r != ARCHIVE_OK)
|
||||
|
@ -53,6 +53,7 @@ archive_read_support_format_empty(struct archive *_a)
|
||||
archive_read_format_empty_read_header,
|
||||
archive_read_format_empty_read_data,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
return (r);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* Copyright (c) 2009 Andreas Henriksson <andreas@fatal.se>
|
||||
* Copyright (c) 2009-2011 Michihiro NAKAJIMA
|
||||
* Copyright (c) 2009-2012 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -374,6 +374,8 @@ struct iso9660 {
|
||||
size_t utf16be_path_len;
|
||||
unsigned char *utf16be_previous_path;
|
||||
size_t utf16be_previous_path_len;
|
||||
/* Null buufer used in bidder to improve its performance. */
|
||||
unsigned char null[2048];
|
||||
};
|
||||
|
||||
static int archive_read_format_iso9660_bid(struct archive_read *, int);
|
||||
@ -475,6 +477,7 @@ archive_read_support_format_iso9660(struct archive *_a)
|
||||
archive_read_format_iso9660_read_header,
|
||||
archive_read_format_iso9660_read_data,
|
||||
archive_read_format_iso9660_read_data_skip,
|
||||
NULL,
|
||||
archive_read_format_iso9660_cleanup);
|
||||
|
||||
if (r != ARCHIVE_OK) {
|
||||
@ -587,6 +590,23 @@ archive_read_format_iso9660_options(struct archive_read *a,
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
static int
|
||||
isNull(struct iso9660 *iso9660, const unsigned char *h, unsigned offset,
|
||||
unsigned bytes)
|
||||
{
|
||||
|
||||
while (bytes >= sizeof(iso9660->null)) {
|
||||
if (!memcmp(iso9660->null, h + offset, sizeof(iso9660->null)))
|
||||
return (0);
|
||||
offset += sizeof(iso9660->null);
|
||||
bytes -= sizeof(iso9660->null);
|
||||
}
|
||||
if (bytes)
|
||||
return memcmp(iso9660->null, h + offset, bytes) == 0;
|
||||
else
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
isBootRecord(struct iso9660 *iso9660, const unsigned char *h)
|
||||
{
|
||||
@ -632,8 +652,6 @@ isVolumePartition(struct iso9660 *iso9660, const unsigned char *h)
|
||||
static int
|
||||
isVDSetTerminator(struct iso9660 *iso9660, const unsigned char *h)
|
||||
{
|
||||
int i;
|
||||
|
||||
(void)iso9660; /* UNUSED */
|
||||
|
||||
/* Type of the Volume Descriptor Set Terminator must be 255. */
|
||||
@ -645,9 +663,8 @@ isVDSetTerminator(struct iso9660 *iso9660, const unsigned char *h)
|
||||
return (0);
|
||||
|
||||
/* Reserved field must be 0. */
|
||||
for (i = 7; i < 2048; ++i)
|
||||
if (h[i] != 0)
|
||||
return (0);
|
||||
if (!isNull(iso9660, h, 7, 2048-7))
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
}
|
||||
@ -708,7 +725,6 @@ isSVD(struct iso9660 *iso9660, const unsigned char *h)
|
||||
ssize_t logical_block_size;
|
||||
int32_t volume_block;
|
||||
int32_t location;
|
||||
int i;
|
||||
|
||||
(void)iso9660; /* UNUSED */
|
||||
|
||||
@ -717,15 +733,12 @@ isSVD(struct iso9660 *iso9660, const unsigned char *h)
|
||||
return (0);
|
||||
|
||||
/* Reserved field must be 0. */
|
||||
for (i = 0; i < SVD_reserved1_size; ++i)
|
||||
if (h[SVD_reserved1_offset + i] != 0)
|
||||
return (0);
|
||||
for (i = 0; i < SVD_reserved2_size; ++i)
|
||||
if (h[SVD_reserved2_offset + i] != 0)
|
||||
return (0);
|
||||
for (i = 0; i < SVD_reserved3_size; ++i)
|
||||
if (h[SVD_reserved3_offset + i] != 0)
|
||||
return (0);
|
||||
if (!isNull(iso9660, h, SVD_reserved1_offset, SVD_reserved1_size))
|
||||
return (0);
|
||||
if (!isNull(iso9660, h, SVD_reserved2_offset, SVD_reserved2_size))
|
||||
return (0);
|
||||
if (!isNull(iso9660, h, SVD_reserved3_offset, SVD_reserved3_size))
|
||||
return (0);
|
||||
|
||||
/* File structure version must be 1 for ISO9660/ECMA119. */
|
||||
if (h[SVD_file_structure_version_offset] != 1)
|
||||
@ -771,7 +784,6 @@ isEVD(struct iso9660 *iso9660, const unsigned char *h)
|
||||
ssize_t logical_block_size;
|
||||
int32_t volume_block;
|
||||
int32_t location;
|
||||
int i;
|
||||
|
||||
(void)iso9660; /* UNUSED */
|
||||
|
||||
@ -788,14 +800,12 @@ isEVD(struct iso9660 *iso9660, const unsigned char *h)
|
||||
return (0);
|
||||
|
||||
/* Reserved field must be 0. */
|
||||
for (i = 0; i < PVD_reserved2_size; ++i)
|
||||
if (h[PVD_reserved2_offset + i] != 0)
|
||||
return (0);
|
||||
if (!isNull(iso9660, h, PVD_reserved2_offset, PVD_reserved2_size))
|
||||
return (0);
|
||||
|
||||
/* Reserved field must be 0. */
|
||||
for (i = 0; i < PVD_reserved3_size; ++i)
|
||||
if (h[PVD_reserved3_offset + i] != 0)
|
||||
return (0);
|
||||
if (!isNull(iso9660, h, PVD_reserved3_offset, PVD_reserved3_size))
|
||||
return (0);
|
||||
|
||||
/* Logical block size must be > 0. */
|
||||
/* I've looked at Ecma 119 and can't find any stronger
|
||||
@ -830,14 +840,12 @@ isEVD(struct iso9660 *iso9660, const unsigned char *h)
|
||||
return (0);
|
||||
|
||||
/* Reserved field must be 0. */
|
||||
for (i = 0; i < PVD_reserved4_size; ++i)
|
||||
if (h[PVD_reserved4_offset + i] != 0)
|
||||
return (0);
|
||||
if (!isNull(iso9660, h, PVD_reserved4_offset, PVD_reserved4_size))
|
||||
return (0);
|
||||
|
||||
/* Reserved field must be 0. */
|
||||
for (i = 0; i < PVD_reserved5_size; ++i)
|
||||
if (h[PVD_reserved5_offset + i] != 0)
|
||||
return (0);
|
||||
if (!isNull(iso9660, h, PVD_reserved5_offset, PVD_reserved5_size))
|
||||
return (0);
|
||||
|
||||
/* Read Root Directory Record in Volume Descriptor. */
|
||||
p = h + PVD_root_directory_record_offset;
|
||||
@ -869,14 +877,12 @@ isPVD(struct iso9660 *iso9660, const unsigned char *h)
|
||||
return (0);
|
||||
|
||||
/* Reserved field must be 0. */
|
||||
for (i = 0; i < PVD_reserved2_size; ++i)
|
||||
if (h[PVD_reserved2_offset + i] != 0)
|
||||
return (0);
|
||||
if (!isNull(iso9660, h, PVD_reserved2_offset, PVD_reserved2_size))
|
||||
return (0);
|
||||
|
||||
/* Reserved field must be 0. */
|
||||
for (i = 0; i < PVD_reserved3_size; ++i)
|
||||
if (h[PVD_reserved3_offset + i] != 0)
|
||||
return (0);
|
||||
if (!isNull(iso9660, h, PVD_reserved3_offset, PVD_reserved3_size))
|
||||
return (0);
|
||||
|
||||
/* Logical block size must be > 0. */
|
||||
/* I've looked at Ecma 119 and can't find any stronger
|
||||
@ -919,9 +925,8 @@ isPVD(struct iso9660 *iso9660, const unsigned char *h)
|
||||
return (0);
|
||||
|
||||
/* Reserved field must be 0. */
|
||||
for (i = 0; i < PVD_reserved5_size; ++i)
|
||||
if (h[PVD_reserved5_offset + i] != 0)
|
||||
return (0);
|
||||
if (!isNull(iso9660, h, PVD_reserved5_offset, PVD_reserved5_size))
|
||||
return (0);
|
||||
|
||||
/* XXX TODO: Check other values for sanity; reject more
|
||||
* malformed PVDs. XXX */
|
||||
@ -934,8 +939,10 @@ isPVD(struct iso9660 *iso9660, const unsigned char *h)
|
||||
if (!iso9660->primary.location) {
|
||||
iso9660->logical_block_size = logical_block_size;
|
||||
iso9660->volume_block = volume_block;
|
||||
iso9660->volume_size = logical_block_size * (uint64_t)volume_block;
|
||||
iso9660->primary.location = archive_le32dec(p + DR_extent_offset);
|
||||
iso9660->volume_size =
|
||||
logical_block_size * (uint64_t)volume_block;
|
||||
iso9660->primary.location =
|
||||
archive_le32dec(p + DR_extent_offset);
|
||||
iso9660->primary.size = archive_le32dec(p + DR_size_offset);
|
||||
}
|
||||
|
||||
@ -951,6 +958,12 @@ read_children(struct archive_read *a, struct file_info *parent)
|
||||
size_t step, skip_size;
|
||||
|
||||
iso9660 = (struct iso9660 *)(a->format->data);
|
||||
/* flush any remaining bytes from the last round to ensure
|
||||
* we're positioned */
|
||||
if (iso9660->entry_bytes_unconsumed) {
|
||||
__archive_read_consume(a, iso9660->entry_bytes_unconsumed);
|
||||
iso9660->entry_bytes_unconsumed = 0;
|
||||
}
|
||||
if (iso9660->current_position > parent->offset) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Ignoring out-of-order directory (%s) %jd > %jd",
|
||||
@ -1059,6 +1072,94 @@ read_children(struct archive_read *a, struct file_info *parent)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
choose_volume(struct archive_read *a, struct iso9660 *iso9660)
|
||||
{
|
||||
struct file_info *file;
|
||||
int64_t skipsize;
|
||||
struct vd *vd;
|
||||
const void *block;
|
||||
char seenJoliet;
|
||||
|
||||
vd = &(iso9660->primary);
|
||||
if (!iso9660->opt_support_joliet)
|
||||
iso9660->seenJoliet = 0;
|
||||
if (iso9660->seenJoliet &&
|
||||
vd->location > iso9660->joliet.location)
|
||||
/* This condition is unlikely; by way of caution. */
|
||||
vd = &(iso9660->joliet);
|
||||
|
||||
skipsize = LOGICAL_BLOCK_SIZE * vd->location;
|
||||
skipsize = __archive_read_consume(a, skipsize);
|
||||
if (skipsize < 0)
|
||||
return ((int)skipsize);
|
||||
iso9660->current_position = skipsize;
|
||||
|
||||
block = __archive_read_ahead(a, vd->size, NULL);
|
||||
if (block == NULL) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Failed to read full block when scanning "
|
||||
"ISO9660 directory list");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* While reading Root Directory, flag seenJoliet must be zero to
|
||||
* avoid converting special name 0x00(Current Directory) and
|
||||
* next byte to UCS2.
|
||||
*/
|
||||
seenJoliet = iso9660->seenJoliet;/* Save flag. */
|
||||
iso9660->seenJoliet = 0;
|
||||
file = parse_file_info(a, NULL, block);
|
||||
if (file == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
iso9660->seenJoliet = seenJoliet;
|
||||
|
||||
/*
|
||||
* If the iso image has both RockRidge and Joliet, we preferentially
|
||||
* use RockRidge Extensions rather than Joliet ones.
|
||||
*/
|
||||
if (vd == &(iso9660->primary) && iso9660->seenRockridge
|
||||
&& iso9660->seenJoliet)
|
||||
iso9660->seenJoliet = 0;
|
||||
|
||||
if (vd == &(iso9660->primary) && !iso9660->seenRockridge
|
||||
&& iso9660->seenJoliet) {
|
||||
/* Switch reading data from primary to joliet. */
|
||||
vd = &(iso9660->joliet);
|
||||
skipsize = LOGICAL_BLOCK_SIZE * vd->location;
|
||||
skipsize -= iso9660->current_position;
|
||||
skipsize = __archive_read_consume(a, skipsize);
|
||||
if (skipsize < 0)
|
||||
return ((int)skipsize);
|
||||
iso9660->current_position += skipsize;
|
||||
|
||||
block = __archive_read_ahead(a, vd->size, NULL);
|
||||
if (block == NULL) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Failed to read full block when scanning "
|
||||
"ISO9660 directory list");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
iso9660->seenJoliet = 0;
|
||||
file = parse_file_info(a, NULL, block);
|
||||
if (file == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
iso9660->seenJoliet = seenJoliet;
|
||||
}
|
||||
|
||||
/* Store the root directory in the pending list. */
|
||||
if (add_entry(a, iso9660, file) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
if (iso9660->seenRockridge) {
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_ISO9660_ROCKRIDGE;
|
||||
a->archive.archive_format_name =
|
||||
"ISO9660 with Rockridge extensions";
|
||||
}
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_iso9660_read_header(struct archive_read *a,
|
||||
struct archive_entry *entry)
|
||||
@ -1075,86 +1176,9 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
|
||||
}
|
||||
|
||||
if (iso9660->current_position == 0) {
|
||||
int64_t skipsize;
|
||||
struct vd *vd;
|
||||
const void *block;
|
||||
char seenJoliet;
|
||||
|
||||
vd = &(iso9660->primary);
|
||||
if (!iso9660->opt_support_joliet)
|
||||
iso9660->seenJoliet = 0;
|
||||
if (iso9660->seenJoliet &&
|
||||
vd->location > iso9660->joliet.location)
|
||||
/* This condition is unlikely; by way of caution. */
|
||||
vd = &(iso9660->joliet);
|
||||
|
||||
skipsize = LOGICAL_BLOCK_SIZE * vd->location;
|
||||
skipsize = __archive_read_consume(a, skipsize);
|
||||
if (skipsize < 0)
|
||||
return ((int)skipsize);
|
||||
iso9660->current_position = skipsize;
|
||||
|
||||
block = __archive_read_ahead(a, vd->size, NULL);
|
||||
if (block == NULL) {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Failed to read full block when scanning "
|
||||
"ISO9660 directory list");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* While reading Root Directory, flag seenJoliet
|
||||
* must be zero to avoid converting special name
|
||||
* 0x00(Current Directory) and next byte to UCS2.
|
||||
*/
|
||||
seenJoliet = iso9660->seenJoliet;/* Save flag. */
|
||||
iso9660->seenJoliet = 0;
|
||||
file = parse_file_info(a, NULL, block);
|
||||
if (file == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
iso9660->seenJoliet = seenJoliet;
|
||||
if (vd == &(iso9660->primary) && iso9660->seenRockridge
|
||||
&& iso9660->seenJoliet)
|
||||
/*
|
||||
* If iso image has RockRidge and Joliet,
|
||||
* we use RockRidge Extensions.
|
||||
*/
|
||||
iso9660->seenJoliet = 0;
|
||||
if (vd == &(iso9660->primary) && !iso9660->seenRockridge
|
||||
&& iso9660->seenJoliet) {
|
||||
/* Switch reading data from primary to joliet. */
|
||||
vd = &(iso9660->joliet);
|
||||
skipsize = LOGICAL_BLOCK_SIZE * vd->location;
|
||||
skipsize -= iso9660->current_position;
|
||||
skipsize = __archive_read_consume(a, skipsize);
|
||||
if (skipsize < 0)
|
||||
return ((int)skipsize);
|
||||
iso9660->current_position += skipsize;
|
||||
|
||||
block = __archive_read_ahead(a, vd->size, NULL);
|
||||
if (block == NULL) {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Failed to read full block when scanning "
|
||||
"ISO9660 directory list");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
iso9660->seenJoliet = 0;
|
||||
file = parse_file_info(a, NULL, block);
|
||||
if (file == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
iso9660->seenJoliet = seenJoliet;
|
||||
}
|
||||
/* Store the root directory in the pending list. */
|
||||
if (add_entry(a, iso9660, file) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
if (iso9660->seenRockridge) {
|
||||
a->archive.archive_format =
|
||||
ARCHIVE_FORMAT_ISO9660_ROCKRIDGE;
|
||||
a->archive.archive_format_name =
|
||||
"ISO9660 with Rockridge extensions";
|
||||
}
|
||||
r = choose_volume(a, iso9660);
|
||||
if (r != ARCHIVE_OK)
|
||||
return (r);
|
||||
}
|
||||
|
||||
file = NULL;/* Eliminate a warning. */
|
||||
@ -1227,14 +1251,14 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
|
||||
}
|
||||
|
||||
iso9660->entry_bytes_remaining = file->size;
|
||||
iso9660->entry_sparse_offset = 0; /* Offset for sparse-file-aware clients. */
|
||||
/* Offset for sparse-file-aware clients. */
|
||||
iso9660->entry_sparse_offset = 0;
|
||||
|
||||
if (file->offset + file->size > iso9660->volume_size) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"File is beyond end-of-media: %s",
|
||||
archive_entry_pathname(entry));
|
||||
iso9660->entry_bytes_remaining = 0;
|
||||
iso9660->entry_sparse_offset = 0;
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
@ -1286,36 +1310,33 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
|
||||
iso9660->previous_pathname.s);
|
||||
archive_entry_unset_size(entry);
|
||||
iso9660->entry_bytes_remaining = 0;
|
||||
iso9660->entry_sparse_offset = 0;
|
||||
return (rd_r);
|
||||
}
|
||||
|
||||
/* Except for the hardlink case above, if the offset of the
|
||||
* next entry is before our current position, we can't seek
|
||||
* backwards to extract it, so issue a warning. Note that
|
||||
* this can only happen if this entry was added to the heap
|
||||
* after we passed this offset, that is, only if the directory
|
||||
* mentioning this entry is later than the body of the entry.
|
||||
* Such layouts are very unusual; most ISO9660 writers lay out
|
||||
* and record all directory information first, then store
|
||||
* all file bodies. */
|
||||
/* TODO: Someday, libarchive's I/O core will support optional
|
||||
* seeking. When that day comes, this code should attempt to
|
||||
* seek and only return the error if the seek fails. That
|
||||
* will give us support for whacky ISO images that require
|
||||
* seeking while retaining the ability to read almost all ISO
|
||||
* images in a streaming fashion. */
|
||||
if ((file->mode & AE_IFMT) != AE_IFDIR &&
|
||||
file->offset < iso9660->current_position) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Ignoring out-of-order file @%jx (%s) %jd < %jd",
|
||||
(intmax_t)file->number,
|
||||
iso9660->pathname.s,
|
||||
(intmax_t)file->offset,
|
||||
(intmax_t)iso9660->current_position);
|
||||
iso9660->entry_bytes_remaining = 0;
|
||||
iso9660->entry_sparse_offset = 0;
|
||||
return (ARCHIVE_WARN);
|
||||
int64_t r64;
|
||||
|
||||
r64 = __archive_read_seek(a, file->offset, SEEK_SET);
|
||||
if (r64 != (int64_t)file->offset) {
|
||||
/* We can't seek backwards to extract it, so issue
|
||||
* a warning. Note that this can only happen if
|
||||
* this entry was added to the heap after we passed
|
||||
* this offset, that is, only if the directory
|
||||
* mentioning this entry is later than the body of
|
||||
* the entry. Such layouts are very unusual; most
|
||||
* ISO9660 writers lay out and record all directory
|
||||
* information first, then store all file bodies. */
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Ignoring out-of-order file @%jx (%s) %jd < %jd",
|
||||
(intmax_t)file->number,
|
||||
iso9660->pathname.s,
|
||||
(intmax_t)file->offset,
|
||||
(intmax_t)iso9660->current_position);
|
||||
iso9660->entry_bytes_remaining = 0;
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
iso9660->current_position = (uint64_t)r64;
|
||||
}
|
||||
|
||||
/* Initialize zisofs variables. */
|
||||
@ -1356,7 +1377,6 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
|
||||
archive_entry_set_nlink(entry, 2 + file->subdirs);
|
||||
/* Directory data has been read completely. */
|
||||
iso9660->entry_bytes_remaining = 0;
|
||||
iso9660->entry_sparse_offset = 0;
|
||||
}
|
||||
|
||||
if (rd_r != ARCHIVE_OK)
|
||||
@ -1426,7 +1446,7 @@ zisofs_read_data(struct archive_read *a,
|
||||
zisofs->block_pointers_size = xsize;
|
||||
|
||||
/* Allocate uncompressed data buffer. */
|
||||
xsize = 1UL << zisofs->pz_log2_bs;
|
||||
xsize = (size_t)1UL << zisofs->pz_log2_bs;
|
||||
if (zisofs->uncompressed_buffer_size < xsize) {
|
||||
if (zisofs->uncompressed_buffer != NULL)
|
||||
free(zisofs->uncompressed_buffer);
|
||||
@ -1563,9 +1583,10 @@ zisofs_read_data(struct archive_read *a,
|
||||
if (avail > zisofs->block_avail)
|
||||
zisofs->stream.avail_in = zisofs->block_avail;
|
||||
else
|
||||
zisofs->stream.avail_in = avail;
|
||||
zisofs->stream.avail_in = (uInt)avail;
|
||||
zisofs->stream.next_out = zisofs->uncompressed_buffer;
|
||||
zisofs->stream.avail_out = zisofs->uncompressed_buffer_size;
|
||||
zisofs->stream.avail_out =
|
||||
(uInt)zisofs->uncompressed_buffer_size;
|
||||
|
||||
r = inflate(&zisofs->stream, 0);
|
||||
switch (r) {
|
||||
@ -1580,7 +1601,7 @@ zisofs_read_data(struct archive_read *a,
|
||||
uncompressed_size =
|
||||
zisofs->uncompressed_buffer_size - zisofs->stream.avail_out;
|
||||
avail -= zisofs->stream.next_in - p;
|
||||
zisofs->block_avail -= zisofs->stream.next_in - p;
|
||||
zisofs->block_avail -= (uint32_t)(zisofs->stream.next_in - p);
|
||||
}
|
||||
next_data:
|
||||
bytes_read -= avail;
|
||||
@ -1590,7 +1611,7 @@ zisofs_read_data(struct archive_read *a,
|
||||
iso9660->entry_sparse_offset += uncompressed_size;
|
||||
iso9660->entry_bytes_remaining -= bytes_read;
|
||||
iso9660->current_position += bytes_read;
|
||||
zisofs->pz_offset += bytes_read;
|
||||
zisofs->pz_offset += (uint32_t)bytes_read;
|
||||
iso9660->entry_bytes_unconsumed += bytes_read;
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
@ -1873,9 +1894,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
|
||||
if (iso9660->opt_support_rockridge) {
|
||||
if (parent == NULL && rr_end - rr_start >= 7) {
|
||||
p = rr_start;
|
||||
if (p[0] == 'S' && p[1] == 'P'
|
||||
&& p[2] == 7 && p[3] == 1
|
||||
&& p[4] == 0xBE && p[5] == 0xEF) {
|
||||
if (memcmp(p, "SP\x07\x01\xbe\xef", 6) == 0) {
|
||||
/*
|
||||
* SP extension stores the suspOffset
|
||||
* (Number of bytes to skip between
|
||||
@ -1935,6 +1954,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
|
||||
if (iso9660->seenRockridge) {
|
||||
if (parent != NULL && parent->parent == NULL &&
|
||||
(flags & 0x02) && iso9660->rr_moved == NULL &&
|
||||
file->name.s &&
|
||||
(strcmp(file->name.s, "rr_moved") == 0 ||
|
||||
strcmp(file->name.s, ".rr_moved") == 0)) {
|
||||
iso9660->rr_moved = file;
|
||||
@ -2067,14 +2087,9 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
|
||||
int data_length = p[2] - 4;
|
||||
int version = p[3];
|
||||
|
||||
/*
|
||||
* Yes, each 'if' here does test p[0] again.
|
||||
* Otherwise, the fall-through handling to catch
|
||||
* unsupported extensions doesn't work.
|
||||
*/
|
||||
switch(p[0]) {
|
||||
case 'C':
|
||||
if (p[0] == 'C' && p[1] == 'E') {
|
||||
if (p[1] == 'E') {
|
||||
if (version == 1 && data_length == 24) {
|
||||
/*
|
||||
* CE extension comprises:
|
||||
@ -2092,53 +2107,42 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
|
||||
!= ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (p[0] == 'C' && p[1] == 'L') {
|
||||
else if (p[1] == 'L') {
|
||||
if (version == 1 && data_length == 8) {
|
||||
file->cl_offset = (uint64_t)
|
||||
iso9660->logical_block_size *
|
||||
(uint64_t)archive_le32dec(data);
|
||||
iso9660->seenRockridge = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
break;
|
||||
case 'N':
|
||||
if (p[0] == 'N' && p[1] == 'M') {
|
||||
if (p[1] == 'M') {
|
||||
if (version == 1) {
|
||||
parse_rockridge_NM1(file,
|
||||
data, data_length);
|
||||
iso9660->seenRockridge = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
break;
|
||||
case 'P':
|
||||
if (p[0] == 'P' && p[1] == 'D') {
|
||||
/*
|
||||
* PD extension is padding;
|
||||
* contents are always ignored.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
if (p[0] == 'P' && p[1] == 'L') {
|
||||
/*
|
||||
* PL extension won't appear;
|
||||
* contents are always ignored.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
if (p[0] == 'P' && p[1] == 'N') {
|
||||
/*
|
||||
* PD extension is padding;
|
||||
* contents are always ignored.
|
||||
*
|
||||
* PL extension won't appear;
|
||||
* contents are always ignored.
|
||||
*/
|
||||
if (p[1] == 'N') {
|
||||
if (version == 1 && data_length == 16) {
|
||||
file->rdev = toi(data,4);
|
||||
file->rdev <<= 32;
|
||||
file->rdev |= toi(data + 8, 4);
|
||||
iso9660->seenRockridge = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (p[0] == 'P' && p[1] == 'X') {
|
||||
else if (p[1] == 'X') {
|
||||
/*
|
||||
* PX extension comprises:
|
||||
* 8 bytes for mode,
|
||||
@ -2165,35 +2169,31 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
|
||||
= toi(data + 32, 4);
|
||||
iso9660->seenRockridge = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
break;
|
||||
case 'R':
|
||||
if (p[0] == 'R' && p[1] == 'E' && version == 1) {
|
||||
if (p[1] == 'E' && version == 1) {
|
||||
file->re = 1;
|
||||
iso9660->seenRockridge = 1;
|
||||
break;
|
||||
}
|
||||
if (p[0] == 'R' && p[1] == 'R' && version == 1) {
|
||||
else if (p[1] == 'R' && version == 1) {
|
||||
/*
|
||||
* RR extension comprises:
|
||||
* one byte flag value
|
||||
* This extension is obsolete,
|
||||
* so contents are always ignored.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
break;
|
||||
case 'S':
|
||||
if (p[0] == 'S' && p[1] == 'L') {
|
||||
if (p[1] == 'L') {
|
||||
if (version == 1) {
|
||||
parse_rockridge_SL1(file,
|
||||
data, data_length);
|
||||
iso9660->seenRockridge = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (p[0] == 'S' && p[1] == 'T'
|
||||
else if (p[1] == 'T'
|
||||
&& data_length == 0 && version == 1) {
|
||||
/*
|
||||
* ST extension marks end of this
|
||||
@ -2208,32 +2208,27 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
|
||||
iso9660->seenRockridge = 0;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
break;
|
||||
case 'T':
|
||||
if (p[0] == 'T' && p[1] == 'F') {
|
||||
if (p[1] == 'F') {
|
||||
if (version == 1) {
|
||||
parse_rockridge_TF1(file,
|
||||
data, data_length);
|
||||
iso9660->seenRockridge = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
break;
|
||||
case 'Z':
|
||||
if (p[0] == 'Z' && p[1] == 'F') {
|
||||
if (p[1] == 'F') {
|
||||
if (version == 1)
|
||||
parse_rockridge_ZF1(file,
|
||||
data, data_length);
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
break;
|
||||
default:
|
||||
/* The FALLTHROUGHs above leave us here for
|
||||
* any unsupported extension. */
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
p += p[2];
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
@ -2893,8 +2888,9 @@ next_cache_entry(struct archive_read *a, struct iso9660 *iso9660,
|
||||
|
||||
fatal_rr:
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Failed to connect 'CL' pointer to 'RE' rr_moved pointer of"
|
||||
"Rockridge extensions");
|
||||
"Failed to connect 'CL' pointer to 'RE' rr_moved pointer of "
|
||||
"Rockridge extensions: current position = %jd, CL offset = %jd",
|
||||
(intmax_t)iso9660->current_position, (intmax_t)file->cl_offset);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
@ -3226,10 +3222,12 @@ dump_isodirrec(FILE *out, const unsigned char *isodirrec)
|
||||
fprintf(out, " ilv %d,",
|
||||
toi(isodirrec + DR_interleave_offset, DR_interleave_size));
|
||||
fprintf(out, " seq %d,",
|
||||
toi(isodirrec + DR_volume_sequence_number_offset, DR_volume_sequence_number_size));
|
||||
toi(isodirrec + DR_volume_sequence_number_offset,
|
||||
DR_volume_sequence_number_size));
|
||||
fprintf(out, " nl %d:",
|
||||
toi(isodirrec + DR_name_len_offset, DR_name_len_size));
|
||||
fprintf(out, " `%.*s'",
|
||||
toi(isodirrec + DR_name_len_offset, DR_name_len_size), isodirrec + DR_name_offset);
|
||||
toi(isodirrec + DR_name_len_offset, DR_name_len_size),
|
||||
isodirrec + DR_name_offset);
|
||||
}
|
||||
#endif
|
||||
|
@ -272,7 +272,7 @@ static int lha_skip_sfx(struct archive_read *);
|
||||
static time_t lha_dos_time(const unsigned char *);
|
||||
static time_t lha_win_time(uint64_t, long *);
|
||||
static unsigned char lha_calcsum(unsigned char, const void *,
|
||||
int, int);
|
||||
int, size_t);
|
||||
static int lha_parse_linkname(struct archive_string *,
|
||||
struct archive_string *);
|
||||
static int lha_read_data_none(struct archive_read *, const void **,
|
||||
@ -319,6 +319,7 @@ archive_read_support_format_lha(struct archive *_a)
|
||||
archive_read_format_lha_read_header,
|
||||
archive_read_format_lha_read_data,
|
||||
archive_read_format_lha_read_data_skip,
|
||||
NULL,
|
||||
archive_read_format_lha_cleanup);
|
||||
|
||||
if (r != ARCHIVE_OK)
|
||||
@ -1634,7 +1635,7 @@ lha_parse_linkname(struct archive_string *linkname,
|
||||
struct archive_string *pathname)
|
||||
{
|
||||
char * linkptr;
|
||||
int symlen;
|
||||
size_t symlen;
|
||||
|
||||
linkptr = strchr(pathname->s, '|');
|
||||
if (linkptr != NULL) {
|
||||
@ -1689,12 +1690,12 @@ lha_win_time(uint64_t wintime, long *ns)
|
||||
}
|
||||
|
||||
static unsigned char
|
||||
lha_calcsum(unsigned char sum, const void *pp, int offset, int size)
|
||||
lha_calcsum(unsigned char sum, const void *pp, int offset, size_t size)
|
||||
{
|
||||
unsigned char const *p = (unsigned char const *)pp;
|
||||
|
||||
p += offset;
|
||||
while (--size >= 0)
|
||||
for (;size > 0; --size)
|
||||
sum += *p++;
|
||||
return (sum);
|
||||
}
|
||||
@ -2019,7 +2020,7 @@ lzh_copy_from_window(struct lzh_stream *strm, struct lzh_dec *ds)
|
||||
copy_bytes = (size_t)strm->avail_out;
|
||||
memcpy(strm->next_out,
|
||||
ds->w_buff + ds->copy_pos, copy_bytes);
|
||||
ds->copy_pos += copy_bytes;
|
||||
ds->copy_pos += (int)copy_bytes;
|
||||
} else {
|
||||
if (ds->w_remaining <= strm->avail_out)
|
||||
copy_bytes = ds->w_remaining;
|
||||
@ -2027,7 +2028,7 @@ lzh_copy_from_window(struct lzh_stream *strm, struct lzh_dec *ds)
|
||||
copy_bytes = (size_t)strm->avail_out;
|
||||
memcpy(strm->next_out,
|
||||
ds->w_buff + ds->w_size - ds->w_remaining, copy_bytes);
|
||||
ds->w_remaining -= copy_bytes;
|
||||
ds->w_remaining -= (int)copy_bytes;
|
||||
}
|
||||
strm->next_out += copy_bytes;
|
||||
strm->avail_out -= copy_bytes;
|
||||
@ -2481,7 +2482,7 @@ lzh_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits)
|
||||
bits = tbl_bits;
|
||||
else
|
||||
bits = HTBL_BITS;
|
||||
hf->tbl = malloc((1 << bits) * sizeof(hf->tbl[0]));
|
||||
hf->tbl = malloc(((size_t)1 << bits) * sizeof(hf->tbl[0]));
|
||||
if (hf->tbl == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@ -2491,7 +2492,7 @@ lzh_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits)
|
||||
if (hf->tree == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
hf->len_size = len_size;
|
||||
hf->len_size = (int)len_size;
|
||||
hf->tbl_bits = tbl_bits;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* Copyright (c) 2008 Joerg Sonnenberger
|
||||
* Copyright (c) 2011 Michihiro NAKAJIMA
|
||||
* Copyright (c) 2011-2012 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -55,6 +55,9 @@ __FBSDID("$FreeBSD$");
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
#ifndef O_CLOEXEC
|
||||
#define O_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
#define MTREE_HAS_DEVICE 0x0001
|
||||
#define MTREE_HAS_FFLAGS 0x0002
|
||||
@ -69,6 +72,7 @@ __FBSDID("$FreeBSD$");
|
||||
#define MTREE_HAS_UNAME 0x0400
|
||||
|
||||
#define MTREE_HAS_OPTIONAL 0x0800
|
||||
#define MTREE_HAS_NOCHANGE 0x1000 /* FreeBSD specific */
|
||||
|
||||
struct mtree_option {
|
||||
struct mtree_option *next;
|
||||
@ -103,6 +107,7 @@ struct mtree {
|
||||
|
||||
static int bid_keycmp(const char *, const char *, ssize_t);
|
||||
static int cleanup(struct archive_read *);
|
||||
static int detect_form(struct archive_read *, int *);
|
||||
static int mtree_bid(struct archive_read *, int);
|
||||
static int parse_file(struct archive_read *, struct archive_entry *,
|
||||
struct mtree *, struct mtree_entry *, int *);
|
||||
@ -200,7 +205,7 @@ archive_read_support_format_mtree(struct archive *_a)
|
||||
mtree->fd = -1;
|
||||
|
||||
r = __archive_read_register_format(a, mtree, "mtree",
|
||||
mtree_bid, NULL, read_header, read_data, skip, cleanup);
|
||||
mtree_bid, NULL, read_header, read_data, skip, NULL, cleanup);
|
||||
|
||||
if (r != ARCHIVE_OK)
|
||||
free(mtree);
|
||||
@ -349,7 +354,7 @@ bid_keycmp(const char *p, const char *key, ssize_t len)
|
||||
* Returns the length of a detected keyword.
|
||||
* Returns 0 if any keywords were not found.
|
||||
*/
|
||||
static ssize_t
|
||||
static int
|
||||
bid_keyword(const char *p, ssize_t len)
|
||||
{
|
||||
static const char *keys_c[] = {
|
||||
@ -368,7 +373,7 @@ bid_keyword(const char *p, ssize_t len)
|
||||
"md5", "md5digest", "mode", NULL
|
||||
};
|
||||
static const char *keys_no[] = {
|
||||
"nlink", "optional", NULL
|
||||
"nlink", "nochange", "optional", NULL
|
||||
};
|
||||
static const char *keys_r[] = {
|
||||
"rmd160", "rmd160digest", NULL
|
||||
@ -419,7 +424,7 @@ bid_keyword(const char *p, ssize_t len)
|
||||
* When "unset" is specified, expects a set of "<space characters>keyword".
|
||||
*/
|
||||
static int
|
||||
bid_keyword_list(const char *p, ssize_t len, int unset)
|
||||
bid_keyword_list(const char *p, ssize_t len, int unset, int last_is_path)
|
||||
{
|
||||
int l;
|
||||
int keycnt = 0;
|
||||
@ -437,8 +442,10 @@ bid_keyword_list(const char *p, ssize_t len, int unset)
|
||||
break;
|
||||
if (p[0] == '\\' && (p[1] == '\n' || p[1] == '\r'))
|
||||
break;
|
||||
if (!blank) /* No blank character. */
|
||||
if (!blank && !last_is_path) /* No blank character. */
|
||||
return (-1);
|
||||
if (last_is_path && len == 0)
|
||||
return (keycnt);
|
||||
|
||||
if (unset) {
|
||||
l = bid_keycmp(p, "all", len);
|
||||
@ -473,7 +480,7 @@ bid_keyword_list(const char *p, ssize_t len, int unset)
|
||||
}
|
||||
|
||||
static int
|
||||
bid_entry(const char *p, ssize_t len)
|
||||
bid_entry(const char *p, ssize_t len, ssize_t nl, int *last_is_path)
|
||||
{
|
||||
int f = 0;
|
||||
static const unsigned char safe_char[256] = {
|
||||
@ -500,22 +507,60 @@ bid_entry(const char *p, ssize_t len)
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */
|
||||
};
|
||||
ssize_t ll = len;
|
||||
const char *pp = p;
|
||||
|
||||
*last_is_path = 0;
|
||||
/*
|
||||
* Skip the path-name which is quoted.
|
||||
*/
|
||||
while (len > 0 && *p != ' ' && *p != '\t') {
|
||||
if (!safe_char[*(const unsigned char *)p])
|
||||
return (-1);
|
||||
++p;
|
||||
--len;
|
||||
while (ll > 0 && *pp != ' ' &&*pp != '\t' && *pp != '\r' &&
|
||||
*pp != '\n') {
|
||||
if (!safe_char[*(const unsigned char *)pp]) {
|
||||
f = 0;
|
||||
break;
|
||||
}
|
||||
++pp;
|
||||
--ll;
|
||||
++f;
|
||||
}
|
||||
/* If a path-name was not found, returns error. */
|
||||
if (f == 0)
|
||||
return (-1);
|
||||
/* If a path-name was not found at the first, try to check
|
||||
* a mtree format ``NetBSD's mtree -D'' creates, which
|
||||
* places the path-name at the last. */
|
||||
if (f == 0) {
|
||||
const char *pb = p + len - nl;
|
||||
int name_len = 0;
|
||||
int slash;
|
||||
|
||||
return (bid_keyword_list(p, len, 0));
|
||||
/* Do not accept multi lines for form D. */
|
||||
if (pb-2 >= p &&
|
||||
pb[-1] == '\\' && (pb[-2] == ' ' || pb[-2] == '\t'))
|
||||
return (-1);
|
||||
if (pb-1 >= p && pb[-1] == '\\')
|
||||
return (-1);
|
||||
|
||||
slash = 0;
|
||||
while (p <= --pb && *pb != ' ' && *pb != '\t') {
|
||||
if (!safe_char[*(const unsigned char *)pb])
|
||||
return (-1);
|
||||
name_len++;
|
||||
/* The pathname should have a slash in this
|
||||
* format. */
|
||||
if (*pb == '/')
|
||||
slash = 1;
|
||||
}
|
||||
if (name_len == 0 || slash == 0)
|
||||
return (-1);
|
||||
/* If '/' is placed at the first in this field, this is not
|
||||
* a valid filename. */
|
||||
if (pb[1] == '/')
|
||||
return (-1);
|
||||
ll = len - nl - name_len;
|
||||
pp = p;
|
||||
*last_is_path = 1;
|
||||
}
|
||||
|
||||
return (bid_keyword_list(pp, ll, 0, *last_is_path));
|
||||
}
|
||||
|
||||
#define MAX_BID_ENTRY 3
|
||||
@ -525,14 +570,11 @@ mtree_bid(struct archive_read *a, int best_bid)
|
||||
{
|
||||
const char *signature = "#mtree";
|
||||
const char *p;
|
||||
ssize_t avail, ravail;
|
||||
ssize_t len, nl;
|
||||
int detected_bytes = 0, entry_cnt = 0, multiline = 0;
|
||||
|
||||
(void)best_bid; /* UNUSED */
|
||||
|
||||
/* Now let's look at the actual header and see if it matches. */
|
||||
p = __archive_read_ahead(a, strlen(signature), &avail);
|
||||
p = __archive_read_ahead(a, strlen(signature), NULL);
|
||||
if (p == NULL)
|
||||
return (-1);
|
||||
|
||||
@ -542,6 +584,24 @@ mtree_bid(struct archive_read *a, int best_bid)
|
||||
/*
|
||||
* There is not a mtree signature. Let's try to detect mtree format.
|
||||
*/
|
||||
return (detect_form(a, NULL));
|
||||
}
|
||||
|
||||
static int
|
||||
detect_form(struct archive_read *a, int *is_form_d)
|
||||
{
|
||||
const char *p;
|
||||
ssize_t avail, ravail;
|
||||
ssize_t detected_bytes = 0, len, nl;
|
||||
int entry_cnt = 0, multiline = 0;
|
||||
int form_D = 0;/* The archive is generated by `NetBSD mtree -D'
|
||||
* (In this source we call it `form D') . */
|
||||
|
||||
if (is_form_d != NULL)
|
||||
*is_form_d = 0;
|
||||
p = __archive_read_ahead(a, 1, &avail);
|
||||
if (p == NULL)
|
||||
return (-1);
|
||||
ravail = avail;
|
||||
for (;;) {
|
||||
len = next_line(a, &p, &avail, &ravail, &nl);
|
||||
@ -566,7 +626,7 @@ mtree_bid(struct archive_read *a, int best_bid)
|
||||
} else {
|
||||
/* A continuance line; the terminal
|
||||
* character of previous line was '\' character. */
|
||||
if (bid_keyword_list(p, len, 0) <= 0)
|
||||
if (bid_keyword_list(p, len, 0, 0) <= 0)
|
||||
break;
|
||||
if (multiline == 1)
|
||||
detected_bytes += len;
|
||||
@ -581,9 +641,25 @@ mtree_bid(struct archive_read *a, int best_bid)
|
||||
continue;
|
||||
}
|
||||
if (p[0] != '/') {
|
||||
if (bid_entry(p, len) >= 0) {
|
||||
int last_is_path, keywords;
|
||||
|
||||
keywords = bid_entry(p, len, nl, &last_is_path);
|
||||
if (keywords >= 0) {
|
||||
detected_bytes += len;
|
||||
if (p[len-nl-1] == '\\')
|
||||
if (form_D == 0) {
|
||||
if (last_is_path)
|
||||
form_D = 1;
|
||||
else if (keywords > 0)
|
||||
/* This line is not `form D'. */
|
||||
form_D = -1;
|
||||
} else if (form_D == 1) {
|
||||
if (!last_is_path && keywords > 0)
|
||||
/* This this is not `form D'
|
||||
* and We cannot accept mixed
|
||||
* format. */
|
||||
break;
|
||||
}
|
||||
if (!last_is_path && p[len-nl-1] == '\\')
|
||||
/* This line continues. */
|
||||
multiline = 1;
|
||||
else {
|
||||
@ -596,13 +672,13 @@ mtree_bid(struct archive_read *a, int best_bid)
|
||||
} else
|
||||
break;
|
||||
} else if (strncmp(p, "/set", 4) == 0) {
|
||||
if (bid_keyword_list(p+4, len-4, 0) <= 0)
|
||||
if (bid_keyword_list(p+4, len-4, 0, 0) <= 0)
|
||||
break;
|
||||
/* This line continues. */
|
||||
if (p[len-nl-1] == '\\')
|
||||
multiline = 2;
|
||||
} else if (strncmp(p, "/unset", 6) == 0) {
|
||||
if (bid_keyword_list(p+6, len-6, 1) <= 0)
|
||||
if (bid_keyword_list(p+6, len-6, 1, 0) <= 0)
|
||||
break;
|
||||
/* This line continues. */
|
||||
if (p[len-nl-1] == '\\')
|
||||
@ -614,8 +690,13 @@ mtree_bid(struct archive_read *a, int best_bid)
|
||||
p += len;
|
||||
avail -= len;
|
||||
}
|
||||
if (entry_cnt >= MAX_BID_ENTRY || (entry_cnt > 0 && len == 0))
|
||||
if (entry_cnt >= MAX_BID_ENTRY || (entry_cnt > 0 && len == 0)) {
|
||||
if (is_form_d != NULL) {
|
||||
if (form_D == 1)
|
||||
*is_form_d = 1;
|
||||
}
|
||||
return (32);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -739,12 +820,12 @@ process_global_unset(struct archive_read *a,
|
||||
|
||||
static int
|
||||
process_add_entry(struct archive_read *a, struct mtree *mtree,
|
||||
struct mtree_option **global, const char *line,
|
||||
struct mtree_entry **last_entry)
|
||||
struct mtree_option **global, const char *line, ssize_t line_len,
|
||||
struct mtree_entry **last_entry, int is_form_d)
|
||||
{
|
||||
struct mtree_entry *entry;
|
||||
struct mtree_option *iter;
|
||||
const char *next, *eq;
|
||||
const char *next, *eq, *name, *end;
|
||||
size_t len;
|
||||
int r;
|
||||
|
||||
@ -765,17 +846,46 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
|
||||
(*last_entry)->next = entry;
|
||||
*last_entry = entry;
|
||||
|
||||
len = strcspn(line, " \t\r\n");
|
||||
if (is_form_d) {
|
||||
/*
|
||||
* This form places the file name as last parameter.
|
||||
*/
|
||||
name = line + line_len -1;
|
||||
while (line_len > 0) {
|
||||
if (*name != '\r' && *name != '\n' &&
|
||||
*name != '\t' && *name != ' ')
|
||||
break;
|
||||
name--;
|
||||
line_len--;
|
||||
}
|
||||
len = 0;
|
||||
while (line_len > 0) {
|
||||
if (*name == '\r' || *name == '\n' ||
|
||||
*name == '\t' || *name == ' ') {
|
||||
name++;
|
||||
break;
|
||||
}
|
||||
name--;
|
||||
line_len--;
|
||||
len++;
|
||||
}
|
||||
end = name;
|
||||
} else {
|
||||
len = strcspn(line, " \t\r\n");
|
||||
name = line;
|
||||
line += len;
|
||||
end = line + line_len;
|
||||
}
|
||||
|
||||
if ((entry->name = malloc(len + 1)) == NULL) {
|
||||
archive_set_error(&a->archive, errno, "Can't allocate memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
memcpy(entry->name, line, len);
|
||||
memcpy(entry->name, name, len);
|
||||
entry->name[len] = '\0';
|
||||
parse_escapes(entry->name, entry);
|
||||
|
||||
line += len;
|
||||
for (iter = *global; iter != NULL; iter = iter->next) {
|
||||
r = add_option(a, &entry->options, iter->value,
|
||||
strlen(iter->value));
|
||||
@ -787,6 +897,8 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
|
||||
next = line + strspn(line, " \t\r\n");
|
||||
if (*next == '\0')
|
||||
return (ARCHIVE_OK);
|
||||
if (next >= end)
|
||||
return (ARCHIVE_OK);
|
||||
line = next;
|
||||
next = line + strcspn(line, " \t\r\n");
|
||||
eq = strchr(line, '=');
|
||||
@ -811,7 +923,7 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
|
||||
char *p;
|
||||
struct mtree_option *global;
|
||||
struct mtree_entry *last_entry;
|
||||
int r;
|
||||
int r, is_form_d;
|
||||
|
||||
mtree->archive_format = ARCHIVE_FORMAT_MTREE;
|
||||
mtree->archive_format_name = "mtree";
|
||||
@ -819,6 +931,8 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
|
||||
global = NULL;
|
||||
last_entry = NULL;
|
||||
|
||||
(void)detect_form(a, &is_form_d);
|
||||
|
||||
for (counter = 1; ; ++counter) {
|
||||
len = readline(a, mtree, &p, 65536);
|
||||
if (len == 0) {
|
||||
@ -828,7 +942,7 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
|
||||
}
|
||||
if (len < 0) {
|
||||
free_options(global);
|
||||
return (len);
|
||||
return ((int)len);
|
||||
}
|
||||
/* Leading whitespace is never significant, ignore it. */
|
||||
while (*p == ' ' || *p == '\t') {
|
||||
@ -841,8 +955,8 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
|
||||
if (*p == '\r' || *p == '\n' || *p == '\0')
|
||||
continue;
|
||||
if (*p != '/') {
|
||||
r = process_add_entry(a, mtree, &global, p,
|
||||
&last_entry);
|
||||
r = process_add_entry(a, mtree, &global, p, len,
|
||||
&last_entry, is_form_d);
|
||||
} else if (strncmp(p, "/set", 4) == 0) {
|
||||
if (p[4] != ' ' && p[4] != '\t')
|
||||
break;
|
||||
@ -1008,7 +1122,8 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
|
||||
|
||||
if (archive_entry_filetype(entry) == AE_IFREG ||
|
||||
archive_entry_filetype(entry) == AE_IFDIR) {
|
||||
mtree->fd = open(path, O_RDONLY | O_BINARY);
|
||||
mtree->fd = open(path, O_RDONLY | O_BINARY | O_CLOEXEC);
|
||||
__archive_ensure_cloexec_flag(mtree->fd);
|
||||
if (mtree->fd == -1 &&
|
||||
(errno != ENOENT ||
|
||||
archive_strlen(&mtree->contents_name) > 0)) {
|
||||
@ -1091,15 +1206,19 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
|
||||
* if it wasn't already parsed from the specification.
|
||||
*/
|
||||
if (st != NULL) {
|
||||
if ((parsed_kws & MTREE_HAS_DEVICE) == 0 &&
|
||||
if (((parsed_kws & MTREE_HAS_DEVICE) == 0 ||
|
||||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0) &&
|
||||
(archive_entry_filetype(entry) == AE_IFCHR ||
|
||||
archive_entry_filetype(entry) == AE_IFBLK))
|
||||
archive_entry_set_rdev(entry, st->st_rdev);
|
||||
if ((parsed_kws & (MTREE_HAS_GID | MTREE_HAS_GNAME)) == 0)
|
||||
if ((parsed_kws & (MTREE_HAS_GID | MTREE_HAS_GNAME)) == 0 ||
|
||||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0)
|
||||
archive_entry_set_gid(entry, st->st_gid);
|
||||
if ((parsed_kws & (MTREE_HAS_UID | MTREE_HAS_UNAME)) == 0)
|
||||
if ((parsed_kws & (MTREE_HAS_UID | MTREE_HAS_UNAME)) == 0 ||
|
||||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0)
|
||||
archive_entry_set_uid(entry, st->st_uid);
|
||||
if ((parsed_kws & MTREE_HAS_MTIME) == 0) {
|
||||
if ((parsed_kws & MTREE_HAS_MTIME) == 0 ||
|
||||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0) {
|
||||
#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
|
||||
archive_entry_set_mtime(entry, st->st_mtime,
|
||||
st->st_mtimespec.tv_nsec);
|
||||
@ -1119,11 +1238,14 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
|
||||
archive_entry_set_mtime(entry, st->st_mtime, 0);
|
||||
#endif
|
||||
}
|
||||
if ((parsed_kws & MTREE_HAS_NLINK) == 0)
|
||||
if ((parsed_kws & MTREE_HAS_NLINK) == 0 ||
|
||||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0)
|
||||
archive_entry_set_nlink(entry, st->st_nlink);
|
||||
if ((parsed_kws & MTREE_HAS_PERM) == 0)
|
||||
if ((parsed_kws & MTREE_HAS_PERM) == 0 ||
|
||||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0)
|
||||
archive_entry_set_perm(entry, st->st_mode);
|
||||
if ((parsed_kws & MTREE_HAS_SIZE) == 0)
|
||||
if ((parsed_kws & MTREE_HAS_SIZE) == 0 ||
|
||||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0)
|
||||
archive_entry_set_size(entry, st->st_size);
|
||||
archive_entry_set_ino(entry, st->st_ino);
|
||||
archive_entry_set_dev(entry, st->st_dev);
|
||||
@ -1213,6 +1335,10 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
|
||||
if (*key == '\0')
|
||||
return (ARCHIVE_OK);
|
||||
|
||||
if (strcmp(key, "nochange") == 0) {
|
||||
*parsed_kws |= MTREE_HAS_NOCHANGE;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
if (strcmp(key, "optional") == 0) {
|
||||
*parsed_kws |= MTREE_HAS_OPTIONAL;
|
||||
return (ARCHIVE_OK);
|
||||
|
@ -199,6 +199,13 @@ struct lzss
|
||||
int64_t position;
|
||||
};
|
||||
|
||||
struct data_block_offsets
|
||||
{
|
||||
int64_t header_size;
|
||||
int64_t start_offset;
|
||||
int64_t end_offset;
|
||||
};
|
||||
|
||||
struct rar
|
||||
{
|
||||
/* Entries from main RAR header */
|
||||
@ -217,6 +224,7 @@ struct rar
|
||||
long mnsec;
|
||||
mode_t mode;
|
||||
char *filename;
|
||||
char *filename_save;
|
||||
size_t filename_allocated;
|
||||
|
||||
/* File header optional entries */
|
||||
@ -234,6 +242,7 @@ struct rar
|
||||
int64_t bytes_uncopied;
|
||||
int64_t offset;
|
||||
int64_t offset_outgoing;
|
||||
int64_t offset_seek;
|
||||
char valid;
|
||||
unsigned int unp_offset;
|
||||
unsigned int unp_buffer_size;
|
||||
@ -243,6 +252,10 @@ struct rar
|
||||
char entry_eof;
|
||||
unsigned long crc_calculated;
|
||||
int found_first_header;
|
||||
char has_endarc_header;
|
||||
struct data_block_offsets *dbo;
|
||||
unsigned int cursor;
|
||||
unsigned int nodes;
|
||||
|
||||
/* LZSS members */
|
||||
struct huffman_code maincode;
|
||||
@ -301,6 +314,8 @@ static int archive_read_format_rar_read_header(struct archive_read *,
|
||||
static int archive_read_format_rar_read_data(struct archive_read *,
|
||||
const void **, size_t *, int64_t *);
|
||||
static int archive_read_format_rar_read_data_skip(struct archive_read *a);
|
||||
static int64_t archive_read_format_rar_seek_data(struct archive_read *, int64_t,
|
||||
int);
|
||||
static int archive_read_format_rar_cleanup(struct archive_read *);
|
||||
|
||||
/* Support functions */
|
||||
@ -328,6 +343,7 @@ static int make_table_recurse(struct archive_read *, struct huffman_code *, int,
|
||||
static int64_t expand(struct archive_read *, int64_t);
|
||||
static int copy_from_lzss_window(struct archive_read *, const void **,
|
||||
int64_t, int);
|
||||
static const void *rar_read_ahead(struct archive_read *, size_t, ssize_t *);
|
||||
|
||||
/*
|
||||
* Bit stream reader.
|
||||
@ -449,11 +465,9 @@ rar_br_fillup(struct archive_read *a, struct rar_br *br)
|
||||
__archive_read_consume(a, rar->bytes_unconsumed);
|
||||
rar->bytes_unconsumed = 0;
|
||||
}
|
||||
br->next_in = __archive_read_ahead(a, 1, &(br->avail_in));
|
||||
br->next_in = rar_read_ahead(a, 1, &(br->avail_in));
|
||||
if (br->next_in == NULL)
|
||||
return (0);
|
||||
if (br->avail_in > rar->bytes_remaining)
|
||||
br->avail_in = (ssize_t)rar->bytes_remaining;
|
||||
if (br->avail_in == 0)
|
||||
return (0);
|
||||
}
|
||||
@ -473,15 +487,13 @@ rar_br_preparation(struct archive_read *a, struct rar_br *br)
|
||||
struct rar *rar = (struct rar *)(a->format->data);
|
||||
|
||||
if (rar->bytes_remaining > 0) {
|
||||
br->next_in = __archive_read_ahead(a, 1, &(br->avail_in));
|
||||
br->next_in = rar_read_ahead(a, 1, &(br->avail_in));
|
||||
if (br->next_in == NULL) {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Truncated RAR file data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (br->avail_in > rar->bytes_remaining)
|
||||
br->avail_in = (ssize_t)rar->bytes_remaining;
|
||||
if (br->cache_avail == 0)
|
||||
(void)rar_br_fillup(a, br);
|
||||
}
|
||||
@ -642,6 +654,7 @@ archive_read_support_format_rar(struct archive *_a)
|
||||
archive_read_format_rar_read_header,
|
||||
archive_read_format_rar_read_data,
|
||||
archive_read_format_rar_read_data_skip,
|
||||
archive_read_format_rar_seek_data,
|
||||
archive_read_format_rar_cleanup);
|
||||
|
||||
if (r != ARCHIVE_OK)
|
||||
@ -844,13 +857,6 @@ archive_read_format_rar_read_header(struct archive_read *a,
|
||||
sizeof(rar->reserved2));
|
||||
}
|
||||
|
||||
if (rar->main_flags & MHD_VOLUME ||
|
||||
rar->main_flags & MHD_FIRSTVOLUME)
|
||||
{
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"RAR volume support unavailable.");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (rar->main_flags & MHD_PASSWORD)
|
||||
{
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
@ -858,7 +864,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
crc32_val = crc32(0, (const unsigned char *)p + 2, skip - 2);
|
||||
crc32_val = crc32(0, (const unsigned char *)p + 2, (unsigned)skip - 2);
|
||||
if ((crc32_val & 0xffff) != archive_le16dec(p)) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Header CRC error");
|
||||
@ -875,6 +881,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
|
||||
case SUB_HEAD:
|
||||
case PROTECT_HEAD:
|
||||
case SIGN_HEAD:
|
||||
case ENDARC_HEAD:
|
||||
flags = archive_le16dec(p + 3);
|
||||
skip = archive_le16dec(p + 5);
|
||||
if (skip < 7) {
|
||||
@ -900,13 +907,15 @@ archive_read_format_rar_read_header(struct archive_read *a,
|
||||
p = h;
|
||||
}
|
||||
|
||||
crc32_val = crc32(0, (const unsigned char *)p + 2, skip - 2);
|
||||
crc32_val = crc32(0, (const unsigned char *)p + 2, (unsigned)skip - 2);
|
||||
if ((crc32_val & 0xffff) != archive_le16dec(p)) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Header CRC error");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
__archive_read_consume(a, skip);
|
||||
if (head_type == ENDARC_HEAD)
|
||||
return (ARCHIVE_EOF);
|
||||
break;
|
||||
|
||||
case NEWSUB_HEAD:
|
||||
@ -914,9 +923,6 @@ archive_read_format_rar_read_header(struct archive_read *a,
|
||||
return ret;
|
||||
break;
|
||||
|
||||
case ENDARC_HEAD:
|
||||
return (ARCHIVE_EOF);
|
||||
|
||||
default:
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Bad RAR file");
|
||||
@ -938,10 +944,12 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff,
|
||||
rar->bytes_unconsumed = 0;
|
||||
}
|
||||
|
||||
if (rar->entry_eof) {
|
||||
if (rar->entry_eof || rar->offset_seek >= rar->unp_size) {
|
||||
*buff = NULL;
|
||||
*size = 0;
|
||||
*offset = rar->offset;
|
||||
if (*offset < rar->unp_size)
|
||||
*offset = rar->unp_size;
|
||||
return (ARCHIVE_EOF);
|
||||
}
|
||||
|
||||
@ -975,6 +983,7 @@ archive_read_format_rar_read_data_skip(struct archive_read *a)
|
||||
{
|
||||
struct rar *rar;
|
||||
int64_t bytes_skipped;
|
||||
int ret;
|
||||
|
||||
rar = (struct rar *)(a->format->data);
|
||||
|
||||
@ -989,9 +998,179 @@ archive_read_format_rar_read_data_skip(struct archive_read *a)
|
||||
if (bytes_skipped < 0)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
/* Compressed data to skip must be read from each header in a multivolume
|
||||
* archive.
|
||||
*/
|
||||
if (rar->main_flags & MHD_VOLUME && rar->file_flags & FHD_SPLIT_AFTER)
|
||||
{
|
||||
ret = archive_read_format_rar_read_header(a, a->entry);
|
||||
if (ret == (ARCHIVE_EOF))
|
||||
ret = archive_read_format_rar_read_header(a, a->entry);
|
||||
if (ret != (ARCHIVE_OK))
|
||||
return ret;
|
||||
return archive_read_format_rar_read_data_skip(a);
|
||||
}
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int64_t
|
||||
archive_read_format_rar_seek_data(struct archive_read *a, int64_t offset,
|
||||
int whence)
|
||||
{
|
||||
int64_t client_offset, ret;
|
||||
unsigned int i;
|
||||
struct rar *rar = (struct rar *)(a->format->data);
|
||||
|
||||
if (rar->compression_method == COMPRESS_METHOD_STORE)
|
||||
{
|
||||
/* Modify the offset for use with SEEK_SET */
|
||||
switch (whence)
|
||||
{
|
||||
case SEEK_CUR:
|
||||
client_offset = rar->offset_seek;
|
||||
break;
|
||||
case SEEK_END:
|
||||
client_offset = rar->unp_size;
|
||||
break;
|
||||
case SEEK_SET:
|
||||
default:
|
||||
client_offset = 0;
|
||||
}
|
||||
client_offset += offset;
|
||||
if (client_offset < 0)
|
||||
{
|
||||
/* Can't seek past beginning of data block */
|
||||
return -1;
|
||||
}
|
||||
else if (client_offset > rar->unp_size)
|
||||
{
|
||||
/*
|
||||
* Set the returned offset but only seek to the end of
|
||||
* the data block.
|
||||
*/
|
||||
rar->offset_seek = client_offset;
|
||||
client_offset = rar->unp_size;
|
||||
}
|
||||
|
||||
client_offset += rar->dbo[0].start_offset;
|
||||
i = 0;
|
||||
while (i < rar->cursor)
|
||||
{
|
||||
i++;
|
||||
client_offset += rar->dbo[i].start_offset - rar->dbo[i-1].end_offset;
|
||||
}
|
||||
if (rar->main_flags & MHD_VOLUME)
|
||||
{
|
||||
/* Find the appropriate offset among the multivolume archive */
|
||||
while (1)
|
||||
{
|
||||
if (client_offset < rar->dbo[rar->cursor].start_offset &&
|
||||
rar->file_flags & FHD_SPLIT_BEFORE)
|
||||
{
|
||||
/* Search backwards for the correct data block */
|
||||
if (rar->cursor == 0)
|
||||
{
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Attempt to seek past beginning of RAR data block");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
rar->cursor--;
|
||||
client_offset -= rar->dbo[rar->cursor+1].start_offset -
|
||||
rar->dbo[rar->cursor].end_offset;
|
||||
if (client_offset < rar->dbo[rar->cursor].start_offset)
|
||||
continue;
|
||||
ret = __archive_read_seek(a, rar->dbo[rar->cursor].start_offset -
|
||||
rar->dbo[rar->cursor].header_size, SEEK_SET);
|
||||
if (ret < (ARCHIVE_OK))
|
||||
return ret;
|
||||
ret = archive_read_format_rar_read_header(a, a->entry);
|
||||
if (ret != (ARCHIVE_OK))
|
||||
{
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Error during seek of RAR file");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
rar->cursor--;
|
||||
break;
|
||||
}
|
||||
else if (client_offset > rar->dbo[rar->cursor].end_offset &&
|
||||
rar->file_flags & FHD_SPLIT_AFTER)
|
||||
{
|
||||
/* Search forward for the correct data block */
|
||||
rar->cursor++;
|
||||
if (rar->cursor < rar->nodes &&
|
||||
client_offset > rar->dbo[rar->cursor].end_offset)
|
||||
{
|
||||
client_offset += rar->dbo[rar->cursor].start_offset -
|
||||
rar->dbo[rar->cursor-1].end_offset;
|
||||
continue;
|
||||
}
|
||||
rar->cursor--;
|
||||
ret = __archive_read_seek(a, rar->dbo[rar->cursor].end_offset,
|
||||
SEEK_SET);
|
||||
if (ret < (ARCHIVE_OK))
|
||||
return ret;
|
||||
ret = archive_read_format_rar_read_header(a, a->entry);
|
||||
if (ret == (ARCHIVE_EOF))
|
||||
{
|
||||
rar->has_endarc_header = 1;
|
||||
ret = archive_read_format_rar_read_header(a, a->entry);
|
||||
}
|
||||
if (ret != (ARCHIVE_OK))
|
||||
{
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Error during seek of RAR file");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
client_offset += rar->dbo[rar->cursor].start_offset -
|
||||
rar->dbo[rar->cursor-1].end_offset;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ret = __archive_read_seek(a, client_offset, SEEK_SET);
|
||||
if (ret < (ARCHIVE_OK))
|
||||
return ret;
|
||||
rar->bytes_remaining = rar->dbo[rar->cursor].end_offset - ret;
|
||||
i = rar->cursor;
|
||||
while (i > 0)
|
||||
{
|
||||
i--;
|
||||
ret -= rar->dbo[i+1].start_offset - rar->dbo[i].end_offset;
|
||||
}
|
||||
ret -= rar->dbo[0].start_offset;
|
||||
|
||||
/* Always restart reading the file after a seek */
|
||||
a->read_data_block = NULL;
|
||||
a->read_data_offset = 0;
|
||||
a->read_data_output_offset = 0;
|
||||
a->read_data_remaining = 0;
|
||||
rar->bytes_unconsumed = 0;
|
||||
rar->offset = 0;
|
||||
|
||||
/*
|
||||
* If a seek past the end of file was requested, return the requested
|
||||
* offset.
|
||||
*/
|
||||
if (ret == rar->unp_size && rar->offset_seek > rar->unp_size)
|
||||
return rar->offset_seek;
|
||||
|
||||
/* Return the new offset */
|
||||
rar->offset_seek = ret;
|
||||
return rar->offset_seek;
|
||||
}
|
||||
else
|
||||
{
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Seeking of compressed RAR files is unsupported");
|
||||
}
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_rar_cleanup(struct archive_read *a)
|
||||
{
|
||||
@ -1000,6 +1179,8 @@ archive_read_format_rar_cleanup(struct archive_read *a)
|
||||
rar = (struct rar *)(a->format->data);
|
||||
free_codes(a);
|
||||
free(rar->filename);
|
||||
free(rar->filename_save);
|
||||
free(rar->dbo);
|
||||
free(rar->unp_buffer);
|
||||
free(rar->lzss.window);
|
||||
__archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context, &g_szalloc);
|
||||
@ -1138,6 +1319,8 @@ read_header(struct archive_read *a, struct archive_entry *entry,
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
rar->bytes_remaining = rar->packed_size;
|
||||
|
||||
/* TODO: RARv3 subblocks contain comments. For now the complete block is
|
||||
* consumed at the end.
|
||||
*/
|
||||
@ -1177,13 +1360,13 @@ read_header(struct archive_read *a, struct archive_entry *entry,
|
||||
{
|
||||
if (filename_size != strlen(filename))
|
||||
{
|
||||
unsigned char highbyte, flagbits, flagbyte, offset;
|
||||
unsigned fn_end;
|
||||
unsigned char highbyte, flagbits, flagbyte;
|
||||
unsigned fn_end, offset;
|
||||
|
||||
end = filename_size;
|
||||
fn_end = filename_size * 2;
|
||||
filename_size = 0;
|
||||
offset = strlen(filename) + 1;
|
||||
offset = (unsigned)strlen(filename) + 1;
|
||||
highbyte = *(p + offset++);
|
||||
flagbits = 0;
|
||||
flagbyte = 0;
|
||||
@ -1284,6 +1467,51 @@ read_header(struct archive_read *a, struct archive_entry *entry,
|
||||
p += filename_size;
|
||||
}
|
||||
|
||||
/* Split file in multivolume RAR. No more need to process header. */
|
||||
if (rar->filename_save &&
|
||||
!memcmp(rar->filename, rar->filename_save, filename_size + 1))
|
||||
{
|
||||
__archive_read_consume(a, header_size - 7);
|
||||
rar->cursor++;
|
||||
if (rar->cursor >= rar->nodes)
|
||||
{
|
||||
rar->nodes++;
|
||||
if ((rar->dbo =
|
||||
realloc(rar->dbo, sizeof(*rar->dbo) * rar->nodes)) == NULL)
|
||||
{
|
||||
archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory.");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
rar->dbo[rar->cursor].header_size = header_size;
|
||||
rar->dbo[rar->cursor].start_offset = -1;
|
||||
rar->dbo[rar->cursor].end_offset = -1;
|
||||
}
|
||||
if (rar->dbo[rar->cursor].start_offset < 0)
|
||||
{
|
||||
rar->dbo[rar->cursor].start_offset = a->filter->position;
|
||||
rar->dbo[rar->cursor].end_offset = rar->dbo[rar->cursor].start_offset +
|
||||
rar->packed_size;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
rar->filename_save = (char*)realloc(rar->filename_save,
|
||||
filename_size + 1);
|
||||
memcpy(rar->filename_save, rar->filename, filename_size + 1);
|
||||
|
||||
/* Set info for seeking */
|
||||
free(rar->dbo);
|
||||
if ((rar->dbo = calloc(1, sizeof(*rar->dbo))) == NULL)
|
||||
{
|
||||
archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory.");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
rar->dbo[0].header_size = header_size;
|
||||
rar->dbo[0].start_offset = -1;
|
||||
rar->dbo[0].end_offset = -1;
|
||||
rar->cursor = 0;
|
||||
rar->nodes = 1;
|
||||
|
||||
if (rar->file_flags & FHD_SALT)
|
||||
{
|
||||
if (p + 8 > endp) {
|
||||
@ -1304,6 +1532,8 @@ read_header(struct archive_read *a, struct archive_entry *entry,
|
||||
}
|
||||
|
||||
__archive_read_consume(a, header_size - 7);
|
||||
rar->dbo[0].start_offset = a->filter->position;
|
||||
rar->dbo[0].end_offset = rar->dbo[0].start_offset + rar->packed_size;
|
||||
|
||||
switch(file_header.host_os)
|
||||
{
|
||||
@ -1330,9 +1560,9 @@ read_header(struct archive_read *a, struct archive_entry *entry,
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
rar->bytes_remaining = rar->packed_size;
|
||||
rar->bytes_uncopied = rar->bytes_unconsumed = 0;
|
||||
rar->lzss.position = rar->offset = 0;
|
||||
rar->offset_seek = 0;
|
||||
rar->dictionary_size = 0;
|
||||
rar->offset_outgoing = 0;
|
||||
rar->br.cache_avail = 0;
|
||||
@ -1488,7 +1718,7 @@ read_symlink_stored(struct archive_read *a, struct archive_entry *entry,
|
||||
int ret = (ARCHIVE_OK);
|
||||
|
||||
rar = (struct rar *)(a->format->data);
|
||||
if ((h = __archive_read_ahead(a, (size_t)rar->packed_size, NULL)) == NULL)
|
||||
if ((h = rar_read_ahead(a, (size_t)rar->packed_size, NULL)) == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
p = h;
|
||||
|
||||
@ -1518,7 +1748,8 @@ read_data_stored(struct archive_read *a, const void **buff, size_t *size,
|
||||
ssize_t bytes_avail;
|
||||
|
||||
rar = (struct rar *)(a->format->data);
|
||||
if (rar->bytes_remaining == 0)
|
||||
if (rar->bytes_remaining == 0 &&
|
||||
!(rar->main_flags & MHD_VOLUME && rar->file_flags & FHD_SPLIT_AFTER))
|
||||
{
|
||||
*buff = NULL;
|
||||
*size = 0;
|
||||
@ -1532,23 +1763,23 @@ read_data_stored(struct archive_read *a, const void **buff, size_t *size,
|
||||
return (ARCHIVE_EOF);
|
||||
}
|
||||
|
||||
*buff = __archive_read_ahead(a, 1, &bytes_avail);
|
||||
*buff = rar_read_ahead(a, 1, &bytes_avail);
|
||||
if (bytes_avail <= 0)
|
||||
{
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Truncated RAR file data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (bytes_avail > rar->bytes_remaining)
|
||||
bytes_avail = (ssize_t)rar->bytes_remaining;
|
||||
|
||||
*size = bytes_avail;
|
||||
*offset = rar->offset;
|
||||
rar->offset += bytes_avail;
|
||||
rar->offset_seek += bytes_avail;
|
||||
rar->bytes_remaining -= bytes_avail;
|
||||
rar->bytes_unconsumed = bytes_avail;
|
||||
/* Calculate File CRC. */
|
||||
rar->crc_calculated = crc32(rar->crc_calculated, *buff, bytes_avail);
|
||||
rar->crc_calculated = crc32(rar->crc_calculated, *buff,
|
||||
(unsigned)bytes_avail);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
@ -1578,7 +1809,8 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
|
||||
*offset = rar->offset_outgoing;
|
||||
rar->offset_outgoing += *size;
|
||||
/* Calculate File CRC. */
|
||||
rar->crc_calculated = crc32(rar->crc_calculated, *buff, *size);
|
||||
rar->crc_calculated = crc32(rar->crc_calculated, *buff,
|
||||
(unsigned)*size);
|
||||
rar->unp_offset = 0;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
@ -1600,7 +1832,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
|
||||
bs = rar->unp_buffer_size - rar->unp_offset;
|
||||
else
|
||||
bs = (size_t)rar->bytes_uncopied;
|
||||
ret = copy_from_lzss_window(a, buff, rar->offset, bs);
|
||||
ret = copy_from_lzss_window(a, buff, rar->offset, (int)bs);
|
||||
if (ret != ARCHIVE_OK)
|
||||
return (ret);
|
||||
rar->offset += bs;
|
||||
@ -1611,7 +1843,8 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
|
||||
*offset = rar->offset_outgoing;
|
||||
rar->offset_outgoing += *size;
|
||||
/* Calculate File CRC. */
|
||||
rar->crc_calculated = crc32(rar->crc_calculated, *buff, *size);
|
||||
rar->crc_calculated = crc32(rar->crc_calculated, *buff,
|
||||
(unsigned)*size);
|
||||
return (ret);
|
||||
}
|
||||
continue;
|
||||
@ -1728,7 +1961,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
|
||||
bs = rar->unp_buffer_size - rar->unp_offset;
|
||||
else
|
||||
bs = (size_t)rar->bytes_uncopied;
|
||||
ret = copy_from_lzss_window(a, buff, rar->offset, bs);
|
||||
ret = copy_from_lzss_window(a, buff, rar->offset, (int)bs);
|
||||
if (ret != ARCHIVE_OK)
|
||||
return (ret);
|
||||
rar->offset += bs;
|
||||
@ -1744,7 +1977,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
|
||||
*offset = rar->offset_outgoing;
|
||||
rar->offset_outgoing += *size;
|
||||
/* Calculate File CRC. */
|
||||
rar->crc_calculated = crc32(rar->crc_calculated, *buff, *size);
|
||||
rar->crc_calculated = crc32(rar->crc_calculated, *buff, (unsigned)*size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1987,17 +2220,21 @@ parse_codes(struct archive_read *a)
|
||||
/* Seems as though dictionary sizes are not used. Even so, minimize
|
||||
* memory usage as much as possible.
|
||||
*/
|
||||
void *new_window;
|
||||
unsigned int new_size;
|
||||
|
||||
if (rar->unp_size >= DICTIONARY_MAX_SIZE)
|
||||
rar->dictionary_size = DICTIONARY_MAX_SIZE;
|
||||
new_size = DICTIONARY_MAX_SIZE;
|
||||
else
|
||||
rar->dictionary_size = rar_fls((unsigned int)rar->unp_size) << 1;
|
||||
rar->lzss.window = (unsigned char *)realloc(rar->lzss.window,
|
||||
rar->dictionary_size);
|
||||
if (rar->lzss.window == NULL) {
|
||||
new_size = rar_fls((unsigned int)rar->unp_size) << 1;
|
||||
new_window = realloc(rar->lzss.window, new_size);
|
||||
if (new_window == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Unable to allocate memory for uncompressed data.");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
rar->lzss.window = (unsigned char *)new_window;
|
||||
rar->dictionary_size = new_size;
|
||||
memset(rar->lzss.window, 0, rar->dictionary_size);
|
||||
rar->lzss.mask = rar->dictionary_size - 1;
|
||||
}
|
||||
@ -2235,10 +2472,12 @@ add_value(struct archive_read *a, struct huffman_code *code, int value,
|
||||
static int
|
||||
new_node(struct huffman_code *code)
|
||||
{
|
||||
code->tree = (struct huffman_tree_node *)realloc(code->tree,
|
||||
(code->numentries + 1) * sizeof(*code->tree));
|
||||
if (code->tree == NULL)
|
||||
void *new_tree;
|
||||
|
||||
new_tree = realloc(code->tree, (code->numentries + 1) * sizeof(*code->tree));
|
||||
if (new_tree == NULL)
|
||||
return (-1);
|
||||
code->tree = (struct huffman_tree_node *)new_tree;
|
||||
code->tree[code->numentries].branches[0] = -1;
|
||||
code->tree[code->numentries].branches[1] = -2;
|
||||
return 1;
|
||||
@ -2253,8 +2492,8 @@ make_table(struct archive_read *a, struct huffman_code *code)
|
||||
code->tablesize = code->maxlength;
|
||||
|
||||
code->table =
|
||||
(struct huffman_table_entry *)malloc(sizeof(*code->table)
|
||||
* (1 << code->tablesize));
|
||||
(struct huffman_table_entry *)calloc(1, sizeof(*code->table)
|
||||
* ((size_t)1 << code->tablesize));
|
||||
|
||||
return make_table_recurse(a, code, 0, code->table, 0, code->tablesize);
|
||||
}
|
||||
@ -2586,3 +2825,34 @@ copy_from_lzss_window(struct archive_read *a, const void **buffer,
|
||||
*buffer = NULL;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static const void *
|
||||
rar_read_ahead(struct archive_read *a, size_t min, ssize_t *avail)
|
||||
{
|
||||
struct rar *rar = (struct rar *)(a->format->data);
|
||||
const void *h = __archive_read_ahead(a, min, avail);
|
||||
int ret;
|
||||
if (avail)
|
||||
{
|
||||
if (a->read_data_is_posix_read && *avail > (ssize_t)a->read_data_requested)
|
||||
*avail = a->read_data_requested;
|
||||
if (*avail > rar->bytes_remaining)
|
||||
*avail = (ssize_t)rar->bytes_remaining;
|
||||
if (*avail < 0)
|
||||
return NULL;
|
||||
else if (*avail == 0 && rar->main_flags & MHD_VOLUME &&
|
||||
rar->file_flags & FHD_SPLIT_AFTER)
|
||||
{
|
||||
ret = archive_read_format_rar_read_header(a, a->entry);
|
||||
if (ret == (ARCHIVE_EOF))
|
||||
{
|
||||
rar->has_endarc_header = 1;
|
||||
ret = archive_read_format_rar_read_header(a, a->entry);
|
||||
}
|
||||
if (ret != (ARCHIVE_OK))
|
||||
return NULL;
|
||||
return rar_read_ahead(a, min, avail);
|
||||
}
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
@ -77,6 +77,7 @@ archive_read_support_format_raw(struct archive *_a)
|
||||
archive_read_format_raw_read_header,
|
||||
archive_read_format_raw_read_data,
|
||||
archive_read_format_raw_read_data_skip,
|
||||
NULL,
|
||||
archive_read_format_raw_cleanup);
|
||||
if (r != ARCHIVE_OK)
|
||||
free(info);
|
||||
@ -157,7 +158,7 @@ archive_read_format_raw_read_data(struct archive_read *a,
|
||||
/* Record and return an error. */
|
||||
*size = 0;
|
||||
*offset = info->offset;
|
||||
return (avail);
|
||||
return ((int)avail);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -210,10 +210,10 @@ static int read_body_to_string(struct archive_read *, struct tar *,
|
||||
struct archive_string *, const void *h, size_t *);
|
||||
static int solaris_sparse_parse(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, const char *);
|
||||
static int64_t tar_atol(const char *, unsigned);
|
||||
static int64_t tar_atol10(const char *, unsigned);
|
||||
static int64_t tar_atol256(const char *, unsigned);
|
||||
static int64_t tar_atol8(const char *, unsigned);
|
||||
static int64_t tar_atol(const char *, size_t);
|
||||
static int64_t tar_atol10(const char *, size_t);
|
||||
static int64_t tar_atol256(const char *, size_t);
|
||||
static int64_t tar_atol8(const char *, size_t);
|
||||
static int tar_read_header(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, size_t *);
|
||||
static int tohex(int c);
|
||||
@ -253,6 +253,7 @@ archive_read_support_format_tar(struct archive *_a)
|
||||
archive_read_format_tar_read_header,
|
||||
archive_read_format_tar_read_data,
|
||||
archive_read_format_tar_skip,
|
||||
NULL,
|
||||
archive_read_format_tar_cleanup);
|
||||
|
||||
if (r != ARCHIVE_OK)
|
||||
@ -616,13 +617,14 @@ tar_read_header(struct archive_read *a, struct tar *tar,
|
||||
int err;
|
||||
const char *h;
|
||||
const struct archive_entry_header_ustar *header;
|
||||
const struct archive_entry_header_gnutar *gnuheader;
|
||||
|
||||
tar_flush_unconsumed(a, unconsumed);
|
||||
|
||||
/* Read 512-byte header record */
|
||||
h = __archive_read_ahead(a, 512, &bytes);
|
||||
if (bytes < 0)
|
||||
return (bytes);
|
||||
return ((int)bytes);
|
||||
if (bytes == 0) { /* EOF at a block boundary. */
|
||||
/* Some writers do omit the block of nulls. <sigh> */
|
||||
return (ARCHIVE_EOF);
|
||||
@ -703,7 +705,8 @@ tar_read_header(struct archive_read *a, struct tar *tar,
|
||||
err = header_pax_extensions(a, tar, entry, h, unconsumed);
|
||||
break;
|
||||
default:
|
||||
if (memcmp(header->magic, "ustar \0", 8) == 0) {
|
||||
gnuheader = (const struct archive_entry_header_gnutar *)h;
|
||||
if (memcmp(gnuheader->magic, "ustar \0", 8) == 0) {
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_TAR_GNUTAR;
|
||||
a->archive.archive_format_name = "GNU tar format";
|
||||
err = header_gnutar(a, tar, entry, h, unconsumed);
|
||||
@ -752,7 +755,7 @@ tar_read_header(struct archive_read *a, struct tar *tar,
|
||||
bytes_read = gnu_sparse_10_read(a, tar, unconsumed);
|
||||
tar->entry_bytes_remaining -= bytes_read;
|
||||
if (bytes_read < 0)
|
||||
return (bytes_read);
|
||||
return ((int)bytes_read);
|
||||
} else {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
@ -2392,7 +2395,7 @@ solaris_sparse_parse(struct archive_read *a, struct tar *tar,
|
||||
* On read, this implementation supports both extensions.
|
||||
*/
|
||||
static int64_t
|
||||
tar_atol(const char *p, unsigned char_cnt)
|
||||
tar_atol(const char *p, size_t char_cnt)
|
||||
{
|
||||
/*
|
||||
* Technically, GNU tar considers a field to be in base-256
|
||||
@ -2409,70 +2412,55 @@ tar_atol(const char *p, unsigned char_cnt)
|
||||
* it does obey locale.
|
||||
*/
|
||||
static int64_t
|
||||
tar_atol8(const char *p, unsigned char_cnt)
|
||||
tar_atol_base_n(const char *p, size_t char_cnt, int base)
|
||||
{
|
||||
int64_t l, limit, last_digit_limit;
|
||||
int digit, sign, base;
|
||||
int digit, sign;
|
||||
|
||||
base = 8;
|
||||
limit = INT64_MAX / base;
|
||||
last_digit_limit = INT64_MAX % base;
|
||||
|
||||
while (*p == ' ' || *p == '\t')
|
||||
/* the pointer will not be dereferenced if char_cnt is zero
|
||||
* due to the way the && operator is evaulated.
|
||||
*/
|
||||
while (char_cnt != 0 && (*p == ' ' || *p == '\t')) {
|
||||
p++;
|
||||
if (*p == '-') {
|
||||
char_cnt--;
|
||||
}
|
||||
|
||||
sign = 1;
|
||||
if (char_cnt != 0 && *p == '-') {
|
||||
sign = -1;
|
||||
p++;
|
||||
} else
|
||||
sign = 1;
|
||||
char_cnt--;
|
||||
}
|
||||
|
||||
l = 0;
|
||||
digit = *p - '0';
|
||||
while (digit >= 0 && digit < base && char_cnt-- > 0) {
|
||||
if (l>limit || (l == limit && digit > last_digit_limit)) {
|
||||
l = INT64_MAX; /* Truncate on overflow. */
|
||||
break;
|
||||
if (char_cnt != 0) {
|
||||
digit = *p - '0';
|
||||
while (digit >= 0 && digit < base && char_cnt != 0) {
|
||||
if (l>limit || (l == limit && digit > last_digit_limit)) {
|
||||
l = INT64_MAX; /* Truncate on overflow. */
|
||||
break;
|
||||
}
|
||||
l = (l * base) + digit;
|
||||
digit = *++p - '0';
|
||||
char_cnt--;
|
||||
}
|
||||
l = (l * base) + digit;
|
||||
digit = *++p - '0';
|
||||
}
|
||||
return (sign < 0) ? -l : l;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that this implementation does not (and should not!) obey
|
||||
* locale settings; you cannot simply substitute strtol here, since
|
||||
* it does obey locale.
|
||||
*/
|
||||
static int64_t
|
||||
tar_atol10(const char *p, unsigned char_cnt)
|
||||
tar_atol8(const char *p, size_t char_cnt)
|
||||
{
|
||||
int64_t l, limit, last_digit_limit;
|
||||
int base, digit, sign;
|
||||
return tar_atol_base_n(p, char_cnt, 8);
|
||||
}
|
||||
|
||||
base = 10;
|
||||
limit = INT64_MAX / base;
|
||||
last_digit_limit = INT64_MAX % base;
|
||||
|
||||
while (*p == ' ' || *p == '\t')
|
||||
p++;
|
||||
if (*p == '-') {
|
||||
sign = -1;
|
||||
p++;
|
||||
} else
|
||||
sign = 1;
|
||||
|
||||
l = 0;
|
||||
digit = *p - '0';
|
||||
while (digit >= 0 && digit < base && char_cnt-- > 0) {
|
||||
if (l > limit || (l == limit && digit > last_digit_limit)) {
|
||||
l = INT64_MAX; /* Truncate on overflow. */
|
||||
break;
|
||||
}
|
||||
l = (l * base) + digit;
|
||||
digit = *++p - '0';
|
||||
}
|
||||
return (sign < 0) ? -l : l;
|
||||
static int64_t
|
||||
tar_atol10(const char *p, size_t char_cnt)
|
||||
{
|
||||
return tar_atol_base_n(p, char_cnt, 10);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2481,7 +2469,7 @@ tar_atol10(const char *p, unsigned char_cnt)
|
||||
* ignored.
|
||||
*/
|
||||
static int64_t
|
||||
tar_atol256(const char *_p, unsigned char_cnt)
|
||||
tar_atol256(const char *_p, size_t char_cnt)
|
||||
{
|
||||
int64_t l, upper_limit, lower_limit;
|
||||
const unsigned char *p = (const unsigned char *)_p;
|
||||
|
@ -467,6 +467,7 @@ archive_read_support_format_xar(struct archive *_a)
|
||||
xar_read_header,
|
||||
xar_read_data,
|
||||
xar_read_data_skip,
|
||||
NULL,
|
||||
xar_cleanup);
|
||||
if (r != ARCHIVE_OK)
|
||||
free(xar);
|
||||
|
@ -57,6 +57,7 @@ struct zip_entry {
|
||||
int64_t gid;
|
||||
int64_t uid;
|
||||
struct archive_entry *entry;
|
||||
struct archive_string rsrcname;
|
||||
time_t mtime;
|
||||
time_t atime;
|
||||
time_t ctime;
|
||||
@ -69,6 +70,7 @@ struct zip_entry {
|
||||
|
||||
struct zip {
|
||||
/* Structural information about the archive. */
|
||||
int64_t end_of_central_directory_offset;
|
||||
int64_t central_directory_offset;
|
||||
size_t central_directory_size;
|
||||
size_t central_directory_entries;
|
||||
@ -80,6 +82,7 @@ struct zip {
|
||||
struct zip_entry *zip_entries;
|
||||
struct zip_entry *entry;
|
||||
struct archive_rb_tree tree;
|
||||
struct archive_rb_tree tree_rsrc;
|
||||
|
||||
size_t unconsumed;
|
||||
|
||||
@ -120,29 +123,33 @@ struct zip {
|
||||
#define ZIP_STRONG_ENCRYPTED (1<<6)
|
||||
#define ZIP_UTF8_NAME (1<<11)
|
||||
|
||||
static int archive_read_format_zip_streamable_bid(struct archive_read *, int);
|
||||
static int archive_read_format_zip_seekable_bid(struct archive_read *, int);
|
||||
static int archive_read_format_zip_streamable_bid(struct archive_read *,
|
||||
int);
|
||||
static int archive_read_format_zip_seekable_bid(struct archive_read *,
|
||||
int);
|
||||
static int archive_read_format_zip_options(struct archive_read *,
|
||||
const char *, const char *);
|
||||
static int archive_read_format_zip_cleanup(struct archive_read *);
|
||||
static int archive_read_format_zip_read_data(struct archive_read *,
|
||||
const void **, size_t *, int64_t *);
|
||||
static int archive_read_format_zip_read_data_skip(struct archive_read *a);
|
||||
static int archive_read_format_zip_seekable_read_header(struct archive_read *,
|
||||
struct archive_entry *);
|
||||
static int archive_read_format_zip_streamable_read_header(struct archive_read *,
|
||||
struct archive_entry *);
|
||||
static int archive_read_format_zip_seekable_read_header(
|
||||
struct archive_read *, struct archive_entry *);
|
||||
static int archive_read_format_zip_streamable_read_header(
|
||||
struct archive_read *, struct archive_entry *);
|
||||
static ssize_t zip_get_local_file_header_size(struct archive_read *, size_t);
|
||||
#ifdef HAVE_ZLIB_H
|
||||
static int zip_deflate_init(struct archive_read *, struct zip *);
|
||||
static int zip_read_data_deflate(struct archive_read *a, const void **buff,
|
||||
size_t *size, int64_t *offset);
|
||||
#endif
|
||||
static int zip_read_data_none(struct archive_read *a, const void **buff,
|
||||
size_t *size, int64_t *offset);
|
||||
static int zip_read_local_file_header(struct archive_read *a,
|
||||
struct archive_entry *entry, struct zip *);
|
||||
struct archive_entry *entry, struct zip *);
|
||||
static time_t zip_time(const char *);
|
||||
static const char *compression_name(int compression);
|
||||
static void process_extra(const char *, size_t, struct zip_entry *);
|
||||
static void process_extra(const char *, size_t, struct zip_entry *);
|
||||
|
||||
int archive_read_support_format_zip_streamable(struct archive *);
|
||||
int archive_read_support_format_zip_seekable(struct archive *);
|
||||
@ -173,6 +180,7 @@ archive_read_support_format_zip_streamable(struct archive *_a)
|
||||
archive_read_format_zip_streamable_read_header,
|
||||
archive_read_format_zip_read_data,
|
||||
archive_read_format_zip_read_data_skip,
|
||||
NULL,
|
||||
archive_read_format_zip_cleanup);
|
||||
|
||||
if (r != ARCHIVE_OK)
|
||||
@ -206,6 +214,7 @@ archive_read_support_format_zip_seekable(struct archive *_a)
|
||||
archive_read_format_zip_seekable_read_header,
|
||||
archive_read_format_zip_read_data,
|
||||
archive_read_format_zip_read_data_skip,
|
||||
NULL,
|
||||
archive_read_format_zip_cleanup);
|
||||
|
||||
if (r != ARCHIVE_OK)
|
||||
@ -255,8 +264,48 @@ archive_read_format_zip_seekable_bid(struct archive_read *a, int best_bid)
|
||||
/* First four bytes are signature for end of central directory
|
||||
record. Four zero bytes ensure this isn't a multi-volume
|
||||
Zip file (which we don't yet support). */
|
||||
if (memcmp(p, "PK\005\006\000\000\000\000", 8) != 0)
|
||||
return 0;
|
||||
if (memcmp(p, "PK\005\006\000\000\000\000", 8) != 0) {
|
||||
int64_t i, tail;
|
||||
int found;
|
||||
|
||||
/*
|
||||
* If there is a comment in end of central directory
|
||||
* record, 22 bytes are too short. we have to read more
|
||||
* to properly detect the record. Hopefully, a length
|
||||
* of the comment is not longer than 16362 bytes(16K-22).
|
||||
*/
|
||||
if (filesize + 22 > 1024 * 16) {
|
||||
tail = 1024 * 16;
|
||||
filesize = __archive_read_seek(a, tail * -1, SEEK_END);
|
||||
} else {
|
||||
tail = filesize + 22;
|
||||
filesize = __archive_read_seek(a, 0, SEEK_SET);
|
||||
}
|
||||
if (filesize < 0)
|
||||
return 0;
|
||||
if ((p = __archive_read_ahead(a, (size_t)tail, NULL)) == NULL)
|
||||
return 0;
|
||||
for (found = 0, i = 0;!found && i < tail - 22;) {
|
||||
switch (p[i]) {
|
||||
case 'P':
|
||||
if (memcmp(p+i,
|
||||
"PK\005\006\000\000\000\000", 8) == 0) {
|
||||
p += i;
|
||||
filesize += tail -
|
||||
(22 + archive_le16dec(p+20));
|
||||
found = 1;
|
||||
} else
|
||||
i += 8;
|
||||
break;
|
||||
case 'K': i += 7; break;
|
||||
case 005: i += 6; break;
|
||||
case 006: i += 5; break;
|
||||
default: i += 1; break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Since we've already done the hard work of finding the
|
||||
end of central directory record, let's save the important
|
||||
@ -264,12 +313,14 @@ archive_read_format_zip_seekable_bid(struct archive_read *a, int best_bid)
|
||||
zip->central_directory_entries = archive_le16dec(p + 10);
|
||||
zip->central_directory_size = archive_le32dec(p + 12);
|
||||
zip->central_directory_offset = archive_le32dec(p + 16);
|
||||
zip->end_of_central_directory_offset = filesize;
|
||||
|
||||
/* Just one volume, so central dir must all be on this volume. */
|
||||
if (zip->central_directory_entries != archive_le16dec(p + 8))
|
||||
return 0;
|
||||
/* Central directory can't extend beyond end of this file. */
|
||||
if (zip->central_directory_offset + (int64_t)zip->central_directory_size > filesize)
|
||||
if (zip->central_directory_offset +
|
||||
(int64_t)zip->central_directory_size > filesize)
|
||||
return 0;
|
||||
|
||||
/* This is just a tiny bit higher than the maximum returned by
|
||||
@ -296,17 +347,92 @@ cmp_key(const struct archive_rb_node *n, const void *key)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
rsrc_cmp_node(const struct archive_rb_node *n1,
|
||||
const struct archive_rb_node *n2)
|
||||
{
|
||||
const struct zip_entry *e1 = (const struct zip_entry *)n1;
|
||||
const struct zip_entry *e2 = (const struct zip_entry *)n2;
|
||||
|
||||
return (strcmp(e2->rsrcname.s, e1->rsrcname.s));
|
||||
}
|
||||
|
||||
static int
|
||||
rsrc_cmp_key(const struct archive_rb_node *n, const void *key)
|
||||
{
|
||||
const struct zip_entry *e = (const struct zip_entry *)n;
|
||||
return (strcmp((const char *)key, e->rsrcname.s));
|
||||
}
|
||||
|
||||
static const char *
|
||||
rsrc_basename(const char *name, size_t name_length)
|
||||
{
|
||||
const char *s, *r;
|
||||
|
||||
r = s = name;
|
||||
for (;;) {
|
||||
s = memchr(s, '/', name_length - (s - name));
|
||||
if (s == NULL)
|
||||
break;
|
||||
r = ++s;
|
||||
}
|
||||
return (r);
|
||||
}
|
||||
|
||||
static void
|
||||
expose_parent_dirs(struct zip *zip, const char *name, size_t name_length)
|
||||
{
|
||||
struct archive_string str;
|
||||
struct zip_entry *dir;
|
||||
char *s;
|
||||
|
||||
archive_string_init(&str);
|
||||
archive_strncpy(&str, name, name_length);
|
||||
for (;;) {
|
||||
s = strrchr(str.s, '/');
|
||||
if (s == NULL)
|
||||
break;
|
||||
*s = '\0';
|
||||
/* Transfer the parent directory from zip->tree_rsrc RB
|
||||
* tree to zip->tree RB tree to expose. */
|
||||
dir = (struct zip_entry *)
|
||||
__archive_rb_tree_find_node(&zip->tree_rsrc, str.s);
|
||||
if (dir == NULL)
|
||||
break;
|
||||
__archive_rb_tree_remove_node(&zip->tree_rsrc, &dir->node);
|
||||
archive_string_free(&dir->rsrcname);
|
||||
__archive_rb_tree_insert_node(&zip->tree, &dir->node);
|
||||
}
|
||||
archive_string_free(&str);
|
||||
}
|
||||
|
||||
static int
|
||||
slurp_central_directory(struct archive_read *a, struct zip *zip)
|
||||
{
|
||||
unsigned i;
|
||||
int64_t correction;
|
||||
static const struct archive_rb_tree_ops rb_ops = {
|
||||
&cmp_node, &cmp_key
|
||||
};
|
||||
static const struct archive_rb_tree_ops rb_rsrc_ops = {
|
||||
&rsrc_cmp_node, &rsrc_cmp_key
|
||||
};
|
||||
|
||||
/*
|
||||
* Consider the archive file we are reading may be SFX.
|
||||
* So we have to calculate a SFX header size to revise
|
||||
* ZIP header offsets.
|
||||
*/
|
||||
correction = zip->end_of_central_directory_offset -
|
||||
(zip->central_directory_offset + zip->central_directory_size);
|
||||
/* The central directory offset is relative value, and so
|
||||
* we revise this offset for SFX. */
|
||||
zip->central_directory_offset += correction;
|
||||
|
||||
__archive_read_seek(a, zip->central_directory_offset, SEEK_SET);
|
||||
zip->offset = zip->central_directory_offset;
|
||||
__archive_rb_tree_init(&zip->tree, &rb_ops);
|
||||
__archive_rb_tree_init(&zip->tree_rsrc, &rb_rsrc_ops);
|
||||
|
||||
zip->zip_entries = calloc(zip->central_directory_entries,
|
||||
sizeof(struct zip_entry));
|
||||
@ -314,7 +440,7 @@ slurp_central_directory(struct archive_read *a, struct zip *zip)
|
||||
struct zip_entry *zip_entry = &zip->zip_entries[i];
|
||||
size_t filename_length, extra_length, comment_length;
|
||||
uint32_t external_attributes;
|
||||
const char *p;
|
||||
const char *name, *p, *r;
|
||||
|
||||
if ((p = __archive_read_ahead(a, 46, NULL)) == NULL)
|
||||
return ARCHIVE_FATAL;
|
||||
@ -339,7 +465,8 @@ slurp_central_directory(struct archive_read *a, struct zip *zip)
|
||||
/* disk_start = archive_le16dec(p + 34); */ /* Better be zero. */
|
||||
/* internal_attributes = archive_le16dec(p + 36); */ /* text bit */
|
||||
external_attributes = archive_le32dec(p + 38);
|
||||
zip_entry->local_header_offset = archive_le32dec(p + 42);
|
||||
zip_entry->local_header_offset =
|
||||
archive_le32dec(p + 42) + correction;
|
||||
|
||||
/* If we can't guess the mode, leave it zero here;
|
||||
when we read the local file header we might get
|
||||
@ -348,8 +475,50 @@ slurp_central_directory(struct archive_read *a, struct zip *zip)
|
||||
if (zip_entry->system == 3) {
|
||||
zip_entry->mode = external_attributes >> 16;
|
||||
}
|
||||
/* Register an entry to RB tree to sort it by file offset. */
|
||||
__archive_rb_tree_insert_node(&zip->tree, &zip_entry->node);
|
||||
|
||||
/*
|
||||
* Mac resource fork files are stored under the
|
||||
* "__MACOSX/" directory, so we should check if
|
||||
* it is.
|
||||
*/
|
||||
/* Make sure we have the file name. */
|
||||
if ((p = __archive_read_ahead(a, 46 + filename_length, NULL))
|
||||
== NULL)
|
||||
return ARCHIVE_FATAL;
|
||||
name = p + 46;
|
||||
r = rsrc_basename(name, filename_length);
|
||||
if (filename_length >= 9 &&
|
||||
strncmp("__MACOSX/", name, 9) == 0) {
|
||||
/* If this file is not a resource fork nor
|
||||
* a directory. We should treat it as a non
|
||||
* resource fork file to expose it. */
|
||||
if (name[filename_length-1] != '/' &&
|
||||
(r - name < 3 || r[0] != '.' || r[1] != '_')) {
|
||||
__archive_rb_tree_insert_node(&zip->tree,
|
||||
&zip_entry->node);
|
||||
/* Expose its parent directories. */
|
||||
expose_parent_dirs(zip, name, filename_length);
|
||||
} else {
|
||||
/* This file is a resource fork file or
|
||||
* a directory. */
|
||||
archive_strncpy(&(zip_entry->rsrcname), name,
|
||||
filename_length);
|
||||
__archive_rb_tree_insert_node(&zip->tree_rsrc,
|
||||
&zip_entry->node);
|
||||
}
|
||||
} else {
|
||||
/* Generate resource fork name to find its resource
|
||||
* file at zip->tree_rsrc. */
|
||||
archive_strcpy(&(zip_entry->rsrcname), "__MACOSX/");
|
||||
archive_strncat(&(zip_entry->rsrcname), name, r - name);
|
||||
archive_strcat(&(zip_entry->rsrcname), "._");
|
||||
archive_strncat(&(zip_entry->rsrcname),
|
||||
name + (r - name), filename_length - (r - name));
|
||||
/* Register an entry to RB tree to sort it by
|
||||
* file offset. */
|
||||
__archive_rb_tree_insert_node(&zip->tree,
|
||||
&zip_entry->node);
|
||||
}
|
||||
|
||||
/* We don't read the filename until we get to the
|
||||
local file header. Reading it here would speed up
|
||||
@ -378,11 +547,150 @@ zip_read_consume(struct archive_read *a, int64_t bytes)
|
||||
return (skip);
|
||||
}
|
||||
|
||||
static int
|
||||
zip_read_mac_metadata(struct archive_read *a, struct archive_entry *entry,
|
||||
struct zip_entry *rsrc)
|
||||
{
|
||||
struct zip *zip = (struct zip *)a->format->data;
|
||||
unsigned char *metadata, *mp;
|
||||
int64_t offset = zip->offset;
|
||||
size_t remaining_bytes, metadata_bytes;
|
||||
ssize_t hsize;
|
||||
int ret = ARCHIVE_OK, eof;
|
||||
|
||||
switch(rsrc->compression) {
|
||||
case 0: /* No compression. */
|
||||
#ifdef HAVE_ZLIB_H
|
||||
case 8: /* Deflate compression. */
|
||||
#endif
|
||||
break;
|
||||
default: /* Unsupported compression. */
|
||||
/* Return a warning. */
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Unsupported ZIP compression method (%s)",
|
||||
compression_name(rsrc->compression));
|
||||
/* We can't decompress this entry, but we will
|
||||
* be able to skip() it and try the next entry. */
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
if (rsrc->uncompressed_size > (128 * 1024)) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Mac metadata is too large: %jd > 128K bytes",
|
||||
(intmax_t)rsrc->uncompressed_size);
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
metadata = malloc((size_t)rsrc->uncompressed_size);
|
||||
if (metadata == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate memory for Mac metadata");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
if (zip->offset < rsrc->local_header_offset)
|
||||
zip_read_consume(a, rsrc->local_header_offset - zip->offset);
|
||||
else if (zip->offset != rsrc->local_header_offset) {
|
||||
__archive_read_seek(a, rsrc->local_header_offset, SEEK_SET);
|
||||
zip->offset = zip->entry->local_header_offset;
|
||||
}
|
||||
|
||||
hsize = zip_get_local_file_header_size(a, 0);
|
||||
zip_read_consume(a, hsize);
|
||||
|
||||
remaining_bytes = (size_t)rsrc->compressed_size;
|
||||
metadata_bytes = (size_t)rsrc->uncompressed_size;
|
||||
mp = metadata;
|
||||
eof = 0;
|
||||
while (!eof && remaining_bytes) {
|
||||
const unsigned char *p;
|
||||
ssize_t bytes_avail;
|
||||
size_t bytes_used;
|
||||
|
||||
p = __archive_read_ahead(a, 1, &bytes_avail);
|
||||
if (p == NULL) {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Truncated ZIP file header");
|
||||
ret = ARCHIVE_WARN;
|
||||
goto exit_mac_metadata;
|
||||
}
|
||||
if ((size_t)bytes_avail > remaining_bytes)
|
||||
bytes_avail = remaining_bytes;
|
||||
switch(rsrc->compression) {
|
||||
case 0: /* No compression. */
|
||||
memcpy(mp, p, bytes_avail);
|
||||
bytes_used = (size_t)bytes_avail;
|
||||
metadata_bytes -= bytes_used;
|
||||
mp += bytes_used;
|
||||
if (metadata_bytes == 0)
|
||||
eof = 1;
|
||||
break;
|
||||
#ifdef HAVE_ZLIB_H
|
||||
case 8: /* Deflate compression. */
|
||||
{
|
||||
int r;
|
||||
|
||||
ret = zip_deflate_init(a, zip);
|
||||
if (ret != ARCHIVE_OK)
|
||||
goto exit_mac_metadata;
|
||||
zip->stream.next_in =
|
||||
(Bytef *)(uintptr_t)(const void *)p;
|
||||
zip->stream.avail_in = (uInt)bytes_avail;
|
||||
zip->stream.total_in = 0;
|
||||
zip->stream.next_out = mp;
|
||||
zip->stream.avail_out = (uInt)metadata_bytes;
|
||||
zip->stream.total_out = 0;
|
||||
|
||||
r = inflate(&zip->stream, 0);
|
||||
switch (r) {
|
||||
case Z_OK:
|
||||
break;
|
||||
case Z_STREAM_END:
|
||||
eof = 1;
|
||||
break;
|
||||
case Z_MEM_ERROR:
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Out of memory for ZIP decompression");
|
||||
ret = ARCHIVE_FATAL;
|
||||
goto exit_mac_metadata;
|
||||
default:
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"ZIP decompression failed (%d)", r);
|
||||
ret = ARCHIVE_FATAL;
|
||||
goto exit_mac_metadata;
|
||||
}
|
||||
bytes_used = zip->stream.total_in;
|
||||
metadata_bytes -= zip->stream.total_out;
|
||||
mp += zip->stream.total_out;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
bytes_used = 0;
|
||||
break;
|
||||
}
|
||||
zip_read_consume(a, bytes_used);
|
||||
remaining_bytes -= bytes_used;
|
||||
}
|
||||
archive_entry_copy_mac_metadata(entry, metadata,
|
||||
(size_t)rsrc->uncompressed_size - metadata_bytes);
|
||||
|
||||
__archive_read_seek(a, offset, SEEK_SET);
|
||||
zip->offset = offset;
|
||||
exit_mac_metadata:
|
||||
zip->decompress_init = 0;
|
||||
free(metadata);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_zip_seekable_read_header(struct archive_read *a,
|
||||
struct archive_entry *entry)
|
||||
{
|
||||
struct zip *zip = (struct zip *)a->format->data;
|
||||
struct zip_entry *rsrc;
|
||||
int r, ret = ARCHIVE_OK;
|
||||
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_ZIP;
|
||||
@ -408,7 +716,19 @@ archive_read_format_zip_seekable_read_header(struct archive_read *a,
|
||||
return ARCHIVE_EOF;
|
||||
--zip->entries_remaining;
|
||||
|
||||
if (zip->offset != zip->entry->local_header_offset) {
|
||||
if (zip->entry->rsrcname.s)
|
||||
rsrc = (struct zip_entry *)__archive_rb_tree_find_node(
|
||||
&zip->tree_rsrc, zip->entry->rsrcname.s);
|
||||
else
|
||||
rsrc = NULL;
|
||||
|
||||
/* File entries are sorted by the header offset, we should mostly
|
||||
* use zip_read_consume to advance a read point to avoid redundant
|
||||
* data reading. */
|
||||
if (zip->offset < zip->entry->local_header_offset)
|
||||
zip_read_consume(a,
|
||||
zip->entry->local_header_offset - zip->offset);
|
||||
else if (zip->offset != zip->entry->local_header_offset) {
|
||||
__archive_read_seek(a, zip->entry->local_header_offset,
|
||||
SEEK_SET);
|
||||
zip->offset = zip->entry->local_header_offset;
|
||||
@ -463,6 +783,11 @@ archive_read_format_zip_seekable_read_header(struct archive_read *a,
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rsrc) {
|
||||
int ret2 = zip_read_mac_metadata(a, entry, rsrc);
|
||||
if (ret2 < ret)
|
||||
ret = ret2;
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
@ -513,7 +838,8 @@ archive_read_format_zip_options(struct archive_read *a,
|
||||
} else if (strcmp(key, "hdrcharset") == 0) {
|
||||
if (val == NULL || val[0] == 0)
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"zip: hdrcharset option needs a character-set name");
|
||||
"zip: hdrcharset option needs a character-set name"
|
||||
);
|
||||
else {
|
||||
zip->sconv = archive_string_conversion_from_charset(
|
||||
&a->archive, val, 0);
|
||||
@ -549,7 +875,8 @@ archive_read_format_zip_streamable_read_header(struct archive_read *a,
|
||||
if (zip->zip_entries == NULL) {
|
||||
zip->zip_entries = malloc(sizeof(struct zip_entry));
|
||||
if (zip->zip_entries == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM, "Out of memory");
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Out of memory");
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
}
|
||||
@ -578,7 +905,8 @@ archive_read_format_zip_streamable_read_header(struct archive_read *a,
|
||||
if (p[2] == '\003' && p[3] == '\004') {
|
||||
/* Regular file entry. */
|
||||
zip_read_consume(a, skipped);
|
||||
return zip_read_local_file_header(a, entry, zip);
|
||||
return zip_read_local_file_header(a,
|
||||
entry, zip);
|
||||
}
|
||||
|
||||
if (p[2] == '\005' && p[3] == '\006')
|
||||
@ -592,6 +920,29 @@ archive_read_format_zip_streamable_read_header(struct archive_read *a,
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
zip_get_local_file_header_size(struct archive_read *a, size_t extra)
|
||||
{
|
||||
const char *p;
|
||||
ssize_t filename_length, extra_length;
|
||||
|
||||
if ((p = __archive_read_ahead(a, extra + 30, NULL)) == NULL) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Truncated ZIP file header");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
p += extra;
|
||||
|
||||
if (memcmp(p, "PK\003\004", 4) != 0) {
|
||||
archive_set_error(&a->archive, -1, "Damaged Zip archive");
|
||||
return ARCHIVE_WARN;
|
||||
}
|
||||
filename_length = archive_le16dec(p + 26);
|
||||
extra_length = archive_le16dec(p + 28);
|
||||
|
||||
return (30 + filename_length + extra_length);
|
||||
}
|
||||
|
||||
/*
|
||||
* Assumes file pointer is at beginning of local file header.
|
||||
*/
|
||||
@ -648,8 +999,8 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
|
||||
zip_read_consume(a, 30);
|
||||
|
||||
if (zip->have_central_directory) {
|
||||
/* If we read the central dir entry, we must have size information
|
||||
as well, so ignore the length-at-end flag. */
|
||||
/* If we read the central dir entry, we must have size
|
||||
* information as well, so ignore the length-at-end flag. */
|
||||
zip_entry->flags &= ~ZIP_LENGTH_AT_END;
|
||||
/* If we have values from both the local file header
|
||||
and the central directory, warn about mismatches
|
||||
@ -657,19 +1008,22 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
|
||||
writers always put zero in the local header; don't
|
||||
bother warning about that. */
|
||||
if (local_crc32 != 0 && local_crc32 != zip_entry->crc32) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Inconsistent CRC32 values");
|
||||
ret = ARCHIVE_WARN;
|
||||
}
|
||||
if (compressed_size != 0
|
||||
&& compressed_size != zip_entry->compressed_size) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Inconsistent compressed size");
|
||||
ret = ARCHIVE_WARN;
|
||||
}
|
||||
if (uncompressed_size != 0
|
||||
&& uncompressed_size != zip_entry->uncompressed_size) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Inconsistent uncompressed size");
|
||||
ret = ARCHIVE_WARN;
|
||||
}
|
||||
@ -868,13 +1222,16 @@ archive_read_format_zip_read_data(struct archive_read *a,
|
||||
return (r);
|
||||
/* Update checksum */
|
||||
if (*size)
|
||||
zip->entry_crc32 = crc32(zip->entry_crc32, *buff, *size);
|
||||
zip->entry_crc32 = crc32(zip->entry_crc32, *buff,
|
||||
(unsigned)*size);
|
||||
/* If we hit the end, swallow any end-of-data marker. */
|
||||
if (zip->end_of_entry) {
|
||||
/* Check file size, CRC against these values. */
|
||||
if (zip->entry->compressed_size != zip->entry_compressed_bytes_read) {
|
||||
if (zip->entry->compressed_size !=
|
||||
zip->entry_compressed_bytes_read) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"ZIP compressed data is wrong size (read %jd, expected %jd)",
|
||||
"ZIP compressed data is wrong size "
|
||||
"(read %jd, expected %jd)",
|
||||
(intmax_t)zip->entry_compressed_bytes_read,
|
||||
(intmax_t)zip->entry->compressed_size);
|
||||
return (ARCHIVE_WARN);
|
||||
@ -884,7 +1241,8 @@ archive_read_format_zip_read_data(struct archive_read *a,
|
||||
if ((zip->entry->uncompressed_size & UINT32_MAX)
|
||||
!= (zip->entry_uncompressed_bytes_read & UINT32_MAX)) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"ZIP uncompressed data is wrong size (read %jd, expected %jd)",
|
||||
"ZIP uncompressed data is wrong size "
|
||||
"(read %jd, expected %jd)",
|
||||
(intmax_t)zip->entry_uncompressed_bytes_read,
|
||||
(intmax_t)zip->entry->uncompressed_size);
|
||||
return (ARCHIVE_WARN);
|
||||
@ -947,7 +1305,8 @@ zip_read_data_none(struct archive_read *a, const void **_buff,
|
||||
that are longer than this, so a failure to get at
|
||||
least 16 bytes really does indicate a truncated
|
||||
file. */
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Truncated ZIP file data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@ -956,8 +1315,10 @@ zip_read_data_none(struct archive_read *a, const void **_buff,
|
||||
if (p[0] == 'P' && p[1] == 'K'
|
||||
&& p[2] == '\007' && p[3] == '\010'
|
||||
&& archive_le32dec(p + 4) == zip->entry_crc32
|
||||
&& archive_le32dec(p + 8) == zip->entry_compressed_bytes_read
|
||||
&& archive_le32dec(p + 12) == zip->entry_uncompressed_bytes_read) {
|
||||
&& archive_le32dec(p + 8) ==
|
||||
zip->entry_compressed_bytes_read
|
||||
&& archive_le32dec(p + 12) ==
|
||||
zip->entry_uncompressed_bytes_read) {
|
||||
zip->entry->crc32 = archive_le32dec(p + 4);
|
||||
zip->entry->compressed_size = archive_le32dec(p + 8);
|
||||
zip->entry->uncompressed_size = archive_le32dec(p + 12);
|
||||
@ -968,9 +1329,10 @@ zip_read_data_none(struct archive_read *a, const void **_buff,
|
||||
/* If not at EOF, ensure we consume at least one byte. */
|
||||
++p;
|
||||
|
||||
/* Scan forward until we see where a PK\007\010 signature might be. */
|
||||
/* Return bytes up until that point. On the next call, the code
|
||||
above will verify the data descriptor. */
|
||||
/* Scan forward until we see where a PK\007\010 signature
|
||||
* might be. */
|
||||
/* Return bytes up until that point. On the next call,
|
||||
* the code above will verify the data descriptor. */
|
||||
while (p < buff + bytes_avail - 4) {
|
||||
if (p[3] == 'P') { p += 3; }
|
||||
else if (p[3] == 'K') { p += 2; }
|
||||
@ -989,7 +1351,8 @@ zip_read_data_none(struct archive_read *a, const void **_buff,
|
||||
/* Grab a bunch of bytes. */
|
||||
buff = __archive_read_ahead(a, 1, &bytes_avail);
|
||||
if (bytes_avail <= 0) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Truncated ZIP file data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@ -1006,6 +1369,31 @@ zip_read_data_none(struct archive_read *a, const void **_buff,
|
||||
}
|
||||
|
||||
#ifdef HAVE_ZLIB_H
|
||||
static int
|
||||
zip_deflate_init(struct archive_read *a, struct zip *zip)
|
||||
{
|
||||
int r;
|
||||
|
||||
/* If we haven't yet read any data, initialize the decompressor. */
|
||||
if (!zip->decompress_init) {
|
||||
if (zip->stream_valid)
|
||||
r = inflateReset(&zip->stream);
|
||||
else
|
||||
r = inflateInit2(&zip->stream,
|
||||
-15 /* Don't check for zlib header */);
|
||||
if (r != Z_OK) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Can't initialize ZIP decompression.");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
/* Stream structure has been set up. */
|
||||
zip->stream_valid = 1;
|
||||
/* We've initialized decompression for this stream. */
|
||||
zip->decompress_init = 1;
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
zip_read_data_deflate(struct archive_read *a, const void **buff,
|
||||
size_t *size, int64_t *offset)
|
||||
@ -1031,23 +1419,9 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
|
||||
}
|
||||
}
|
||||
|
||||
/* If we haven't yet read any data, initialize the decompressor. */
|
||||
if (!zip->decompress_init) {
|
||||
if (zip->stream_valid)
|
||||
r = inflateReset(&zip->stream);
|
||||
else
|
||||
r = inflateInit2(&zip->stream,
|
||||
-15 /* Don't check for zlib header */);
|
||||
if (r != Z_OK) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Can't initialize ZIP decompression.");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
/* Stream structure has been set up. */
|
||||
zip->stream_valid = 1;
|
||||
/* We've initialized decompression for this stream. */
|
||||
zip->decompress_init = 1;
|
||||
}
|
||||
r = zip_deflate_init(a, zip);
|
||||
if (r != ARCHIVE_OK)
|
||||
return (r);
|
||||
|
||||
/*
|
||||
* Note: '1' here is a performance optimization.
|
||||
@ -1073,10 +1447,10 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
|
||||
* cast to remove 'const'.
|
||||
*/
|
||||
zip->stream.next_in = (Bytef *)(uintptr_t)(const void *)compressed_buff;
|
||||
zip->stream.avail_in = bytes_avail;
|
||||
zip->stream.avail_in = (uInt)bytes_avail;
|
||||
zip->stream.total_in = 0;
|
||||
zip->stream.next_out = zip->uncompressed_buffer;
|
||||
zip->stream.avail_out = zip->uncompressed_buffer_size;
|
||||
zip->stream.avail_out = (uInt)zip->uncompressed_buffer_size;
|
||||
zip->stream.total_out = 0;
|
||||
|
||||
r = inflate(&zip->stream, 0);
|
||||
@ -1116,7 +1490,8 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
/* Consume the optional PK\007\010 marker. */
|
||||
if (p[0] == 'P' && p[1] == 'K' && p[2] == '\007' && p[3] == '\010') {
|
||||
if (p[0] == 'P' && p[1] == 'K' &&
|
||||
p[2] == '\007' && p[3] == '\010') {
|
||||
zip->entry->crc32 = archive_le32dec(p + 4);
|
||||
zip->entry->compressed_size = archive_le32dec(p + 8);
|
||||
zip->entry->uncompressed_size = archive_le32dec(p + 12);
|
||||
@ -1176,7 +1551,8 @@ archive_read_format_zip_read_data_skip(struct archive_read *a)
|
||||
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,
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Truncated ZIP file data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@ -1206,6 +1582,11 @@ archive_read_format_zip_cleanup(struct archive_read *a)
|
||||
if (zip->stream_valid)
|
||||
inflateEnd(&zip->stream);
|
||||
#endif
|
||||
if (zip->zip_entries && zip->central_directory_entries) {
|
||||
unsigned i;
|
||||
for (i = 0; i < zip->central_directory_entries; i++)
|
||||
archive_string_free(&(zip->zip_entries[i].rsrcname));
|
||||
}
|
||||
free(zip->zip_entries);
|
||||
free(zip->uncompressed_buffer);
|
||||
archive_string_free(&(zip->extra));
|
||||
@ -1288,11 +1669,14 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
|
||||
/* Info-ZIP Unix Extra Field (old version) "UX". */
|
||||
if (datasize >= 8) {
|
||||
zip_entry->atime = archive_le32dec(p + offset);
|
||||
zip_entry->mtime = archive_le32dec(p + offset + 4);
|
||||
zip_entry->mtime =
|
||||
archive_le32dec(p + offset + 4);
|
||||
}
|
||||
if (datasize >= 12) {
|
||||
zip_entry->uid = archive_le16dec(p + offset + 8);
|
||||
zip_entry->gid = archive_le16dec(p + offset + 10);
|
||||
zip_entry->uid =
|
||||
archive_le16dec(p + offset + 8);
|
||||
zip_entry->gid =
|
||||
archive_le16dec(p + offset + 10);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1306,7 +1690,8 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
|
||||
if (datasize >= 2)
|
||||
zip_entry->uid = archive_le16dec(p + offset);
|
||||
if (datasize >= 4)
|
||||
zip_entry->gid = archive_le16dec(p + offset + 2);
|
||||
zip_entry->gid =
|
||||
archive_le16dec(p + offset + 2);
|
||||
break;
|
||||
case 0x7875:
|
||||
{
|
||||
@ -1318,22 +1703,26 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
|
||||
/* get a uid size. */
|
||||
uidsize = p[offset+1];
|
||||
if (uidsize == 2)
|
||||
zip_entry->uid = archive_le16dec(
|
||||
p + offset + 2);
|
||||
zip_entry->uid =
|
||||
archive_le16dec(
|
||||
p + offset + 2);
|
||||
else if (uidsize == 4 && datasize >= 6)
|
||||
zip_entry->uid = archive_le32dec(
|
||||
p + offset + 2);
|
||||
zip_entry->uid =
|
||||
archive_le32dec(
|
||||
p + offset + 2);
|
||||
}
|
||||
if (datasize >= (2 + uidsize + 3)) {
|
||||
/* get a gid size. */
|
||||
gidsize = p[offset+2+uidsize];
|
||||
if (gidsize == 2)
|
||||
zip_entry->gid = archive_le16dec(
|
||||
p+offset+2+uidsize+1);
|
||||
zip_entry->gid =
|
||||
archive_le16dec(
|
||||
p+offset+2+uidsize+1);
|
||||
else if (gidsize == 4 &&
|
||||
datasize >= (2 + uidsize + 5))
|
||||
zip_entry->gid = archive_le32dec(
|
||||
p+offset+2+uidsize+1);
|
||||
zip_entry->gid =
|
||||
archive_le32dec(
|
||||
p+offset+2+uidsize+1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -486,13 +486,13 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
|
||||
* UTF-16BE/LE NFD ===> UTF-16 NFC
|
||||
* UTF-16BE/LE NFC ===> UTF-16 NFD
|
||||
*/
|
||||
count = utf16nbytes(s, length);
|
||||
count = (int)utf16nbytes(s, length);
|
||||
} else {
|
||||
/*
|
||||
* UTF-8 NFD ===> UTF-16 NFC
|
||||
* UTF-8 NFC ===> UTF-16 NFD
|
||||
*/
|
||||
count = mbsnbytes(s, length);
|
||||
count = (int)mbsnbytes(s, length);
|
||||
}
|
||||
u16.s = (char *)dest->s;
|
||||
u16.length = dest->length << 1;;
|
||||
@ -507,7 +507,7 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
|
||||
sc->flag = saved_flag;/* restore the saved flag. */
|
||||
return (ret);
|
||||
} else if (sc != NULL && (sc->flag & SCONV_FROM_UTF16)) {
|
||||
count = utf16nbytes(s, length);
|
||||
count = (int)utf16nbytes(s, length);
|
||||
count >>= 1; /* to be WCS length */
|
||||
/* Allocate memory for WCS. */
|
||||
if (NULL == archive_wstring_ensure(dest,
|
||||
@ -550,8 +550,8 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
|
||||
return (-1);
|
||||
/* Convert MBS to WCS. */
|
||||
count = MultiByteToWideChar(from_cp,
|
||||
mbflag, s, length, dest->s + dest->length,
|
||||
(dest->buffer_length >> 1) -1);
|
||||
mbflag, s, (int)length, dest->s + dest->length,
|
||||
(int)(dest->buffer_length >> 1) -1);
|
||||
if (count == 0 &&
|
||||
GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
||||
/* Expand the WCS buffer. */
|
||||
@ -727,7 +727,7 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as,
|
||||
else
|
||||
dp = &defchar_used;
|
||||
count = WideCharToMultiByte(to_cp, 0, ws, wslen,
|
||||
as->s + as->length, as->buffer_length-1, NULL, dp);
|
||||
as->s + as->length, (int)as->buffer_length-1, NULL, dp);
|
||||
if (count == 0 &&
|
||||
GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
||||
/* Expand the MBS buffer and retry. */
|
||||
@ -1120,8 +1120,8 @@ create_sconv_object(const char *fc, const char *tc,
|
||||
}
|
||||
sc->to_charset = strdup(tc);
|
||||
if (sc->to_charset == NULL) {
|
||||
free(sc);
|
||||
free(sc->from_charset);
|
||||
free(sc);
|
||||
return (NULL);
|
||||
}
|
||||
archive_string_init(&sc->utftmp);
|
||||
@ -1997,7 +1997,7 @@ static int
|
||||
iconv_strncat_in_locale(struct archive_string *as, const void *_p,
|
||||
size_t length, struct archive_string_conv *sc)
|
||||
{
|
||||
ICONV_CONST char *inp;
|
||||
ICONV_CONST char *itp;
|
||||
size_t remaining;
|
||||
iconv_t cd;
|
||||
char *outp;
|
||||
@ -2018,12 +2018,12 @@ iconv_strncat_in_locale(struct archive_string *as, const void *_p,
|
||||
return (-1);
|
||||
|
||||
cd = sc->cd;
|
||||
inp = (char *)(uintptr_t)_p;
|
||||
itp = (char *)(uintptr_t)_p;
|
||||
remaining = length;
|
||||
outp = as->s + as->length;
|
||||
avail = as->buffer_length - as->length - to_size;
|
||||
while (remaining >= (size_t)from_size) {
|
||||
size_t result = iconv(cd, &inp, &remaining, &outp, &avail);
|
||||
size_t result = iconv(cd, &itp, &remaining, &outp, &avail);
|
||||
|
||||
if (result != (size_t)-1)
|
||||
break; /* Conversion completed. */
|
||||
@ -2065,7 +2065,7 @@ iconv_strncat_in_locale(struct archive_string *as, const void *_p,
|
||||
*outp++ = '?';
|
||||
avail--;
|
||||
}
|
||||
inp += from_size;
|
||||
itp += from_size;
|
||||
remaining -= from_size;
|
||||
return_value = -1; /* failure */
|
||||
} else {
|
||||
@ -2145,7 +2145,7 @@ invalid_mbs(const void *_p, size_t n, struct archive_string_conv *sc)
|
||||
if (codepage != CP_UTF8)
|
||||
mbflag |= MB_PRECOMPOSED;
|
||||
|
||||
if (MultiByteToWideChar(codepage, mbflag, p, n, NULL, 0) == 0)
|
||||
if (MultiByteToWideChar(codepage, mbflag, p, (int)n, NULL, 0) == 0)
|
||||
return (-1); /* Invalid */
|
||||
return (0); /* Okay */
|
||||
}
|
||||
@ -2202,8 +2202,8 @@ best_effort_strncat_in_locale(struct archive_string *as, const void *_p,
|
||||
size_t length, struct archive_string_conv *sc)
|
||||
{
|
||||
size_t remaining;
|
||||
char *outp;
|
||||
const uint8_t *inp;
|
||||
char *otp;
|
||||
const uint8_t *itp;
|
||||
size_t avail;
|
||||
int return_value = 0; /* success */
|
||||
|
||||
@ -2227,41 +2227,41 @@ best_effort_strncat_in_locale(struct archive_string *as, const void *_p,
|
||||
return (-1);
|
||||
|
||||
remaining = length;
|
||||
inp = (const uint8_t *)_p;
|
||||
outp = as->s + as->length;
|
||||
itp = (const uint8_t *)_p;
|
||||
otp = as->s + as->length;
|
||||
avail = as->buffer_length - as->length -1;
|
||||
while (*inp && remaining > 0) {
|
||||
if (*inp > 127 && (sc->flag & SCONV_TO_UTF8)) {
|
||||
while (*itp && remaining > 0) {
|
||||
if (*itp > 127 && (sc->flag & SCONV_TO_UTF8)) {
|
||||
if (avail < UTF8_R_CHAR_SIZE) {
|
||||
as->length = outp - as->s;
|
||||
as->length = otp - as->s;
|
||||
if (NULL == archive_string_ensure(as,
|
||||
as->buffer_length + remaining +
|
||||
UTF8_R_CHAR_SIZE))
|
||||
return (-1);
|
||||
outp = as->s + as->length;
|
||||
otp = as->s + as->length;
|
||||
avail = as->buffer_length - as->length -1;
|
||||
}
|
||||
/*
|
||||
* When coping a string in UTF-8, unknown character
|
||||
* should be U+FFFD (replacement character).
|
||||
*/
|
||||
UTF8_SET_R_CHAR(outp);
|
||||
outp += UTF8_R_CHAR_SIZE;
|
||||
UTF8_SET_R_CHAR(otp);
|
||||
otp += UTF8_R_CHAR_SIZE;
|
||||
avail -= UTF8_R_CHAR_SIZE;
|
||||
inp++;
|
||||
itp++;
|
||||
remaining--;
|
||||
return_value = -1;
|
||||
} else if (*inp > 127) {
|
||||
*outp++ = '?';
|
||||
inp++;
|
||||
} else if (*itp > 127) {
|
||||
*otp++ = '?';
|
||||
itp++;
|
||||
remaining--;
|
||||
return_value = -1;
|
||||
} else {
|
||||
*outp++ = (char)*inp++;
|
||||
*otp++ = (char)*itp++;
|
||||
remaining--;
|
||||
}
|
||||
}
|
||||
as->length = outp - as->s;
|
||||
as->length = otp - as->s;
|
||||
as->s[as->length] = '\0';
|
||||
return (return_value);
|
||||
}
|
||||
@ -2322,7 +2322,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
|
||||
|
||||
/* Invalide sequence or there are not plenty bytes. */
|
||||
if ((int)n < cnt) {
|
||||
cnt = n;
|
||||
cnt = (int)n;
|
||||
for (i = 1; i < cnt; i++) {
|
||||
if ((s[i] & 0xc0) != 0x80) {
|
||||
cnt = i;
|
||||
@ -2391,7 +2391,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
|
||||
else
|
||||
cnt = 1;
|
||||
if ((int)n < cnt)
|
||||
cnt = n;
|
||||
cnt = (int)n;
|
||||
for (i = 1; i < cnt; i++) {
|
||||
if ((s[i] & 0xc0) != 0x80) {
|
||||
cnt = i;
|
||||
@ -2447,11 +2447,12 @@ combine_surrogate_pair(uint32_t uc, uint32_t uc2)
|
||||
static int
|
||||
cesu8_to_unicode(uint32_t *pwc, const char *s, size_t n)
|
||||
{
|
||||
uint32_t wc, wc2;
|
||||
uint32_t wc = 0;
|
||||
int cnt;
|
||||
|
||||
cnt = _utf8_to_unicode(&wc, s, n);
|
||||
if (cnt == 3 && IS_HIGH_SURROGATE_LA(wc)) {
|
||||
uint32_t wc2 = 0;
|
||||
if (n - 3 < 3) {
|
||||
/* Invalid byte sequence. */
|
||||
goto invalid_sequence;
|
||||
@ -3396,7 +3397,6 @@ archive_string_normalize_D(struct archive_string *as, const void *_p,
|
||||
break;
|
||||
REPLACE_UC_WITH(uc2);
|
||||
n = n2;
|
||||
ucptr = s;
|
||||
goto check_first_code;
|
||||
}
|
||||
as->length = p - as->s;
|
||||
@ -3478,9 +3478,9 @@ strncat_from_utf8_libarchive2(struct archive_string *as,
|
||||
* Translates the wide-character into the current locale MBS.
|
||||
*/
|
||||
#if HAVE_WCRTOMB
|
||||
n = wcrtomb(p, wc, &shift_state);
|
||||
n = (int)wcrtomb(p, wc, &shift_state);
|
||||
#else
|
||||
n = wctomb(p, wc);
|
||||
n = (int)wctomb(p, wc);
|
||||
#endif
|
||||
if (n == -1)
|
||||
return (-1);
|
||||
@ -3579,13 +3579,13 @@ win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes,
|
||||
do {
|
||||
defchar = 0;
|
||||
ll = WideCharToMultiByte(sc->to_cp, 0,
|
||||
(LPCWSTR)u16, bytes>>1, mbs, mbs_size,
|
||||
(LPCWSTR)u16, (int)bytes>>1, mbs, (int)mbs_size,
|
||||
NULL, &defchar);
|
||||
if (ll == 0 &&
|
||||
GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
||||
/* Need more buffer for MBS. */
|
||||
ll = WideCharToMultiByte(sc->to_cp, 0,
|
||||
(LPCWSTR)u16, bytes, NULL, 0, NULL, NULL);
|
||||
(LPCWSTR)u16, (int)bytes, NULL, 0, NULL, NULL);
|
||||
if (archive_string_ensure(as, ll +1) == NULL)
|
||||
return (-1);
|
||||
mbs = as->s + as->length;
|
||||
@ -3662,12 +3662,12 @@ win_strncat_to_utf16(struct archive_string *as16, const void *_p,
|
||||
}
|
||||
do {
|
||||
count = MultiByteToWideChar(sc->from_cp,
|
||||
MB_PRECOMPOSED, s, length, (LPWSTR)u16, (int)avail>>1);
|
||||
MB_PRECOMPOSED, s, (int)length, (LPWSTR)u16, (int)avail>>1);
|
||||
if (count == 0 &&
|
||||
GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
||||
/* Need more buffer for UTF-16 string */
|
||||
count = MultiByteToWideChar(sc->from_cp,
|
||||
MB_PRECOMPOSED, s, length, NULL, 0);
|
||||
MB_PRECOMPOSED, s, (int)length, NULL, 0);
|
||||
if (archive_string_ensure(as16, (count +1) * 2)
|
||||
== NULL)
|
||||
return (-1);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2009,2010 Michihiro NAKAJIMA
|
||||
* Copyright (c) 2009-2012 Michihiro NAKAJIMA
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -50,6 +50,10 @@ __FBSDID("$FreeBSD$");
|
||||
#include "archive_private.h"
|
||||
#include "archive_string.h"
|
||||
|
||||
#ifndef O_CLOEXEC
|
||||
#define O_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
/* Generic initialization of 'struct archive' objects. */
|
||||
int
|
||||
__archive_clean(struct archive *a)
|
||||
@ -239,7 +243,7 @@ __archive_mktemp(const char *tmpdir)
|
||||
errno = ENOMEM;
|
||||
goto exit_tmpfile;
|
||||
}
|
||||
GetTempPathW(l, tmp);
|
||||
GetTempPathW((DWORD)l, tmp);
|
||||
archive_wstrcpy(&temp_name, tmp);
|
||||
free(tmp);
|
||||
} else {
|
||||
@ -293,7 +297,8 @@ __archive_mktemp(const char *tmpdir)
|
||||
|
||||
/* Generate a random file name through CryptGenRandom(). */
|
||||
p = xp;
|
||||
if (!CryptGenRandom(hProv, (ep - p)*sizeof(wchar_t), (BYTE*)p)) {
|
||||
if (!CryptGenRandom(hProv, (DWORD)(ep - p)*sizeof(wchar_t),
|
||||
(BYTE*)p)) {
|
||||
la_dosmaperr(GetLastError());
|
||||
goto exit_tmpfile;
|
||||
}
|
||||
@ -385,6 +390,7 @@ __archive_mktemp(const char *tmpdir)
|
||||
fd = mkstemp(temp_name.s);
|
||||
if (fd < 0)
|
||||
goto exit_tmpfile;
|
||||
__archive_ensure_cloexec_flag(fd);
|
||||
unlink(temp_name.s);
|
||||
exit_tmpfile:
|
||||
archive_string_free(&temp_name);
|
||||
@ -438,7 +444,8 @@ __archive_mktemp(const char *tmpdir)
|
||||
archive_strcat(&temp_name, "XXXXXXXXXX");
|
||||
ep = temp_name.s + archive_strlen(&temp_name);
|
||||
|
||||
fd = open("/dev/random", O_RDONLY);
|
||||
fd = open("/dev/random", O_RDONLY | O_CLOEXEC);
|
||||
__archive_ensure_cloexec_flag(fd);
|
||||
if (fd < 0)
|
||||
seed = time(NULL);
|
||||
else {
|
||||
@ -452,10 +459,12 @@ __archive_mktemp(const char *tmpdir)
|
||||
p = tp;
|
||||
while (p < ep)
|
||||
*p++ = num[((unsigned)rand_r(&seed)) % sizeof(num)];
|
||||
fd = open(temp_name.s, O_CREAT | O_EXCL | O_RDWR, 0600);
|
||||
fd = open(temp_name.s, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC,
|
||||
0600);
|
||||
} while (fd < 0 && errno == EEXIST);
|
||||
if (fd < 0)
|
||||
goto exit_tmpfile;
|
||||
__archive_ensure_cloexec_flag(fd);
|
||||
unlink(temp_name.s);
|
||||
exit_tmpfile:
|
||||
archive_string_free(&temp_name);
|
||||
@ -464,3 +473,29 @@ __archive_mktemp(const char *tmpdir)
|
||||
|
||||
#endif /* HAVE_MKSTEMP */
|
||||
#endif /* !_WIN32 || __CYGWIN__ */
|
||||
|
||||
/*
|
||||
* Set FD_CLOEXEC flag to a file descriptor if it is not set.
|
||||
* We have to set the flag if the platform does not provide O_CLOEXEC
|
||||
* or F_DUPFD_CLOEXEC flags.
|
||||
*
|
||||
* Note: This function is absolutely called after creating a new file
|
||||
* descriptor even if the platform seemingly provides O_CLOEXEC or
|
||||
* F_DUPFD_CLOEXEC macros because it is possible that the platform
|
||||
* merely declares those macros, especially Linux 2.6.18 - 2.6.24 do it.
|
||||
*/
|
||||
void
|
||||
__archive_ensure_cloexec_flag(int fd)
|
||||
{
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
(void)fd; /* UNSED */
|
||||
#else
|
||||
int flags;
|
||||
|
||||
if (fd >= 0) {
|
||||
flags = fcntl(fd, F_GETFD);
|
||||
if (flags != -1 && (flags & FD_CLOEXEC) == 0)
|
||||
fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -66,6 +66,13 @@ archive_read_close(struct archive *a)
|
||||
return ((a->vtable->archive_close)(a));
|
||||
}
|
||||
|
||||
int
|
||||
archive_write_fail(struct archive *a)
|
||||
{
|
||||
a->state = ARCHIVE_STATE_FATAL;
|
||||
return a->state;
|
||||
}
|
||||
|
||||
int
|
||||
archive_write_free(struct archive *a)
|
||||
{
|
||||
|
@ -232,6 +232,10 @@ __archive_write_filter(struct archive_write_filter *f,
|
||||
int r;
|
||||
if (length == 0)
|
||||
return(ARCHIVE_OK);
|
||||
if (f->write == NULL)
|
||||
/* If unset, a fatal error has already ocuured, so this filter
|
||||
* didn't open. We cannot write anything. */
|
||||
return(ARCHIVE_FATAL);
|
||||
r = (f->write)(f, buff, length);
|
||||
f->bytes_written += length;
|
||||
return (r);
|
||||
@ -437,6 +441,8 @@ archive_write_client_close(struct archive_write_filter *f)
|
||||
(*a->client_closer)(&a->archive, a->client_data);
|
||||
free(state->buffer);
|
||||
free(state);
|
||||
/* Clear the close handler myself not to be called again. */
|
||||
f->close = NULL;
|
||||
a->client_data = NULL;
|
||||
return (ret);
|
||||
}
|
||||
|
@ -45,9 +45,13 @@ struct { int code; int (*setter)(struct archive *); } codes[] =
|
||||
{ ARCHIVE_FILTER_GZIP, archive_write_add_filter_gzip },
|
||||
{ ARCHIVE_FILTER_BZIP2, archive_write_add_filter_bzip2 },
|
||||
{ ARCHIVE_FILTER_COMPRESS, archive_write_add_filter_compress },
|
||||
{ ARCHIVE_FILTER_LZMA, archive_write_add_filter_lzma },
|
||||
{ ARCHIVE_FILTER_XZ, archive_write_add_filter_xz },
|
||||
{ ARCHIVE_FILTER_GRZIP, archive_write_add_filter_grzip },
|
||||
{ ARCHIVE_FILTER_LRZIP, archive_write_add_filter_lrzip },
|
||||
{ ARCHIVE_FILTER_LZIP, archive_write_add_filter_lzip },
|
||||
{ ARCHIVE_FILTER_LZMA, archive_write_add_filter_lzma },
|
||||
{ ARCHIVE_FILTER_LZOP, archive_write_add_filter_lzip },
|
||||
{ ARCHIVE_FILTER_UU, archive_write_add_filter_uuencode },
|
||||
{ ARCHIVE_FILTER_XZ, archive_write_add_filter_xz },
|
||||
{ -1, NULL }
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,314 @@
|
||||
/*-
|
||||
* Copyright (c) 2012 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_string.h"
|
||||
#include "archive_write_private.h"
|
||||
|
||||
#define LBYTES 57
|
||||
|
||||
struct private_b64encode {
|
||||
int mode;
|
||||
struct archive_string name;
|
||||
struct archive_string encoded_buff;
|
||||
size_t bs;
|
||||
size_t hold_len;
|
||||
unsigned char hold[LBYTES];
|
||||
};
|
||||
|
||||
static int archive_filter_b64encode_options(struct archive_write_filter *,
|
||||
const char *, const char *);
|
||||
static int archive_filter_b64encode_open(struct archive_write_filter *);
|
||||
static int archive_filter_b64encode_write(struct archive_write_filter *,
|
||||
const void *, size_t);
|
||||
static int archive_filter_b64encode_close(struct archive_write_filter *);
|
||||
static int archive_filter_b64encode_free(struct archive_write_filter *);
|
||||
static void b64_encode(struct archive_string *, const unsigned char *, size_t);
|
||||
static int64_t atol8(const char *, size_t);
|
||||
|
||||
static const char base64[] = {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
|
||||
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
||||
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
|
||||
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
|
||||
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
|
||||
'w', 'x', 'y', 'z', '0', '1', '2', '3',
|
||||
'4', '5', '6', '7', '8', '9', '+', '/'
|
||||
};
|
||||
|
||||
/*
|
||||
* Add a compress filter to this write handle.
|
||||
*/
|
||||
int
|
||||
archive_write_add_filter_b64encode(struct archive *_a)
|
||||
{
|
||||
struct archive_write *a = (struct archive_write *)_a;
|
||||
struct archive_write_filter *f = __archive_write_allocate_filter(_a);
|
||||
struct private_b64encode *state;
|
||||
|
||||
archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_write_add_filter_uu");
|
||||
|
||||
state = (struct private_b64encode *)calloc(1, sizeof(*state));
|
||||
if (state == NULL) {
|
||||
archive_set_error(f->archive, ENOMEM,
|
||||
"Can't allocate data for b64encode filter");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
archive_strcpy(&state->name, "-");
|
||||
state->mode = 0644;
|
||||
|
||||
f->data = state;
|
||||
f->name = "b64encode";
|
||||
f->code = ARCHIVE_FILTER_UU;
|
||||
f->open = archive_filter_b64encode_open;
|
||||
f->options = archive_filter_b64encode_options;
|
||||
f->write = archive_filter_b64encode_write;
|
||||
f->close = archive_filter_b64encode_close;
|
||||
f->free = archive_filter_b64encode_free;
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set write options.
|
||||
*/
|
||||
static int
|
||||
archive_filter_b64encode_options(struct archive_write_filter *f, const char *key,
|
||||
const char *value)
|
||||
{
|
||||
struct private_b64encode *state = (struct private_b64encode *)f->data;
|
||||
|
||||
if (strcmp(key, "mode") == 0) {
|
||||
if (value == NULL) {
|
||||
archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
|
||||
"mode option requires octal digits");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
state->mode = (int)atol8(value, strlen(value)) & 0777;
|
||||
return (ARCHIVE_OK);
|
||||
} else if (strcmp(key, "name") == 0) {
|
||||
if (value == NULL) {
|
||||
archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
|
||||
"name option requires a string");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
archive_strcpy(&state->name, value);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/* Note: The "warn" return is just to inform the options
|
||||
* supervisor that we didn't handle it. It will generate
|
||||
* a suitable error if no one used this option. */
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup callback.
|
||||
*/
|
||||
static int
|
||||
archive_filter_b64encode_open(struct archive_write_filter *f)
|
||||
{
|
||||
struct private_b64encode *state = (struct private_b64encode *)f->data;
|
||||
size_t bs = 65536, bpb;
|
||||
int ret;
|
||||
|
||||
ret = __archive_write_open_filter(f->next_filter);
|
||||
if (ret != ARCHIVE_OK)
|
||||
return (ret);
|
||||
|
||||
if (f->archive->magic == ARCHIVE_WRITE_MAGIC) {
|
||||
/* Buffer size should be a multiple number of the of bytes
|
||||
* per block for performance. */
|
||||
bpb = archive_write_get_bytes_per_block(f->archive);
|
||||
if (bpb > bs)
|
||||
bs = bpb;
|
||||
else if (bpb != 0)
|
||||
bs -= bs % bpb;
|
||||
}
|
||||
|
||||
state->bs = bs;
|
||||
if (archive_string_ensure(&state->encoded_buff, bs + 512) == NULL) {
|
||||
archive_set_error(f->archive, ENOMEM,
|
||||
"Can't allocate data for b64encode buffer");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
archive_string_sprintf(&state->encoded_buff, "begin-base64 %o %s\n",
|
||||
state->mode, state->name.s);
|
||||
|
||||
f->data = state;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
b64_encode(struct archive_string *as, const unsigned char *p, size_t len)
|
||||
{
|
||||
int c;
|
||||
|
||||
for (; len >= 3; p += 3, len -= 3) {
|
||||
c = p[0] >> 2;
|
||||
archive_strappend_char(as, base64[c]);
|
||||
c = ((p[0] & 0x03) << 4) | ((p[1] & 0xf0) >> 4);
|
||||
archive_strappend_char(as, base64[c]);
|
||||
c = ((p[1] & 0x0f) << 2) | ((p[2] & 0xc0) >> 6);
|
||||
archive_strappend_char(as, base64[c]);
|
||||
c = p[2] & 0x3f;
|
||||
archive_strappend_char(as, base64[c]);
|
||||
}
|
||||
if (len > 0) {
|
||||
c = p[0] >> 2;
|
||||
archive_strappend_char(as, base64[c]);
|
||||
c = (p[0] & 0x03) << 4;
|
||||
if (len == 1) {
|
||||
archive_strappend_char(as, base64[c]);
|
||||
archive_strappend_char(as, '=');
|
||||
archive_strappend_char(as, '=');
|
||||
} else {
|
||||
c |= (p[1] & 0xf0) >> 4;
|
||||
archive_strappend_char(as, base64[c]);
|
||||
c = (p[1] & 0x0f) << 2;
|
||||
archive_strappend_char(as, base64[c]);
|
||||
archive_strappend_char(as, '=');
|
||||
}
|
||||
}
|
||||
archive_strappend_char(as, '\n');
|
||||
}
|
||||
|
||||
/*
|
||||
* Write data to the encoded stream.
|
||||
*/
|
||||
static int
|
||||
archive_filter_b64encode_write(struct archive_write_filter *f, const void *buff,
|
||||
size_t length)
|
||||
{
|
||||
struct private_b64encode *state = (struct private_b64encode *)f->data;
|
||||
const unsigned char *p = buff;
|
||||
int ret = ARCHIVE_OK;
|
||||
|
||||
if (length == 0)
|
||||
return (ret);
|
||||
|
||||
if (state->hold_len) {
|
||||
while (state->hold_len < LBYTES && length > 0) {
|
||||
state->hold[state->hold_len++] = *p++;
|
||||
length--;
|
||||
}
|
||||
if (state->hold_len < LBYTES)
|
||||
return (ret);
|
||||
b64_encode(&state->encoded_buff, state->hold, LBYTES);
|
||||
state->hold_len = 0;
|
||||
}
|
||||
|
||||
for (; length >= LBYTES; length -= LBYTES, p += LBYTES)
|
||||
b64_encode(&state->encoded_buff, p, LBYTES);
|
||||
|
||||
/* Save remaining bytes. */
|
||||
if (length > 0) {
|
||||
memcpy(state->hold, p, length);
|
||||
state->hold_len = length;
|
||||
}
|
||||
while (archive_strlen(&state->encoded_buff) >= state->bs) {
|
||||
ret = __archive_write_filter(f->next_filter,
|
||||
state->encoded_buff.s, state->bs);
|
||||
memmove(state->encoded_buff.s,
|
||||
state->encoded_buff.s + state->bs,
|
||||
state->encoded_buff.length - state->bs);
|
||||
state->encoded_buff.length -= state->bs;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish the compression...
|
||||
*/
|
||||
static int
|
||||
archive_filter_b64encode_close(struct archive_write_filter *f)
|
||||
{
|
||||
struct private_b64encode *state = (struct private_b64encode *)f->data;
|
||||
int ret, ret2;
|
||||
|
||||
/* Flush remaining bytes. */
|
||||
if (state->hold_len != 0)
|
||||
b64_encode(&state->encoded_buff, state->hold, state->hold_len);
|
||||
archive_string_sprintf(&state->encoded_buff, "====\n");
|
||||
/* Write the last block */
|
||||
archive_write_set_bytes_in_last_block(f->archive, 1);
|
||||
ret = __archive_write_filter(f->next_filter,
|
||||
state->encoded_buff.s, archive_strlen(&state->encoded_buff));
|
||||
ret2 = __archive_write_close_filter(f->next_filter);
|
||||
if (ret > ret2)
|
||||
ret = ret2;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_filter_b64encode_free(struct archive_write_filter *f)
|
||||
{
|
||||
struct private_b64encode *state = (struct private_b64encode *)f->data;
|
||||
|
||||
archive_string_free(&state->name);
|
||||
archive_string_free(&state->encoded_buff);
|
||||
free(state);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int64_t
|
||||
atol8(const char *p, size_t char_cnt)
|
||||
{
|
||||
int64_t l;
|
||||
int digit;
|
||||
|
||||
l = 0;
|
||||
while (char_cnt-- > 0) {
|
||||
if (*p >= '0' && *p <= '7')
|
||||
digit = *p - '0';
|
||||
else
|
||||
break;
|
||||
p++;
|
||||
l <<= 3;
|
||||
l |= digit;
|
||||
}
|
||||
return (l);
|
||||
}
|
||||
|
@ -0,0 +1,75 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* Copyright (c) 2012 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
|
||||
/* A table that maps names to functions. */
|
||||
static
|
||||
struct { const char *name; int (*setter)(struct archive *); } names[] =
|
||||
{
|
||||
{ "b64encode", archive_write_add_filter_b64encode },
|
||||
{ "bzip2", archive_write_add_filter_bzip2 },
|
||||
{ "compress", archive_write_add_filter_compress },
|
||||
{ "grzip", archive_write_add_filter_grzip },
|
||||
{ "gzip", archive_write_add_filter_gzip },
|
||||
{ "lrzip", archive_write_add_filter_lrzip },
|
||||
{ "lzip", archive_write_add_filter_lzip },
|
||||
{ "lzma", archive_write_add_filter_lzma },
|
||||
{ "lzop", archive_write_add_filter_lzop },
|
||||
{ "uuencode", archive_write_add_filter_uuencode },
|
||||
{ "xz", archive_write_add_filter_xz },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
int
|
||||
archive_write_add_filter_by_name(struct archive *a, const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; names[i].name != NULL; i++) {
|
||||
if (strcmp(name, names[i].name) == 0)
|
||||
return ((names[i].setter)(a));
|
||||
}
|
||||
|
||||
archive_set_error(a, EINVAL, "No such filter '%s'", name);
|
||||
a->state = ARCHIVE_STATE_FATAL;
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* Copyright (c) 2012 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -54,32 +55,18 @@ archive_write_set_compression_bzip2(struct archive *a)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR)
|
||||
int
|
||||
archive_write_add_filter_bzip2(struct archive *a)
|
||||
{
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
"bzip2 compression not supported on this platform");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
#else
|
||||
/* Don't compile this if we don't have bzlib. */
|
||||
|
||||
struct private_data {
|
||||
int compression_level;
|
||||
#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
|
||||
bz_stream stream;
|
||||
int64_t total_in;
|
||||
char *compressed;
|
||||
size_t compressed_buffer_size;
|
||||
#else
|
||||
struct archive_write_program_data *pdata;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Yuck. bzlib.h is not const-correct, so I need this one bit
|
||||
* of ugly hackery to convert a const * pointer to a non-const pointer.
|
||||
*/
|
||||
#define SET_NEXT_IN(st,src) \
|
||||
(st)->stream.next_in = (char *)(uintptr_t)(const void *)(src)
|
||||
|
||||
static int archive_compressor_bzip2_close(struct archive_write_filter *);
|
||||
static int archive_compressor_bzip2_free(struct archive_write_filter *);
|
||||
static int archive_compressor_bzip2_open(struct archive_write_filter *);
|
||||
@ -87,8 +74,6 @@ static int archive_compressor_bzip2_options(struct archive_write_filter *,
|
||||
const char *, const char *);
|
||||
static int archive_compressor_bzip2_write(struct archive_write_filter *,
|
||||
const void *, size_t);
|
||||
static int drive_compressor(struct archive_write_filter *,
|
||||
struct private_data *, int finishing);
|
||||
|
||||
/*
|
||||
* Add a bzip2 compression filter to this write handle.
|
||||
@ -115,11 +100,64 @@ archive_write_add_filter_bzip2(struct archive *_a)
|
||||
f->close = &archive_compressor_bzip2_close;
|
||||
f->free = &archive_compressor_bzip2_free;
|
||||
f->open = &archive_compressor_bzip2_open;
|
||||
f->code = ARCHIVE_COMPRESSION_BZIP2;
|
||||
f->code = ARCHIVE_FILTER_BZIP2;
|
||||
f->name = "bzip2";
|
||||
#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
|
||||
return (ARCHIVE_OK);
|
||||
#else
|
||||
data->pdata = __archive_write_program_allocate();
|
||||
if (data->pdata == NULL) {
|
||||
free(data);
|
||||
archive_set_error(&a->archive, ENOMEM, "Out of memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
data->compression_level = 0;
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Using external bzip2 program");
|
||||
return (ARCHIVE_WARN);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Set write options.
|
||||
*/
|
||||
static int
|
||||
archive_compressor_bzip2_options(struct archive_write_filter *f,
|
||||
const char *key, const char *value)
|
||||
{
|
||||
struct private_data *data = (struct private_data *)f->data;
|
||||
|
||||
if (strcmp(key, "compression-level") == 0) {
|
||||
if (value == NULL || !(value[0] >= '0' && value[0] <= '9') ||
|
||||
value[1] != '\0')
|
||||
return (ARCHIVE_WARN);
|
||||
data->compression_level = value[0] - '0';
|
||||
/* Make '0' be a synonym for '1'. */
|
||||
/* This way, bzip2 compressor supports the same 0..9
|
||||
* range of levels as gzip. */
|
||||
if (data->compression_level < 1)
|
||||
data->compression_level = 1;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/* Note: The "warn" return is just to inform the options
|
||||
* supervisor that we didn't handle it. It will generate
|
||||
* a suitable error if no one used this option. */
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
|
||||
/* Don't compile this if we don't have bzlib. */
|
||||
|
||||
/*
|
||||
* Yuck. bzlib.h is not const-correct, so I need this one bit
|
||||
* of ugly hackery to convert a const * pointer to a non-const pointer.
|
||||
*/
|
||||
#define SET_NEXT_IN(st,src) \
|
||||
(st)->stream.next_in = (char *)(uintptr_t)(const void *)(src)
|
||||
static int drive_compressor(struct archive_write_filter *,
|
||||
struct private_data *, int finishing);
|
||||
|
||||
/*
|
||||
* Setup callback.
|
||||
*/
|
||||
@ -194,34 +232,6 @@ archive_compressor_bzip2_open(struct archive_write_filter *f)
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Set write options.
|
||||
*/
|
||||
static int
|
||||
archive_compressor_bzip2_options(struct archive_write_filter *f,
|
||||
const char *key, const char *value)
|
||||
{
|
||||
struct private_data *data = (struct private_data *)f->data;
|
||||
|
||||
if (strcmp(key, "compression-level") == 0) {
|
||||
if (value == NULL || !(value[0] >= '0' && value[0] <= '9') ||
|
||||
value[1] != '\0')
|
||||
return (ARCHIVE_WARN);
|
||||
data->compression_level = value[0] - '0';
|
||||
/* Make '0' be a synonym for '1'. */
|
||||
/* This way, bzip2 compressor supports the same 0..9
|
||||
* range of levels as gzip. */
|
||||
if (data->compression_level < 1)
|
||||
data->compression_level = 1;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/* Note: The "warn" return is just to inform the options
|
||||
* supervisor that we didn't handle it. It will generate
|
||||
* a suitable error if no one used this option. */
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write data to the compressed stream.
|
||||
*
|
||||
@ -343,4 +353,55 @@ drive_compressor(struct archive_write_filter *f,
|
||||
}
|
||||
}
|
||||
|
||||
#else /* HAVE_BZLIB_H && BZ_CONFIG_ERROR */
|
||||
|
||||
static int
|
||||
archive_compressor_bzip2_open(struct archive_write_filter *f)
|
||||
{
|
||||
struct private_data *data = (struct private_data *)f->data;
|
||||
struct archive_string as;
|
||||
int r;
|
||||
|
||||
archive_string_init(&as);
|
||||
archive_strcpy(&as, "bzip2");
|
||||
|
||||
/* Specify compression level. */
|
||||
if (data->compression_level > 0) {
|
||||
archive_strcat(&as, " -");
|
||||
archive_strappend_char(&as, '0' + data->compression_level);
|
||||
}
|
||||
f->write = archive_compressor_bzip2_write;
|
||||
|
||||
r = __archive_write_program_open(f, data->pdata, as.s);
|
||||
archive_string_free(&as);
|
||||
return (r);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_compressor_bzip2_write(struct archive_write_filter *f, const void *buff,
|
||||
size_t length)
|
||||
{
|
||||
struct private_data *data = (struct private_data *)f->data;
|
||||
|
||||
return __archive_write_program_write(f, data->pdata, buff, length);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_compressor_bzip2_close(struct archive_write_filter *f)
|
||||
{
|
||||
struct private_data *data = (struct private_data *)f->data;
|
||||
|
||||
return __archive_write_program_close(f, data->pdata);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_compressor_bzip2_free(struct archive_write_filter *f)
|
||||
{
|
||||
struct private_data *data = (struct private_data *)f->data;
|
||||
|
||||
__archive_write_program_free(data->pdata);
|
||||
free(data);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#endif /* HAVE_BZLIB_H && BZ_CONFIG_ERROR */
|
||||
|
@ -135,7 +135,7 @@ archive_write_add_filter_compress(struct archive *_a)
|
||||
archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_write_add_filter_compress");
|
||||
f->open = &archive_compressor_compress_open;
|
||||
f->code = ARCHIVE_COMPRESSION_COMPRESS;
|
||||
f->code = ARCHIVE_FILTER_COMPRESS;
|
||||
f->name = "compress";
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
@ -150,7 +150,7 @@ archive_compressor_compress_open(struct archive_write_filter *f)
|
||||
struct private_data *state;
|
||||
size_t bs = 65536, bpb;
|
||||
|
||||
f->code = ARCHIVE_COMPRESSION_COMPRESS;
|
||||
f->code = ARCHIVE_FILTER_COMPRESS;
|
||||
f->name = "compress";
|
||||
|
||||
ret = __archive_write_open_filter(f->next_filter);
|
||||
|
135
contrib/libarchive/libarchive/archive_write_add_filter_grzip.c
Normal file
135
contrib/libarchive/libarchive/archive_write_add_filter_grzip.c
Normal file
@ -0,0 +1,135 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_write_private.h"
|
||||
|
||||
struct write_grzip {
|
||||
struct archive_write_program_data *pdata;
|
||||
};
|
||||
|
||||
static int archive_write_grzip_open(struct archive_write_filter *);
|
||||
static int archive_write_grzip_options(struct archive_write_filter *,
|
||||
const char *, const char *);
|
||||
static int archive_write_grzip_write(struct archive_write_filter *,
|
||||
const void *, size_t);
|
||||
static int archive_write_grzip_close(struct archive_write_filter *);
|
||||
static int archive_write_grzip_free(struct archive_write_filter *);
|
||||
|
||||
int
|
||||
archive_write_add_filter_grzip(struct archive *_a)
|
||||
{
|
||||
struct archive_write_filter *f = __archive_write_allocate_filter(_a);
|
||||
struct write_grzip *data;
|
||||
|
||||
archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_write_add_filter_grzip");
|
||||
|
||||
data = calloc(1, sizeof(*data));
|
||||
if (data == NULL) {
|
||||
archive_set_error(_a, ENOMEM, "Can't allocate memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
data->pdata = __archive_write_program_allocate();
|
||||
if (data->pdata == NULL) {
|
||||
free(data);
|
||||
archive_set_error(_a, ENOMEM, "Can't allocate memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
f->name = "grzip";
|
||||
f->code = ARCHIVE_FILTER_GRZIP;
|
||||
f->data = data;
|
||||
f->open = archive_write_grzip_open;
|
||||
f->options = archive_write_grzip_options;
|
||||
f->write = archive_write_grzip_write;
|
||||
f->close = archive_write_grzip_close;
|
||||
f->free = archive_write_grzip_free;
|
||||
|
||||
/* Note: This filter always uses an external program, so we
|
||||
* return "warn" to inform of the fact. */
|
||||
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
|
||||
"Using external grzip program for grzip compression");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_grzip_options(struct archive_write_filter *f, const char *key,
|
||||
const char *value)
|
||||
{
|
||||
(void)f; /* UNUSED */
|
||||
(void)key; /* UNUSED */
|
||||
(void)value; /* UNUSED */
|
||||
/* Note: The "warn" return is just to inform the options
|
||||
* supervisor that we didn't handle it. It will generate
|
||||
* a suitable error if no one used this option. */
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_grzip_open(struct archive_write_filter *f)
|
||||
{
|
||||
struct write_grzip *data = (struct write_grzip *)f->data;
|
||||
|
||||
return __archive_write_program_open(f, data->pdata, "grzip");
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_grzip_write(struct archive_write_filter *f,
|
||||
const void *buff, size_t length)
|
||||
{
|
||||
struct write_grzip *data = (struct write_grzip *)f->data;
|
||||
|
||||
return __archive_write_program_write(f, data->pdata, buff, length);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_grzip_close(struct archive_write_filter *f)
|
||||
{
|
||||
struct write_grzip *data = (struct write_grzip *)f->data;
|
||||
|
||||
return __archive_write_program_close(f, data->pdata);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_grzip_free(struct archive_write_filter *f)
|
||||
{
|
||||
struct write_grzip *data = (struct write_grzip *)f->data;
|
||||
|
||||
__archive_write_program_free(data->pdata);
|
||||
free(data);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
@ -43,6 +43,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_compression_gzip.c 201
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_string.h"
|
||||
#include "archive_write_private.h"
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
@ -54,24 +55,20 @@ archive_write_set_compression_gzip(struct archive *a)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ZLIB_H
|
||||
int
|
||||
archive_write_add_filter_gzip(struct archive *a)
|
||||
{
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
"gzip compression not supported on this platform");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
#else
|
||||
/* Don't compile this if we don't have zlib. */
|
||||
|
||||
struct private_data {
|
||||
int compression_level;
|
||||
int timestamp;
|
||||
#ifdef HAVE_ZLIB_H
|
||||
z_stream stream;
|
||||
int64_t total_in;
|
||||
unsigned char *compressed;
|
||||
size_t compressed_buffer_size;
|
||||
unsigned long crc;
|
||||
#else
|
||||
struct archive_write_program_data *pdata;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
@ -88,8 +85,10 @@ static int archive_compressor_gzip_write(struct archive_write_filter *,
|
||||
const void *, size_t);
|
||||
static int archive_compressor_gzip_close(struct archive_write_filter *);
|
||||
static int archive_compressor_gzip_free(struct archive_write_filter *);
|
||||
#ifdef HAVE_ZLIB_H
|
||||
static int drive_compressor(struct archive_write_filter *,
|
||||
struct private_data *, int finishing);
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
@ -110,16 +109,72 @@ archive_write_add_filter_gzip(struct archive *_a)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
f->data = data;
|
||||
data->compression_level = Z_DEFAULT_COMPRESSION;
|
||||
f->open = &archive_compressor_gzip_open;
|
||||
f->options = &archive_compressor_gzip_options;
|
||||
f->close = &archive_compressor_gzip_close;
|
||||
f->free = &archive_compressor_gzip_free;
|
||||
f->code = ARCHIVE_COMPRESSION_GZIP;
|
||||
f->code = ARCHIVE_FILTER_GZIP;
|
||||
f->name = "gzip";
|
||||
#ifdef HAVE_ZLIB_H
|
||||
data->compression_level = Z_DEFAULT_COMPRESSION;
|
||||
return (ARCHIVE_OK);
|
||||
#else
|
||||
data->pdata = __archive_write_program_allocate();
|
||||
if (data->pdata == NULL) {
|
||||
free(data);
|
||||
archive_set_error(&a->archive, ENOMEM, "Out of memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
data->compression_level = 0;
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Using external gzip program");
|
||||
return (ARCHIVE_WARN);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
archive_compressor_gzip_free(struct archive_write_filter *f)
|
||||
{
|
||||
struct private_data *data = (struct private_data *)f->data;
|
||||
|
||||
#ifdef HAVE_ZLIB_H
|
||||
free(data->compressed);
|
||||
#else
|
||||
__archive_write_program_free(data->pdata);
|
||||
#endif
|
||||
free(data);
|
||||
f->data = NULL;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set write options.
|
||||
*/
|
||||
static int
|
||||
archive_compressor_gzip_options(struct archive_write_filter *f, const char *key,
|
||||
const char *value)
|
||||
{
|
||||
struct private_data *data = (struct private_data *)f->data;
|
||||
|
||||
if (strcmp(key, "compression-level") == 0) {
|
||||
if (value == NULL || !(value[0] >= '0' && value[0] <= '9') ||
|
||||
value[1] != '\0')
|
||||
return (ARCHIVE_WARN);
|
||||
data->compression_level = value[0] - '0';
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
if (strcmp(key, "timestamp") == 0) {
|
||||
data->timestamp = (value == NULL)?-1:1;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/* Note: The "warn" return is just to inform the options
|
||||
* supervisor that we didn't handle it. It will generate
|
||||
* a suitable error if no one used this option. */
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
#ifdef HAVE_ZLIB_H
|
||||
/*
|
||||
* Setup callback.
|
||||
*/
|
||||
@ -128,7 +183,6 @@ archive_compressor_gzip_open(struct archive_write_filter *f)
|
||||
{
|
||||
struct private_data *data = (struct private_data *)f->data;
|
||||
int ret;
|
||||
time_t t;
|
||||
|
||||
ret = __archive_write_open_filter(f->next_filter);
|
||||
if (ret != ARCHIVE_OK)
|
||||
@ -137,8 +191,8 @@ archive_compressor_gzip_open(struct archive_write_filter *f)
|
||||
if (data->compressed == NULL) {
|
||||
size_t bs = 65536, bpb;
|
||||
if (f->archive->magic == ARCHIVE_WRITE_MAGIC) {
|
||||
/* Buffer size should be a multiple number of the of bytes
|
||||
* per block for performance. */
|
||||
/* Buffer size should be a multiple number of
|
||||
* the of bytes per block for performance. */
|
||||
bpb = archive_write_get_bytes_per_block(f->archive);
|
||||
if (bpb > bs)
|
||||
bs = bpb;
|
||||
@ -157,18 +211,21 @@ archive_compressor_gzip_open(struct archive_write_filter *f)
|
||||
|
||||
data->crc = crc32(0L, NULL, 0);
|
||||
data->stream.next_out = data->compressed;
|
||||
data->stream.avail_out = data->compressed_buffer_size;
|
||||
data->stream.avail_out = (uInt)data->compressed_buffer_size;
|
||||
|
||||
/* Prime output buffer with a gzip header. */
|
||||
t = time(NULL);
|
||||
data->compressed[0] = 0x1f; /* GZip signature bytes */
|
||||
data->compressed[1] = 0x8b;
|
||||
data->compressed[2] = 0x08; /* "Deflate" compression */
|
||||
data->compressed[3] = 0; /* No options */
|
||||
data->compressed[4] = (uint8_t)(t)&0xff; /* Timestamp */
|
||||
data->compressed[5] = (uint8_t)(t>>8)&0xff;
|
||||
data->compressed[6] = (uint8_t)(t>>16)&0xff;
|
||||
data->compressed[7] = (uint8_t)(t>>24)&0xff;
|
||||
if (data->timestamp >= 0) {
|
||||
time_t t = time(NULL);
|
||||
data->compressed[4] = (uint8_t)(t)&0xff; /* Timestamp */
|
||||
data->compressed[5] = (uint8_t)(t>>8)&0xff;
|
||||
data->compressed[6] = (uint8_t)(t>>16)&0xff;
|
||||
data->compressed[7] = (uint8_t)(t>>24)&0xff;
|
||||
} else
|
||||
memset(&data->compressed[4], 0, 4);
|
||||
data->compressed[8] = 0; /* No deflate options */
|
||||
data->compressed[9] = 3; /* OS=Unix */
|
||||
data->stream.next_out += 10;
|
||||
@ -201,8 +258,8 @@ archive_compressor_gzip_open(struct archive_write_filter *f)
|
||||
"compression library: invalid setup parameter");
|
||||
break;
|
||||
case Z_MEM_ERROR:
|
||||
archive_set_error(f->archive, ENOMEM, "Internal error initializing "
|
||||
"compression library");
|
||||
archive_set_error(f->archive, ENOMEM,
|
||||
"Internal error initializing compression library");
|
||||
break;
|
||||
case Z_VERSION_ERROR:
|
||||
archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
|
||||
@ -214,29 +271,6 @@ archive_compressor_gzip_open(struct archive_write_filter *f)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set write options.
|
||||
*/
|
||||
static int
|
||||
archive_compressor_gzip_options(struct archive_write_filter *f, const char *key,
|
||||
const char *value)
|
||||
{
|
||||
struct private_data *data = (struct private_data *)f->data;
|
||||
|
||||
if (strcmp(key, "compression-level") == 0) {
|
||||
if (value == NULL || !(value[0] >= '0' && value[0] <= '9') ||
|
||||
value[1] != '\0')
|
||||
return (ARCHIVE_WARN);
|
||||
data->compression_level = value[0] - '0';
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/* Note: The "warn" return is just to inform the options
|
||||
* supervisor that we didn't handle it. It will generate
|
||||
* a suitable error if no one used this option. */
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write data to the compressed stream.
|
||||
*/
|
||||
@ -248,12 +282,12 @@ archive_compressor_gzip_write(struct archive_write_filter *f, const void *buff,
|
||||
int ret;
|
||||
|
||||
/* Update statistics */
|
||||
data->crc = crc32(data->crc, (const Bytef *)buff, length);
|
||||
data->crc = crc32(data->crc, (const Bytef *)buff, (uInt)length);
|
||||
data->total_in += length;
|
||||
|
||||
/* Compress input data to output buffer */
|
||||
SET_NEXT_IN(data, buff);
|
||||
data->stream.avail_in = length;
|
||||
data->stream.avail_in = (uInt)length;
|
||||
if ((ret = drive_compressor(f, data, 0)) != ARCHIVE_OK)
|
||||
return (ret);
|
||||
|
||||
@ -303,16 +337,6 @@ archive_compressor_gzip_close(struct archive_write_filter *f)
|
||||
return (r1 < ret ? r1 : ret);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_compressor_gzip_free(struct archive_write_filter *f)
|
||||
{
|
||||
struct private_data *data = (struct private_data *)f->data;
|
||||
free(data->compressed);
|
||||
free(data);
|
||||
f->data = NULL;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility function to push input data through compressor,
|
||||
* writing full output blocks as necessary.
|
||||
@ -334,7 +358,8 @@ drive_compressor(struct archive_write_filter *f,
|
||||
if (ret != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
data->stream.next_out = data->compressed;
|
||||
data->stream.avail_out = data->compressed_buffer_size;
|
||||
data->stream.avail_out =
|
||||
(uInt)data->compressed_buffer_size;
|
||||
}
|
||||
|
||||
/* If there's nothing to do, we're done. */
|
||||
@ -367,4 +392,51 @@ drive_compressor(struct archive_write_filter *f,
|
||||
}
|
||||
}
|
||||
|
||||
#else /* HAVE_ZLIB_H */
|
||||
|
||||
static int
|
||||
archive_compressor_gzip_open(struct archive_write_filter *f)
|
||||
{
|
||||
struct private_data *data = (struct private_data *)f->data;
|
||||
struct archive_string as;
|
||||
int r;
|
||||
|
||||
archive_string_init(&as);
|
||||
archive_strcpy(&as, "gzip");
|
||||
|
||||
/* Specify compression level. */
|
||||
if (data->compression_level > 0) {
|
||||
archive_strcat(&as, " -");
|
||||
archive_strappend_char(&as, '0' + data->compression_level);
|
||||
}
|
||||
if (data->timestamp < 0)
|
||||
/* Do not save timestamp. */
|
||||
archive_strcat(&as, " -n");
|
||||
else if (data->timestamp > 0)
|
||||
/* Save timestamp. */
|
||||
archive_strcat(&as, " -N");
|
||||
|
||||
f->write = archive_compressor_gzip_write;
|
||||
r = __archive_write_program_open(f, data->pdata, as.s);
|
||||
archive_string_free(&as);
|
||||
return (r);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_compressor_gzip_write(struct archive_write_filter *f, const void *buff,
|
||||
size_t length)
|
||||
{
|
||||
struct private_data *data = (struct private_data *)f->data;
|
||||
|
||||
return __archive_write_program_write(f, data->pdata, buff, length);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_compressor_gzip_close(struct archive_write_filter *f)
|
||||
{
|
||||
struct private_data *data = (struct private_data *)f->data;
|
||||
|
||||
return __archive_write_program_close(f, data->pdata);
|
||||
}
|
||||
|
||||
#endif /* HAVE_ZLIB_H */
|
||||
|
192
contrib/libarchive/libarchive/archive_write_add_filter_lrzip.c
Normal file
192
contrib/libarchive/libarchive/archive_write_add_filter_lrzip.c
Normal file
@ -0,0 +1,192 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_string.h"
|
||||
#include "archive_write_private.h"
|
||||
|
||||
struct write_lrzip {
|
||||
struct archive_write_program_data *pdata;
|
||||
int compression_level;
|
||||
enum { lzma = 0, bzip2, gzip, lzo, zpaq } compression;
|
||||
};
|
||||
|
||||
static int archive_write_lrzip_open(struct archive_write_filter *);
|
||||
static int archive_write_lrzip_options(struct archive_write_filter *,
|
||||
const char *, const char *);
|
||||
static int archive_write_lrzip_write(struct archive_write_filter *,
|
||||
const void *, size_t);
|
||||
static int archive_write_lrzip_close(struct archive_write_filter *);
|
||||
static int archive_write_lrzip_free(struct archive_write_filter *);
|
||||
|
||||
int
|
||||
archive_write_add_filter_lrzip(struct archive *_a)
|
||||
{
|
||||
struct archive_write_filter *f = __archive_write_allocate_filter(_a);
|
||||
struct write_lrzip *data;
|
||||
|
||||
archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_write_add_filter_lrzip");
|
||||
|
||||
data = calloc(1, sizeof(*data));
|
||||
if (data == NULL) {
|
||||
archive_set_error(_a, ENOMEM, "Can't allocate memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
data->pdata = __archive_write_program_allocate();
|
||||
if (data->pdata == NULL) {
|
||||
free(data);
|
||||
archive_set_error(_a, ENOMEM, "Can't allocate memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
f->name = "lrzip";
|
||||
f->code = ARCHIVE_FILTER_LRZIP;
|
||||
f->data = data;
|
||||
f->open = archive_write_lrzip_open;
|
||||
f->options = archive_write_lrzip_options;
|
||||
f->write = archive_write_lrzip_write;
|
||||
f->close = archive_write_lrzip_close;
|
||||
f->free = archive_write_lrzip_free;
|
||||
|
||||
/* Note: This filter always uses an external program, so we
|
||||
* return "warn" to inform of the fact. */
|
||||
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
|
||||
"Using external lrzip program for lrzip compression");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_lrzip_options(struct archive_write_filter *f, const char *key,
|
||||
const char *value)
|
||||
{
|
||||
struct write_lrzip *data = (struct write_lrzip *)f->data;
|
||||
|
||||
if (strcmp(key, "compression") == 0) {
|
||||
if (value == NULL)
|
||||
return (ARCHIVE_WARN);
|
||||
else if (strcmp(value, "bzip2") == 0)
|
||||
data->compression = bzip2;
|
||||
else if (strcmp(value, "gzip") == 0)
|
||||
data->compression = gzip;
|
||||
else if (strcmp(value, "lzo") == 0)
|
||||
data->compression = lzo;
|
||||
else if (strcmp(value, "zpaq") == 0)
|
||||
data->compression = zpaq;
|
||||
else
|
||||
return (ARCHIVE_WARN);
|
||||
return (ARCHIVE_OK);
|
||||
} else if (strcmp(key, "compression-level") == 0) {
|
||||
if (value == NULL || !(value[0] >= '1' && value[0] <= '9') ||
|
||||
value[1] != '\0')
|
||||
return (ARCHIVE_WARN);
|
||||
data->compression_level = value[0] - '0';
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
/* Note: The "warn" return is just to inform the options
|
||||
* supervisor that we didn't handle it. It will generate
|
||||
* a suitable error if no one used this option. */
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_lrzip_open(struct archive_write_filter *f)
|
||||
{
|
||||
struct write_lrzip *data = (struct write_lrzip *)f->data;
|
||||
struct archive_string as;
|
||||
int r;
|
||||
|
||||
archive_string_init(&as);
|
||||
archive_strcpy(&as, "lrzip -q");
|
||||
|
||||
/* Specify compression type. */
|
||||
switch (data->compression) {
|
||||
case lzma:/* default compression */
|
||||
break;
|
||||
case bzip2:
|
||||
archive_strcat(&as, " -b");
|
||||
break;
|
||||
case gzip:
|
||||
archive_strcat(&as, " -g");
|
||||
break;
|
||||
case lzo:
|
||||
archive_strcat(&as, " -l");
|
||||
break;
|
||||
case zpaq:
|
||||
archive_strcat(&as, " -z");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Specify compression level. */
|
||||
if (data->compression_level > 0) {
|
||||
archive_strcat(&as, " -L ");
|
||||
archive_strappend_char(&as, '0' + data->compression_level);
|
||||
}
|
||||
|
||||
r = __archive_write_program_open(f, data->pdata, as.s);
|
||||
archive_string_free(&as);
|
||||
return (r);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_lrzip_write(struct archive_write_filter *f,
|
||||
const void *buff, size_t length)
|
||||
{
|
||||
struct write_lrzip *data = (struct write_lrzip *)f->data;
|
||||
|
||||
return __archive_write_program_write(f, data->pdata, buff, length);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_lrzip_close(struct archive_write_filter *f)
|
||||
{
|
||||
struct write_lrzip *data = (struct write_lrzip *)f->data;
|
||||
|
||||
return __archive_write_program_close(f, data->pdata);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_lrzip_free(struct archive_write_filter *f)
|
||||
{
|
||||
struct write_lrzip *data = (struct write_lrzip *)f->data;
|
||||
|
||||
__archive_write_program_free(data->pdata);
|
||||
free(data);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
486
contrib/libarchive/libarchive/archive_write_add_filter_lzop.c
Normal file
486
contrib/libarchive/libarchive/archive_write_add_filter_lzop.c
Normal file
@ -0,0 +1,486 @@
|
||||
/*-
|
||||
* Copyright (c) 2012 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
|
||||
__FBSDID("$FreeBSD$");
|
||||
//#undef HAVE_LZO_LZOCONF_H
|
||||
//#undef HAVE_LZO_LZO1X_H
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
#ifdef HAVE_LZO_LZOCONF_H
|
||||
#include <lzo/lzoconf.h>
|
||||
#endif
|
||||
#ifdef HAVE_LZO_LZO1X_H
|
||||
#include <lzo/lzo1x.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_string.h"
|
||||
#include "archive_endian.h"
|
||||
#include "archive_write_private.h"
|
||||
|
||||
enum lzo_method {
|
||||
METHOD_LZO1X_1 = 1,
|
||||
METHOD_LZO1X_1_15 = 2,
|
||||
METHOD_LZO1X_999 = 3
|
||||
};
|
||||
struct write_lzop {
|
||||
int compression_level;
|
||||
#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
|
||||
unsigned char *uncompressed;
|
||||
size_t uncompressed_buffer_size;
|
||||
size_t uncompressed_avail_bytes;
|
||||
unsigned char *compressed;
|
||||
size_t compressed_buffer_size;
|
||||
enum lzo_method method;
|
||||
unsigned char level;
|
||||
lzo_voidp work_buffer;
|
||||
lzo_uint32 work_buffer_size;
|
||||
char header_written;
|
||||
#else
|
||||
struct archive_write_program_data *pdata;
|
||||
#endif
|
||||
};
|
||||
|
||||
static int archive_write_lzop_open(struct archive_write_filter *);
|
||||
static int archive_write_lzop_options(struct archive_write_filter *,
|
||||
const char *, const char *);
|
||||
static int archive_write_lzop_write(struct archive_write_filter *,
|
||||
const void *, size_t);
|
||||
static int archive_write_lzop_close(struct archive_write_filter *);
|
||||
static int archive_write_lzop_free(struct archive_write_filter *);
|
||||
|
||||
#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
|
||||
/* Maximum block size. */
|
||||
#define BLOCK_SIZE (256 * 1024)
|
||||
/* Block infomation is composed of uncompressed size(4 bytes),
|
||||
* compressed size(4 bytes) and the checksum of uncompressed data(4 bytes)
|
||||
* in this lzop writer. */
|
||||
#define BLOCK_INfO_SIZE 12
|
||||
|
||||
#define HEADER_VERSION 9
|
||||
#define HEADER_LIBVERSION 11
|
||||
#define HEADER_METHOD 15
|
||||
#define HEADER_LEVEL 16
|
||||
#define HEADER_MTIME_LOW 25
|
||||
#define HEADER_MTIME_HIGH 29
|
||||
#define HEADER_H_CHECKSUM 34
|
||||
|
||||
/*
|
||||
* Header template.
|
||||
*/
|
||||
static const unsigned char header[] = {
|
||||
/* LZOP Magic code 9 bytes */
|
||||
0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a,
|
||||
/* LZOP utility version(fake data) 2 bytes */
|
||||
0x10, 0x30,
|
||||
/* LZO library version 2 bytes */
|
||||
0x09, 0x40,
|
||||
/* Minimum required LZO library version 2 bytes */
|
||||
0x09, 0x40,
|
||||
/* Method */
|
||||
1,
|
||||
/* Level */
|
||||
5,
|
||||
/* Flags 4 bytes
|
||||
* -OS Unix
|
||||
* -Stdout
|
||||
* -Stdin
|
||||
* -Adler32 used for uncompressed data 4 bytes */
|
||||
0x03, 0x00, 0x00, 0x0d,
|
||||
/* Mode (AE_IFREG | 0644) 4 bytes */
|
||||
0x00, 0x00, 0x81, 0xa4,
|
||||
/* Mtime low 4 bytes */
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
/* Mtime high 4 bytes */
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
/* Filename length */
|
||||
0x00,
|
||||
/* Header checksum 4 bytes */
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
#endif
|
||||
|
||||
int
|
||||
archive_write_add_filter_lzop(struct archive *_a)
|
||||
{
|
||||
struct archive_write_filter *f = __archive_write_allocate_filter(_a);
|
||||
struct write_lzop *data;
|
||||
|
||||
archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_write_add_filter_lzop");
|
||||
|
||||
data = calloc(1, sizeof(*data));
|
||||
if (data == NULL) {
|
||||
archive_set_error(_a, ENOMEM, "Can't allocate memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
f->name = "lzop";
|
||||
f->code = ARCHIVE_FILTER_LZOP;
|
||||
f->data = data;
|
||||
f->open = archive_write_lzop_open;
|
||||
f->options = archive_write_lzop_options;
|
||||
f->write = archive_write_lzop_write;
|
||||
f->close = archive_write_lzop_close;
|
||||
f->free = archive_write_lzop_free;
|
||||
#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
|
||||
if (lzo_init() != LZO_E_OK) {
|
||||
free(data);
|
||||
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
|
||||
"lzo_init(type check) failed");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (lzo_version() < 0x940) {
|
||||
free(data);
|
||||
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
|
||||
"liblzo library is too old(%s < 0.940)",
|
||||
lzo_version_string());
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
data->compression_level = 5;
|
||||
return (ARCHIVE_OK);
|
||||
#else
|
||||
data->pdata = __archive_write_program_allocate();
|
||||
if (data->pdata == NULL) {
|
||||
free(data);
|
||||
archive_set_error(_a, ENOMEM, "Can't allocate memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
data->compression_level = 0;
|
||||
/* Note: We return "warn" to inform of using an external lzop
|
||||
* program. */
|
||||
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
|
||||
"Using external lzop program for lzop compression");
|
||||
return (ARCHIVE_WARN);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_lzop_free(struct archive_write_filter *f)
|
||||
{
|
||||
struct write_lzop *data = (struct write_lzop *)f->data;
|
||||
|
||||
#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
|
||||
free(data->uncompressed);
|
||||
free(data->compressed);
|
||||
free(data->work_buffer);
|
||||
#else
|
||||
__archive_write_program_free(data->pdata);
|
||||
#endif
|
||||
free(data);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_lzop_options(struct archive_write_filter *f, const char *key,
|
||||
const char *value)
|
||||
{
|
||||
struct write_lzop *data = (struct write_lzop *)f->data;
|
||||
|
||||
if (strcmp(key, "compression-level") == 0) {
|
||||
if (value == NULL || !(value[0] >= '1' && value[0] <= '9') ||
|
||||
value[1] != '\0')
|
||||
return (ARCHIVE_WARN);
|
||||
data->compression_level = value[0] - '0';
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
/* Note: The "warn" return is just to inform the options
|
||||
* supervisor that we didn't handle it. It will generate
|
||||
* a suitable error if no one used this option. */
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
|
||||
static int
|
||||
archive_write_lzop_open(struct archive_write_filter *f)
|
||||
{
|
||||
struct write_lzop *data = (struct write_lzop *)f->data;
|
||||
int ret;
|
||||
|
||||
ret = __archive_write_open_filter(f->next_filter);
|
||||
if (ret != ARCHIVE_OK)
|
||||
return (ret);
|
||||
|
||||
switch (data->compression_level) {
|
||||
case 1:
|
||||
data->method = METHOD_LZO1X_1_15; data->level = 1; break;
|
||||
default:
|
||||
case 2: case 3: case 4: case 5: case 6:
|
||||
data->method = METHOD_LZO1X_1; data->level = 5; break;
|
||||
case 7:
|
||||
data->method = METHOD_LZO1X_999; data->level = 7; break;
|
||||
case 8:
|
||||
data->method = METHOD_LZO1X_999; data->level = 8; break;
|
||||
case 9:
|
||||
data->method = METHOD_LZO1X_999; data->level = 9; break;
|
||||
}
|
||||
switch (data->method) {
|
||||
case METHOD_LZO1X_1:
|
||||
data->work_buffer_size = LZO1X_1_MEM_COMPRESS; break;
|
||||
case METHOD_LZO1X_1_15:
|
||||
data->work_buffer_size = LZO1X_1_15_MEM_COMPRESS; break;
|
||||
case METHOD_LZO1X_999:
|
||||
data->work_buffer_size = LZO1X_999_MEM_COMPRESS; break;
|
||||
}
|
||||
if (data->work_buffer == NULL) {
|
||||
data->work_buffer = (lzo_voidp)malloc(data->work_buffer_size);
|
||||
if (data->work_buffer == NULL) {
|
||||
archive_set_error(f->archive, ENOMEM,
|
||||
"Can't allocate data for compression buffer");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
}
|
||||
if (data->compressed == NULL) {
|
||||
data->compressed_buffer_size = sizeof(header) +
|
||||
BLOCK_SIZE + (BLOCK_SIZE >> 4) + 64 + 3;
|
||||
data->compressed = (unsigned char *)
|
||||
malloc(data->compressed_buffer_size);
|
||||
if (data->compressed == NULL) {
|
||||
archive_set_error(f->archive, ENOMEM,
|
||||
"Can't allocate data for compression buffer");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
}
|
||||
if (data->uncompressed == NULL) {
|
||||
data->uncompressed_buffer_size = BLOCK_SIZE;
|
||||
data->uncompressed = (unsigned char *)
|
||||
malloc(data->uncompressed_buffer_size);
|
||||
if (data->uncompressed == NULL) {
|
||||
archive_set_error(f->archive, ENOMEM,
|
||||
"Can't allocate data for compression buffer");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
data->uncompressed_avail_bytes = BLOCK_SIZE;
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
make_header(struct archive_write_filter *f)
|
||||
{
|
||||
struct write_lzop *data = (struct write_lzop *)f->data;
|
||||
int64_t t;
|
||||
uint32_t checksum;
|
||||
|
||||
memcpy(data->compressed, header, sizeof(header));
|
||||
/* Overwrite library version. */
|
||||
data->compressed[HEADER_LIBVERSION] = (unsigned char )
|
||||
(lzo_version() >> 8) & 0xff;
|
||||
data->compressed[HEADER_LIBVERSION + 1] = (unsigned char )
|
||||
lzo_version() & 0xff;
|
||||
/* Overwrite method and level. */
|
||||
data->compressed[HEADER_METHOD] = (unsigned char)data->method;
|
||||
data->compressed[HEADER_LEVEL] = data->level;
|
||||
/* Overwrite mtime with current time. */
|
||||
t = (int64_t)time(NULL);
|
||||
archive_be32enc(&data->compressed[HEADER_MTIME_LOW],
|
||||
(uint32_t)(t & 0xffffffff));
|
||||
archive_be32enc(&data->compressed[HEADER_MTIME_HIGH],
|
||||
(uint32_t)((t >> 32) & 0xffffffff));
|
||||
/* Overwrite header checksum with calculated value. */
|
||||
checksum = lzo_adler32(1, data->compressed + HEADER_VERSION,
|
||||
(lzo_uint)(HEADER_H_CHECKSUM - HEADER_VERSION));
|
||||
archive_be32enc(&data->compressed[HEADER_H_CHECKSUM], checksum);
|
||||
return (sizeof(header));
|
||||
}
|
||||
|
||||
static int
|
||||
drive_compressor(struct archive_write_filter *f)
|
||||
{
|
||||
struct write_lzop *data = (struct write_lzop *)f->data;
|
||||
unsigned char *p;
|
||||
const int block_info_bytes = 12;
|
||||
int header_bytes, r;
|
||||
lzo_uint usize, csize;
|
||||
uint32_t checksum;
|
||||
|
||||
if (!data->header_written) {
|
||||
header_bytes = make_header(f);
|
||||
data->header_written = 1;
|
||||
} else
|
||||
header_bytes = 0;
|
||||
p = data->compressed;
|
||||
|
||||
usize = (lzo_uint)
|
||||
(data->uncompressed_buffer_size - data->uncompressed_avail_bytes);
|
||||
csize = 0;
|
||||
switch (data->method) {
|
||||
default:
|
||||
case METHOD_LZO1X_1:
|
||||
r = lzo1x_1_compress(data->uncompressed, usize,
|
||||
p + header_bytes + block_info_bytes, &csize,
|
||||
data->work_buffer);
|
||||
break;
|
||||
case METHOD_LZO1X_1_15:
|
||||
r = lzo1x_1_15_compress(data->uncompressed, usize,
|
||||
p + header_bytes + block_info_bytes, &csize,
|
||||
data->work_buffer);
|
||||
break;
|
||||
case METHOD_LZO1X_999:
|
||||
r = lzo1x_999_compress_level(data->uncompressed, usize,
|
||||
p + header_bytes + block_info_bytes, &csize,
|
||||
data->work_buffer, NULL, 0, 0, data->level);
|
||||
break;
|
||||
}
|
||||
if (r != LZO_E_OK) {
|
||||
archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Lzop compression failed: returned status %d", r);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
/* Store uncompressed size. */
|
||||
archive_be32enc(p + header_bytes, (uint32_t)usize);
|
||||
/* Store the checksum of the uncompressed data. */
|
||||
checksum = lzo_adler32(1, data->uncompressed, usize);
|
||||
archive_be32enc(p + header_bytes + 8, checksum);
|
||||
|
||||
if (csize < usize) {
|
||||
/* Store compressed size. */
|
||||
archive_be32enc(p + header_bytes + 4, (uint32_t)csize);
|
||||
r = __archive_write_filter(f->next_filter, data->compressed,
|
||||
header_bytes + block_info_bytes + csize);
|
||||
} else {
|
||||
/*
|
||||
* This case, we output uncompressed data instead.
|
||||
*/
|
||||
/* Store uncompressed size as compressed size. */
|
||||
archive_be32enc(p + header_bytes + 4, (uint32_t)usize);
|
||||
r = __archive_write_filter(f->next_filter, data->compressed,
|
||||
header_bytes + block_info_bytes);
|
||||
if (r != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
r = __archive_write_filter(f->next_filter, data->uncompressed,
|
||||
usize);
|
||||
}
|
||||
|
||||
if (r != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_lzop_write(struct archive_write_filter *f,
|
||||
const void *buff, size_t length)
|
||||
{
|
||||
struct write_lzop *data = (struct write_lzop *)f->data;
|
||||
const char *p = buff;
|
||||
int r;
|
||||
|
||||
do {
|
||||
if (data->uncompressed_avail_bytes > length) {
|
||||
memcpy(data->uncompressed
|
||||
+ data->uncompressed_buffer_size
|
||||
- data->uncompressed_avail_bytes,
|
||||
p, length);
|
||||
data->uncompressed_avail_bytes -= length;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
memcpy(data->uncompressed + data->uncompressed_buffer_size
|
||||
- data->uncompressed_avail_bytes,
|
||||
p, data->uncompressed_avail_bytes);
|
||||
length -= data->uncompressed_avail_bytes;
|
||||
p += data->uncompressed_avail_bytes;
|
||||
data->uncompressed_avail_bytes = 0;
|
||||
|
||||
r = drive_compressor(f);
|
||||
if (r != ARCHIVE_OK) return (r);
|
||||
data->uncompressed_avail_bytes = BLOCK_SIZE;
|
||||
} while (length);
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_lzop_close(struct archive_write_filter *f)
|
||||
{
|
||||
struct write_lzop *data = (struct write_lzop *)f->data;
|
||||
const uint32_t endmark = 0;
|
||||
int r;
|
||||
|
||||
if (data->uncompressed_avail_bytes < BLOCK_SIZE) {
|
||||
/* Compress and output remaining data. */
|
||||
r = drive_compressor(f);
|
||||
if (r != ARCHIVE_OK)
|
||||
return (r);
|
||||
}
|
||||
/* Write a zero uncompressed size as the end mark of the series of
|
||||
* compressed block. */
|
||||
r = __archive_write_filter(f->next_filter, &endmark, sizeof(endmark));
|
||||
if (r != ARCHIVE_OK)
|
||||
return (r);
|
||||
return (__archive_write_close_filter(f->next_filter));
|
||||
}
|
||||
|
||||
#else
|
||||
static int
|
||||
archive_write_lzop_open(struct archive_write_filter *f)
|
||||
{
|
||||
struct write_lzop *data = (struct write_lzop *)f->data;
|
||||
struct archive_string as;
|
||||
int r;
|
||||
|
||||
archive_string_init(&as);
|
||||
archive_strcpy(&as, "lzop");
|
||||
/* Specify compression level. */
|
||||
if (data->compression_level > 0) {
|
||||
archive_strappend_char(&as, ' ');
|
||||
archive_strappend_char(&as, '-');
|
||||
archive_strappend_char(&as, '0' + data->compression_level);
|
||||
}
|
||||
|
||||
r = __archive_write_program_open(f, data->pdata, as.s);
|
||||
archive_string_free(&as);
|
||||
return (r);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_lzop_write(struct archive_write_filter *f,
|
||||
const void *buff, size_t length)
|
||||
{
|
||||
struct write_lzop *data = (struct write_lzop *)f->data;
|
||||
|
||||
return __archive_write_program_write(f, data->pdata, buff, length);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_lzop_close(struct archive_write_filter *f)
|
||||
{
|
||||
struct write_lzop *data = (struct write_lzop *)f->data;
|
||||
|
||||
return __archive_write_program_close(f, data->pdata);
|
||||
}
|
||||
#endif
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2007 Joerg Sonnenberger
|
||||
* Copyright (c) 2012 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -44,7 +45,9 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_compression_program.c
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_string.h"
|
||||
#include "archive_write_private.h"
|
||||
#include "filter_fork.h"
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
int
|
||||
@ -55,36 +58,24 @@ archive_write_set_compression_program(struct archive *a, const char *cmd)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This capability is only available on POSIX systems. */
|
||||
#if (!defined(HAVE_PIPE) || !defined(HAVE_FCNTL) || \
|
||||
!(defined(HAVE_FORK) || defined(HAVE_VFORK))) && (!defined(_WIN32) || defined(__CYGWIN__))
|
||||
|
||||
/*
|
||||
* On non-Posix systems, allow the program to build, but choke if
|
||||
* this function is actually invoked.
|
||||
*/
|
||||
int
|
||||
archive_write_add_filter_program(struct archive *_a, const char *cmd)
|
||||
{
|
||||
archive_set_error(_a, -1,
|
||||
"External compression programs not supported on this platform");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
struct archive_write_program_data {
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
HANDLE child;
|
||||
#else
|
||||
|
||||
#include "filter_fork.h"
|
||||
|
||||
struct private_data {
|
||||
char *cmd;
|
||||
char *description;
|
||||
pid_t child;
|
||||
#endif
|
||||
int child_stdin, child_stdout;
|
||||
|
||||
char *child_buf;
|
||||
size_t child_buf_len, child_buf_avail;
|
||||
};
|
||||
|
||||
struct private_data {
|
||||
struct archive_write_program_data *pdata;
|
||||
struct archive_string description;
|
||||
char *cmd;
|
||||
};
|
||||
|
||||
static int archive_compressor_program_open(struct archive_write_filter *);
|
||||
static int archive_compressor_program_write(struct archive_write_filter *,
|
||||
const void *, size_t);
|
||||
@ -99,35 +90,125 @@ int
|
||||
archive_write_add_filter_program(struct archive *_a, const char *cmd)
|
||||
{
|
||||
struct archive_write_filter *f = __archive_write_allocate_filter(_a);
|
||||
struct archive_write *a = (struct archive_write *)_a;
|
||||
struct private_data *data;
|
||||
static const char *prefix = "Program: ";
|
||||
archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_write_add_filter_program");
|
||||
data = calloc(1, sizeof(*data));
|
||||
if (data == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM, "Out of memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
data->cmd = strdup(cmd);
|
||||
data->description = (char *)malloc(strlen(prefix) + strlen(cmd) + 1);
|
||||
strcpy(data->description, prefix);
|
||||
strcat(data->description, cmd);
|
||||
|
||||
f->name = data->description;
|
||||
f->data = data;
|
||||
f->open = &archive_compressor_program_open;
|
||||
f->code = ARCHIVE_COMPRESSION_PROGRAM;
|
||||
archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_write_add_filter_program");
|
||||
|
||||
f->data = calloc(1, sizeof(*data));
|
||||
if (f->data == NULL)
|
||||
goto memerr;
|
||||
data = (struct private_data *)f->data;
|
||||
|
||||
data->cmd = strdup(cmd);
|
||||
if (data->cmd == NULL)
|
||||
goto memerr;
|
||||
|
||||
data->pdata = __archive_write_program_allocate();
|
||||
if (data->pdata == NULL)
|
||||
goto memerr;
|
||||
|
||||
/* Make up a description string. */
|
||||
if (archive_string_ensure(&data->description,
|
||||
strlen(prefix) + strlen(cmd) + 1) == NULL)
|
||||
goto memerr;
|
||||
archive_strcpy(&data->description, prefix);
|
||||
archive_strcat(&data->description, cmd);
|
||||
|
||||
f->name = data->description.s;
|
||||
f->code = ARCHIVE_FILTER_PROGRAM;
|
||||
f->open = archive_compressor_program_open;
|
||||
f->write = archive_compressor_program_write;
|
||||
f->close = archive_compressor_program_close;
|
||||
f->free = archive_compressor_program_free;
|
||||
return (ARCHIVE_OK);
|
||||
memerr:
|
||||
archive_compressor_program_free(f);
|
||||
archive_set_error(_a, ENOMEM,
|
||||
"Can't allocate memory for filter program");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup callback.
|
||||
*/
|
||||
static int
|
||||
archive_compressor_program_open(struct archive_write_filter *f)
|
||||
{
|
||||
struct private_data *data = (struct private_data *)f->data;
|
||||
|
||||
return __archive_write_program_open(f, data->pdata, data->cmd);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_compressor_program_write(struct archive_write_filter *f,
|
||||
const void *buff, size_t length)
|
||||
{
|
||||
struct private_data *data = (struct private_data *)f->data;
|
||||
|
||||
return __archive_write_program_write(f, data->pdata, buff, length);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_compressor_program_close(struct archive_write_filter *f)
|
||||
{
|
||||
struct private_data *data = (struct private_data *)f->data;
|
||||
|
||||
return __archive_write_program_close(f, data->pdata);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_compressor_program_free(struct archive_write_filter *f)
|
||||
{
|
||||
struct private_data *data = (struct private_data *)f->data;
|
||||
|
||||
if (data) {
|
||||
free(data->cmd);
|
||||
archive_string_free(&data->description);
|
||||
__archive_write_program_free(data->pdata);
|
||||
free(data);
|
||||
f->data = NULL;
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate resources for executing an external program.
|
||||
*/
|
||||
struct archive_write_program_data *
|
||||
__archive_write_program_allocate(void)
|
||||
{
|
||||
struct archive_write_program_data *data;
|
||||
|
||||
data = calloc(1, sizeof(struct archive_write_program_data));
|
||||
if (data == NULL)
|
||||
return (data);
|
||||
data->child_stdin = -1;
|
||||
data->child_stdout = -1;
|
||||
return (data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Release the resources.
|
||||
*/
|
||||
int
|
||||
__archive_write_program_free(struct archive_write_program_data *data)
|
||||
{
|
||||
|
||||
if (data) {
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
if (data->child)
|
||||
CloseHandle(data->child);
|
||||
#endif
|
||||
free(data->child_buf);
|
||||
free(data);
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
int
|
||||
__archive_write_program_open(struct archive_write_filter *f,
|
||||
struct archive_write_program_data *data, const char *cmd)
|
||||
{
|
||||
pid_t child;
|
||||
int ret;
|
||||
|
||||
ret = __archive_write_open_filter(f->next_filter);
|
||||
@ -146,23 +227,34 @@ archive_compressor_program_open(struct archive_write_filter *f)
|
||||
}
|
||||
}
|
||||
|
||||
if ((data->child = __archive_create_child(data->cmd,
|
||||
&data->child_stdin, &data->child_stdout)) == -1) {
|
||||
child = __archive_create_child(cmd, &data->child_stdin,
|
||||
&data->child_stdout);
|
||||
if (child == -1) {
|
||||
archive_set_error(f->archive, EINVAL,
|
||||
"Can't initialise filter");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
f->write = archive_compressor_program_write;
|
||||
f->close = archive_compressor_program_close;
|
||||
f->free = archive_compressor_program_free;
|
||||
return (0);
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
data->child = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, child);
|
||||
if (data->child == NULL) {
|
||||
close(data->child_stdin);
|
||||
data->child_stdin = -1;
|
||||
close(data->child_stdout);
|
||||
data->child_stdout = -1;
|
||||
archive_set_error(f->archive, EINVAL,
|
||||
"Can't initialise filter");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
#else
|
||||
data->child = child;
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
child_write(struct archive_write_filter *f, const char *buf, size_t buf_len)
|
||||
child_write(struct archive_write_filter *f,
|
||||
struct archive_write_program_data *data, const char *buf, size_t buf_len)
|
||||
{
|
||||
struct private_data *data = f->data;
|
||||
ssize_t ret;
|
||||
|
||||
if (data->child_stdin == -1)
|
||||
@ -218,30 +310,28 @@ child_write(struct archive_write_filter *f, const char *buf, size_t buf_len)
|
||||
|
||||
ret = __archive_write_filter(f->next_filter,
|
||||
data->child_buf, data->child_buf_avail);
|
||||
if (ret <= 0)
|
||||
if (ret != ARCHIVE_OK)
|
||||
return (-1);
|
||||
|
||||
if ((size_t)ret < data->child_buf_avail) {
|
||||
memmove(data->child_buf, data->child_buf + ret,
|
||||
data->child_buf_avail - ret);
|
||||
}
|
||||
data->child_buf_avail -= ret;
|
||||
data->child_buf_avail = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write data to the compressed stream.
|
||||
* Write data to the filter stream.
|
||||
*/
|
||||
static int
|
||||
archive_compressor_program_write(struct archive_write_filter *f,
|
||||
const void *buff, size_t length)
|
||||
int
|
||||
__archive_write_program_write(struct archive_write_filter *f,
|
||||
struct archive_write_program_data *data, const void *buff, size_t length)
|
||||
{
|
||||
ssize_t ret;
|
||||
const char *buf;
|
||||
|
||||
if (data->child == 0)
|
||||
return (ARCHIVE_OK);
|
||||
|
||||
buf = buff;
|
||||
while (length > 0) {
|
||||
ret = child_write(f, buf, length);
|
||||
ret = child_write(f, data, buf, length);
|
||||
if (ret == -1 || ret == 0) {
|
||||
archive_set_error(f->archive, EIO,
|
||||
"Can't write to filter");
|
||||
@ -253,17 +343,19 @@ archive_compressor_program_write(struct archive_write_filter *f,
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish the compression...
|
||||
* Finish the filtering...
|
||||
*/
|
||||
static int
|
||||
archive_compressor_program_close(struct archive_write_filter *f)
|
||||
int
|
||||
__archive_write_program_close(struct archive_write_filter *f,
|
||||
struct archive_write_program_data *data)
|
||||
{
|
||||
struct private_data *data = (struct private_data *)f->data;
|
||||
int ret, r1, status;
|
||||
ssize_t bytes_read;
|
||||
|
||||
if (data->child == 0)
|
||||
return __archive_write_close_filter(f->next_filter);
|
||||
|
||||
ret = 0;
|
||||
close(data->child_stdin);
|
||||
data->child_stdin = -1;
|
||||
@ -304,6 +396,10 @@ archive_compressor_program_close(struct archive_write_filter *f)
|
||||
close(data->child_stdout);
|
||||
while (waitpid(data->child, &status, 0) == -1 && errno == EINTR)
|
||||
continue;
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
CloseHandle(data->child);
|
||||
#endif
|
||||
data->child = 0;
|
||||
|
||||
if (status != 0) {
|
||||
archive_set_error(f->archive, EIO,
|
||||
@ -314,16 +410,3 @@ archive_compressor_program_close(struct archive_write_filter *f)
|
||||
return (r1 < ret ? r1 : ret);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_compressor_program_free(struct archive_write_filter *f)
|
||||
{
|
||||
struct private_data *data = (struct private_data *)f->data;
|
||||
free(data->cmd);
|
||||
free(data->description);
|
||||
free(data->child_buf);
|
||||
free(data);
|
||||
f->data = NULL;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#endif /* !defined(HAVE_PIPE) || !defined(HAVE_VFORK) || !defined(HAVE_FCNTL) */
|
||||
|
@ -0,0 +1,305 @@
|
||||
/*-
|
||||
* Copyright (c) 2012 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_string.h"
|
||||
#include "archive_write_private.h"
|
||||
|
||||
#define LBYTES 45
|
||||
|
||||
struct private_uuencode {
|
||||
int mode;
|
||||
struct archive_string name;
|
||||
struct archive_string encoded_buff;
|
||||
size_t bs;
|
||||
size_t hold_len;
|
||||
unsigned char hold[LBYTES];
|
||||
};
|
||||
|
||||
static int archive_filter_uuencode_options(struct archive_write_filter *,
|
||||
const char *, const char *);
|
||||
static int archive_filter_uuencode_open(struct archive_write_filter *);
|
||||
static int archive_filter_uuencode_write(struct archive_write_filter *,
|
||||
const void *, size_t);
|
||||
static int archive_filter_uuencode_close(struct archive_write_filter *);
|
||||
static int archive_filter_uuencode_free(struct archive_write_filter *);
|
||||
static void uu_encode(struct archive_string *, const unsigned char *, size_t);
|
||||
static int64_t atol8(const char *, size_t);
|
||||
|
||||
/*
|
||||
* Add a compress filter to this write handle.
|
||||
*/
|
||||
int
|
||||
archive_write_add_filter_uuencode(struct archive *_a)
|
||||
{
|
||||
struct archive_write *a = (struct archive_write *)_a;
|
||||
struct archive_write_filter *f = __archive_write_allocate_filter(_a);
|
||||
struct private_uuencode *state;
|
||||
|
||||
archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_write_add_filter_uu");
|
||||
|
||||
state = (struct private_uuencode *)calloc(1, sizeof(*state));
|
||||
if (state == NULL) {
|
||||
archive_set_error(f->archive, ENOMEM,
|
||||
"Can't allocate data for uuencode filter");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
archive_strcpy(&state->name, "-");
|
||||
state->mode = 0644;
|
||||
|
||||
f->data = state;
|
||||
f->name = "uuencode";
|
||||
f->code = ARCHIVE_FILTER_UU;
|
||||
f->open = archive_filter_uuencode_open;
|
||||
f->options = archive_filter_uuencode_options;
|
||||
f->write = archive_filter_uuencode_write;
|
||||
f->close = archive_filter_uuencode_close;
|
||||
f->free = archive_filter_uuencode_free;
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set write options.
|
||||
*/
|
||||
static int
|
||||
archive_filter_uuencode_options(struct archive_write_filter *f, const char *key,
|
||||
const char *value)
|
||||
{
|
||||
struct private_uuencode *state = (struct private_uuencode *)f->data;
|
||||
|
||||
if (strcmp(key, "mode") == 0) {
|
||||
if (value == NULL) {
|
||||
archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
|
||||
"mode option requires octal digits");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
state->mode = (int)atol8(value, strlen(value)) & 0777;
|
||||
return (ARCHIVE_OK);
|
||||
} else if (strcmp(key, "name") == 0) {
|
||||
if (value == NULL) {
|
||||
archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
|
||||
"name option requires a string");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
archive_strcpy(&state->name, value);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/* Note: The "warn" return is just to inform the options
|
||||
* supervisor that we didn't handle it. It will generate
|
||||
* a suitable error if no one used this option. */
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup callback.
|
||||
*/
|
||||
static int
|
||||
archive_filter_uuencode_open(struct archive_write_filter *f)
|
||||
{
|
||||
struct private_uuencode *state = (struct private_uuencode *)f->data;
|
||||
size_t bs = 65536, bpb;
|
||||
int ret;
|
||||
|
||||
ret = __archive_write_open_filter(f->next_filter);
|
||||
if (ret != ARCHIVE_OK)
|
||||
return (ret);
|
||||
|
||||
if (f->archive->magic == ARCHIVE_WRITE_MAGIC) {
|
||||
/* Buffer size should be a multiple number of the of bytes
|
||||
* per block for performance. */
|
||||
bpb = archive_write_get_bytes_per_block(f->archive);
|
||||
if (bpb > bs)
|
||||
bs = bpb;
|
||||
else if (bpb != 0)
|
||||
bs -= bs % bpb;
|
||||
}
|
||||
|
||||
state->bs = bs;
|
||||
if (archive_string_ensure(&state->encoded_buff, bs + 512) == NULL) {
|
||||
archive_set_error(f->archive, ENOMEM,
|
||||
"Can't allocate data for uuencode buffer");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
archive_string_sprintf(&state->encoded_buff, "begin %o %s\n",
|
||||
state->mode, state->name.s);
|
||||
|
||||
f->data = state;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
uu_encode(struct archive_string *as, const unsigned char *p, size_t len)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = (int)len;
|
||||
archive_strappend_char(as, c?c + 0x20:'`');
|
||||
for (; len >= 3; p += 3, len -= 3) {
|
||||
c = p[0] >> 2;
|
||||
archive_strappend_char(as, c?c + 0x20:'`');
|
||||
c = ((p[0] & 0x03) << 4) | ((p[1] & 0xf0) >> 4);
|
||||
archive_strappend_char(as, c?c + 0x20:'`');
|
||||
c = ((p[1] & 0x0f) << 2) | ((p[2] & 0xc0) >> 6);
|
||||
archive_strappend_char(as, c?c + 0x20:'`');
|
||||
c = p[2] & 0x3f;
|
||||
archive_strappend_char(as, c?c + 0x20:'`');
|
||||
}
|
||||
if (len > 0) {
|
||||
c = p[0] >> 2;
|
||||
archive_strappend_char(as, c?c + 0x20:'`');
|
||||
c = (p[0] & 0x03) << 4;
|
||||
if (len == 1) {
|
||||
archive_strappend_char(as, c?c + 0x20:'`');
|
||||
archive_strappend_char(as, '`');
|
||||
archive_strappend_char(as, '`');
|
||||
} else {
|
||||
c |= (p[1] & 0xf0) >> 4;
|
||||
archive_strappend_char(as, c?c + 0x20:'`');
|
||||
c = (p[1] & 0x0f) << 2;
|
||||
archive_strappend_char(as, c?c + 0x20:'`');
|
||||
archive_strappend_char(as, '`');
|
||||
}
|
||||
}
|
||||
archive_strappend_char(as, '\n');
|
||||
}
|
||||
|
||||
/*
|
||||
* Write data to the encoded stream.
|
||||
*/
|
||||
static int
|
||||
archive_filter_uuencode_write(struct archive_write_filter *f, const void *buff,
|
||||
size_t length)
|
||||
{
|
||||
struct private_uuencode *state = (struct private_uuencode *)f->data;
|
||||
const unsigned char *p = buff;
|
||||
int ret = ARCHIVE_OK;
|
||||
|
||||
if (length == 0)
|
||||
return (ret);
|
||||
|
||||
if (state->hold_len) {
|
||||
while (state->hold_len < LBYTES && length > 0) {
|
||||
state->hold[state->hold_len++] = *p++;
|
||||
length--;
|
||||
}
|
||||
if (state->hold_len < LBYTES)
|
||||
return (ret);
|
||||
uu_encode(&state->encoded_buff, state->hold, LBYTES);
|
||||
state->hold_len = 0;
|
||||
}
|
||||
|
||||
for (; length >= LBYTES; length -= LBYTES, p += LBYTES)
|
||||
uu_encode(&state->encoded_buff, p, LBYTES);
|
||||
|
||||
/* Save remaining bytes. */
|
||||
if (length > 0) {
|
||||
memcpy(state->hold, p, length);
|
||||
state->hold_len = length;
|
||||
}
|
||||
while (archive_strlen(&state->encoded_buff) >= state->bs) {
|
||||
ret = __archive_write_filter(f->next_filter,
|
||||
state->encoded_buff.s, state->bs);
|
||||
memmove(state->encoded_buff.s,
|
||||
state->encoded_buff.s + state->bs,
|
||||
state->encoded_buff.length - state->bs);
|
||||
state->encoded_buff.length -= state->bs;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish the compression...
|
||||
*/
|
||||
static int
|
||||
archive_filter_uuencode_close(struct archive_write_filter *f)
|
||||
{
|
||||
struct private_uuencode *state = (struct private_uuencode *)f->data;
|
||||
int ret, ret2;
|
||||
|
||||
/* Flush remaining bytes. */
|
||||
if (state->hold_len != 0)
|
||||
uu_encode(&state->encoded_buff, state->hold, state->hold_len);
|
||||
archive_string_sprintf(&state->encoded_buff, "`\nend\n");
|
||||
/* Write the last block */
|
||||
archive_write_set_bytes_in_last_block(f->archive, 1);
|
||||
ret = __archive_write_filter(f->next_filter,
|
||||
state->encoded_buff.s, archive_strlen(&state->encoded_buff));
|
||||
ret2 = __archive_write_close_filter(f->next_filter);
|
||||
if (ret > ret2)
|
||||
ret = ret2;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_filter_uuencode_free(struct archive_write_filter *f)
|
||||
{
|
||||
struct private_uuencode *state = (struct private_uuencode *)f->data;
|
||||
|
||||
archive_string_free(&state->name);
|
||||
archive_string_free(&state->encoded_buff);
|
||||
free(state);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int64_t
|
||||
atol8(const char *p, size_t char_cnt)
|
||||
{
|
||||
int64_t l;
|
||||
int digit;
|
||||
|
||||
l = 0;
|
||||
while (char_cnt-- > 0) {
|
||||
if (*p >= '0' && *p <= '7')
|
||||
digit = *p - '0';
|
||||
else
|
||||
break;
|
||||
p++;
|
||||
l <<= 3;
|
||||
l |= digit;
|
||||
}
|
||||
return (l);
|
||||
}
|
||||
|
@ -172,7 +172,7 @@ archive_write_add_filter_xz(struct archive *_a)
|
||||
f = __archive_write_allocate_filter(_a);
|
||||
r = common_setup(f);
|
||||
if (r == ARCHIVE_OK) {
|
||||
f->code = ARCHIVE_COMPRESSION_XZ;
|
||||
f->code = ARCHIVE_FILTER_XZ;
|
||||
f->name = "xz";
|
||||
}
|
||||
return (r);
|
||||
@ -192,7 +192,7 @@ archive_write_add_filter_lzma(struct archive *_a)
|
||||
f = __archive_write_allocate_filter(_a);
|
||||
r = common_setup(f);
|
||||
if (r == ARCHIVE_OK) {
|
||||
f->code = ARCHIVE_COMPRESSION_LZMA;
|
||||
f->code = ARCHIVE_FILTER_LZMA;
|
||||
f->name = "lzma";
|
||||
}
|
||||
return (r);
|
||||
@ -209,7 +209,7 @@ archive_write_add_filter_lzip(struct archive *_a)
|
||||
f = __archive_write_allocate_filter(_a);
|
||||
r = common_setup(f);
|
||||
if (r == ARCHIVE_OK) {
|
||||
f->code = ARCHIVE_COMPRESSION_LZIP;
|
||||
f->code = ARCHIVE_FILTER_LZIP;
|
||||
f->name = "lzip";
|
||||
}
|
||||
return (r);
|
||||
@ -225,12 +225,12 @@ archive_compressor_xz_init_stream(struct archive_write_filter *f,
|
||||
data->stream = lzma_stream_init_data;
|
||||
data->stream.next_out = data->compressed;
|
||||
data->stream.avail_out = data->compressed_buffer_size;
|
||||
if (f->code == ARCHIVE_COMPRESSION_XZ)
|
||||
if (f->code == ARCHIVE_FILTER_XZ)
|
||||
ret = lzma_stream_encoder(&(data->stream),
|
||||
data->lzmafilters, LZMA_CHECK_CRC64);
|
||||
else if (f->code == ARCHIVE_COMPRESSION_LZMA)
|
||||
else if (f->code == ARCHIVE_FILTER_LZMA)
|
||||
ret = lzma_alone_encoder(&(data->stream), &data->lzma_opt);
|
||||
else { /* ARCHIVE_COMPRESSION_LZIP */
|
||||
else { /* ARCHIVE_FILTER_LZIP */
|
||||
int dict_size = data->lzma_opt.dict_size;
|
||||
int ds, log2dic, wedges;
|
||||
|
||||
@ -321,7 +321,7 @@ archive_compressor_xz_open(struct archive_write_filter *f)
|
||||
f->write = archive_compressor_xz_write;
|
||||
|
||||
/* Initialize compression library. */
|
||||
if (f->code == ARCHIVE_COMPRESSION_LZIP) {
|
||||
if (f->code == ARCHIVE_FILTER_LZIP) {
|
||||
const struct option_value *val =
|
||||
&option_values[data->compression_level];
|
||||
|
||||
@ -393,7 +393,7 @@ archive_compressor_xz_write(struct archive_write_filter *f,
|
||||
|
||||
/* Update statistics */
|
||||
data->total_in += length;
|
||||
if (f->code == ARCHIVE_COMPRESSION_LZIP)
|
||||
if (f->code == ARCHIVE_FILTER_LZIP)
|
||||
data->crc32 = lzma_crc32(buff, length, data->crc32);
|
||||
|
||||
/* Compress input data to output buffer */
|
||||
@ -422,7 +422,7 @@ archive_compressor_xz_close(struct archive_write_filter *f)
|
||||
ret = __archive_write_filter(f->next_filter,
|
||||
data->compressed,
|
||||
data->compressed_buffer_size - data->stream.avail_out);
|
||||
if (f->code == ARCHIVE_COMPRESSION_LZIP && ret == ARCHIVE_OK) {
|
||||
if (f->code == ARCHIVE_FILTER_LZIP && ret == ARCHIVE_OK) {
|
||||
archive_le32enc(data->compressed, data->crc32);
|
||||
archive_le64enc(data->compressed+4, data->total_in);
|
||||
archive_le64enc(data->compressed+12, data->total_out + 20);
|
||||
|
@ -43,7 +43,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_disk.c 201159 2009-12-29 0
|
||||
#include "archive_acl_private.h"
|
||||
#include "archive_write_disk_private.h"
|
||||
|
||||
#ifndef HAVE_POSIX_ACL
|
||||
#if !defined(HAVE_POSIX_ACL) || !defined(ACL_TYPE_NFS4)
|
||||
/* Default empty function body to satisfy mainline code. */
|
||||
int
|
||||
archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
|
||||
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user