#include "archive.h"
#include "archive_private.h"
+#include "archive_string.h"
#include "archive_write_private.h"
#if ARCHIVE_VERSION_NUMBER < 4000000
}
#endif
-#ifndef HAVE_ZLIB_H
-int
-archive_write_add_filter_gzip(struct archive *a)
-{
- archive_set_error(a, ARCHIVE_ERRNO_MISC,
- "gzip compression not supported on this platform");
- return (ARCHIVE_FATAL);
-}
-#else
/* Don't compile this if we don't have zlib. */
struct private_data {
int compression_level;
+#ifdef HAVE_ZLIB_H
z_stream stream;
int64_t total_in;
unsigned char *compressed;
size_t compressed_buffer_size;
unsigned long crc;
+#else
+ struct archive_write_program_data *pdata;
+#endif
};
/*
const void *, size_t);
static int archive_compressor_gzip_close(struct archive_write_filter *);
static int archive_compressor_gzip_free(struct archive_write_filter *);
+#ifdef HAVE_ZLIB_H
static int drive_compressor(struct archive_write_filter *,
struct private_data *, int finishing);
+#endif
/*
return (ARCHIVE_FATAL);
}
f->data = data;
- data->compression_level = Z_DEFAULT_COMPRESSION;
f->open = &archive_compressor_gzip_open;
f->options = &archive_compressor_gzip_options;
f->close = &archive_compressor_gzip_close;
f->free = &archive_compressor_gzip_free;
f->code = ARCHIVE_FILTER_GZIP;
f->name = "gzip";
+#ifdef HAVE_ZLIB_H
+ data->compression_level = Z_DEFAULT_COMPRESSION;
return (ARCHIVE_OK);
+#else
+ data->pdata = __archive_write_program_allocate();
+ if (data->pdata == NULL) {
+ free(data);
+ archive_set_error(&a->archive, ENOMEM, "Out of memory");
+ return (ARCHIVE_FATAL);
+ }
+ data->compression_level = 0;
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Using external gzip program");
+ return (ARCHIVE_WARN);
+#endif
}
static int
archive_compressor_gzip_free(struct archive_write_filter *f)
{
struct private_data *data = (struct private_data *)f->data;
+
+#ifdef HAVE_ZLIB_H
free(data->compressed);
+#else
+ __archive_write_program_free(data->pdata);
+#endif
free(data);
f->data = NULL;
return (ARCHIVE_OK);
return (ARCHIVE_WARN);
}
+#ifdef HAVE_ZLIB_H
/*
* Setup callback.
*/
}
}
+#else /* HAVE_ZLIB_H */
+
+static int
+archive_compressor_gzip_open(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+ struct archive_string as;
+ int r;
+
+ archive_string_init(&as);
+ archive_strcpy(&as, "gzip");
+
+ /* Specify compression level. */
+ if (data->compression_level > 0) {
+ archive_strcat(&as, " -");
+ archive_strappend_char(&as, '0' + data->compression_level);
+ }
+ r = __archive_write_program_set_cmd(data->pdata, as.s);
+ archive_string_free(&as);
+ if (r != ARCHIVE_OK) {
+ archive_set_error(f->archive, ENOMEM, "Can't allocate memory");
+ return (ARCHIVE_FATAL);
+ }
+ f->write = archive_compressor_gzip_write;
+
+ return __archive_write_program_open(f, data->pdata);
+}
+
+static int
+archive_compressor_gzip_write(struct archive_write_filter *f, const void *buff,
+ size_t length)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+ return __archive_write_program_write(f, data->pdata, buff, length);
+}
+
+static int
+archive_compressor_gzip_close(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+ return __archive_write_program_close(f, data->pdata);
+}
+
#endif /* HAVE_ZLIB_H */
assert((a = archive_write_new()) != NULL);
assertA(0 == archive_write_set_format_ustar(a));
r = archive_write_add_filter_gzip(a);
- if (r == ARCHIVE_FATAL) {
+ if (r != ARCHIVE_OK && !canGzip()) {
skipping("Empty write to gzip-compressed archive");
} else {
- assertEqualIntA(a, ARCHIVE_OK, r);
+ if (r != ARCHIVE_OK && canGzip())
+ assertEqualIntA(a, ARCHIVE_WARN, r);
+ else
+ assertEqualIntA(a, ARCHIVE_OK, r);
assertEqualIntA(a, ARCHIVE_OK,
archive_write_open_memory(a, buff, sizeof(buff), &used));
/* Write a file to it. */
*/
static void
-test_truncation(const char *compression, int (*set_compression)(struct archive *))
+test_truncation(const char *compression,
+ int (*set_compression)(struct archive *), int can_prog)
{
struct archive_entry *ae;
struct archive* a;
char path[16];
char *buff, *data;
size_t buffsize, datasize, used1;
- int i, j, r;
+ int i, j, r, use_prog;
buffsize = 2000000;
assert(NULL != (buff = (char *)malloc(buffsize)));
assertEqualIntA(a, ARCHIVE_OK,
archive_write_add_filter_compress(a));
r = (*set_compression)(a);
- if (r == ARCHIVE_FATAL) {
- skipping("%s writing not supported on this platform", compression);
+ if (r != ARCHIVE_OK && !can_prog) {
+ skipping("%s writing not supported on this platform",
+ compression);
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
return;
}
+ use_prog = (r == ARCHIVE_WARN && can_prog);
assertEqualIntA(a, ARCHIVE_OK,
archive_write_set_bytes_per_block(a, 10));
- assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used1));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_open_memory(a, buff, buffsize, &used1));
assert((ae = archive_entry_new()) != NULL);
archive_entry_set_filetype(ae, AE_IFREG);
archive_entry_set_size(ae, datasize);
sprintf(path, "%s%d", compression, i);
archive_entry_copy_pathname(ae, path);
failure(path);
- if (!assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae))) {
+ if (!assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_header(a, ae))) {
archive_write_free(a);
free(data);
free(buff);
data[j] = (char)(rand() % 256);
}
failure(path);
- if (!assertEqualIntA(a, datasize, archive_write_data(a, data, datasize))) {
+ if (!assertEqualIntA(a, datasize,
+ archive_write_data(a, data, datasize))) {
archive_write_free(a);
free(data);
free(buff);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
- assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used1 - used1/64));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_open_memory(a, buff, used1 - used1/64));
for (i = 0; i < 100; i++) {
if (ARCHIVE_OK != archive_read_next_header(a, &ae)) {
failure("Should have non-NULL error message for %s",
break;
}
}
- assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
+ assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK,
+ archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
free(data);
DEFINE_TEST(test_read_truncated_filter)
{
- test_truncation("bzip2", archive_write_add_filter_bzip2);
- test_truncation("compress", archive_write_add_filter_compress);
- test_truncation("gzip", archive_write_add_filter_gzip);
- test_truncation("lzip", archive_write_add_filter_lzip);
- test_truncation("lzma", archive_write_add_filter_lzma);
- test_truncation("xz", archive_write_add_filter_xz);
+ test_truncation("bzip2", archive_write_add_filter_bzip2, 0);
+ test_truncation("compress", archive_write_add_filter_compress, 0);
+ test_truncation("gzip", archive_write_add_filter_gzip, canGzip());
+ test_truncation("lzip", archive_write_add_filter_lzip, 0);
+ test_truncation("lzma", archive_write_add_filter_lzma, 0);
+ test_truncation("xz", archive_write_add_filter_xz, 0);
}
size_t buffsize, datasize;
char path[16];
size_t used1, used2;
- int i, r;
+ int i, r, use_prog = 0;
buffsize = 2000000;
assert(NULL != (buff = (char *)malloc(buffsize)));
assert((a = archive_write_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
r = archive_write_add_filter_gzip(a);
- if (r == ARCHIVE_FATAL) {
- skipping("gzip writing not supported on this platform");
- assertEqualInt(ARCHIVE_OK, archive_write_free(a));
- return;
+ if (r != ARCHIVE_OK) {
+ if (canGzip() && r == ARCHIVE_WARN)
+ use_prog = 1;
+ else {
+ skipping("gzip writing not supported on this platform");
+ assertEqualInt(ARCHIVE_OK, archive_write_free(a));
+ return;
+ }
}
assertEqualIntA(a, ARCHIVE_OK,
archive_write_set_bytes_per_block(a, 10));
assertEqualInt(ARCHIVE_FILTER_GZIP, archive_filter_code(a, 0));
assertEqualString("gzip", archive_filter_name(a, 0));
- assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used1));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_open_memory(a, buff, buffsize, &used1));
assert((ae = archive_entry_new()) != NULL);
archive_entry_set_filetype(ae, AE_IFREG);
archive_entry_set_size(ae, datasize);
assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
assertEqualIntA(a, ARCHIVE_OK,
archive_write_set_bytes_per_block(a, 10));
- assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_gzip(a));
+ assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK,
+ archive_write_add_filter_gzip(a));
assertEqualIntA(a, ARCHIVE_FAILED,
archive_write_set_options(a, "gzip:nonexistent-option=0"));
assertEqualIntA(a, ARCHIVE_OK,
- archive_write_set_options(a, "gzip:compression-level=0"));
+ archive_write_set_options(a, "gzip:compression-level=1"));
assertEqualIntA(a, ARCHIVE_OK,
archive_write_set_filter_option(a, NULL, "compression-level", "9"));
assertEqualIntA(a, ARCHIVE_FAILED,
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
r = archive_read_support_filter_gzip(a);
- if (r == ARCHIVE_WARN) {
+ if (r != ARCHIVE_OK && !use_prog) {
skipping("gzip reading not fully supported on this platform");
} else {
assertEqualIntA(a, ARCHIVE_OK,
assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
assertEqualIntA(a, ARCHIVE_OK,
archive_write_set_bytes_per_block(a, 10));
- assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_gzip(a));
+ assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK,
+ archive_write_add_filter_gzip(a));
assertEqualIntA(a, ARCHIVE_OK,
- archive_write_set_filter_option(a, NULL, "compression-level", "0"));
- assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2));
+ archive_write_set_filter_option(a, NULL, "compression-level", "1"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_open_memory(a, buff, buffsize, &used2));
for (i = 0; i < 100; i++) {
sprintf(path, "file%03d", i);
assert((ae = archive_entry_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
- /* Level 0 really does result in larger data. */
- failure("Compression-level=0 wrote %d bytes; default wrote %d bytes",
+ /* Level 1 really does result in larger data. */
+ failure("Compression-level=1 wrote %d bytes; default wrote %d bytes",
(int)used2, (int)used1);
assert(used2 > used1);
* don't crash or leak memory.
*/
assert((a = archive_write_new()) != NULL);
- assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_gzip(a));
+ assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK,
+ archive_write_add_filter_gzip(a));
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
assert((a = archive_write_new()) != NULL);
- assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_gzip(a));
+ assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK,
+ archive_write_add_filter_gzip(a));
assertEqualInt(ARCHIVE_OK, archive_write_close(a));
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
assert((a = archive_write_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
- assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_gzip(a));
+ assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK,
+ archive_write_add_filter_gzip(a));
assertEqualInt(ARCHIVE_OK, archive_write_close(a));
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
assert((a = archive_write_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
- assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_gzip(a));
+ assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK,
+ archive_write_add_filter_gzip(a));
assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2));
assertEqualInt(ARCHIVE_OK, archive_write_close(a));
assertEqualInt(ARCHIVE_OK, archive_write_free(a));