diff options
author | Michihiro NAKAJIMA <ggcueroad@gmail.com> | 2012-10-04 09:18:30 +0900 |
---|---|---|
committer | Michihiro NAKAJIMA <ggcueroad@gmail.com> | 2012-10-05 09:45:05 +0900 |
commit | 40722a255fe8f25a6a8dcd9d66fda49478756b17 (patch) | |
tree | b424a5777e2299c409b17847d2bf94c736b52404 /libarchive/archive_write_add_filter_program.c | |
parent | 275000dfda9ef9e7b22a31aad0c46d7c8b98d294 (diff) | |
download | libarchive-40722a255fe8f25a6a8dcd9d66fda49478756b17.tar.gz |
Make a filter program be called with its arguments.
Diffstat (limited to 'libarchive/archive_write_add_filter_program.c')
-rw-r--r-- | libarchive/archive_write_add_filter_program.c | 169 |
1 files changed, 152 insertions, 17 deletions
diff --git a/libarchive/archive_write_add_filter_program.c b/libarchive/archive_write_add_filter_program.c index 77896700..7ccc059c 100644 --- a/libarchive/archive_write_add_filter_program.c +++ b/libarchive/archive_write_add_filter_program.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 2007 Joerg Sonnenberger + * Copyright (c) 2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,6 +45,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_compression_program.c #include "archive.h" #include "archive_private.h" +#include "archive_string.h" #include "archive_write_private.h" #include "filter_fork.h" @@ -58,7 +60,8 @@ archive_write_set_compression_program(struct archive *a, const char *cmd) struct private_data { char *cmd; - char *description; + char **argv; + struct archive_string description; pid_t child; int child_stdin, child_stdout; @@ -71,6 +74,8 @@ 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 write_add_filter_programv(struct archive *, const char *, + char * const *); /* * Add a filter to this write handle that passes all data through an @@ -79,28 +84,148 @@ 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]; + 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 = write_add_filter_programv(_a, cmd, argv); + free(argv[0]); + return (r); +} + +int +archive_write_add_filter_programl(struct archive *_a, const char *cmd, + const char *arg, ...) +{ + va_list ap; + char **argv; + char *val; + int i, 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) + 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 = write_add_filter_programv(_a, cmd, argv); + for (i = 0; argv[i] != NULL; i++) + free(argv[i]); + free(argv); + return (r); +memerr: + if (argv) { + for (i = 0; argv[i] != NULL; i++) + free(argv[i]); + free(argv); + } + 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[]) +{ + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_add_filter_programv"); + + return write_add_filter_programv(_a, cmd, argv); +} + +static int +write_add_filter_programv(struct archive *_a, const char *cmd, + char * const argv[]) +{ + struct archive_write_filter *f = __archive_write_allocate_filter(_a); - struct archive_write *a = (struct archive_write *)_a; struct private_data *data; static const char *prefix = "Program: "; - archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, - ARCHIVE_STATE_NEW, "archive_write_add_filter_program"); + int i; + size_t l; + data = calloc(1, sizeof(*data)); - if (data == NULL) { - archive_set_error(&a->archive, ENOMEM, "Out of memory"); - return (ARCHIVE_FATAL); - } + if (data == NULL) + goto memerr; data->cmd = strdup(cmd); - data->description = (char *)malloc(strlen(prefix) + strlen(cmd) + 1); - strcpy(data->description, prefix); - strcat(data->description, cmd); + if (data->cmd == NULL) + goto memerr; + + /* Reproduce argv. */ + for (i = 0; argv[i] != NULL; i++) + ; + data->argv = calloc(i + 1, sizeof(char *)); + if (data->argv == 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; + } + + /* Make up a description string. */ + if (archive_string_ensure(&data->description, l) == NULL) + goto memerr; + archive_strcpy(&data->description, prefix); + archive_strcpy(&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; + f->name = data->description.s; f->data = data; f->open = &archive_compressor_program_open; f->code = ARCHIVE_COMPRESSION_PROGRAM; f->free = archive_compressor_program_free; return (ARCHIVE_OK); +memerr: + archive_compressor_program_free(f); + archive_set_error(_a, ENOMEM, + "Can't allocate memory for filter program"); + return (ARCHIVE_FATAL); } /* @@ -129,6 +254,7 @@ archive_compressor_program_open(struct archive_write_filter *f) } if ((data->child = __archive_create_child(data->cmd, + (char * const *)data->argv, &data->child_stdin, &data->child_stdout)) == -1) { archive_set_error(f->archive, EINVAL, "Can't initialise filter"); @@ -299,10 +425,19 @@ static int archive_compressor_program_free(struct archive_write_filter *f) { struct private_data *data = (struct private_data *)f->data; - free(data->cmd); - free(data->description); - free(data->child_buf); - free(data); - f->data = NULL; + + if (data) { + 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); } |