]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Enable bzip2 compression to use an external bzip2 program when
authorMichihiro NAKAJIMA <ggcueroad@gmail.com>
Sat, 13 Oct 2012 10:28:37 +0000 (19:28 +0900)
committerMichihiro NAKAJIMA <ggcueroad@gmail.com>
Sat, 13 Oct 2012 10:28:37 +0000 (19:28 +0900)
libbz2 is unavailable.

libarchive/archive_write_add_filter_bzip2.c
libarchive/test/test_empty_write.c
libarchive/test/test_filter_count.c
libarchive/test/test_read_truncated_filter.c
libarchive/test/test_write_filter_bzip2.c

index 022f7282f99d1345ed04ff4a40dfdd0a78416b8c..e63c574ca60c0632ac65a795c1ed2c28a024b09f 100644 (file)
@@ -1,5 +1,6 @@
 /*-
  * 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
@@ -54,32 +55,18 @@ archive_write_set_compression_bzip2(struct archive *a)
 }
 #endif
 
-#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR)
-int
-archive_write_add_filter_bzip2(struct archive *a)
-{
-       archive_set_error(a, ARCHIVE_ERRNO_MISC,
-           "bzip2 compression not supported on this platform");
-       return (ARCHIVE_FATAL);
-}
-#else
-/* Don't compile this if we don't have bzlib. */
-
 struct private_data {
        int              compression_level;
+#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
        bz_stream        stream;
        int64_t          total_in;
        char            *compressed;
        size_t           compressed_buffer_size;
+#else
+       struct archive_write_program_data *pdata;
+#endif
 };
 
-/*
- * Yuck.  bzlib.h is not const-correct, so I need this one bit
- * of ugly hackery to convert a const * pointer to a non-const pointer.
- */
-#define        SET_NEXT_IN(st,src)                                     \
-       (st)->stream.next_in = (char *)(uintptr_t)(const void *)(src)
-
 static int archive_compressor_bzip2_close(struct archive_write_filter *);
 static int archive_compressor_bzip2_free(struct archive_write_filter *);
 static int archive_compressor_bzip2_open(struct archive_write_filter *);
@@ -87,6 +74,44 @@ static int archive_compressor_bzip2_options(struct archive_write_filter *,
                    const char *, const char *);
 static int archive_compressor_bzip2_write(struct archive_write_filter *,
                    const void *, size_t);
+
+/*
+ * Set write options.
+ */
+static int
+archive_compressor_bzip2_options(struct archive_write_filter *f,
+    const char *key, const char *value)
+{
+       struct private_data *data = (struct private_data *)f->data;
+
+       if (strcmp(key, "compression-level") == 0) {
+               if (value == NULL || !(value[0] >= '0' && value[0] <= '9') ||
+                   value[1] != '\0')
+                       return (ARCHIVE_WARN);
+               data->compression_level = value[0] - '0';
+               /* Make '0' be a synonym for '1'. */
+               /* This way, bzip2 compressor supports the same 0..9
+                * range of levels as gzip. */
+               if (data->compression_level < 1)
+                       data->compression_level = 1;
+               return (ARCHIVE_OK);
+       }
+
+       /* Note: The "warn" return is just to inform the options
+        * supervisor that we didn't handle it.  It will generate
+        * a suitable error if no one used this option. */
+       return (ARCHIVE_WARN);
+}
+
+#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
+/* Don't compile this if we don't have bzlib. */
+
+/*
+ * Yuck.  bzlib.h is not const-correct, so I need this one bit
+ * of ugly hackery to convert a const * pointer to a non-const pointer.
+ */
+#define        SET_NEXT_IN(st,src)                                     \
+       (st)->stream.next_in = (char *)(uintptr_t)(const void *)(src)
 static int drive_compressor(struct archive_write_filter *,
                    struct private_data *, int finishing);
 
@@ -194,34 +219,6 @@ archive_compressor_bzip2_open(struct archive_write_filter *f)
 
 }
 
-/*
- * Set write options.
- */
-static int
-archive_compressor_bzip2_options(struct archive_write_filter *f,
-    const char *key, const char *value)
-{
-       struct private_data *data = (struct private_data *)f->data;
-
-       if (strcmp(key, "compression-level") == 0) {
-               if (value == NULL || !(value[0] >= '0' && value[0] <= '9') ||
-                   value[1] != '\0')
-                       return (ARCHIVE_WARN);
-               data->compression_level = value[0] - '0';
-               /* Make '0' be a synonym for '1'. */
-               /* This way, bzip2 compressor supports the same 0..9
-                * range of levels as gzip. */
-               if (data->compression_level < 1)
-                       data->compression_level = 1;
-               return (ARCHIVE_OK);
-       }
-
-       /* Note: The "warn" return is just to inform the options
-        * supervisor that we didn't handle it.  It will generate
-        * a suitable error if no one used this option. */
-       return (ARCHIVE_WARN);
-}
-
 /*
  * Write data to the compressed stream.
  *
@@ -343,4 +340,49 @@ drive_compressor(struct archive_write_filter *f,
        }
 }
 
+#else /* HAVE_BZLIB_H && BZ_CONFIG_ERROR */
+
+static int
+archive_compressor_bzip2_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, "bzip2");
+
+       /* 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_bzip2_write;
+
+       return __archive_write_program_open(f, data->pdata);
+}
+
+static int
+archive_compressor_bzip2_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_bzip2_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_BZLIB_H && BZ_CONFIG_ERROR */
index 60ba4168cded480add29f5927837d5421683d6be..c35979bfbf45bf65d5af954eb7ac0bbc75d59c5e 100644 (file)
@@ -75,7 +75,7 @@ DEFINE_TEST(test_empty_write)
        assert((a = archive_write_new()) != NULL);
        assertA(0 == archive_write_set_format_ustar(a));
        r = archive_write_add_filter_bzip2(a);
