From: Tim Kientzle Date: Wed, 1 Apr 2009 19:54:33 +0000 (-0400) Subject: Some cleanup and testing of the XZ and LZMA writer: X-Git-Tag: v2.7.0~43 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d43715df4e5495a17742094cd8570f0dc7ed93c2;p=thirdparty%2Flibarchive.git Some cleanup and testing of the XZ and LZMA writer: * Fix the options parser to use a separate config object. * Set the compression code and name at setup time. * Copy the gzip/bzip2 write tests to create new XZ and LZMA write tests SVN-Revision: 898 --- diff --git a/libarchive/archive_write_set_compression_xz.c b/libarchive/archive_write_set_compression_xz.c index ac146dc8f..7981dd915 100644 --- a/libarchive/archive_write_set_compression_xz.c +++ b/libarchive/archive_write_set_compression_xz.c @@ -48,10 +48,18 @@ __FBSDID("$FreeBSD$"); #ifndef HAVE_LZMA_H int -archive_write_set_compression_xz(struct archive *_a) +archive_write_set_compression_xz(struct archive *a) { - (void)_a; /* UNUSED */ - /* Unsupported xz compression, we don't have liblzma */ + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "xz compression not supported on this platform"); + return (ARCHIVE_FATAL); +} + +int +archive_write_set_compression_lzma(struct archive *a) +{ + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "lzma compression not supported on this platform"); return (ARCHIVE_FATAL); } #else @@ -64,17 +72,16 @@ struct private_data { int64_t total_in; unsigned char *compressed; size_t compressed_buffer_size; - /* Options */ - uint32_t compression_level; }; +struct private_config { + int compression_level; +}; -static int archive_compressor_xz_lzma_init(struct archive_write *, int); -static int archive_compressor_lzma_init(struct archive_write *); -static int archive_compressor_xz_finish(struct archive_write *); static int archive_compressor_xz_init(struct archive_write *); static int archive_compressor_xz_options(struct archive_write *, const char *, const char *); +static int archive_compressor_xz_finish(struct archive_write *); static int archive_compressor_xz_write(struct archive_write *, const void *, size_t); static int drive_compressor(struct archive_write *, struct private_data *, @@ -87,35 +94,39 @@ static int drive_compressor(struct archive_write *, struct private_data *, int archive_write_set_compression_xz(struct archive *_a) { + struct private_config *config; struct archive_write *a = (struct archive_write *)_a; __archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, "archive_write_set_compression_xz"); + config = calloc(1, sizeof(*config)); + if (config == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + a->compressor.config = config; + config->compression_level = LZMA_PRESET_DEFAULT; a->compressor.init = &archive_compressor_xz_init; + a->compressor.options = &archive_compressor_xz_options; + a->archive.compression_code = ARCHIVE_COMPRESSION_XZ; + a->archive.compression_name = "xz"; return (ARCHIVE_OK); } +/* LZMA is handled identically, we just need a different compression + * code set. (The liblzma setup looks at the code to determine + * the one place that XZ and LZMA require different handling.) */ int archive_write_set_compression_lzma(struct archive *_a) { struct archive_write *a = (struct archive_write *)_a; - __archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, - ARCHIVE_STATE_NEW, "archive_write_set_compression_lzma"); - a->compressor.init = &archive_compressor_lzma_init; + int r = archive_write_set_compression_xz(_a); + if (r != ARCHIVE_OK) + return (r); + a->archive.compression_code = ARCHIVE_COMPRESSION_LZMA; + a->archive.compression_name = "lzma"; return (ARCHIVE_OK); } -static int -archive_compressor_xz_init(struct archive_write *a) -{ - return (archive_compressor_xz_lzma_init(a, ARCHIVE_COMPRESSION_XZ)); -} - -static int -archive_compressor_lzma_init(struct archive_write *a) -{ - return (archive_compressor_xz_lzma_init(a, ARCHIVE_COMPRESSION_LZMA)); -} - static int archive_compressor_xz_init_stream(struct archive_write *a, struct private_data *state) @@ -152,14 +163,11 @@ archive_compressor_xz_init_stream(struct archive_write *a, * Setup callback. */ static int -archive_compressor_xz_lzma_init(struct archive_write *a, int code) +archive_compressor_xz_init(struct archive_write *a) { int ret; struct private_data *state; - - a->archive.compression_code = code; - a->archive.compression_name = - (code == ARCHIVE_COMPRESSION_XZ)? "xz" : "lzma"; + struct private_config *config; if (a->client_opener != NULL) { ret = (a->client_opener)(&a->archive, a->client_data); @@ -174,6 +182,7 @@ archive_compressor_xz_lzma_init(struct archive_write *a, int code) return (ARCHIVE_FATAL); } memset(state, 0, sizeof(*state)); + config = a->compressor.config; /* * See comment above. We should set compressed_buffer_size to @@ -181,20 +190,17 @@ archive_compressor_xz_lzma_init(struct archive_write *a, int code) */ state->compressed_buffer_size = a->bytes_per_block; state->compressed = (unsigned char *)malloc(state->compressed_buffer_size); - state->compression_level = LZMA_PRESET_DEFAULT; - if (state->compressed == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate data for compression buffer"); free(state); return (ARCHIVE_FATAL); } - a->compressor.options = archive_compressor_xz_options; a->compressor.write = archive_compressor_xz_write; a->compressor.finish = archive_compressor_xz_finish; /* Initialize compression library. */ - if (lzma_lzma_preset(&state->lzma_opt, state->compression_level)) { + if (lzma_lzma_preset(&state->lzma_opt, config->compression_level)) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Internal error initializing compression library"); free(state->compressed); @@ -222,37 +228,15 @@ static int archive_compressor_xz_options(struct archive_write *a, const char *key, const char *value) { - struct private_data *state; - int ret; + struct private_config *config; - state = (struct private_data *)a->compressor.data; + config = (struct private_config *)a->compressor.config; if (strcmp(key, "compression-level") == 0) { - /* - * compression level : 0 .. 9 - */ - int level; - if (value == NULL || !(value[0] >= '0' && value[0] <= '9') || value[1] != '\0') return (ARCHIVE_WARN); - level = value[0] - '0'; - if (level == state->compression_level) - return (ARCHIVE_OK); - if (lzma_lzma_preset(&state->lzma_opt, level)) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Internal error compression library"); - return (ARCHIVE_FATAL); - } - /* - * Reinitialize - */ - lzma_end(&(state->stream)); - ret = archive_compressor_xz_init_stream(a, state); - if (ret == LZMA_OK) { - state->compression_level = level; - return (ARCHIVE_OK); - } - return (ARCHIVE_FATAL); + config->compression_level = value[0] - '0'; + return (ARCHIVE_OK); } return (ARCHIVE_WARN); diff --git a/libarchive/test/test_write_compress_lzma.c b/libarchive/test/test_write_compress_lzma.c new file mode 100644 index 000000000..45e5041a3 --- /dev/null +++ b/libarchive/test/test_write_compress_lzma.c @@ -0,0 +1,219 @@ +/*- + * Copyright (c) 2007-2009 Tim Kientzle + * 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 + * in this position and unchanged. + * 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$"); + +/* + * A basic exercise of lzma reading and writing. + * + */ + +DEFINE_TEST(test_write_compress_lzma) +{ + struct archive_entry *ae; + struct archive* a; + char *buff, *data; + size_t buffsize, datasize; + char path[16]; + size_t used1, used2; + int i, r; + + buffsize = 2000000; + assert(NULL != (buff = (char *)malloc(buffsize))); + + datasize = 10000; + assert(NULL != (data = (char *)malloc(datasize))); + memset(data, 0, datasize); + + /* + * Write a 100 files and read them all back. + */ + assert((a = archive_write_new()) != NULL); + assertA(0 == archive_write_set_format_ustar(a)); + r = archive_write_set_compression_lzma(a); + if (r == ARCHIVE_FATAL) { + skipping("lzma writing not supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_write_finish(a)); + return; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualInt(ARCHIVE_COMPRESSION_LZMA, archive_compression(a)); + assertEqualString("lzma", archive_compression_name(a)); + assertA(0 == archive_write_open_memory(a, buff, buffsize, &used1)); + assertEqualInt(ARCHIVE_COMPRESSION_LZMA, archive_compression(a)); + assertEqualString("lzma", archive_compression_name(a)); + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_size(ae, datasize); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + archive_entry_copy_pathname(ae, path); + assertA(0 == archive_write_header(a, ae)); + assertA(datasize + == (size_t)archive_write_data(a, data, datasize)); + } + archive_entry_free(ae); + archive_write_close(a); + assert(0 == archive_write_finish(a)); + + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_format_all(a)); + r = archive_read_support_compression_lzma(a); + if (r == ARCHIVE_WARN) { + skipping("Can't verify lzma writing by reading back;" + " lzma reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_compression_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used1)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualInt(ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_finish(a)); + + /* + * Repeat the cycle again, this time setting some compression + * options. + */ + assert((a = archive_write_new()) != NULL); + assertA(0 == archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertA(0 == archive_write_set_compression_lzma(a)); + assertEqualIntA(a, ARCHIVE_WARN, + archive_write_set_compressor_options(a, "nonexistent-option=0")); + assertEqualIntA(a, ARCHIVE_WARN, + archive_write_set_compressor_options(a, "compression-level=abc")); + assertEqualIntA(a, ARCHIVE_WARN, + archive_write_set_compressor_options(a, "compression-level=99")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_compressor_options(a, "compression-level=6")); + assertA(0 == 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); + archive_entry_copy_pathname(ae, path); + archive_entry_set_size(ae, datasize); + archive_entry_set_filetype(ae, AE_IFREG); + assertA(0 == archive_write_header(a, ae)); + assertA(datasize == (size_t)archive_write_data(a, data, datasize)); + archive_entry_free(ae); + } + archive_write_close(a); + assert(0 == archive_write_finish(a)); + + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + r = archive_read_support_compression_lzma(a); + if (r == ARCHIVE_WARN) { + skipping("lzma reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_compression_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used2)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + failure("Trying to read %s", path); + if (!assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_finish(a)); + + /* + * Repeat again, with much lower compression. + */ + assert((a = archive_write_new()) != NULL); + assertA(0 == archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertA(0 == archive_write_set_compression_lzma(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_compressor_options(a, "compression-level=0")); + assertA(0 == 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); + archive_entry_copy_pathname(ae, path); + archive_entry_set_size(ae, datasize); + archive_entry_set_filetype(ae, AE_IFREG); + assertA(0 == archive_write_header(a, ae)); + failure("Writing file %s", path); + assertEqualIntA(a, datasize, + (size_t)archive_write_data(a, data, datasize)); + archive_entry_free(ae); + } + archive_write_close(a); + assert(0 == archive_write_finish(a)); + + /* Level 0 really does result in larger data. */ + failure("Compression-level=0 wrote %d bytes; default wrote %d bytes", + (int)used2, (int)used1); + assert(used2 > used1); + + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_support_compression_all(a)); + r = archive_read_support_compression_lzma(a); + if (r == ARCHIVE_WARN) { + skipping("lzma reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used2)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualInt(ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_finish(a)); + + /* + * Clean up. + */ + free(data); + free(buff); +} diff --git a/libarchive/test/test_write_compress_xz.c b/libarchive/test/test_write_compress_xz.c new file mode 100644 index 000000000..290536a83 --- /dev/null +++ b/libarchive/test/test_write_compress_xz.c @@ -0,0 +1,227 @@ +/*- + * Copyright (c) 2007 Tim Kientzle + * 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 + * in this position and unchanged. + * 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$"); + +/* + * A basic exercise of xz reading and writing. + * + * TODO: Add a reference file and make sure we can decompress that. + */ + +DEFINE_TEST(test_write_compress_xz) +{ + struct archive_entry *ae; + struct archive* a; + char *buff, *data; + size_t buffsize, datasize; + char path[16]; + size_t used1, used2; + int i, r; + + buffsize = 2000000; + assert(NULL != (buff = (char *)malloc(buffsize))); + + datasize = 10000; + assert(NULL != (data = (char *)malloc(datasize))); + memset(data, 0, datasize); + + /* + * Write a 100 files and read them all back. + */ + assert((a = archive_write_new()) != NULL); + assertA(0 == archive_write_set_format_ustar(a)); + r = archive_write_set_compression_xz(a); + if (r == ARCHIVE_FATAL) { + skipping("xz writing not supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_write_finish(a)); + return; + } + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertEqualInt(ARCHIVE_COMPRESSION_XZ, archive_compression(a)); + assertEqualString("xz", archive_compression_name(a)); + assertA(0 == archive_write_open_memory(a, buff, buffsize, &used1)); + assertEqualInt(ARCHIVE_COMPRESSION_XZ, archive_compression(a)); + assertEqualString("xz", archive_compression_name(a)); + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_size(ae, datasize); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + archive_entry_copy_pathname(ae, path); + assertA(0 == archive_write_header(a, ae)); + assertA(datasize + == (size_t)archive_write_data(a, data, datasize)); + } + archive_entry_free(ae); + archive_write_close(a); + assert(0 == archive_write_finish(a)); + + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_format_all(a)); + r = archive_read_support_compression_xz(a); + if (r == ARCHIVE_WARN) { + skipping("Can't verify xz writing by reading back;" + " xz reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_compression_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used1)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualInt(ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_finish(a)); + + /* + * Repeat the cycle again, this time setting some compression + * options. + */ + assert((a = archive_write_new()) != NULL); + assertA(0 == archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertA(0 == archive_write_set_compression_xz(a)); + assertEqualIntA(a, ARCHIVE_WARN, + archive_write_set_compressor_options(a, "nonexistent-option=0")); + assertEqualIntA(a, ARCHIVE_WARN, + archive_write_set_compressor_options(a, "compression-level=abc")); + assertEqualIntA(a, ARCHIVE_WARN, + archive_write_set_compressor_options(a, "compression-level=99")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_compressor_options(a, "compression-level=6")); + assertA(0 == 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); + archive_entry_copy_pathname(ae, path); + archive_entry_set_size(ae, datasize); + archive_entry_set_filetype(ae, AE_IFREG); + assertA(0 == archive_write_header(a, ae)); + assertA(datasize == (size_t)archive_write_data(a, data, datasize)); + archive_entry_free(ae); + } + archive_write_close(a); + assert(0 == archive_write_finish(a)); + + /* Curiously, this test fails; the test data above compresses + * better at default compression than at level 9. */ + /* + failure("compression-level=9 wrote %d bytes, default wrote %d bytes", + (int)used2, (int)used1); + assert(used2 < used1); + */ + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + r = archive_read_support_compression_xz(a); + if (r == ARCHIVE_WARN) { + skipping("xz reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_compression_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used2)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + failure("Trying to read %s", path); + if (!assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_finish(a)); + + /* + * Repeat again, with much lower compression. + */ + assert((a = archive_write_new()) != NULL); + assertA(0 == archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, 10)); + assertA(0 == archive_write_set_compression_xz(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_compressor_options(a, "compression-level=0")); + assertA(0 == 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); + archive_entry_copy_pathname(ae, path); + archive_entry_set_size(ae, datasize); + archive_entry_set_filetype(ae, AE_IFREG); + assertA(0 == archive_write_header(a, ae)); + failure("Writing file %s", path); + assertEqualIntA(a, datasize, + (size_t)archive_write_data(a, data, datasize)); + archive_entry_free(ae); + } + archive_write_close(a); + assert(0 == archive_write_finish(a)); + + /* Level 0 really does result in larger data. */ + failure("Compression-level=0 wrote %d bytes; default wrote %d bytes", + (int)used2, (int)used1); + assert(used2 > used1); + + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_support_compression_all(a)); + r = archive_read_support_compression_xz(a); + if (r == ARCHIVE_WARN) { + skipping("xz reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used2)); + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + if (!assertEqualInt(ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, archive_entry_pathname(ae)); + assertEqualInt((int)datasize, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_finish(a)); + + /* + * Clean up. + */ + free(data); + free(buff); +}