libarchive/test/test_read_disk_entry_from_file.c \
libarchive/test/test_read_extract.c \
libarchive/test/test_read_file_nonexistent.c \
+ libarchive/test/test_read_filter_program_signature.c \
libarchive/test/test_read_format_7zip.c \
libarchive/test/test_read_format_ar.c \
libarchive/test/test_read_format_cab.c \
__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 *,
+ (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_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_xz(struct archive *);
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_program(struct archive_read_filter *, const char *);
+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[]);
#endif
/*-
* Copyright (c) 2007 Joerg Sonnenberger
+ * Copyright (c) 2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#include "archive.h"
#include "archive_private.h"
+#include "archive_string.h"
#include "archive_read_private.h"
#include "filter_fork.h"
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.
*/
struct program_bidder {
char *cmd;
+ char **argv;
void *signature;
size_t signature_len;
int inhibit;
* The actual filter needs to track input and output data.
*/
struct program_filter {
- char *description;
+ struct archive_string description;
pid_t child;
int exit_status;
int waitpid_return;
static ssize_t program_filter_read(struct archive_read_filter *,
const void **);
static int program_filter_close(struct archive_read_filter *);
+static void free_state(struct program_bidder *);
+
+static int
+set_bidder_signature(struct archive_read_filter_bidder *bidder,
+ struct program_bidder *state, const void *signature, size_t signature_len)
+{
+
+ if (signature != NULL && signature_len > 0) {
+ state->signature_len = signature_len;
+ state->signature = malloc(signature_len);
+ memcpy(state->signature, signature, signature_len);
+ }
+
+ /*
+ * Fill in the bidder object.
+ */
+ bidder->data = state;
+ bidder->bid = program_bidder_bid;
+ bidder->init = program_bidder_init;
+ bidder->options = NULL;
+ bidder->free = program_bidder_free;
+ return (ARCHIVE_OK);
+}
int
archive_read_support_filter_program_signature(struct archive *_a,
/*
* Allocate our private state.
*/
- state = (struct program_bidder *)calloc(sizeof (*state), 1);
+ state = (struct program_bidder *)calloc(1, sizeof (*state));
if (state == NULL)
+ goto memerr;
+ 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 (signature != NULL && signature_len > 0) {
- state->signature_len = signature_len;
- state->signature = malloc(signature_len);
- memcpy(state->signature, signature, signature_len);
+ 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;
/*
- * Fill in the bidder object.
+ * Get a bidder object from the read core.
*/
- bidder->data = state;
- bidder->bid = program_bidder_bid;
- bidder->init = program_bidder_init;
- bidder->options = NULL;
- bidder->free = program_bidder_free;
- return (ARCHIVE_OK);
+ 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:
+ free_state(state);
+ archive_set_error(_a, ENOMEM, "Can't allocate memory");
+ return (ARCHIVE_FATAL);
}
static int
program_bidder_free(struct archive_read_filter_bidder *self)
{
struct program_bidder *state = (struct program_bidder *)self->data;
- free(state->cmd);
- free(state->signature);
- free(self->data);
+
+ free_state(state);
return (ARCHIVE_OK);
}
+static void
+free_state(struct program_bidder *state)
+{
+
+ if (state) {
+ free(state->cmd);
+ free_argv(state->argv);
+ free(state->signature);
+ free(state);
+ }
+}
+
/*
* If we do have a signature, bid only if that matches.
*
int
__archive_read_program(struct archive_read_filter *self, const char *cmd)
+{
+ char *argv[2];
+ int r;
+
+ argv[0] = strdup(cmd);
+ if (argv[0] == NULL) {
+ archive_set_error(&self->archive->archive, ENOMEM,
+ "Can't allocate input data");
+ return (ARCHIVE_FATAL);
+ }
+ argv[1] = NULL;
+ r = __archive_read_programv(self, cmd, argv);
+ free(argv[0]);
+ return (r);
+}
+
+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[])
{
struct program_filter *state;
static const size_t out_buf_len = 65536;
char *out_buf;
- char *description;
const char *prefix = "Program: ";
+ 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);
- description = (char *)malloc(strlen(prefix) + strlen(cmd) + 1);
- if (state == NULL || out_buf == NULL || description == NULL) {
+ if (state == NULL || out_buf == NULL ||
+ archive_string_ensure(&state->description, l) == NULL) {
archive_set_error(&self->archive->archive, ENOMEM,
"Can't allocate input data");
+ archive_string_free(&state->description);
free(state);
free(out_buf);
- free(description);
return (ARCHIVE_FATAL);
}
+ 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_COMPRESSION_PROGRAM;
- state->description = description;
- strcpy(state->description, prefix);
- strcat(state->description, cmd);
- self->name = state->description;
+ self->name = state->description.s;
state->out_buf = out_buf;
state->out_buf_len = out_buf_len;
- if ((state->child = __archive_create_child(cmd,
+ if ((state->child = __archive_create_child(cmd, argv,
&state->child_stdin, &state->child_stdout)) == -1) {
free(state->out_buf);
free(state);
archive_set_error(&self->archive->archive, EINVAL,
- "Can't initialize filter; unable to run program \"%s\"", cmd);
+ "Can't initialize filter; unable to run program \"%s\"",
+ cmd);
return (ARCHIVE_FATAL);
}
struct program_bidder *bidder_state;
bidder_state = (struct program_bidder *)self->bidder->data;
- return (__archive_read_program(self, bidder_state->cmd));
+ return (__archive_read_programv(self, bidder_state->cmd,
+ bidder_state->argv));
}
static ssize_t
/* Release our private data. */
free(state->out_buf);
- free(state->description);
+ archive_string_free(&state->description);
free(state);
return (e);
/*-
* Copyright (c) 2007 Joerg Sonnenberger
+ * Copyright (c) 2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#include "archive.h"
#include "archive_private.h"
+#include "archive_string.h"
#include "archive_write_private.h"
#include "filter_fork.h"
struct private_data {
char *cmd;
- char *description;
+ char **argv;
+ struct archive_string description;
pid_t child;
int child_stdin, child_stdout;
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
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);
}
/*
}
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");
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);
}
#include "filter_fork.h"
pid_t
-__archive_create_child(const char *path, int *child_stdin, int *child_stdout)
+__archive_create_child(const char *path, char * const argv[], int *child_stdin,
+ int *child_stdout)
{
pid_t child;
int stdin_pipe[2], stdout_pipe[2], tmp;
#if HAVE_POSIX_SPAWNP
posix_spawn_file_actions_t actions;
- char *argv[2];
int r;
#endif
if (r != 0)
goto actions_inited;
}
- argv[0] = strdup(path);
- if (argv[0] == NULL)
- goto actions_inited2;
- argv[1] = NULL;
- r = posix_spawnp(&child, path, &actions, NULL,
- (char ** const)argv, NULL);
- free(argv[0]);
+ r = posix_spawnp(&child, path, &actions, NULL, argv, NULL);
if (r != 0)
goto actions_inited;
posix_spawn_file_actions_destroy(&actions);
_exit(254);
if (stdout_pipe[1] != 1 /* stdout */)
close(stdout_pipe[1]);
- execlp(path, path, (char *)NULL);
+ execvp(path, argv);
_exit(254);
}
#endif /* HAVE_POSIX_SPAWNP */
#if HAVE_POSIX_SPAWNP
actions_inited:
errno = r;
-actions_inited2:
posix_spawn_file_actions_destroy(&actions);
#endif
stdout_opened:
#define FILTER_FORK_H
pid_t
-__archive_create_child(const char *path, int *child_stdin, int *child_stdout);
+__archive_create_child(const char *path, char * const argv[], int *child_stdin,
+ int *child_stdout);
void
__archive_check_child(int in, int out);
*/
#include "archive_platform.h"
+#include "archive_string.h"
#if defined(_WIN32) && !defined(__CYGWIN__)
#include "filter_fork.h"
pid_t
-__archive_create_child(const char *path, int *child_stdin, int *child_stdout)
+__archive_create_child(const char *path, char * const argv[], int *child_stdin,
+ int *child_stdout)
{
HANDLE childStdout[2], childStdin[2],childStderr;
SECURITY_ATTRIBUTES secAtts;
STARTUPINFO staInfo;
PROCESS_INFORMATION childInfo;
- char cmd[MAX_PATH];
+ struct archive_string appname;
+ struct archive_string cmdline;
+ int i, l;
+
+ archive_string_init(&appname);
+ archive_string_init(&cmdline);
+ if (archive_string_ensure(&appname, strlen(path) + 1) == NULL)
+ goto fail;
+ archive_strcpy(&appname, path);
+ for (l = 0, i = 0; argv[i] != NULL; i++) {
+ if (i == 0)
+ continue;
+ l += strlen(argv[i]) + 1;
+ }
+ if (archive_string_ensure(&cmdline, l + 1) == NULL)
+ goto fail;
+ for (i = 0; argv[i] != NULL; i++) {
+ if (i == 0)
+ continue;
+ if (i > 1)
+ archive_strappend_char(&cmdline, ' ');
+ archive_strcat(&cmdline, argv[i]);
+ }
secAtts.nLength = sizeof(SECURITY_ATTRIBUTES);
secAtts.bInheritHandle = TRUE;
staInfo.hStdInput = childStdin[0];
staInfo.wShowWindow = SW_HIDE;
staInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
- strncpy(cmd, path, sizeof(cmd)-1);
- cmd[sizeof(cmd)-1] = '\0';
- if (CreateProcessA(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL,
- &staInfo, &childInfo) == 0) {
+ if (CreateProcessA(appname.s, cmdline.s, NULL, NULL, TRUE, 0,
+ NULL, NULL, &staInfo, &childInfo) == 0) {
CloseHandle(childStdout[0]);
CloseHandle(childStdout[1]);
CloseHandle(childStdin[0]);
CloseHandle(childStdout[1]);
CloseHandle(childStdin[0]);
+ archive_string_free(&appname);
+ archive_string_free(&cmdline);
return (childInfo.dwProcessId);
fail:
+ archive_string_free(&appname);
+ archive_string_free(&cmdline);
return (-1);
}
test_read_disk_entry_from_file.c
test_read_extract.c
test_read_file_nonexistent.c
+ test_read_filter_program_signature.c
test_read_format_7zip.c
test_read_format_ar.c
test_read_format_cab.c
/*-
* Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2012 Michhiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
}
+DEFINE_TEST(test_read_compress_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_compression(a), ARCHIVE_COMPRESSION_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_compress_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;
+ }
+ assert((a = archive_read_new()) != NULL);
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_support_filter_none(a));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_support_filter_programv(a, "gzip", argv));
+ 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_compression(a), ARCHIVE_COMPRESSION_PROGRAM);
+ assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
--- /dev/null
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2012 Michhiro 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 "test.h"
+__FBSDID("$FreeBSD$");
+
+static unsigned char archive[] = {
+31,139,8,0,222,'C','p','C',0,3,211,'c',160,'=','0','0','0','0','7','5','U',
+0,210,134,230,166,6,200,'4',28,'(',24,26,24,27,155,24,152,24,154,27,155,')',
+24,24,26,152,154,25,'2','(',152,210,193,'m',12,165,197,'%',137,'E','@',167,
+148,'d',230,226,'U','G','H',30,234,15,'8','=',10,'F',193,'(',24,5,131,28,
+0,0,29,172,5,240,0,6,0,0};
+#define signature archive
+#define badsignature (&archive[1])
+#define signature_len 4
+
+DEFINE_TEST(test_read_filter_program_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 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_compression(a), ARCHIVE_COMPRESSION_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_compression(a), ARCHIVE_COMPRESSION_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;
+ }
+ assert((a = archive_read_new()) != NULL);
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_support_filter_none(a));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_support_filter_programv_signature(a, "gzip", argv,
+ 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_compression(a), ARCHIVE_COMPRESSION_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_programv_signature(a, "gzip", argv,
+ 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));
+}
/*-
* Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
/* Write it through an external "gzip" program. */
assert((a = archive_write_new()) != NULL);
assertA(0 == archive_write_set_format_ustar(a));
- r = archive_write_set_compression_program(a, "gzip");
+ 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 && !canGunzip()) {
+ 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_compress_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 && canGunzip())
+ 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 && !canGunzip()) {
+ 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_compress_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 && canGunzip())
+ 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);
if (r == ARCHIVE_FATAL) {
skipping("Write compression via external "
"program unsupported on this platform");