-       if (r == ARCHIVE_FATAL) {
+       if (r != ARCHIVE_OK && !canBzip2()) {
                skipping("Empty write to bzip2-compressed archive");
        } else {
                assertEqualIntA(a, ARCHIVE_OK, r);
index e15ab11c6f637b0e165e3f66b5ba947fbc03bc22..4885ab89a52efbadcf89b245ddbf46ea36b049ce 100644 (file)
@@ -32,7 +32,10 @@ static void
 read_test(const char *name)
 {
        struct archive* a = archive_read_new();
-       if(ARCHIVE_OK != archive_read_support_filter_bzip2(a)) {
+       int r;
+
+       r = archive_read_support_filter_bzip2(a);
+       if((ARCHIVE_WARN == r && !canBzip2()) || ARCHIVE_WARN > r) {
                skipping("bzip2 unsupported");
                return;
        }
@@ -52,11 +55,13 @@ write_test(void)
 {
        char buff[4096];
        struct archive* a = archive_write_new();
+       int r;
 
        assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
        assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_per_block(a, 10));
 
-       if(ARCHIVE_OK != archive_write_add_filter_bzip2(a)) {
+       r = archive_write_add_filter_bzip2(a);
+       if((ARCHIVE_WARN == r && !canBzip2()) || ARCHIVE_WARN > r) {
                skipping("bzip2 unsupported");
                return;
        }
index 9128e83eb69fd57c93f4d3729eb21da748df855d..73254d398ceea164e45196cf2fdc987f938cbb05 100644 (file)
@@ -131,7 +131,7 @@ test_truncation(const char *compression,
 
 DEFINE_TEST(test_read_truncated_filter)
 {
-       test_truncation("bzip2", archive_write_add_filter_bzip2, 0);
+       test_truncation("bzip2", archive_write_add_filter_bzip2, canBzip2());
        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);
index 96ac0e62df4804d4d896a7222c62eeb57f01f278..74150c8fb6eba4f1fb191cd526372a7f96a439d1 100644 (file)
@@ -41,7 +41,7 @@ DEFINE_TEST(test_write_filter_bzip2)
        size_t buffsize, datasize;
        char path[16];
        size_t used1, used2;
-       int i, r;
+       int i, r, use_prog;
 
        buffsize = 2000000;
        assert(NULL != (buff = (char *)malloc(buffsize)));
@@ -56,16 +56,19 @@ DEFINE_TEST(test_write_filter_bzip2)
        assert((a = archive_write_new()) != NULL);
        assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
        r = archive_write_add_filter_bzip2(a);
-       if (r == ARCHIVE_FATAL) {
+       use_prog = (r == ARCHIVE_WARN && canBzip2());
+       if (r != ARCHIVE_OK && !use_prog) {
                skipping("bzip2 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_BZIP2, archive_filter_code(a, 0));
        assertEqualString("bzip2", 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));
        assertEqualInt(ARCHIVE_FILTER_BZIP2, archive_filter_code(a, 0));
        assertEqualString("bzip2", archive_filter_name(a, 0));
        assert((ae = archive_entry_new()) != NULL);
@@ -85,7 +88,8 @@ DEFINE_TEST(test_write_filter_bzip2)
        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));
-       assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used1));
+       assertEqualIntA(a, ARCHIVE_OK,
+           archive_read_open_memory(a, buff, used1));
        for (i = 0; i < 999; i++) {
                sprintf(path, "file%03d", i);
                if (!assertEqualInt(0, archive_read_next_header(a, &ae)))
@@ -104,16 +108,22 @@ DEFINE_TEST(test_write_filter_bzip2)
        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_bzip2(a));
-       assertEqualIntA(a, ARCHIVE_FAILED,
-           archive_write_set_filter_option(a, NULL, "nonexistent-option", "0"));
-       assertEqualIntA(a, ARCHIVE_FAILED,
-           archive_write_set_filter_option(a, NULL, "compression-level", "abc"));
-       assertEqualIntA(a, ARCHIVE_FAILED,
-           archive_write_set_filter_option(a, NULL, "compression-level", "99"));
+       if (use_prog)
+               assertEqualIntA(a, ARCHIVE_WARN,
+                   archive_write_add_filter_bzip2(a));
+       else
+               assertEqualIntA(a, ARCHIVE_OK,
+                   archive_write_add_filter_bzip2(a));
+       assertEqualIntA(a, ARCHIVE_FAILED, archive_write_set_filter_option(a,
+           NULL, "nonexistent-option", "0"));
+       assertEqualIntA(a, ARCHIVE_FAILED, archive_write_set_filter_option(a,
+           NULL, "compression-level", "abc"));
+       assertEqualIntA(a, ARCHIVE_FAILED, archive_write_set_filter_option(a,
+           NULL, "compression-level", "99"));
+       assertEqualIntA(a, ARCHIVE_OK, archive_write_set_filter_option(a,
+           NULL, "compression-level", "9"));
        assertEqualIntA(a, ARCHIVE_OK,
-           archive_write_set_filter_option(a, NULL, "compression-level", "9"));
-       assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2));
+           archive_write_open_memory(a, buff, buffsize, &used2));
        for (i = 0; i < 999; i++) {
                sprintf(path, "file%03d", i);
                assert((ae = archive_entry_new()) != NULL);
@@ -121,7 +131,8 @@ DEFINE_TEST(test_write_filter_bzip2)
                archive_entry_set_size(ae, datasize);
                archive_entry_set_filetype(ae, AE_IFREG);
                assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
-               assertA(datasize == (size_t)archive_write_data(a, data, datasize));
+               assertA(datasize == (size_t)archive_write_data(a, data,
+                   datasize));
                archive_entry_free(ae);
        }
        assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
@@ -138,7 +149,8 @@ DEFINE_TEST(test_write_filter_bzip2)
        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));
