From: Michihiro NAKAJIMA Date: Wed, 10 Oct 2012 22:33:00 +0000 (+0900) Subject: Improve archive_write_filter_program handing to be able to X-Git-Tag: v3.1.0~40^2~57 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9e454d6753f7a939e0eb9b0f1eaa454683842d60;p=thirdparty%2Flibarchive.git Improve archive_write_filter_program handing to be able to use options for an external program from archive_write_filter_{grzip,lrzip,lzop}. --- diff --git a/libarchive/archive_write_add_filter_grzip.c b/libarchive/archive_write_add_filter_grzip.c index 6c0478c34..b5255903a 100644 --- a/libarchive/archive_write_add_filter_grzip.c +++ b/libarchive/archive_write_add_filter_grzip.c @@ -27,19 +27,118 @@ __FBSDID("$FreeBSD$"); +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#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) +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. */ + 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) { - char * const argv[] = { "grzip", NULL }; + struct write_grzip *data = (struct write_grzip *)f->data; int r; - r = __archive_write_programv(a, "grzip", ARCHIVE_FILTER_GRZIP, - "grzip", argv); - if (r == ARCHIVE_OK) - /* This filter always uses an external program. */ - r = ARCHIVE_WARN; + r = __archive_write_program_set_cmd(data->pdata, "grzip"); + if (r != ARCHIVE_OK) + goto memerr; + r = __archive_write_program_add_arg(data->pdata, "grzip"); + if (r != ARCHIVE_OK) + goto memerr; + r = __archive_write_program_open(f, data->pdata); return (r); +memerr: + archive_set_error(f->archive, ENOMEM, "Can't allocate memory"); + return (ARCHIVE_FATAL); +} + +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); } diff --git a/libarchive/archive_write_add_filter_lrzip.c b/libarchive/archive_write_add_filter_lrzip.c index 917b2b83e..1f27f686d 100644 --- a/libarchive/archive_write_add_filter_lrzip.c +++ b/libarchive/archive_write_add_filter_lrzip.c @@ -27,19 +27,122 @@ __FBSDID("$FreeBSD$"); +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif + #include "archive.h" #include "archive_write_private.h" +struct write_lrzip { + struct archive_write_program_data *pdata; +}; + +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) +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. */ + return (ARCHIVE_WARN); +} + +static int +archive_write_lrzip_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_lrzip_open(struct archive_write_filter *f) { - char * const argv[] = { "lrzip", "-q", NULL }; + struct write_lrzip *data = (struct write_lrzip *)f->data; int r; - r = __archive_write_programv(a, "lrzip", ARCHIVE_FILTER_LRZIP, - "lrzip", argv); - if (r == ARCHIVE_OK) - /* This filter always uses an external program. */ - r = ARCHIVE_WARN; + r = __archive_write_program_set_cmd(data->pdata, "lrzip"); + if (r != ARCHIVE_OK) + goto memerr; + r = __archive_write_program_add_arg(data->pdata, "lrzip"); + if (r != ARCHIVE_OK) + goto memerr; + r = __archive_write_program_add_arg(data->pdata, "-q"); + if (r != ARCHIVE_OK) + goto memerr; + + r = __archive_write_program_open(f, data->pdata); return (r); +memerr: + archive_set_error(f->archive, ENOMEM, "Can't allocate memory"); + return (ARCHIVE_FATAL); +} + +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); } diff --git a/libarchive/archive_write_add_filter_lzop.c b/libarchive/archive_write_add_filter_lzop.c index d453438f3..59ab99315 100644 --- a/libarchive/archive_write_add_filter_lzop.c +++ b/libarchive/archive_write_add_filter_lzop.c @@ -27,19 +27,118 @@ __FBSDID("$FreeBSD$"); +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif + #include "archive.h" #include "archive_write_private.h" +struct write_lzop { + struct archive_write_program_data *pdata; +}; + +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 *); + int -archive_write_add_filter_lzop(struct archive *a) +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); + } + 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 = "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; + + /* Note: This filter always uses an external program, so we + * return "warn" to inform of the fact. */ + return (ARCHIVE_WARN); +} + +static int +archive_write_lzop_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_lzop_open(struct archive_write_filter *f) { - char * const argv[] = { "lzop", NULL }; + struct write_lzop *data = (struct write_lzop *)f->data; int r; - r = __archive_write_programv(a, "lzop", ARCHIVE_FILTER_LZOP, - "lzop", argv); - /* Return ARCHIVE_WARN since this always uses an external program. */ - if (r == ARCHIVE_OK) - r = ARCHIVE_WARN; + r = __archive_write_program_set_cmd(data->pdata, "lzop"); + if (r != ARCHIVE_OK) + goto memerr; + r = __archive_write_program_add_arg(data->pdata, "lzop"); + if (r != ARCHIVE_OK) + goto memerr; + r = __archive_write_program_open(f, data->pdata); return (r); +memerr: + archive_set_error(f->archive, ENOMEM, "Can't allocate memory"); + return (ARCHIVE_FATAL); +} + +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); +} + +static int +archive_write_lzop_free(struct archive_write_filter *f) +{ + struct write_lzop *data = (struct write_lzop *)f->data; + + __archive_write_program_free(data->pdata); + free(data); + return (ARCHIVE_OK); } diff --git a/libarchive/archive_write_add_filter_program.c b/libarchive/archive_write_add_filter_program.c index cccf70597..d80442eff 100644 --- a/libarchive/archive_write_add_filter_program.c +++ b/libarchive/archive_write_add_filter_program.c @@ -58,10 +58,10 @@ archive_write_set_compression_program(struct archive *a, const char *cmd) } #endif -struct private_data { +struct archive_write_program_data { char *cmd; char **argv; - struct archive_string description; + int argc; #if defined(_WIN32) && !defined(__CYGWIN__) HANDLE child; #else @@ -73,12 +73,19 @@ struct private_data { size_t child_buf_len, child_buf_avail; }; +struct private_data { + struct archive_write_program_data *pdata; + struct archive_string description; +}; + static int archive_compressor_program_open(struct archive_write_filter *); static int archive_compressor_program_write(struct archive_write_filter *, const void *, size_t); static int archive_compressor_program_close(struct archive_write_filter *); static int archive_compressor_program_free(struct archive_write_filter *); +static int init_filter_program(struct archive *, + struct archive_write_program_data *data); /* * Add a filter to this write handle that passes all data through an * external program. @@ -86,81 +93,70 @@ static int archive_compressor_program_free(struct archive_write_filter *); int archive_write_add_filter_program(struct archive *_a, const char *cmd) { - char *argv[2]; + struct archive_write_program_data *pdata; int r; archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, "archive_write_add_filter_program"); - argv[0] = strdup(cmd); - if (argv[0] == NULL) { - archive_set_error(_a, ENOMEM, - "Can't allocate memory for filter program"); - return (ARCHIVE_FATAL); - } - argv[1] = NULL; - r = __archive_write_programv(_a, NULL, ARCHIVE_FILTER_PROGRAM, - cmd, argv); - free(argv[0]); - return (r); + pdata = __archive_write_program_allocate(); + if (pdata == NULL) + goto memerr; + r = __archive_write_program_set_cmd(pdata, cmd); + if (r != ARCHIVE_OK) + goto memerr; + r = __archive_write_program_add_arg(pdata, cmd); + if (r != ARCHIVE_OK) + goto memerr; + r = init_filter_program(_a, pdata); + if (r == ARCHIVE_OK) + return (r); +memerr: + __archive_write_program_free(pdata); + archive_set_error(_a, ENOMEM, + "Can't allocate memory for filter program"); + return (ARCHIVE_FATAL); } int archive_write_add_filter_programl(struct archive *_a, const char *cmd, const char *arg, ...) { + struct archive_write_program_data *pdata; va_list ap; - char **argv; char *val; - int i, r; + int r; archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, "archive_write_add_filter_programl"); - i = 2; - if (arg != NULL) { - va_start(ap, arg); - while (va_arg(ap, char *) != NULL) - i++; - va_end(ap); - } - argv = malloc(i * sizeof(char *)); - if (argv == NULL) + pdata = __archive_write_program_allocate(); + if (pdata == NULL) + goto memerr; + r = __archive_write_program_set_cmd(pdata, cmd); + if (r != ARCHIVE_OK) goto memerr; - if (arg != NULL) { - argv[0] = strdup(arg); - if (argv[0] == NULL) + r = __archive_write_program_add_arg(pdata, arg); + if (r != ARCHIVE_OK) goto memerr; - i = 1; va_start(ap, arg); while ((val = va_arg(ap, char *)) != NULL) { - argv[i] = strdup(val); - if (argv[i] == NULL) + r = __archive_write_program_add_arg(pdata, val); + if (r != ARCHIVE_OK) goto memerr; - i++; } va_end(ap); - argv[i] = NULL; } else { - argv[0] = strdup(cmd); - if (argv[0] == NULL) + r = __archive_write_program_add_arg(pdata, cmd); + if (r != ARCHIVE_OK) goto memerr; - argv[1] = NULL; } - - r = __archive_write_programv(_a, NULL, ARCHIVE_FILTER_PROGRAM, - cmd, argv); - for (i = 0; argv[i] != NULL; i++) - free(argv[i]); - free(argv); - return (r); + r = init_filter_program(_a, pdata); + if (r == ARCHIVE_OK) + return (r); memerr: - if (argv) { - for (i = 0; argv[i] != NULL; i++) - free(argv[i]); - free(argv); - } + __archive_write_program_free(pdata); archive_set_error(_a, ENOMEM, "Can't allocate memory for filter program"); return (ARCHIVE_FATAL); @@ -170,17 +166,44 @@ int archive_write_add_filter_programv(struct archive *_a, const char *cmd, char * const argv[]) { + struct archive_write_program_data *pdata; + int i, r; archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, "archive_write_add_filter_programv"); - return __archive_write_programv(_a, NULL, ARCHIVE_FILTER_PROGRAM, - cmd, argv); + pdata = __archive_write_program_allocate(); + if (pdata == NULL) + goto memerr; + r = __archive_write_program_set_cmd(pdata, cmd); + if (r != ARCHIVE_OK) + goto memerr; + for (i = 0; argv[i] != NULL; i++) { + r = __archive_write_program_add_arg(pdata, argv[i]); + if (r != ARCHIVE_OK) + goto memerr; + } + if (i == 0) { + r = __archive_write_program_add_arg(pdata, cmd); + if (r != ARCHIVE_OK) + goto memerr; + } + r = init_filter_program(_a, pdata); + if (r == ARCHIVE_OK) + return (r); +memerr: + __archive_write_program_free(pdata); + archive_set_error(_a, ENOMEM, + "Can't allocate memory for filter program"); + return (ARCHIVE_FATAL); } -int -__archive_write_programv(struct archive *_a, const char *name, int code, - const char *cmd, char * const argv[]) +/* + * Setup callback. + */ +static int +init_filter_program(struct archive *_a, + struct archive_write_program_data *pdata) { struct archive_write_filter *f = __archive_write_allocate_filter(_a); @@ -192,57 +215,162 @@ __archive_write_programv(struct archive *_a, const char *name, int code, data = calloc(1, sizeof(*data)); if (data == NULL) goto memerr; - data->cmd = strdup(cmd); - if (data->cmd == NULL) - goto memerr; + l = strlen(prefix) + strlen(pdata->cmd) + 1; + for (i = 0; pdata->argv[i] != NULL; i++) + l += strlen(pdata->argv[i]) + 1; - /* Reproduce argv. */ - for (i = 0; argv[i] != NULL; i++) - ; - data->argv = calloc(i + 1, sizeof(char *)); - if (data->argv == NULL) + /* Make up a description string. */ + if (archive_string_ensure(&data->description, l) == NULL) goto memerr; - l = strlen(prefix) + strlen(cmd) + 1; - for (i = 0; argv[i] != NULL; i++) { - data->argv[i] = strdup(argv[i]); - if (data->argv[i] == NULL) - goto memerr; - l += strlen(data->argv[i]) + 1; + archive_strcpy(&data->description, prefix); + archive_strcat(&data->description, pdata->cmd); + for (i = 0; pdata->argv[i] != NULL; i++) { + archive_strappend_char(&data->description, ' '); + archive_strcat(&data->description, pdata->argv[i]); } - - if (name == NULL) { - /* Make up a description string. */ - if (archive_string_ensure(&data->description, l) == NULL) - goto memerr; - archive_strcpy(&data->description, prefix); - archive_strcat(&data->description, cmd); - for (i = 0; argv[i] != NULL; i++) { - archive_strappend_char(&data->description, ' '); - archive_strcat(&data->description, data->argv[i]); - } - f->name = data->description.s; - } else - f->name = name; - f->code = code; + data->pdata = pdata; + f->name = data->description.s; + f->code = ARCHIVE_FILTER_PROGRAM; f->data = data; - f->open = &archive_compressor_program_open; + 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: - free(data); 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); +} + +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; + + archive_string_free(&data->description); + __archive_write_program_free(data->pdata); + free(data); + 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->cmd); + if (data->argv != NULL) { + int i; + for (i = 0; data->argv[i] != NULL; i++) + free(data->argv[i]); + free(data->argv); + } + free(data->child_buf); + free(data); + } + return (ARCHIVE_OK); +} + +/* + * Set the program path. + */ +int +__archive_write_program_set_cmd(struct archive_write_program_data *data, + const char *cmd) +{ + char *newptr; + + newptr = realloc(data->cmd, strlen(cmd) + 1); + if (newptr == NULL) + return (ARCHIVE_FATAL); + data->cmd = newptr; + strcpy(data->cmd, cmd); + return (ARCHIVE_OK); +} + +/* + * Add a argument for the program. + */ +int +__archive_write_program_add_arg(struct archive_write_program_data *data, + const char *arg) +{ + char **newargv; + int i; + + if (data->cmd == NULL) + return (ARCHIVE_FATAL); + + newargv = realloc(data->argv, (data->argc + 2) * sizeof(char *)); + if (newargv == NULL) + return (ARCHIVE_FATAL); + if (newargv != data->argv && data->argv != NULL) { + for (i = 0; i <= data->argc; i++) + newargv[i] = data->argv[i]; + } + 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); +} + +int +__archive_write_program_open(struct archive_write_filter *f, + struct archive_write_program_data *data) +{ pid_t child; int ret; @@ -262,7 +390,7 @@ archive_compressor_program_open(struct archive_write_filter *f) } } - child = __archive_create_child(data->cmd, (char * const *)data->argv, + child = __archive_create_child(data->cmd, data->argv, &data->child_stdin, &data->child_stdout); if (child == -1) { archive_set_error(f->archive, EINVAL, @@ -283,16 +411,13 @@ archive_compressor_program_open(struct archive_write_filter *f) #else data->child = child; #endif - - f->write = archive_compressor_program_write; - f->close = archive_compressor_program_close; - return (0); + 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) @@ -355,18 +480,21 @@ child_write(struct archive_write_filter *f, const char *buf, size_t buf_len) } /* - * 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"); @@ -378,17 +506,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_OK); + ret = 0; close(data->child_stdin); data->child_stdin = -1; @@ -443,27 +573,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; - - if (data) { -#if defined(_WIN32) && !defined(__CYGWIN__) - if (data->child) - CloseHandle(data->child); -#endif - if (data->argv != NULL) { - int i; - for (i = 0; data->argv[i] != NULL; i++) - free(data->argv[i]); - free(data->argv); - } - free(data->cmd); - archive_string_free(&data->description); - free(data->child_buf); - free(data); - f->data = NULL; - } - return (ARCHIVE_OK); -} diff --git a/libarchive/archive_write_private.h b/libarchive/archive_write_private.h index 5a311f3ca..2f31428d4 100644 --- a/libarchive/archive_write_private.h +++ b/libarchive/archive_write_private.h @@ -133,8 +133,17 @@ __archive_write_format_header_ustar(struct archive_write *, char buff[512], struct archive_entry *, int tartype, int strict, struct archive_string_conv *); -int -__archive_write_programv(struct archive *, const char *, int, const char *, - char * const *); - +struct archive_write_program_data; +struct archive_write_program_data * __archive_write_program_allocate(void); +int __archive_write_program_free(struct archive_write_program_data *); +int __archive_write_program_open(struct archive_write_filter *, + struct archive_write_program_data *); +int __archive_write_program_close(struct archive_write_filter *, + struct archive_write_program_data *); +int __archive_write_program_write(struct archive_write_filter *, + struct archive_write_program_data *, const void *, size_t); +int __archive_write_program_set_cmd(struct archive_write_program_data *, + const char *); +int __archive_write_program_add_arg(struct archive_write_program_data *, + const char *); #endif