mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-11-28 09:02:44 +00:00
Merge r491,493,500,507,510,530,543 from libarchive.googlecode.com:
This implements the new generic options framework that provides a way to override format- and compression-specific parameters.
This commit is contained in:
parent
ce54c7c56a
commit
634fb9dd48
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=189438
@ -384,6 +384,19 @@ __LA_DECL int archive_read_data_into_buffer(struct archive *,
|
||||
void *buffer, __LA_SSIZE_T len);
|
||||
__LA_DECL int archive_read_data_into_fd(struct archive *, int fd);
|
||||
|
||||
/*
|
||||
* Set read options.
|
||||
*/
|
||||
/* Apply option string to the format only. */
|
||||
__LA_DECL int archive_read_set_format_options(struct archive *_a,
|
||||
const char *s);
|
||||
/* Apply option string to the filter only. */
|
||||
__LA_DECL int archive_read_set_filter_options(struct archive *_a,
|
||||
const char *s);
|
||||
/* Apply option string to both the format and the filter. */
|
||||
__LA_DECL int archive_read_set_options(struct archive *_a,
|
||||
const char *s);
|
||||
|
||||
/*-
|
||||
* Convenience function to recreate the current entry (whose header
|
||||
* has just been read) on disk.
|
||||
@ -552,6 +565,20 @@ __LA_DECL void archive_write_finish(struct archive *);
|
||||
__LA_DECL int archive_write_finish(struct archive *);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set write options.
|
||||
*/
|
||||
/* Apply option string to the format only. */
|
||||
__LA_DECL int archive_write_set_format_options(struct archive *_a,
|
||||
const char *s);
|
||||
/* Apply option string to the compressor only. */
|
||||
__LA_DECL int archive_write_set_compressor_options(struct archive *_a,
|
||||
const char *s);
|
||||
/* Apply option string to both the format and the compressor. */
|
||||
__LA_DECL int archive_write_set_options(struct archive *_a,
|
||||
const char *s);
|
||||
|
||||
|
||||
/*-
|
||||
* To create objects on disk:
|
||||
* 1) Ask archive_write_disk_new for a new archive_write_disk object.
|
||||
|
@ -102,6 +102,9 @@ void __archive_check_magic(struct archive *, unsigned int magic,
|
||||
|
||||
void __archive_errx(int retvalue, const char *msg) __LA_DEAD;
|
||||
|
||||
int __archive_parse_options(const char *p, const char *fn,
|
||||
int keysize, char *key, int valsize, char *val);
|
||||
|
||||
#define err_combine(a,b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
#endif
|
||||
|
@ -108,6 +108,95 @@ archive_read_extract_set_skip_file(struct archive *_a, dev_t d, ino_t i)
|
||||
a->skip_file_ino = i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set read options for the format.
|
||||
*/
|
||||
int
|
||||
archive_read_set_format_options(struct archive *_a, const char *s)
|
||||
{
|
||||
struct archive_read *a;
|
||||
char key[64], val[64];
|
||||
int len, r;
|
||||
|
||||
a = (struct archive_read *)_a;
|
||||
if (a->format == NULL || a->format->options == NULL ||
|
||||
a->format->name == NULL)
|
||||
/* This format does not support option. */
|
||||
return (ARCHIVE_OK);
|
||||
|
||||
while ((len = __archive_parse_options(s, a->format->name,
|
||||
sizeof(key), key, sizeof(val), val)) > 0) {
|
||||
if (val[0] == '\0')
|
||||
r = a->format->options(a, key, NULL);
|
||||
else
|
||||
r = a->format->options(a, key, val);
|
||||
if (r == ARCHIVE_FATAL)
|
||||
return (r);
|
||||
s += len;
|
||||
}
|
||||
if (len < 0) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Illegal format options.");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set read options for the filter.
|
||||
*/
|
||||
int
|
||||
archive_read_set_filter_options(struct archive *_a, const char *s)
|
||||
{
|
||||
struct archive_read *a;
|
||||
struct archive_read_filter *filter;
|
||||
struct archive_read_filter_bidder *bidder;
|
||||
char key[64], val[64];
|
||||
int len, r;
|
||||
|
||||
a = (struct archive_read *)_a;
|
||||
filter = a->filter;
|
||||
len = 0;
|
||||
for (filter = a->filter; filter != NULL; filter = filter->upstream) {
|
||||
bidder = filter->bidder;
|
||||
if (bidder->options == NULL)
|
||||
/* This bidder does not support option */
|
||||
continue;
|
||||
while ((len = __archive_parse_options(s, filter->name,
|
||||
sizeof(key), key, sizeof(val), val)) > 0) {
|
||||
if (val[0] == '\0')
|
||||
r = bidder->options(bidder, key, NULL);
|
||||
else
|
||||
r = bidder->options(bidder, key, val);
|
||||
if (r == ARCHIVE_FATAL)
|
||||
return (r);
|
||||
s += len;
|
||||
}
|
||||
}
|
||||
if (len < 0) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Illegal format options.");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set read options for the format and the filter.
|
||||
*/
|
||||
int
|
||||
archive_read_set_options(struct archive *_a, const char *s)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = archive_read_set_format_options(_a, s);
|
||||
if (r != ARCHIVE_OK)
|
||||
return (r);
|
||||
r = archive_read_set_filter_options(_a, s);
|
||||
if (r != ARCHIVE_OK)
|
||||
return (r);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Open the archive
|
||||
@ -658,7 +747,9 @@ _archive_read_finish(struct archive *_a)
|
||||
int
|
||||
__archive_read_register_format(struct archive_read *a,
|
||||
void *format_data,
|
||||
const char *name,
|
||||
int (*bid)(struct archive_read *),
|
||||
int (*options)(struct archive_read *, const char *, const char *),
|
||||
int (*read_header)(struct archive_read *, struct archive_entry *),
|
||||
int (*read_data)(struct archive_read *, const void **, size_t *, off_t *),
|
||||
int (*read_data_skip)(struct archive_read *),
|
||||
@ -677,11 +768,13 @@ __archive_read_register_format(struct archive_read *a,
|
||||
return (ARCHIVE_WARN); /* We've already installed */
|
||||
if (a->formats[i].bid == NULL) {
|
||||
a->formats[i].bid = bid;
|
||||
a->formats[i].options = options;
|
||||
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].cleanup = cleanup;
|
||||
a->formats[i].data = format_data;
|
||||
a->formats[i].name = name;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
}
|
||||
|
@ -54,6 +54,9 @@ struct archive_read_filter_bidder {
|
||||
struct archive_read_filter *);
|
||||
/* Initialize a newly-created filter. */
|
||||
int (*init)(struct archive_read_filter *);
|
||||
/* Set an option for the filter bidder. */
|
||||
int (*options)(struct archive_read_filter_bidder *,
|
||||
const char *key, const char *value);
|
||||
/* Release the bidder's configuration data. */
|
||||
int (*free)(struct archive_read_filter_bidder *);
|
||||
};
|
||||
@ -149,7 +152,10 @@ struct archive_read {
|
||||
|
||||
struct archive_format_descriptor {
|
||||
void *data;
|
||||
const char *name;
|
||||
int (*bid)(struct archive_read *);
|
||||
int (*options)(struct archive_read *, const char *key,
|
||||
const char *value);
|
||||
int (*read_header)(struct archive_read *, struct archive_entry *);
|
||||
int (*read_data)(struct archive_read *, const void **, size_t *, off_t *);
|
||||
int (*read_data_skip)(struct archive_read *);
|
||||
@ -166,7 +172,9 @@ struct archive_read {
|
||||
|
||||
int __archive_read_register_format(struct archive_read *a,
|
||||
void *format_data,
|
||||
const char *name,
|
||||
int (*bid)(struct archive_read *),
|
||||
int (*options)(struct archive_read *, const char *, const char *),
|
||||
int (*read_header)(struct archive_read *, struct archive_entry *),
|
||||
int (*read_data)(struct archive_read *, const void **, size_t *, off_t *),
|
||||
int (*read_data_skip)(struct archive_read *),
|
||||
|
@ -84,6 +84,7 @@ archive_read_support_compression_bzip2(struct archive *_a)
|
||||
reader->data = NULL;
|
||||
reader->bid = bzip2_reader_bid;
|
||||
reader->init = bzip2_reader_init;
|
||||
reader->options = NULL;
|
||||
reader->free = bzip2_reader_free;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
@ -152,6 +152,7 @@ archive_read_support_compression_compress(struct archive *_a)
|
||||
bidder->data = NULL;
|
||||
bidder->bid = compress_bidder_bid;
|
||||
bidder->init = compress_bidder_init;
|
||||
bidder->options = NULL;
|
||||
bidder->free = compress_bidder_free;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
@ -90,7 +90,8 @@ archive_read_support_compression_gzip(struct archive *_a)
|
||||
bidder->data = NULL;
|
||||
bidder->bid = gzip_bidder_bid;
|
||||
bidder->init = gzip_bidder_init;
|
||||
bidder->free = NULL; /* No data, so no cleanup necessary. */
|
||||
bidder->options = NULL;
|
||||
bidder->free = NULL;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
|
@ -122,6 +122,7 @@ archive_read_support_compression_program(struct archive *_a, const char *cmd)
|
||||
bidder->data = state;
|
||||
bidder->bid = program_bidder_bid;
|
||||
bidder->init = program_bidder_init;
|
||||
bidder->options = NULL;
|
||||
bidder->free = program_bidder_free;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
@ -105,7 +105,9 @@ archive_read_support_format_ar(struct archive *_a)
|
||||
|
||||
r = __archive_read_register_format(a,
|
||||
ar,
|
||||
"ar",
|
||||
archive_read_format_ar_bid,
|
||||
NULL,
|
||||
archive_read_format_ar_read_header,
|
||||
archive_read_format_ar_read_data,
|
||||
archive_read_format_ar_skip,
|
||||
|
@ -150,7 +150,9 @@ archive_read_support_format_cpio(struct archive *_a)
|
||||
|
||||
r = __archive_read_register_format(a,
|
||||
cpio,
|
||||
"cpio",
|
||||
archive_read_format_cpio_bid,
|
||||
NULL,
|
||||
archive_read_format_cpio_read_header,
|
||||
archive_read_format_cpio_read_data,
|
||||
NULL,
|
||||
|
@ -43,8 +43,10 @@ archive_read_support_format_empty(struct archive *_a)
|
||||
int r;
|
||||
|
||||
r = __archive_read_register_format(a,
|
||||
NULL,
|
||||
NULL,
|
||||
archive_read_format_empty_bid,
|
||||
NULL,
|
||||
archive_read_format_empty_read_header,
|
||||
archive_read_format_empty_read_data,
|
||||
NULL,
|
||||
|
@ -279,7 +279,9 @@ archive_read_support_format_iso9660(struct archive *_a)
|
||||
|
||||
r = __archive_read_register_format(a,
|
||||
iso9660,
|
||||
"iso9660",
|
||||
archive_read_format_iso9660_bid,
|
||||
NULL,
|
||||
archive_read_format_iso9660_read_header,
|
||||
archive_read_format_iso9660_read_data,
|
||||
archive_read_format_iso9660_read_data_skip,
|
||||
|
@ -148,8 +148,8 @@ archive_read_support_format_mtree(struct archive *_a)
|
||||
memset(mtree, 0, sizeof(*mtree));
|
||||
mtree->fd = -1;
|
||||
|
||||
r = __archive_read_register_format(a, mtree,
|
||||
mtree_bid, read_header, read_data, skip, cleanup);
|
||||
r = __archive_read_register_format(a, mtree, "mtree",
|
||||
mtree_bid, NULL, read_header, read_data, skip, cleanup);
|
||||
|
||||
if (r != ARCHIVE_OK)
|
||||
free(mtree);
|
||||
|
@ -253,8 +253,9 @@ archive_read_support_format_tar(struct archive *_a)
|
||||
}
|
||||
memset(tar, 0, sizeof(*tar));
|
||||
|
||||
r = __archive_read_register_format(a, tar,
|
||||
r = __archive_read_register_format(a, tar, "tar",
|
||||
archive_read_format_tar_bid,
|
||||
NULL,
|
||||
archive_read_format_tar_read_header,
|
||||
archive_read_format_tar_read_data,
|
||||
archive_read_format_tar_skip,
|
||||
|
@ -153,7 +153,9 @@ archive_read_support_format_zip(struct archive *_a)
|
||||
|
||||
r = __archive_read_register_format(a,
|
||||
zip,
|
||||
"zip",
|
||||
archive_read_format_zip_bid,
|
||||
NULL,
|
||||
archive_read_format_zip_read_header,
|
||||
archive_read_format_zip_read_data,
|
||||
archive_read_format_zip_read_data_skip,
|
||||
|
@ -1,4 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2009 Michihiro NAKAJIMA
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -186,3 +187,195 @@ __archive_errx(int retvalue, const char *msg)
|
||||
write(2, "\n", 1);
|
||||
exit(retvalue);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse option strings
|
||||
* Detail of option format.
|
||||
* - The option can accept:
|
||||
* "opt-name", "!opt-name", "opt-name=value".
|
||||
*
|
||||
* - The option entries are separated by comma.
|
||||
* e.g "compression=9,opt=XXX,opt-b=ZZZ"
|
||||
*
|
||||
* - The name of option string consist of '-' and alphabet
|
||||
* but character '-' cannot be used for the first character.
|
||||
* (Regular expression is [a-z][-a-z]+)
|
||||
*
|
||||
* - For a specfic format/filter, using the format name with ':'.
|
||||
* e.g "zip:compression=9"
|
||||
* (This "compression=9" option entry is for "zip" format only)
|
||||
*
|
||||
* If another entries follow it, those are not for
|
||||
* the specfic format/filter.
|
||||
* e.g handle "zip:compression=9,opt=XXX,opt-b=ZZZ"
|
||||
* "zip" format/filter handler will get "compression=9"
|
||||
* all format/filter handler will get "opt=XXX"
|
||||
* all format/filter handler will get "opt-b=ZZZ"
|
||||
*
|
||||
* - Whitespace and tab are bypassed.
|
||||
*
|
||||
*/
|
||||
int
|
||||
__archive_parse_options(const char *p, const char *fn, int keysize, char *key,
|
||||
int valsize, char *val)
|
||||
{
|
||||
const char *p_org;
|
||||
int apply;
|
||||
int kidx, vidx;
|
||||
int negative;
|
||||
enum {
|
||||
/* Requested for initialization. */
|
||||
INIT,
|
||||
/* Finding format/filter-name and option-name. */
|
||||
F_BOTH,
|
||||
/* Finding option-name only.
|
||||
* (already detected format/filter-name) */
|
||||
F_NAME,
|
||||
/* Getting option-value. */
|
||||
G_VALUE,
|
||||
} state;
|
||||
|
||||
p_org = p;
|
||||
state = INIT;
|
||||
kidx = vidx = negative = 0;
|
||||
apply = 1;
|
||||
while (*p) {
|
||||
switch (state) {
|
||||
case INIT:
|
||||
kidx = vidx = 0;
|
||||
negative = 0;
|
||||
apply = 1;
|
||||
state = F_BOTH;
|
||||
break;
|
||||
case F_BOTH:
|
||||
case F_NAME:
|
||||
if ((*p >= 'a' && *p <= 'z') ||
|
||||
(*p >= '0' && *p <= '9') || *p == '-') {
|
||||
if (kidx == 0 && !(*p >= 'a' && *p <= 'z'))
|
||||
/* Illegal sequence. */
|
||||
return (-1);
|
||||
if (kidx >= keysize -1)
|
||||
/* Too many characters. */
|
||||
return (-1);
|
||||
key[kidx++] = *p++;
|
||||
} else if (*p == '!') {
|
||||
if (kidx != 0)
|
||||
/* Illegal sequence. */
|
||||
return (-1);
|
||||
negative = 1;
|
||||
++p;
|
||||
} else if (*p == ',') {
|
||||
if (kidx == 0)
|
||||
/* Illegal sequence. */
|
||||
return (-1);
|
||||
if (!negative)
|
||||
val[vidx++] = '1';
|
||||
/* We have got boolean option data. */
|
||||
++p;
|
||||
if (apply)
|
||||
goto complete;
|
||||
else
|
||||
/* This option does not apply to the
|
||||
* format which the fn variable
|
||||
* indicate. */
|
||||
state = INIT;
|
||||
} else if (*p == ':') {
|
||||
/* obuf data is format name */
|
||||
if (state == F_NAME)
|
||||
/* We already found it. */
|
||||
return (-1);
|
||||
if (kidx == 0)
|
||||
/* Illegal sequence. */
|
||||
return (-1);
|
||||
if (negative)
|
||||
/* We cannot accept "!format-name:". */
|
||||
return (-1);
|
||||
key[kidx] = '\0';
|
||||
if (strcmp(fn, key) != 0)
|
||||
/* This option does not apply to the
|
||||
* format which the fn variable
|
||||
* indicate. */
|
||||
apply = 0;
|
||||
kidx = 0;
|
||||
++p;
|
||||
state = F_NAME;
|
||||
} else if (*p == '=') {
|
||||
if (kidx == 0)
|
||||
/* Illegal sequence. */
|
||||
return (-1);
|
||||
if (negative)
|
||||
/* We cannot accept "!opt-name=value". */
|
||||
return (-1);
|
||||
++p;
|
||||
state = G_VALUE;
|
||||
} else if (*p == ' ') {
|
||||
/* Pass the space character */
|
||||
++p;
|
||||
} else {
|
||||
/* Illegal character. */
|
||||
return (-1);
|
||||
}
|
||||
break;
|
||||
case G_VALUE:
|
||||
if (*p == ',') {
|
||||
if (vidx == 0)
|
||||
/* Illegal sequence. */
|
||||
return (-1);
|
||||
/* We have got option data. */
|
||||
++p;
|
||||
if (apply)
|
||||
goto complete;
|
||||
else
|
||||
/* This option does not apply to the
|
||||
* format which the fn variable
|
||||
* indicate. */
|
||||
state = INIT;
|
||||
} else if (*p == ' ') {
|
||||
/* Pass the space character */
|
||||
++p;
|
||||
} else {
|
||||
if (vidx >= valsize -1)
|
||||
/* Too many characters. */
|
||||
return (-1);
|
||||
val[vidx++] = *p++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
case F_BOTH:
|
||||
case F_NAME:
|
||||
if (kidx != 0) {
|
||||
if (!negative)
|
||||
val[vidx++] = '1';
|
||||
/* We have got boolean option. */
|
||||
if (apply)
|
||||
/* This option apply to the format which the
|
||||
* fn variable indicate. */
|
||||
goto complete;
|
||||
}
|
||||
break;
|
||||
case G_VALUE:
|
||||
if (vidx == 0)
|
||||
/* Illegal sequence. */
|
||||
return (-1);
|
||||
/* We have got option value. */
|
||||
if (apply)
|
||||
/* This option apply to the format which the fn
|
||||
* variable indicate. */
|
||||
goto complete;
|
||||
break;
|
||||
case INIT:/* nothing */
|
||||
break;
|
||||
}
|
||||
|
||||
/* End of Option string. */
|
||||
return (0);
|
||||
|
||||
complete:
|
||||
key[kidx] = '\0';
|
||||
val[vidx] = '\0';
|
||||
/* Return a size which we've consumed for detecting option */
|
||||
return ((int)(p - p_org));
|
||||
}
|
||||
|
@ -124,6 +124,87 @@ archive_write_new(void)
|
||||
return (&a->archive);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set write options for the format. Returns 0 if successful.
|
||||
*/
|
||||
int
|
||||
archive_write_set_format_options(struct archive *_a, const char *s)
|
||||
{
|
||||
struct archive_write *a = (struct archive_write *)_a;
|
||||
char key[64], val[64];
|
||||
int len, r;
|
||||
|
||||
if (a->format_options == NULL)
|
||||
/* This format does not support option. */
|
||||
return (ARCHIVE_OK);
|
||||
|
||||
while ((len = __archive_parse_options(s, a->format_name,
|
||||
sizeof(key), key, sizeof(val), val)) > 0) {
|
||||
if (val[0] == '\0')
|
||||
r = a->format_options(a, key, NULL);
|
||||
else
|
||||
r = a->format_options(a, key, val);
|
||||
if (r == ARCHIVE_FATAL)
|
||||
return (r);
|
||||
s += len;
|
||||
}
|
||||
if (len < 0) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Illegal format options.");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set write options for the compressor. Returns 0 if successful.
|
||||
*/
|
||||
int
|
||||
archive_write_set_compressor_options(struct archive *_a, const char *s)
|
||||
{
|
||||
struct archive_write *a = (struct archive_write *)_a;
|
||||
char key[64], val[64];
|
||||
int len, r;
|
||||
|
||||
if (a->compressor.options == NULL)
|
||||
/* This compressor does not support option. */
|
||||
return (ARCHIVE_OK);
|
||||
|
||||
while ((len = __archive_parse_options(s, a->archive.compression_name,
|
||||
sizeof(key), key, sizeof(val), val)) > 0) {
|
||||
if (val[0] == '\0')
|
||||
r = a->compressor.options(a, key, NULL);
|
||||
else
|
||||
r = a->compressor.options(a, key, val);
|
||||
if (r == ARCHIVE_FATAL)
|
||||
return (r);
|
||||
s += len;
|
||||
}
|
||||
if (len < 0) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Illegal format options.");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set write options for the format and the compressor. Returns 0 if successful.
|
||||
*/
|
||||
int
|
||||
archive_write_set_options(struct archive *_a, const char *s)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = archive_write_set_format_options(_a, s);
|
||||
if (r != ARCHIVE_OK)
|
||||
return (r);
|
||||
r = archive_write_set_compressor_options(_a, s);
|
||||
if (r != ARCHIVE_OK)
|
||||
return (r);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the block size. Returns 0 if successful.
|
||||
*/
|
||||
|
@ -77,6 +77,8 @@ struct archive_write {
|
||||
void *data;
|
||||
void *config;
|
||||
int (*init)(struct archive_write *);
|
||||
int (*options)(struct archive_write *,
|
||||
const char *key, const char *value);
|
||||
int (*finish)(struct archive_write *);
|
||||
int (*write)(struct archive_write *, const void *, size_t);
|
||||
} compressor;
|
||||
@ -86,7 +88,10 @@ struct archive_write {
|
||||
* initialized by archive_write_set_format_XXX() calls.
|
||||
*/
|
||||
void *format_data;
|
||||
const char *format_name;
|
||||
int (*format_init)(struct archive_write *);
|
||||
int (*format_options)(struct archive_write *,
|
||||
const char *key, const char *value);
|
||||
int (*format_finish)(struct archive_write *);
|
||||
int (*format_destroy)(struct archive_write *);
|
||||
int (*format_finish_entry)(struct archive_write *);
|
||||
|
@ -61,6 +61,8 @@ struct private_data {
|
||||
unsigned char *compressed;
|
||||
size_t compressed_buffer_size;
|
||||
unsigned long crc;
|
||||
/* Options */
|
||||
int compression_level;
|
||||
};
|
||||
|
||||
|
||||
@ -73,6 +75,8 @@ struct private_data {
|
||||
|
||||
static int archive_compressor_gzip_finish(struct archive_write *);
|
||||
static int archive_compressor_gzip_init(struct archive_write *);
|
||||
static int archive_compressor_gzip_options(struct archive_write *,
|
||||
const char *, const char *);
|
||||
static int archive_compressor_gzip_write(struct archive_write *,
|
||||
const void *, size_t);
|
||||
static int drive_compressor(struct archive_write *, struct private_data *,
|
||||
@ -143,6 +147,7 @@ archive_compressor_gzip_init(struct archive_write *a)
|
||||
state->compressed_buffer_size = a->bytes_per_block;
|
||||
state->compressed = (unsigned char *)malloc(state->compressed_buffer_size);
|
||||
state->crc = crc32(0L, NULL, 0);
|
||||
state->compression_level = Z_DEFAULT_COMPRESSION;
|
||||
|
||||
if (state->compressed == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
@ -169,12 +174,13 @@ archive_compressor_gzip_init(struct archive_write *a)
|
||||
state->stream.next_out += 10;
|
||||
state->stream.avail_out -= 10;
|
||||
|
||||
a->compressor.options = archive_compressor_gzip_options;
|
||||
a->compressor.write = archive_compressor_gzip_write;
|
||||
a->compressor.finish = archive_compressor_gzip_finish;
|
||||
|
||||
/* Initialize compression library. */
|
||||
ret = deflateInit2(&(state->stream),
|
||||
Z_DEFAULT_COMPRESSION,
|
||||
state->compression_level,
|
||||
Z_DEFLATED,
|
||||
-15 /* < 0 to suppress zlib header */,
|
||||
8,
|
||||
@ -212,6 +218,57 @@ archive_compressor_gzip_init(struct archive_write *a)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set write options.
|
||||
*/
|
||||
static int
|
||||
archive_compressor_gzip_options(struct archive_write *a, const char *key,
|
||||
const char *value)
|
||||
{
|
||||
struct private_data *state;
|
||||
int ret;
|
||||
|
||||
state = (struct private_data *)a->compressor.data;
|
||||
if (strcmp(key, "compression-level") == 0) {
|
||||
int level;
|
||||
|
||||
if (value == NULL || !(value[0] >= '0' && value[0] <= '9') ||
|
||||
value[1] != '\0')
|
||||
return (ARCHIVE_WARN);
|
||||
level = value[0] - '0';
|
||||
if (level == state->compression_level)
|
||||
return (ARCHIVE_OK);
|
||||
|
||||
ret = deflateParams(&(state->stream), level,
|
||||
Z_DEFAULT_STRATEGY);
|
||||
if (ret == Z_OK) {
|
||||
state->compression_level = level;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
switch (ret) {
|
||||
case Z_STREAM_ERROR:
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Internal error updating params "
|
||||
"compression library: state was inconsistent "
|
||||
"or parameter was invalid");
|
||||
break;
|
||||
case Z_BUF_ERROR:
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Internal error updating params "
|
||||
"compression library: out buffer was zero");
|
||||
break;
|
||||
default:
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Internal error updatng params "
|
||||
"compression library");
|
||||
break;
|
||||
}
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write data to the compressed stream.
|
||||
*/
|
||||
|
@ -125,6 +125,7 @@ archive_write_set_format_ar(struct archive_write *a)
|
||||
memset(ar, 0, sizeof(*ar));
|
||||
a->format_data = ar;
|
||||
|
||||
a->format_name = "ar";
|
||||
a->format_write_header = archive_write_ar_header;
|
||||
a->format_write_data = archive_write_ar_data;
|
||||
a->format_finish = archive_write_ar_finish;
|
||||
|
@ -92,6 +92,7 @@ archive_write_set_format_cpio(struct archive *_a)
|
||||
a->format_data = cpio;
|
||||
|
||||
a->pad_uncompressed = 1;
|
||||
a->format_name = "cpio";
|
||||
a->format_write_header = archive_write_cpio_header;
|
||||
a->format_write_data = archive_write_cpio_data;
|
||||
a->format_finish_entry = archive_write_cpio_finish_entry;
|
||||
|
@ -97,6 +97,7 @@ archive_write_set_format_cpio_newc(struct archive *_a)
|
||||
a->format_data = cpio;
|
||||
|
||||
a->pad_uncompressed = 1;
|
||||
a->format_name = "cpio";
|
||||
a->format_write_header = archive_write_newc_header;
|
||||
a->format_write_data = archive_write_newc_data;
|
||||
a->format_finish_entry = archive_write_newc_finish_entry;
|
||||
|
@ -107,6 +107,20 @@ archive_write_mtree_header(struct archive_write *a,
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
strappend_bin(struct archive_string *s, const unsigned char *bin, int n)
|
||||
{
|
||||
static const char hex[] = "0123456789abcdef";
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
archive_strappend_char(s, hex[bin[i] >> 4]);
|
||||
archive_strappend_char(s, hex[bin[i] & 0x0f]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
archive_write_mtree_finish_entry(struct archive_write *a)
|
||||
{
|
||||
@ -248,6 +262,7 @@ archive_write_set_format_mtree(struct archive *_a)
|
||||
a->format_destroy = archive_write_mtree_destroy;
|
||||
|
||||
a->pad_uncompressed = 0;
|
||||
a->format_name = "mtree";
|
||||
a->format_write_header = archive_write_mtree_header;
|
||||
a->format_finish = archive_write_mtree_finish;
|
||||
a->format_write_data = archive_write_mtree_data;
|
||||
|
@ -111,6 +111,7 @@ archive_write_set_format_pax(struct archive *_a)
|
||||
a->format_data = pax;
|
||||
|
||||
a->pad_uncompressed = 1;
|
||||
a->format_name = "pax";
|
||||
a->format_write_header = archive_write_pax_header;
|
||||
a->format_write_data = archive_write_pax_data;
|
||||
a->format_finish = archive_write_pax_finish;
|
||||
|
@ -121,6 +121,7 @@ archive_write_set_format_shar(struct archive *_a)
|
||||
a->format_data = shar;
|
||||
|
||||
a->pad_uncompressed = 0;
|
||||
a->format_name = "shar";
|
||||
a->format_write_header = archive_write_shar_header;
|
||||
a->format_finish = archive_write_shar_finish;
|
||||
a->format_destroy = archive_write_shar_destroy;
|
||||
|
@ -181,6 +181,7 @@ archive_write_set_format_ustar(struct archive *_a)
|
||||
a->format_data = ustar;
|
||||
|
||||
a->pad_uncompressed = 1; /* Mimic gtar in this respect. */
|
||||
a->format_name = "ustar";
|
||||
a->format_write_header = archive_write_ustar_header;
|
||||
a->format_write_data = archive_write_ustar_data;
|
||||
a->format_finish = archive_write_ustar_finish;
|
||||
|
Loading…
Reference in New Issue
Block a user