-       assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used2));
+       assertEqualIntA(a, ARCHIVE_OK,
+           archive_read_open_memory(a, buff, used2));
        for (i = 0; i < 999; i++) {
                sprintf(path, "file%03d", i);
                if (!assertEqualInt(0, archive_read_next_header(a, &ae)))
@@ -156,10 +168,16 @@ DEFINE_TEST(test_write_filter_bzip2)
        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_bzip2(a));
+       if (use_prog)
+               assertEqualIntA(a, ARCHIVE_WARN,
+                   archive_write_add_filter_bzip2(a));
+       else
+               assertEqualIntA(a, ARCHIVE_OK,
+                   archive_write_add_filter_bzip2(a));
+       assertEqualIntA(a, ARCHIVE_OK, archive_write_set_filter_option(a,
+           NULL, "compression-level", "1"));
        assertEqualIntA(a, ARCHIVE_OK,
-           archive_write_set_filter_option(a, NULL, "compression-level", "1"));
-       assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2));
+           archive_write_open_memory(a, buff, buffsize, &used2));
        for (i = 0; i < 999; i++) {
                sprintf(path, "file%03d", i);
                assert((ae = archive_entry_new()) != NULL);
@@ -183,7 +201,8 @@ DEFINE_TEST(test_write_filter_bzip2)
        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));
-       assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used2));
+       assertEqualIntA(a, ARCHIVE_OK,
+           archive_read_open_memory(a, buff, used2));
        for (i = 0; i < 999; i++) {
                sprintf(path, "file%03d", i);
                if (!assertEqualInt(0, archive_read_next_header(a, &ae)))
@@ -199,24 +218,45 @@ DEFINE_TEST(test_write_filter_bzip2)
         * don't crash or leak memory.
         */
        assert((a = archive_write_new()) != NULL);
-       assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_bzip2(a));
+       if (use_prog)
+               assertEqualIntA(a, ARCHIVE_WARN,
+                   archive_write_add_filter_bzip2(a));
+       else
+               assertEqualIntA(a, ARCHIVE_OK,
+                   archive_write_add_filter_bzip2(a));
        assertEqualInt(ARCHIVE_OK, archive_write_free(a));
 
        assert((a = archive_write_new()) != NULL);
-       assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_bzip2(a));
+       if (use_prog)
+               assertEqualIntA(a, ARCHIVE_WARN,
+                   archive_write_add_filter_bzip2(a));
+       else
+               assertEqualIntA(a, ARCHIVE_OK,
+                   archive_write_add_filter_bzip2(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_bzip2(a));
+       if (use_prog)
+               assertEqualIntA(a, ARCHIVE_WARN,
+                   archive_write_add_filter_bzip2(a));
+       else
+               assertEqualIntA(a, ARCHIVE_OK,
+                   archive_write_add_filter_bzip2(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_bzip2(a));
-       assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2));
+       if (use_prog)
+               assertEqualIntA(a, ARCHIVE_WARN,
+                   archive_write_add_filter_bzip2(a));
+       else
+               assertEqualIntA(a, ARCHIVE_OK,
+                   archive_write_add_filter_bzip2(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));