summaryrefslogtreecommitdiff
path: root/libarchive/archive_write_add_filter_program.c
diff options
context:
space:
mode:
authorMichihiro NAKAJIMA <ggcueroad@gmail.com>2012-10-04 09:18:30 +0900
committerMichihiro NAKAJIMA <ggcueroad@gmail.com>2012-10-05 09:45:05 +0900
commit40722a255fe8f25a6a8dcd9d66fda49478756b17 (patch)
treeb424a5777e2299c409b17847d2bf94c736b52404 /libarchive/archive_write_add_filter_program.c
parent275000dfda9ef9e7b22a31aad0c46d7c8b98d294 (diff)
downloadlibarchive-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.c169
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);
}