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
acc60b03c1
@ -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 @@ success:
|
||||
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 @@ read_more:
|
||||
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 @@ read_more:
|
||||
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 @@ read_more:
|
||||
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 @@ read_more:
|
||||
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 @@ read_more:
|
||||
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 @@ read_more:
|
||||
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 @@ next_data:
|
||||
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 @@ next_data:
|
||||
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 @@ check_first_code:
|
||||
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 @@ exit_tmpfile:
|
||||
|
||||
#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 @@ cleanup:
|
||||
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 @@ cleanup:
|
||||
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…
x
Reference in New Issue
Block a user