From: Michihiro NAKAJIMA Date: Thu, 11 Oct 2012 02:13:20 +0000 (+0900) Subject: Parse a command line instead of using X-Git-Tag: v3.1.0~40^2~54 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5ebbfd1fa7f2a82abbfff8af284777324ce9077b;p=thirdparty%2Flibarchive.git Parse a command line instead of using archive_write_add_filter_programl, archive_write_add_filter_programv, archive_read_support_filter_programl, archive_read_support_filter_programv, archive_read_support_filter_programl_signature and archive_read_support_filter_programv_signature. And so remove those functions, which I recently added. --- diff --git a/Makefile.am b/Makefile.am index 5052643b6..74770b845 100644 --- a/Makefile.am +++ b/Makefile.am @@ -90,6 +90,8 @@ libarchive_la_SOURCES= \ libarchive/archive_acl.c \ libarchive/archive_acl_private.h \ libarchive/archive_check_magic.c \ + libarchive/archive_cmdline.c \ + libarchive/archive_cmdline_private.h \ libarchive/archive_crc32.h \ libarchive/archive_crypto.c \ libarchive/archive_crypto_private.h \ diff --git a/libarchive/CMakeLists.txt b/libarchive/CMakeLists.txt index 4bdb648e1..2d9809b23 100644 --- a/libarchive/CMakeLists.txt +++ b/libarchive/CMakeLists.txt @@ -15,6 +15,9 @@ SET(include_HEADERS SET(libarchive_SOURCES archive_acl.c archive_check_magic.c + archive_cmdline.c + archive_cmdline_private.h + archive_crc32.h archive_crypto.c archive_crypto_private.h archive_endian.h diff --git a/libarchive/archive.h b/libarchive/archive.h index dd3e1906a..d73e62519 100644 --- a/libarchive/archive.h +++ b/libarchive/archive.h @@ -348,23 +348,9 @@ __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_programl(struct archive *, - const char *command, const char *arg, - .../* (char *)0 */); -__LA_DECL int archive_read_support_filter_programv(struct archive *, - const char *command, char * const argv[]); __LA_DECL int archive_read_support_filter_program_signature (struct archive *, const char * /* cmd */, const void * /* match */, size_t); -__LA_DECL int archive_read_support_filter_programl_signature - (struct archive *, const char * /* cmd */, - const char * /* arg */, - .../* , (char *)0, const void *, size_t */); -__LA_DECL int archive_read_support_filter_programv_signature - (struct archive *, const char * /* cmd */, - char * const [] /* argv */, - 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 *); @@ -644,10 +630,6 @@ __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_programl(struct archive *, - const char *cmd, const char *arg, .../*, (char *)0 */); -__LA_DECL int archive_write_add_filter_programv(struct archive *, - const char *cmd, char * const argv[]); __LA_DECL int archive_write_add_filter_uuencode(struct archive *); __LA_DECL int archive_write_add_filter_xz(struct archive *); diff --git a/libarchive/archive_cmdline.c b/libarchive/archive_cmdline.c new file mode 100644 index 000000000..5129ab3d6 --- /dev/null +++ b/libarchive/archive_cmdline.c @@ -0,0 +1,222 @@ +/*- + * 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 +#endif +#ifdef HAVE_STDLIB_H +# include +#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; s++) { + if (*s == '\\') { + if (s[1] != '\0') + archive_strappend_char(as, s[0]); + } else if (*s == '"') + break; + else + archive_strappend_char(as, s[0]); + } + 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); +} + diff --git a/libarchive/archive_cmdline_private.h b/libarchive/archive_cmdline_private.h new file mode 100644 index 000000000..85fba1e11 --- /dev/null +++ b/libarchive/archive_cmdline_private.h @@ -0,0 +1,45 @@ +/*- + * 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 +#error This header is only to be used internally to libarchive. +#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 diff --git a/libarchive/archive_read_private.h b/libarchive/archive_read_private.h index 2dc9645ca..de3f3cdb5 100644 --- a/libarchive/archive_read_private.h +++ b/libarchive/archive_read_private.h @@ -225,8 +225,5 @@ int64_t __archive_read_seek(struct archive_read*, int64_t, int); 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_programl(struct archive_read_filter *, const char *, - const char *, .../*, (char *)0 */); -int __archive_read_programv(struct archive_read_filter *, const char *, - char * const argv[]); +int __archive_read_program(struct archive_read_filter *, const char *); #endif diff --git a/libarchive/archive_read_support_filter_bzip2.c b/libarchive/archive_read_support_filter_bzip2.c index 4d07e81d0..0050fab0f 100644 --- a/libarchive/archive_read_support_filter_bzip2.c +++ b/libarchive/archive_read_support_filter_bzip2.c @@ -170,8 +170,8 @@ bzip2_reader_init(struct archive_read_filter *self) { int r; - r = __archive_read_programl(self, "bunzip2", "bunzip2", NULL); - /* Note: We set the format here even if __archive_read_programl() + r = __archive_read_program(self, "bunzip2"); + /* 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_BZIP2; diff --git a/libarchive/archive_read_support_filter_grzip.c b/libarchive/archive_read_support_filter_grzip.c index 7a132ab2d..61403f6dc 100644 --- a/libarchive/archive_read_support_filter_grzip.c +++ b/libarchive/archive_read_support_filter_grzip.c @@ -109,8 +109,8 @@ grzip_bidder_init(struct archive_read_filter *self) { int r; - r = __archive_read_programl(self, "grzip", "grzip", "-d", NULL); - /* Note: We set the format here even if __archive_read_programl() + 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; diff --git a/libarchive/archive_read_support_filter_gzip.c b/libarchive/archive_read_support_filter_gzip.c index fb3d1f4ae..50a6a6bf5 100644 --- a/libarchive/archive_read_support_filter_gzip.c +++ b/libarchive/archive_read_support_filter_gzip.c @@ -231,8 +231,8 @@ gzip_bidder_init(struct archive_read_filter *self) { int r; - r = __archive_read_programl(self, "gzip", "gzip", "-d", NULL); - /* Note: We set the format here even if __archive_read_programl() + 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_FILTER_GZIP; diff --git a/libarchive/archive_read_support_filter_lrzip.c b/libarchive/archive_read_support_filter_lrzip.c index 2cfd76e88..62d3f9b6a 100644 --- a/libarchive/archive_read_support_filter_lrzip.c +++ b/libarchive/archive_read_support_filter_lrzip.c @@ -119,8 +119,8 @@ lrzip_bidder_init(struct archive_read_filter *self) { int r; - r = __archive_read_programl(self, "lrzip", "lrzip", "-q", "-d", NULL); - /* Note: We set the format here even if __archive_read_programl() + 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; diff --git a/libarchive/archive_read_support_filter_lzop.c b/libarchive/archive_read_support_filter_lzop.c index 4c8e0e0d2..cfaa30879 100644 --- a/libarchive/archive_read_support_filter_lzop.c +++ b/libarchive/archive_read_support_filter_lzop.c @@ -109,8 +109,8 @@ lzop_bidder_init(struct archive_read_filter *self) { int r; - r = __archive_read_programl(self, "lzop", "lzop", "-d", NULL); - /* Note: We set the format here even if __archive_read_programl() + 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; diff --git a/libarchive/archive_read_support_filter_program.c b/libarchive/archive_read_support_filter_program.c index f2b0e0df9..850ab4545 100644 --- a/libarchive/archive_read_support_filter_program.c +++ b/libarchive/archive_read_support_filter_program.c @@ -82,72 +82,6 @@ archive_read_support_filter_program(struct archive *a, const char *cmd) return (archive_read_support_filter_program_signature(a, cmd, NULL, 0)); } -static void -free_argv(char **argv) -{ - int i; - - if (argv) { - for (i = 0; argv[i] != NULL; i++) - free(argv[i]); - free(argv); - } -} - -int -archive_read_support_filter_programl(struct archive *a, const char *cmd, - const char *arg, ...) -{ - va_list ap; - char **argv; - int i, r; - - i = 2; - if (arg != NULL) { - va_start(ap, arg); - while (va_arg(ap, char *) != NULL) - i++; - va_end(ap); - } - argv = calloc(i, sizeof(char *)); - if (argv == NULL) - goto memerr; - argv[0] = strdup((arg)?arg:cmd); - if (argv[0] == NULL) - goto memerr; - i = 1; - va_start(ap, arg); - if (arg) { - char *val; - while ((val = va_arg(ap, char *)) != NULL) { - argv[i] = strdup(val); - if (argv[i] == NULL) { - va_end(ap); - goto memerr; - } - i++; - } - } - va_end(ap); - argv[i] = NULL; - r = archive_read_support_filter_programv_signature(a, cmd, argv, - NULL, 0); - free_argv(argv); - return (r); -memerr: - free_argv(argv); - archive_set_error(a, ENOMEM, "Can't allocate memory"); - return (ARCHIVE_FATAL); -} - -int -archive_read_support_filter_programv(struct archive *a, const char *cmd, - char * const argv[]) -{ - return (archive_read_support_filter_programv_signature(a, cmd, argv, - NULL, 0)); -} - /* * The bidder object stores the command and the signature to watch for. * The 'inhibit' entry here is used to ensure that unchecked filters never @@ -155,7 +89,6 @@ archive_read_support_filter_programv(struct archive *a, const char *cmd, */ struct program_bidder { char *cmd; - char **argv; void *signature; size_t signature_len; int inhibit; @@ -234,124 +167,6 @@ archive_read_support_filter_program_signature(struct archive *_a, state->cmd = strdup(cmd); if (state->cmd == NULL) goto memerr; - state->argv = calloc(2, sizeof(char *)); - if (state->argv == NULL) - goto memerr; - state->argv[0] = strdup(cmd); - if (state->argv[0] == NULL) - goto memerr; - state->argv[1] = NULL; - - 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); -} - -int -archive_read_support_filter_programl_signature(struct archive *_a, - const char *cmd, const char *arg, .../* , signature, signature_len */) -{ - struct archive_read *a = (struct archive_read *)_a; - struct archive_read_filter_bidder *bidder; - struct program_bidder *state; - const void *signature; - size_t signature_len; - va_list ap; - int i; - - /* - * Get a bidder object from the read core. - */ - if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK) - return (ARCHIVE_FATAL); - - /* - * Allocate our private state. - */ - state = (struct program_bidder *)calloc(1, sizeof (*state)); - if (state == NULL) - goto memerr; - state->cmd = strdup(cmd); - if (state->cmd == NULL) - goto memerr; - - i = 2; - if (arg != NULL) { - va_start(ap, arg); - while (va_arg(ap, char *) != NULL) - i++; - va_end(ap); - } - state->argv = calloc(i, sizeof(char *)); - if (state->argv == NULL) - goto memerr; - state->argv[0] = strdup((arg)?arg:cmd); - if (state->argv[0] == NULL) - goto memerr; - i = 1; - va_start(ap, arg); - if (arg) { - char *val; - while ((val = va_arg(ap, char *)) != NULL) { - state->argv[i] = strdup(val); - if (state->argv[i] == NULL) { - va_end(ap); - goto memerr; - } - i++; - } - } - signature = va_arg(ap, const void *); - signature_len = va_arg(ap, size_t); - va_end(ap); - state->argv[i] = NULL; - - 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); -} - -int -archive_read_support_filter_programv_signature(struct archive *_a, - const char *cmd, char * const argv[], const void *signature, - size_t signature_len) -{ - struct archive_read *a = (struct archive_read *)_a; - struct archive_read_filter_bidder *bidder; - struct program_bidder *state; - int i; - - /* - * Get a bidder object from the read core. - */ - if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK) - return (ARCHIVE_FATAL); - - /* - * Allocate our private state. - */ - state = (struct program_bidder *)calloc(1, sizeof (*state)); - if (state == NULL) - goto memerr; - state->cmd = strdup(cmd); - if (state->cmd == NULL) - goto memerr; - - for (i = 0; argv[i] != NULL; i++) - ; - state->argv = calloc(i + 1, sizeof(char *)); - if (state->argv == NULL) - goto memerr; - for (i = 0; argv[i] != NULL; i++) { - state->argv[i] = strdup(argv[i]); - if (state->argv[i] == NULL) - goto memerr; - } - state->argv[i] = NULL; return set_bidder_signature(bidder, state, signature, signature_len); memerr: @@ -375,7 +190,6 @@ free_state(struct program_bidder *state) if (state) { free(state->cmd); - free_argv(state->argv); free(state->signature); free(state); } @@ -579,71 +393,16 @@ child_read(struct archive_read_filter *self, char *buf, size_t buf_len) } int -__archive_read_programl(struct archive_read_filter *self, const char *cmd, - const char *arg, ...) -{ - va_list ap; - char **argv; - char *val; - int i, r; - - 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) - goto memerr; - - if (arg != NULL) { - argv[0] = strdup(arg); - if (argv[0] == NULL) - goto memerr; - i = 1; - va_start(ap, arg); - while ((val = va_arg(ap, char *)) != NULL) { - argv[i] = strdup(val); - if (argv[i] == NULL) - goto memerr; - i++; - } - va_end(ap); - argv[i] = NULL; - } else { - argv[0] = strdup(cmd); - if (argv[0] == NULL) - goto memerr; - argv[1] = NULL; - } - - r = __archive_read_programv(self, cmd, argv); - free_argv(argv); - return (r); -memerr: - free_argv(argv); - archive_set_error(&self->archive->archive, ENOMEM, - "Can't allocate input data"); - return (ARCHIVE_FATAL); -} - -int -__archive_read_programv(struct archive_read_filter *self, const char *cmd, - char * const argv[]) +__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; const char *prefix = "Program: "; pid_t child; - int i; size_t l; l = strlen(prefix) + strlen(cmd) + 1; - for (i = 0; argv[i] != NULL; i++) - l += strlen(argv[i]) + 1; state = (struct program_filter *)calloc(1, sizeof(*state)); out_buf = (char *)malloc(out_buf_len); if (state == NULL || out_buf == NULL || @@ -659,10 +418,6 @@ __archive_read_programv(struct archive_read_filter *self, const char *cmd, } archive_strcpy(&state->description, prefix); archive_strcat(&state->description, cmd); - for (i = 0; argv[i] != NULL; i++) { - archive_strappend_char(&state->description, ' '); - archive_strcat(&state->description, argv[i]); - } self->code = ARCHIVE_FILTER_PROGRAM; self->name = state->description.s; @@ -670,7 +425,7 @@ __archive_read_programv(struct archive_read_filter *self, const char *cmd, state->out_buf = out_buf; state->out_buf_len = out_buf_len; - child = __archive_create_child(cmd, argv, &state->child_stdin, + child = __archive_create_child(cmd, &state->child_stdin, &state->child_stdout); if (child == -1) { free(state->out_buf); @@ -710,8 +465,7 @@ program_bidder_init(struct archive_read_filter *self) struct program_bidder *bidder_state; bidder_state = (struct program_bidder *)self->bidder->data; - return (__archive_read_programv(self, bidder_state->cmd, - bidder_state->argv)); + return (__archive_read_program(self, bidder_state->cmd)); } static ssize_t diff --git a/libarchive/archive_read_support_filter_xz.c b/libarchive/archive_read_support_filter_xz.c index e94c29e3f..ea47fe43a 100644 --- a/libarchive/archive_read_support_filter_xz.c +++ b/libarchive/archive_read_support_filter_xz.c @@ -941,8 +941,8 @@ lzma_bidder_init(struct archive_read_filter *self) { int r; - r = __archive_read_programl(self, "unlzma", "unlzma", NULL); - /* Note: We set the format here even if __archive_read_programl() + r = __archive_read_program(self, "unlzma"); + /* 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_LZMA; @@ -958,8 +958,8 @@ xz_bidder_init(struct archive_read_filter *self) { int r; - r = __archive_read_programl(self, "unxz", "unxz", NULL); - /* Note: We set the format here even if __archive_read_programl() + r = __archive_read_program(self, "unxz"); + /* 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_XZ; @@ -972,8 +972,8 @@ lzip_bidder_init(struct archive_read_filter *self) { int r; - r = __archive_read_programl(self, "unlzip", "unlzip", NULL); - /* Note: We set the format here even if __archive_read_programl() + r = __archive_read_program(self, "unlzip"); + /* 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_LZIP; diff --git a/libarchive/archive_write_add_filter_grzip.c b/libarchive/archive_write_add_filter_grzip.c index b5255903a..dc58ed05f 100644 --- a/libarchive/archive_write_add_filter_grzip.c +++ b/libarchive/archive_write_add_filter_grzip.c @@ -104,16 +104,11 @@ archive_write_grzip_open(struct archive_write_filter *f) int r; 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); + if (r != ARCHIVE_OK) { + archive_set_error(f->archive, ENOMEM, "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + return __archive_write_program_open(f, data->pdata); } static int diff --git a/libarchive/archive_write_add_filter_lrzip.c b/libarchive/archive_write_add_filter_lrzip.c index 1ffb78bf3..578ca84ef 100644 --- a/libarchive/archive_write_add_filter_lrzip.c +++ b/libarchive/archive_write_add_filter_lrzip.c @@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$"); #endif #include "archive.h" +#include "archive_string.h" #include "archive_write_private.h" struct write_lrzip { @@ -126,60 +127,44 @@ 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; - 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; + archive_string_init(&as); + archive_strcpy(&as, "lrzip -q"); /* Specify compression type. */ switch (data->compression) { case lzma:/* default compression */ break; case bzip2: - r = __archive_write_program_add_arg(data->pdata, "-b"); - if (r != ARCHIVE_OK) - goto memerr; + archive_strcat(&as, " -b"); break; case gzip: - r = __archive_write_program_add_arg(data->pdata, "-g"); - if (r != ARCHIVE_OK) - goto memerr; + archive_strcat(&as, " -g"); break; case lzo: - r = __archive_write_program_add_arg(data->pdata, "-l"); - if (r != ARCHIVE_OK) - goto memerr; + archive_strcat(&as, " -l"); break; case zpaq: - r = __archive_write_program_add_arg(data->pdata, "-z"); - if (r != ARCHIVE_OK) - goto memerr; + archive_strcat(&as, " -z"); break; } /* Specify compression level. */ if (data->compression_level > 0) { - char level[2]; - r = __archive_write_program_add_arg(data->pdata, "-L"); - if (r != ARCHIVE_OK) - goto memerr; - level[0] = '0' + data->compression_level; - level[1] = '\0'; - r = __archive_write_program_add_arg(data->pdata, level); - if (r != ARCHIVE_OK) - goto memerr; + archive_strcat(&as, " -L "); + archive_strappend_char(&as, '0' + data->compression_level); } + r = __archive_write_program_set_cmd(data->pdata, as.s); + if (r != ARCHIVE_OK) + goto memerr; + archive_string_free(&as); r = __archive_write_program_open(f, data->pdata); return (r); memerr: + archive_string_free(&as); archive_set_error(f->archive, ENOMEM, "Can't allocate memory"); return (ARCHIVE_FATAL); } diff --git a/libarchive/archive_write_add_filter_lzop.c b/libarchive/archive_write_add_filter_lzop.c index 06af6d71a..7106c7095 100644 --- a/libarchive/archive_write_add_filter_lzop.c +++ b/libarchive/archive_write_add_filter_lzop.c @@ -33,8 +33,12 @@ __FBSDID("$FreeBSD$"); #ifdef HAVE_STDLIB_H #include #endif +#ifdef HAVE_STRING_H +#include +#endif #include "archive.h" +#include "archive_string.h" #include "archive_write_private.h" struct write_lzop { @@ -108,27 +112,25 @@ 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; - 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; + archive_string_init(&as); + archive_strcpy(&as, "lzop"); /* Specify compression level. */ if (data->compression_level > 0) { - char level[3]; - level[0] = '-'; - level[1] = '0' + data->compression_level; - level[2] = '\0'; - r = __archive_write_program_add_arg(data->pdata, level); - if (r != ARCHIVE_OK) - goto memerr; + archive_strappend_char(&as, '-'); + archive_strappend_char(&as, '0' + data->compression_level); } + r = __archive_write_program_set_cmd(data->pdata, as.s); + if (r != ARCHIVE_OK) + goto memerr; + archive_string_free(&as); + r = __archive_write_program_open(f, data->pdata); return (r); memerr: + archive_string_free(&as); archive_set_error(f->archive, ENOMEM, "Can't allocate memory"); return (ARCHIVE_FATAL); } diff --git a/libarchive/archive_write_add_filter_program.c b/libarchive/archive_write_add_filter_program.c index d80442eff..16dcc54be 100644 --- a/libarchive/archive_write_add_filter_program.c +++ b/libarchive/archive_write_add_filter_program.c @@ -60,8 +60,6 @@ archive_write_set_compression_program(struct archive *a, const char *cmd) struct archive_write_program_data { char *cmd; - char **argv; - int argc; #if defined(_WIN32) && !defined(__CYGWIN__) HANDLE child; #else @@ -84,8 +82,6 @@ static int archive_compressor_program_write(struct archive_write_filter *, 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. @@ -93,7 +89,10 @@ static int init_filter_program(struct archive *, 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_program_data *pdata; + struct private_data *data; + static const char *prefix = "Program: "; int r; archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, @@ -105,129 +104,18 @@ archive_write_add_filter_program(struct archive *_a, const char *cmd) 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 *val; - int r; - - archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, - ARCHIVE_STATE_NEW, "archive_write_add_filter_programl"); - - 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) { - r = __archive_write_program_add_arg(pdata, arg); - if (r != ARCHIVE_OK) - goto memerr; - va_start(ap, arg); - while ((val = va_arg(ap, char *)) != NULL) { - r = __archive_write_program_add_arg(pdata, val); - if (r != ARCHIVE_OK) - goto memerr; - } - va_end(ap); - } else { - 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_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"); - - 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); -} - -/* - * 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); - struct private_data *data; - static const char *prefix = "Program: "; - int i; - size_t l; data = calloc(1, sizeof(*data)); if (data == NULL) goto memerr; - l = strlen(prefix) + strlen(pdata->cmd) + 1; - for (i = 0; pdata->argv[i] != NULL; i++) - l += strlen(pdata->argv[i]) + 1; /* Make up a description string. */ - if (archive_string_ensure(&data->description, l) == NULL) + if (archive_string_ensure(&data->description, + strlen(prefix) + strlen(cmd) + 1) == NULL) goto memerr; 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]); - } + archive_strcat(&data->description, cmd); + data->pdata = pdata; f->name = data->description.s; f->code = ARCHIVE_FILTER_PROGRAM; @@ -238,7 +126,7 @@ init_filter_program(struct archive *_a, f->free = archive_compressor_program_free; return (ARCHIVE_OK); memerr: - archive_compressor_program_free(f); + __archive_write_program_free(pdata); archive_set_error(_a, ENOMEM, "Can't allocate memory for filter program"); return (ARCHIVE_FATAL); @@ -308,13 +196,6 @@ __archive_write_program_free(struct archive_write_program_data *data) 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); } @@ -322,49 +203,22 @@ __archive_write_program_free(struct archive_write_program_data *data) } /* - * Set the program path. + * 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_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; + free(data->cmd); + data->cmd = strdup(cmd); 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); + return ARCHIVE_OK; } int @@ -390,7 +244,7 @@ __archive_write_program_open(struct archive_write_filter *f, } } - child = __archive_create_child(data->cmd, data->argv, + child = __archive_create_child(data->cmd, &data->child_stdin, &data->child_stdout); if (child == -1) { archive_set_error(f->archive, EINVAL, diff --git a/libarchive/archive_write_private.h b/libarchive/archive_write_private.h index 2f31428d4..c394bcfa5 100644 --- a/libarchive/archive_write_private.h +++ b/libarchive/archive_write_private.h @@ -140,10 +140,8 @@ 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 *); +int __archive_write_program_write(struct archive_write_filter *, + struct archive_write_program_data *, const void *, size_t); #endif diff --git a/libarchive/filter_fork.h b/libarchive/filter_fork.h index 1652c85d0..a28272bee 100644 --- a/libarchive/filter_fork.h +++ b/libarchive/filter_fork.h @@ -33,8 +33,7 @@ #define FILTER_FORK_H pid_t -__archive_create_child(const char *path, char * const argv[], int *child_stdin, - int *child_stdout); +__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout); void __archive_check_child(int in, int out); diff --git a/libarchive/filter_fork_posix.c b/libarchive/filter_fork_posix.c index bfaa5adce..02dbd4bb4 100644 --- a/libarchive/filter_fork_posix.c +++ b/libarchive/filter_fork_posix.c @@ -67,11 +67,13 @@ __FBSDID("$FreeBSD: head/lib/libarchive/filter_fork.c 182958 2008-09-12 05:33:00 # include #endif +#include "archive.h" +#include "archive_cmdline_private.h" + #include "filter_fork.h" pid_t -__archive_create_child(const char *path, char * const argv[], int *child_stdin, - int *child_stdout) +__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout) { pid_t child; int stdin_pipe[2], stdout_pipe[2], tmp; @@ -79,6 +81,13 @@ __archive_create_child(const char *path, char * const argv[], int *child_stdin, posix_spawn_file_actions_t actions; int r; #endif + struct archive_cmdline *cmdline; + + cmdline = __archive_cmdline_allocate(); + if (cmdline == NULL) + goto state_allocated; + if (__archive_cmdline_parse(cmdline, cmd) != ARCHIVE_OK) + goto state_allocated; if (pipe(stdin_pipe) == -1) goto state_allocated; @@ -128,7 +137,8 @@ __archive_create_child(const char *path, char * const argv[], int *child_stdin, if (r != 0) goto actions_inited; } - r = posix_spawnp(&child, path, &actions, NULL, argv, NULL); + r = posix_spawnp(&child, cmdline->path, &actions, NULL, + cmdline->argv, NULL); if (r != 0) goto actions_inited; posix_spawn_file_actions_destroy(&actions); @@ -153,7 +163,7 @@ __archive_create_child(const char *path, char * const argv[], int *child_stdin, _exit(254); if (stdout_pipe[1] != 1 /* stdout */) close(stdout_pipe[1]); - execvp(path, argv); + execvp(cmdline->path, cmdline->argv); _exit(254); } #endif /* HAVE_POSIX_SPAWNP */ @@ -165,6 +175,7 @@ __archive_create_child(const char *path, char * const argv[], int *child_stdin, fcntl(*child_stdin, F_SETFL, O_NONBLOCK); *child_stdout = stdout_pipe[0]; fcntl(*child_stdout, F_SETFL, O_NONBLOCK); + __archive_cmdline_free(cmdline); return child; @@ -180,6 +191,7 @@ stdin_opened: close(stdin_pipe[0]); close(stdin_pipe[1]); state_allocated: + __archive_cmdline_free(cmdline); return -1; } diff --git a/libarchive/filter_fork_windows.c b/libarchive/filter_fork_windows.c index 9c458d66d..43fce7719 100644 --- a/libarchive/filter_fork_windows.c +++ b/libarchive/filter_fork_windows.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2009 Michihiro NAKAJIMA + * Copyright (c) 2009-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,15 +24,15 @@ */ #include "archive_platform.h" -#include "archive_string.h" #if defined(_WIN32) && !defined(__CYGWIN__) +#include "archive_cmdline_private.h" +#include "archive_string.h" #include "filter_fork.h" pid_t -__archive_create_child(const char *cmd, char * const argv[], int *child_stdin, - int *child_stdout) +__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout) { HANDLE childStdout[2], childStdin[2],childStderr; SECURITY_ATTRIBUTES secAtts; @@ -40,6 +40,7 @@ __archive_create_child(const char *cmd, char * const argv[], int *child_stdin, PROCESS_INFORMATION childInfo; struct archive_string cmdline; struct archive_string fullpath; + struct archive_cmdline *acmd; char *arg0, *ext; int i, l; DWORD fl, fl_old; @@ -50,26 +51,33 @@ __archive_create_child(const char *cmd, char * const argv[], int *child_stdin, archive_string_init(&cmdline); archive_string_init(&fullpath); + acmd = __archive_cmdline_allocate(); + if (acmd == NULL) + goto fail; + if (__archive_cmdline_parse(acmd, cmd) != ARCHIVE_OK) + goto fail; + /* - * Search the full path of 'cmd'. - * NOTE: This does not need if we give CreateProcessA 'cmd' as a part - * of the cmdline and give CreateProcessA NULL as first parameter, - * but I do not like that way. + * Search the full path of 'path'. + * NOTE: This does not need if we give CreateProcessA 'path' as + * a part of the cmdline and give CreateProcessA NULL as first + * parameter, but I do not like that way. */ - ext = strrchr(cmd, '.'); + ext = strrchr(acmd->path, '.'); if (ext == NULL || strlen(ext) > 4) - /* 'cmd' does not have a proper extension, so we have to + /* 'path' does not have a proper extension, so we have to * give SearchPath() ".exe" as the extension. */ ext = ".exe"; else - ext = NULL;/* 'cmd' has an extension. */ + ext = NULL;/* 'path' has an extension. */ fl = MAX_PATH; do { if (archive_string_ensure(&fullpath, fl) == NULL) goto fail; fl_old = fl; - fl = SearchPathA(NULL, cmd, ext, fl, fullpath.s, &arg0); + fl = SearchPathA(NULL, acmd->path, ext, fl, fullpath.s, + &arg0); } while (fl != 0 && fl > fl_old); if (fl == 0) goto fail; @@ -77,22 +85,22 @@ __archive_create_child(const char *cmd, char * const argv[], int *child_stdin, /* * Make a command line. */ - for (l = 0, i = 0; argv[i] != NULL; i++) { + for (l = 0, i = 0; acmd->argv[i] != NULL; i++) { if (i == 0) continue; - l += strlen(argv[i]) + 1; + l += strlen(acmd->argv[i]) + 1; } if (archive_string_ensure(&cmdline, l + 1) == NULL) goto fail; - for (i = 0; argv[i] != NULL; i++) { + for (i = 0; acmd->argv[i] != NULL; i++) { if (i == 0) { const char *p, *sp; - if ((p = strchr(argv[i], '/')) != NULL || - (p = strchr(argv[i], '\\')) != NULL) + if ((p = strchr(acmd->argv[i], '/')) != NULL || + (p = strchr(acmd->argv[i], '\\')) != NULL) p++; else - p = argv[i]; + p = acmd->argv[i]; if ((sp = strchr(p, ' ')) != NULL) archive_strappend_char(&cmdline, '"'); archive_strcat(&cmdline, p); @@ -100,7 +108,7 @@ __archive_create_child(const char *cmd, char * const argv[], int *child_stdin, archive_strappend_char(&cmdline, '"'); } else { archive_strappend_char(&cmdline, ' '); - archive_strcat(&cmdline, argv[i]); + archive_strcat(&cmdline, acmd->argv[i]); } } if (i <= 1) { @@ -151,6 +159,7 @@ __archive_create_child(const char *cmd, char * const argv[], int *child_stdin, archive_string_free(&cmdline); archive_string_free(&fullpath); + __archive_cmdline_free(acmd); return (childInfo.dwProcessId); fail: @@ -166,6 +175,7 @@ fail: CloseHandle(childStderr); archive_string_free(&cmdline); archive_string_free(&fullpath); + __archive_cmdline_free(acmd); return (-1); } diff --git a/libarchive/test/test_read_filter_program.c b/libarchive/test/test_read_filter_program.c index 15f45a94d..a27589a14 100644 --- a/libarchive/test/test_read_filter_program.c +++ b/libarchive/test/test_read_filter_program.c @@ -61,101 +61,6 @@ DEFINE_TEST(test_read_filter_program) /* * If we have "gzip -d", try using that. */ - if (!canGunzip()) { - skipping("Can't run gunzip program on this platform"); - return; - } - assert((a = archive_read_new()) != NULL); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_filter_none(a)); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_filter_program(a, "gunzip")); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_format_all(a)); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_open_memory(a, archive, sizeof(archive))); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_next_header(a, &ae)); - assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_PROGRAM); - assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualInt(ARCHIVE_OK, archive_read_free(a)); -} - - -DEFINE_TEST(test_read_filter_programl) -{ - int r; - struct archive_entry *ae; - struct archive *a; - - /* - * First, test handling when a non-existent compression - * program is requested. - */ - assert((a = archive_read_new()) != NULL); - r = archive_read_support_filter_program(a, "nonexistent"); - if (r == ARCHIVE_FATAL) { - skipping("archive_read_support_filter_program() " - "unsupported on this platform"); - return; - } - assertEqualIntA(a, ARCHIVE_OK, r); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_format_all(a)); - assertEqualIntA(a, ARCHIVE_FATAL, - archive_read_open_memory(a, archive, sizeof(archive))); - assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - - if (!canGzip()) { - skipping("Can't run gzip program on this platform"); - return; - } - assert((a = archive_read_new()) != NULL); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_filter_none(a)); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_filter_programl(a, "gzip", "gzip", - "-d", NULL)); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_format_all(a)); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_open_memory(a, archive, sizeof(archive))); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_next_header(a, &ae)); - assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_PROGRAM); - assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualInt(ARCHIVE_OK, archive_read_free(a)); -} - -DEFINE_TEST(test_read_filter_programv) -{ - int r; - struct archive_entry *ae; - struct archive *a; - char * const argv[] = {"gzip", "-d", NULL}; - - /* - * First, test handling when a non-existent compression - * program is requested. - */ - assert((a = archive_read_new()) != NULL); - r = archive_read_support_filter_program(a, "nonexistent"); - if (r == ARCHIVE_FATAL) { - skipping("archive_read_support_filter_program() " - "unsupported on this platform"); - return; - } - assertEqualIntA(a, ARCHIVE_OK, r); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_format_all(a)); - assertEqualIntA(a, ARCHIVE_FATAL, - archive_read_open_memory(a, archive, sizeof(archive))); - assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - if (!canGzip()) { skipping("Can't run gzip program on this platform"); return; @@ -164,7 +69,7 @@ DEFINE_TEST(test_read_filter_programv) assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_none(a)); assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_filter_programv(a, "gzip", argv)); + archive_read_support_filter_program(a, "gzip -d")); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, diff --git a/libarchive/test/test_read_filter_program_signature.c b/libarchive/test/test_read_filter_program_signature.c index 0fbedc3a7..110addb87 100644 --- a/libarchive/test/test_read_filter_program_signature.c +++ b/libarchive/test/test_read_filter_program_signature.c @@ -64,134 +64,6 @@ DEFINE_TEST(test_read_filter_program_signature) /* * If we have "gzip -d", try using that. */ - if (!canGunzip()) { - skipping("Can't run gunzip program on this platform"); - return; - } - assert((a = archive_read_new()) != NULL); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_filter_none(a)); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_filter_program_signature(a, "gunzip", - signature, signature_len)); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_format_all(a)); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_open_memory(a, archive, sizeof(archive))); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_next_header(a, &ae)); - assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_PROGRAM); - assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - - /* - * Test bad signature. - */ - assert((a = archive_read_new()) != NULL); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_filter_none(a)); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_filter_program_signature(a, "gunzip", - badsignature, signature_len)); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_format_all(a)); - assertEqualIntA(a, ARCHIVE_FATAL, - archive_read_open_memory(a, archive, sizeof(archive))); - assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualInt(ARCHIVE_OK, archive_read_free(a)); -} - - -DEFINE_TEST(test_read_filter_programl_signature) -{ - int r; - struct archive_entry *ae; - struct archive *a; - - /* - * First, test handling when a non-existent compression - * program is requested. - */ - assert((a = archive_read_new()) != NULL); - r = archive_read_support_filter_program(a, "nonexistent"); - if (r == ARCHIVE_FATAL) { - skipping("archive_read_support_filter_program() " - "unsupported on this platform"); - return; - } - assertEqualIntA(a, ARCHIVE_OK, r); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_format_all(a)); - assertEqualIntA(a, ARCHIVE_FATAL, - archive_read_open_memory(a, archive, sizeof(archive))); - assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - - if (!canGzip()) { - skipping("Can't run gzip program on this platform"); - return; - } - assert((a = archive_read_new()) != NULL); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_filter_none(a)); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_filter_programl_signature(a, "gzip", "gzip", - "-d", NULL, signature, signature_len)); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_format_all(a)); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_open_memory(a, archive, sizeof(archive))); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_next_header(a, &ae)); - assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_PROGRAM); - assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - - /* - * Test bad signature. - */ - assert((a = archive_read_new()) != NULL); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_filter_none(a)); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_filter_programl_signature(a, "gzip", "gzip", - "-d", NULL, badsignature, signature_len)); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_format_all(a)); - assertEqualIntA(a, ARCHIVE_FATAL, - archive_read_open_memory(a, archive, sizeof(archive))); - assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualInt(ARCHIVE_OK, archive_read_free(a)); -} - -DEFINE_TEST(test_read_filter_programv_signature) -{ - int r; - struct archive_entry *ae; - struct archive *a; - char * const argv[] = {"gzip", "-d", NULL}; - - /* - * First, test handling when a non-existent compression - * program is requested. - */ - assert((a = archive_read_new()) != NULL); - r = archive_read_support_filter_program(a, "nonexistent"); - if (r == ARCHIVE_FATAL) { - skipping("archive_read_support_filter_program() " - "unsupported on this platform"); - return; - } - assertEqualIntA(a, ARCHIVE_OK, r); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_format_all(a)); - assertEqualIntA(a, ARCHIVE_FATAL, - archive_read_open_memory(a, archive, sizeof(archive))); - assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - if (!canGzip()) { skipping("Can't run gzip program on this platform"); return; @@ -200,7 +72,7 @@ DEFINE_TEST(test_read_filter_programv_signature) assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_none(a)); assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_filter_programv_signature(a, "gzip", argv, + archive_read_support_filter_program_signature(a, "gzip -d", signature, signature_len)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); @@ -220,7 +92,7 @@ DEFINE_TEST(test_read_filter_programv_signature) assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_none(a)); assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_filter_programv_signature(a, "gzip", argv, + archive_read_support_filter_program_signature(a, "gunzip", badsignature, signature_len)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); diff --git a/libarchive/test/test_write_filter_program.c b/libarchive/test/test_write_filter_program.c index ad6261e89..c156b6d55 100644 --- a/libarchive/test/test_write_filter_program.c +++ b/libarchive/test/test_write_filter_program.c @@ -55,196 +55,7 @@ DEFINE_TEST(test_write_filter_program) /* Write it through an external "gzip" program. */ assert((a = archive_write_new()) != NULL); assertA(0 == archive_write_set_format_ustar(a)); - r = archive_write_add_filter_program(a, "gzip"); - if (r == ARCHIVE_FATAL) { - skipping("Write compression via external " - "program unsupported on this platform"); - archive_write_free(a); - return; - } - assertA(0 == archive_write_set_bytes_per_block(a, blocksize)); - assertA(0 == archive_write_set_bytes_in_last_block(a, blocksize)); - assertA(blocksize == archive_write_get_bytes_in_last_block(a)); - assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used)); - assertA(blocksize == archive_write_get_bytes_in_last_block(a)); - - /* - * Write a file to it. - */ - assert((ae = archive_entry_new()) != NULL); - archive_entry_set_mtime(ae, 1, 10); - archive_entry_copy_pathname(ae, "file"); - archive_entry_set_mode(ae, S_IFREG | 0755); - archive_entry_set_size(ae, 8); - - assertA(0 == archive_write_header(a, ae)); - archive_entry_free(ae); - assertA(8 == archive_write_data(a, "12345678", 9)); - - /* Close out the archive. */ - assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualInt(ARCHIVE_OK, archive_write_free(a)); - - /* - * Now, read the data back through the built-in gzip support. - */ - assert((a = archive_read_new()) != NULL); - assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); - r = archive_read_support_filter_gzip(a); - /* The compression_gzip() handler will fall back to gunzip - * automatically, but if we know gunzip isn't available, then - * skip the rest. */ - if (r != ARCHIVE_OK && !canGzip()) { - skipping("No libz and no gunzip program, " - "unable to verify gzip compression"); - assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - return; - } - assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); - - if (!assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae))) { - archive_read_free(a); - return; - } - - assertEqualInt(1, archive_entry_mtime(ae)); - assertEqualInt(0, archive_entry_atime(ae)); - assertEqualInt(0, archive_entry_ctime(ae)); - assertEqualString("file", archive_entry_pathname(ae)); - assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae)); - assertEqualInt(8, archive_entry_size(ae)); - assertEqualIntA(a, 8, archive_read_data(a, buff2, 10)); - assertEqualMem(buff2, "12345678", 8); - - /* Verify the end of the archive. */ - assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualInt(ARCHIVE_OK, archive_read_free(a)); -} - -DEFINE_TEST(test_write_filter_programl) -{ - struct archive_entry *ae; - struct archive *a; - size_t used; - int blocksize = 1024; - int r; - - if (!canGzip()) { - skipping("Cannot run 'gzip'"); - return; - } - /* NOTE: Setting blocksize=1024 will cause gunzip failure because - * it add extra bytes that gunzip ignores with its warning and - * exit code 1. So we should set blocksize=1 in order not to - * yield the extra bytes when using gunzip. */ - assert((a = archive_read_new()) != NULL); - r = archive_read_support_filter_gzip(a); - if (r != ARCHIVE_OK && canGzip()) - blocksize = 1; - assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - - /* Create a new archive in memory. */ - /* Write it through an external "gzip" program. */ - assert((a = archive_write_new()) != NULL); - assertA(0 == archive_write_set_format_ustar(a)); - r = archive_write_add_filter_programl(a, "gzip", "gzip", NULL); - if (r == ARCHIVE_FATAL) { - skipping("Write compression via external " - "program unsupported on this platform"); - archive_write_free(a); - return; - } - assertA(0 == archive_write_set_bytes_per_block(a, blocksize)); - assertA(0 == archive_write_set_bytes_in_last_block(a, blocksize)); - assertA(blocksize == archive_write_get_bytes_in_last_block(a)); - assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used)); - assertA(blocksize == archive_write_get_bytes_in_last_block(a)); - - /* - * Write a file to it. - */ - assert((ae = archive_entry_new()) != NULL); - archive_entry_set_mtime(ae, 1, 10); - archive_entry_copy_pathname(ae, "file"); - archive_entry_set_mode(ae, S_IFREG | 0755); - archive_entry_set_size(ae, 8); - - assertA(0 == archive_write_header(a, ae)); - archive_entry_free(ae); - assertA(8 == archive_write_data(a, "12345678", 9)); - - /* Close out the archive. */ - assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualInt(ARCHIVE_OK, archive_write_free(a)); - - /* - * Now, read the data back through the built-in gzip support. - */ - assert((a = archive_read_new()) != NULL); - assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); - r = archive_read_support_filter_gzip(a); - /* The compression_gzip() handler will fall back to gunzip - * automatically, but if we know gunzip isn't available, then - * skip the rest. */ - if (r != ARCHIVE_OK && !canGzip()) { - skipping("No libz and no gunzip program, " - "unable to verify gzip compression"); - assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - return; - } - assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); - - if (!assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae))) { - archive_read_free(a); - return; - } - - assertEqualInt(1, archive_entry_mtime(ae)); - assertEqualInt(0, archive_entry_atime(ae)); - assertEqualInt(0, archive_entry_ctime(ae)); - assertEqualString("file", archive_entry_pathname(ae)); - assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae)); - assertEqualInt(8, archive_entry_size(ae)); - assertEqualIntA(a, 8, archive_read_data(a, buff2, 10)); - assertEqualMem(buff2, "12345678", 8); - - /* Verify the end of the archive. */ - assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualInt(ARCHIVE_OK, archive_read_free(a)); -} - -DEFINE_TEST(test_write_filter_programv) -{ - struct archive_entry *ae; - struct archive *a; - size_t used; - int blocksize = 1024; - int r; - char * const argv[] = {"gzip", NULL}; - - if (!canGzip()) { - skipping("Cannot run 'gzip'"); - return; - } - /* NOTE: Setting blocksize=1024 will cause gunzip failure because - * it add extra bytes that gunzip ignores with its warning and - * exit code 1. So we should set blocksize=1 in order not to - * yield the extra bytes when using gunzip. */ - assert((a = archive_read_new()) != NULL); - r = archive_read_support_filter_gzip(a); - if (r != ARCHIVE_OK && canGzip()) - blocksize = 1; - assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - - /* Create a new archive in memory. */ - /* Write it through an external "gzip" program. */ - assert((a = archive_write_new()) != NULL); - assertA(0 == archive_write_set_format_ustar(a)); - r = archive_write_add_filter_programv(a, "gzip", argv); + r = archive_write_add_filter_program(a, "gzip -6"); if (r == ARCHIVE_FATAL) { skipping("Write compression via external " "program unsupported on this platform");