From: Michihiro NAKAJIMA Date: Tue, 9 Oct 2012 23:17:05 +0000 (+0900) Subject: Add support for grzip compression. X-Git-Tag: v3.1.0~40^2~59 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=630ead783593075e974858372b9c171abb2df28a;p=thirdparty%2Flibarchive.git Add support for grzip compression. --- diff --git a/Makefile.am b/Makefile.am index 8814cbe95..5052643b6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -133,6 +133,7 @@ libarchive_la_SOURCES= \ libarchive/archive_read_support_filter_all.c \ libarchive/archive_read_support_filter_bzip2.c \ libarchive/archive_read_support_filter_compress.c \ + libarchive/archive_read_support_filter_grzip.c \ libarchive/archive_read_support_filter_gzip.c \ libarchive/archive_read_support_filter_lrzip.c \ libarchive/archive_read_support_filter_lzop.c \ @@ -174,13 +175,14 @@ libarchive_la_SOURCES= \ libarchive/archive_write_private.h \ libarchive/archive_write_add_filter.c \ libarchive/archive_write_add_filter_b64encode.c \ - libarchive/archive_write_add_filter_bzip2.c \ - libarchive/archive_write_add_filter_compress.c \ + libarchive/archive_write_add_filter_bzip2.c \ + libarchive/archive_write_add_filter_compress.c \ + libarchive/archive_write_add_filter_grzip.c \ libarchive/archive_write_add_filter_gzip.c \ libarchive/archive_write_add_filter_lrzip.c \ libarchive/archive_write_add_filter_lzop.c \ libarchive/archive_write_add_filter_none.c \ - libarchive/archive_write_add_filter_program.c \ + libarchive/archive_write_add_filter_program.c \ libarchive/archive_write_add_filter_uuencode.c \ libarchive/archive_write_add_filter_xz.c \ libarchive/archive_write_set_format.c \ @@ -334,11 +336,12 @@ libarchive_test_SOURCES= \ 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_grzip.c \ + libarchive/test/test_read_filter_lrzip.c \ + libarchive/test/test_read_filter_lzop.c \ libarchive/test/test_read_filter_program.c \ libarchive/test/test_read_filter_program_signature.c \ libarchive/test/test_read_filter_uudecode.c \ - libarchive/test/test_read_filter_lrzip.c \ - libarchive/test/test_read_filter_lzop.c \ libarchive/test/test_read_format_7zip.c \ libarchive/test/test_read_format_ar.c \ libarchive/test/test_read_format_cab.c \ @@ -511,6 +514,7 @@ libarchive_test_EXTRA_DIST=\ libarchive/test/test_rar_multivolume_single_file.part1.rar.uu \ libarchive/test/test_rar_multivolume_single_file.part2.rar.uu \ libarchive/test/test_rar_multivolume_single_file.part3.rar.uu \ + libarchive/test/test_read_filter_grzip.tar.grz.uu \ libarchive/test/test_read_filter_lrzip.tar.lrz.uu \ libarchive/test/test_read_filter_lzop.tar.lzo.uu \ libarchive/test/test_read_format_7zip_bcj_bzip2.7z.uu \ @@ -713,6 +717,7 @@ bsdtar_test_SOURCES= \ tar/test/test_empty_mtree.c \ tar/test/test_extract_tar_Z.c \ tar/test/test_extract_tar_bz2.c \ + tar/test/test_extract_tar_grz.c \ tar/test/test_extract_tar_gz.c \ tar/test/test_extract_tar_lrz.c \ tar/test/test_extract_tar_lz.c \ @@ -732,6 +737,7 @@ bsdtar_test_SOURCES= \ tar/test/test_option_b64encode.c \ tar/test/test_option_exclude.c \ tar/test/test_option_gid_gname.c \ + tar/test/test_option_grzip.c \ tar/test/test_option_k.c \ tar/test/test_option_keep_newer_files.c \ tar/test/test_option_lrzip.c \ @@ -776,6 +782,7 @@ bsdtar_test_EXTRA_DIST= \ tar/test/list.h \ tar/test/test_extract.tar.Z.uu \ tar/test/test_extract.tar.bz2.uu \ + tar/test/test_extract.tar.grz.uu \ tar/test/test_extract.tar.gz.uu \ tar/test/test_extract.tar.lrz.uu \ tar/test/test_extract.tar.lz.uu \ @@ -855,6 +862,7 @@ bsdcpio_test_SOURCES= \ cpio/test/test_cmdline.c \ cpio/test/test_extract_cpio_Z.c \ cpio/test/test_extract_cpio_bz2.c \ + cpio/test/test_extract_cpio_grz.c \ cpio/test/test_extract_cpio_gz.c \ cpio/test/test_extract_cpio_lrz.c \ cpio/test/test_extract_cpio_lz.c \ @@ -874,6 +882,7 @@ bsdcpio_test_SOURCES= \ cpio/test/test_option_c.c \ cpio/test/test_option_d.c \ cpio/test/test_option_f.c \ + cpio/test/test_option_grzip.c \ cpio/test/test_option_help.c \ cpio/test/test_option_l.c \ cpio/test/test_option_lrzip.c \ @@ -913,6 +922,7 @@ bsdcpio_test_EXTRA_DIST= \ cpio/test/list.h \ cpio/test/test_extract.cpio.Z.uu \ cpio/test/test_extract.cpio.bz2.uu \ + cpio/test/test_extract.cpio.grz.uu \ cpio/test/test_extract.cpio.gz.uu \ cpio/test/test_extract.cpio.lrz.uu \ cpio/test/test_extract.cpio.lz.uu \ diff --git a/cpio/cmdline.c b/cpio/cmdline.c index 3dff0b6b3..0121fd139 100644 --- a/cpio/cmdline.c +++ b/cpio/cmdline.c @@ -67,6 +67,7 @@ static const struct option { { "extract", 0, 'i' }, { "file", 1, 'F' }, { "format", 1, 'H' }, + { "grzip", 0, OPTION_GRZIP }, { "help", 0, 'h' }, { "insecure", 0, OPTION_INSECURE }, { "link", 0, 'l' }, diff --git a/cpio/cpio.c b/cpio/cpio.c index 89fc25bd0..95e8e0806 100644 --- a/cpio/cpio.c +++ b/cpio/cpio.c @@ -237,6 +237,9 @@ main(int argc, char *argv[]) lafe_errc(1, 0, "Error : %s", archive_error_string(cpio->matching)); break; + case OPTION_GRZIP: + cpio->compress = opt; + break; case 'H': /* GNU cpio (also --format) */ cpio->format = cpio->argument; break; @@ -525,6 +528,9 @@ mode_out(struct cpio *cpio) if (cpio->archive == NULL) lafe_errc(1, 0, "Failed to allocate archive object"); switch (cpio->compress) { + case OPTION_GRZIP: + r = archive_write_add_filter_grzip(cpio->archive); + break; case 'J': r = archive_write_add_filter_xz(cpio->archive); break; diff --git a/cpio/cpio.h b/cpio/cpio.h index b1d89427f..3e951ce74 100644 --- a/cpio/cpio.h +++ b/cpio/cpio.h @@ -98,6 +98,7 @@ const char *owner_parse(const char *, int *, int *); /* Fake short equivalents for long options that otherwise lack them. */ enum { OPTION_B64ENCODE = 1, + OPTION_GRZIP, OPTION_INSECURE, OPTION_LRZIP, OPTION_LZMA, diff --git a/cpio/test/CMakeLists.txt b/cpio/test/CMakeLists.txt index 3713cd3d8..09ca2c7d9 100644 --- a/cpio/test/CMakeLists.txt +++ b/cpio/test/CMakeLists.txt @@ -15,6 +15,7 @@ IF(ENABLE_CPIO AND ENABLE_TEST) test_cmdline.c test_extract_cpio_Z test_extract_cpio_bz2 + test_extract_cpio_grz test_extract_cpio_gz test_extract_cpio_lrz test_extract_cpio_lz @@ -34,6 +35,7 @@ IF(ENABLE_CPIO AND ENABLE_TEST) test_option_c.c test_option_d.c test_option_f.c + test_option_grzip.c test_option_help.c test_option_l.c test_option_lrzip.c diff --git a/cpio/test/main.c b/cpio/test/main.c index 12dc0cebd..1eb15ac10 100644 --- a/cpio/test/main.c +++ b/cpio/test/main.c @@ -1887,6 +1887,21 @@ canGunzip(void) return (value); } +/* + * Can this platform run the grzip program? + */ +int +canGrzip(void) +{ + static int tested = 0, value = 0; + if (!tested) { + tested = 1; + if (systemf("grzip -V %s", redirectArgs) == 0) + value = 1; + } + return (value); +} + /* * Can this platform run the lrzip program? */ diff --git a/cpio/test/test.h b/cpio/test/test.h index 01f902ef2..e218a155f 100644 --- a/cpio/test/test.h +++ b/cpio/test/test.h @@ -275,6 +275,9 @@ int canGzip(void); /* Return true if this platform can run the "gunzip" program. */ int canGunzip(void); +/* Return true if this platform can run the "grzip" program. */ +int canGrzip(void); + /* Return true if this platform can run the "lrzip" program. */ int canLrzip(void); diff --git a/cpio/test/test_extract.cpio.grz.uu b/cpio/test/test_extract.cpio.grz.uu new file mode 100644 index 000000000..19045a9dd --- /dev/null +++ b/cpio/test/test_extract.cpio.grz.uu @@ -0,0 +1,7 @@ +begin 644 test_extract.cpio.grz +M1U)::7!)20`"!#HI``(``*P-```&`0``"````&X````B%2.02C`PK`#__..F +MI;8=99?N!6`:IQJ:XU/T"`W`B"?N/D9-0K6VN/D\.2>0,#J&)3G"\^YE?X_' +M_K._F':0[`DL%IQ=<,Z-JH>V$S,?.[`&42C7]J^XQ@9OY!Z$!$^JLQPKZU[: +/!M,+.$MY:Y(HS<<]U`&` +` +end diff --git a/cpio/test/test_extract_cpio_grz.c b/cpio/test/test_extract_cpio_grz.c new file mode 100644 index 000000000..f1a080597 --- /dev/null +++ b/cpio/test/test_extract_cpio_grz.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2012 Michihiro 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$"); + +DEFINE_TEST(test_extract_cpio_grz) +{ + const char *reffile = "test_extract.cpio.grz"; + int f; + + extract_reference_file(reffile); + f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canGrzip()) { + assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err", + testprog, reffile)); + + assertFileExists("file1"); + assertTextFileContents("contents of file1.\n", "file1"); + assertFileExists("file2"); + assertTextFileContents("contents of file2.\n", "file2"); + assertEmptyFile("test.out"); + assertTextFileContents("1 block\n", "test.err"); + } else { + skipping("It seems grzip is not supported on this platform"); + } +} diff --git a/cpio/test/test_option_grzip.c b/cpio/test/test_option_grzip.c new file mode 100644 index 000000000..dfce2e064 --- /dev/null +++ b/cpio/test/test_option_grzip.c @@ -0,0 +1,52 @@ +/*- + * 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 + * 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$"); + +DEFINE_TEST(test_option_grzip) +{ + char *p; + size_t s; + + if (!canGrzip()) { + skipping("grzip is not supported on this platform"); + return; + } + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Archive it with grzip compression. */ + assertEqualInt(0, + systemf("echo f | %s -o --grzip >archive.out 2>archive.err", + testprog)); + p = slurpfile(&s, "archive.err"); + p[s] = '\0'; + /* Check that the archive file has an grzip signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "GRZipII\x00\x02\x04:)", 12); +} diff --git a/libarchive/CMakeLists.txt b/libarchive/CMakeLists.txt index 3f0709e44..4bdb648e1 100644 --- a/libarchive/CMakeLists.txt +++ b/libarchive/CMakeLists.txt @@ -58,6 +58,7 @@ SET(libarchive_SOURCES archive_read_support_filter_bzip2.c archive_read_support_filter_compress.c archive_read_support_filter_gzip.c + archive_read_support_filter_grzip.c archive_read_support_filter_lrzip.c archive_read_support_filter_lzop.c archive_read_support_filter_none.c @@ -100,6 +101,7 @@ SET(libarchive_SOURCES archive_write_add_filter_b64encode.c archive_write_add_filter_bzip2.c archive_write_add_filter_compress.c + archive_write_add_filter_grzip.c archive_write_add_filter_gzip.c archive_write_add_filter_lrzip.c archive_write_add_filter_lzop.c diff --git a/libarchive/archive.h b/libarchive/archive.h index 53afb847c..dd3e1906a 100644 --- a/libarchive/archive.h +++ b/libarchive/archive.h @@ -222,6 +222,7 @@ typedef int archive_switch_callback(struct archive *, void *_client_data1, #define ARCHIVE_FILTER_LZIP 9 #define ARCHIVE_FILTER_LRZIP 10 #define ARCHIVE_FILTER_LZOP 11 +#define ARCHIVE_FILTER_GRZIP 12 #if ARCHIVE_VERSION_NUMBER < 4000000 #define ARCHIVE_COMPRESSION_NONE ARCHIVE_FILTER_NONE @@ -339,6 +340,7 @@ __LA_DECL int archive_read_support_filter_all(struct archive *); __LA_DECL int archive_read_support_filter_bzip2(struct archive *); __LA_DECL int archive_read_support_filter_compress(struct archive *); __LA_DECL int archive_read_support_filter_gzip(struct archive *); +__LA_DECL int archive_read_support_filter_grzip(struct archive *); __LA_DECL int archive_read_support_filter_lrzip(struct archive *); __LA_DECL int archive_read_support_filter_lzip(struct archive *); __LA_DECL int archive_read_support_filter_lzma(struct archive *); @@ -633,6 +635,7 @@ __LA_DECL int archive_write_add_filter(struct archive *, int filter_code); __LA_DECL int archive_write_add_filter_b64encode(struct archive *); __LA_DECL int archive_write_add_filter_bzip2(struct archive *); __LA_DECL int archive_write_add_filter_compress(struct archive *); +__LA_DECL int archive_write_add_filter_grzip(struct archive *); __LA_DECL int archive_write_add_filter_gzip(struct archive *); __LA_DECL int archive_write_add_filter_lrzip(struct archive *); __LA_DECL int archive_write_add_filter_lzip(struct archive *); diff --git a/libarchive/archive_read_support_filter_all.c b/libarchive/archive_read_support_filter_all.c index dcd770325..d38f1122a 100644 --- a/libarchive/archive_read_support_filter_all.c +++ b/libarchive/archive_read_support_filter_all.c @@ -63,10 +63,12 @@ archive_read_support_filter_all(struct archive *a) archive_read_support_filter_uu(a); /* The decode code doesn't use an outside library. */ archive_read_support_filter_rpm(a); - /* The decode code always uses "lrzip -d" command-line. */ + /* The decode code always uses "lrzip -q -d" command-line. */ archive_read_support_filter_lrzip(a); /* The decode code always uses "lzop -d" command-line. */ archive_read_support_filter_lzop(a); + /* The decode code always uses "grzip -d" command-line. */ + archive_read_support_filter_grzip(a); /* Note: We always return ARCHIVE_OK here, even if some of the * above return ARCHIVE_WARN. The intent here is to enable diff --git a/libarchive/archive_read_support_filter_grzip.c b/libarchive/archive_read_support_filter_grzip.c new file mode 100644 index 000000000..7a132ab2d --- /dev/null +++ b/libarchive/archive_read_support_filter_grzip.c @@ -0,0 +1,119 @@ +/*- + * Copyright (c) 2012 Michihiro 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 "archive_platform.h" + +__FBSDID("$FreeBSD$"); + + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_read_private.h" + +static const unsigned char grzip_magic[] = { + 0x47, 0x52, 0x5a, 0x69, 0x70, 0x49, 0x49, 0x00, + 0x02, 0x04, 0x3a, 0x29 }; + +static int grzip_bidder_bid(struct archive_read_filter_bidder *, + struct archive_read_filter *); +static int grzip_bidder_init(struct archive_read_filter *); + + +static int +grzip_reader_free(struct archive_read_filter_bidder *self) +{ + (void)self; /* UNUSED */ + return (ARCHIVE_OK); +} + +int +archive_read_support_filter_grzip(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_filter_bidder *reader; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_filter_grzip"); + + if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + reader->data = NULL; + reader->bid = grzip_bidder_bid; + reader->init = grzip_bidder_init; + reader->options = NULL; + reader->free = grzip_reader_free; + /* This filter always uses an external program. */ + return (ARCHIVE_WARN); +} + +/* + * Bidder just verifies the header and returns the number of verified bits. + */ +static int +grzip_bidder_bid(struct archive_read_filter_bidder *self, + struct archive_read_filter *filter) +{ + const unsigned char *p; + ssize_t avail; + + (void)self; /* UNUSED */ + + p = __archive_read_filter_ahead(filter, sizeof(grzip_magic), &avail); + if (p == NULL || avail == 0) + return (0); + + if (memcmp(p, grzip_magic, sizeof(grzip_magic))) + return (0); + + return (sizeof(grzip_magic) * 8); +} + +static int +grzip_bidder_init(struct archive_read_filter *self) +{ + int r; + + r = __archive_read_programl(self, "grzip", "grzip", "-d", NULL); + /* Note: We set the format here even if __archive_read_programl() + * above fails. We do, after all, know what the format is + * even if we weren't able to read it. */ + self->code = ARCHIVE_FILTER_GRZIP; + self->name = "grzip"; + return (r); +} diff --git a/libarchive/archive_write_add_filter_grzip.c b/libarchive/archive_write_add_filter_grzip.c new file mode 100644 index 000000000..6c0478c34 --- /dev/null +++ b/libarchive/archive_write_add_filter_grzip.c @@ -0,0 +1,45 @@ +/*- + * Copyright (c) 2003-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. + * 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 "archive_platform.h" + +__FBSDID("$FreeBSD$"); + +#include "archive.h" +#include "archive_write_private.h" + +int +archive_write_add_filter_grzip(struct archive *a) +{ + char * const argv[] = { "grzip", NULL }; + int r; + + r = __archive_write_programv(a, "grzip", ARCHIVE_FILTER_GRZIP, + "grzip", argv); + if (r == ARCHIVE_OK) + /* This filter always uses an external program. */ + r = ARCHIVE_WARN; + return (r); +} diff --git a/libarchive/test/CMakeLists.txt b/libarchive/test/CMakeLists.txt index 54e5bda7a..e6471c714 100644 --- a/libarchive/test/CMakeLists.txt +++ b/libarchive/test/CMakeLists.txt @@ -75,11 +75,12 @@ IF(ENABLE_TEST) test_read_disk_entry_from_file.c test_read_extract.c test_read_file_nonexistent.c + test_read_filter_grzip.c + test_read_filter_lrzip.c + test_read_filter_lzop.c test_read_filter_program.c test_read_filter_program_signature.c test_read_filter_uudecode.c - test_read_filter_lrzip.c - test_read_filter_lzop.c test_read_format_7zip.c test_read_format_ar.c test_read_format_cab.c diff --git a/libarchive/test/main.c b/libarchive/test/main.c index 1f2a733de..ac77c7d58 100644 --- a/libarchive/test/main.c +++ b/libarchive/test/main.c @@ -1885,6 +1885,21 @@ canGunzip(void) return (value); } +/* + * Can this platform run the grzip program? + */ +int +canGrzip(void) +{ + static int tested = 0, value = 0; + if (!tested) { + tested = 1; + if (systemf("grzip -V %s", redirectArgs) == 0) + value = 1; + } + return (value); +} + /* * Can this platform run the lrzip program? */ diff --git a/libarchive/test/test.h b/libarchive/test/test.h index bdd10672f..22942861e 100644 --- a/libarchive/test/test.h +++ b/libarchive/test/test.h @@ -275,6 +275,9 @@ int canGzip(void); /* Return true if this platform can run the "gunzip" program. */ int canGunzip(void); +/* Return true if this platform can run the "grzip" program. */ +int canGrzip(void); + /* Return true if this platform can run the "lrzip" program. */ int canLrzip(void); diff --git a/libarchive/test/test_read_filter_grzip.c b/libarchive/test/test_read_filter_grzip.c new file mode 100644 index 000000000..43bd5bca2 --- /dev/null +++ b/libarchive/test/test_read_filter_grzip.c @@ -0,0 +1,67 @@ +/*- + * Copyright (c) 2003-2008 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. + * 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" + +DEFINE_TEST(test_read_filter_grzip) +{ + const char *name = "test_read_filter_grzip.tar.grz"; + /* grzip tracks directories as files, ensure that we list everything */ + const char *n[] = { + "f1", "f2", "f3", "d1/f1", "d1/f2", "d1/f3", NULL }; + struct archive_entry *ae; + struct archive *a; + int i; + + if (!canGrzip()) { + skipping("grzip command-line program not found"); + return; + } + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_WARN, archive_read_support_filter_grzip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + extract_reference_file(name); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, name, 200)); + + /* Read entries, match up names with list above. */ + for (i = 0; n[i] != NULL; ++i) { + failure("Could not read file %d (%s) from %s", i, n[i], name); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae)); + assertEqualString(n[i], archive_entry_pathname(ae)); + } + + /* Verify the end-of-archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify that the format detection worked. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_GRZIP); + assertEqualString(archive_filter_name(a, 0), "grzip"); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/libarchive/test/test_read_filter_grzip.tar.grz.uu b/libarchive/test/test_read_filter_grzip.tar.grz.uu new file mode 100644 index 000000000..3f55b9347 --- /dev/null +++ b/libarchive/test/test_read_filter_grzip.tar.grz.uu @@ -0,0 +1,8 @@ +begin 644 test_read_filter_grzip.tar.grz +M1U)::7!)20`"!#HI`!P``*P,```L`0``\````)D```#Y.$+F+B8PQP#^C=PP +MI/#7H?$H,(_!0<=O!,4![T/;;'S,=B0_3(R1=9"=YKA%RKR-\,+PJIO2]!I*2V31X]P[DN$GOgname = bsdtar->argument; break; + case OPTION_GRZIP: + if (bsdtar->create_compression != '\0') + lafe_errc(1, 0, + "Can't specify both -%c and -%c", opt, + bsdtar->create_compression); + bsdtar->create_compression = opt; + break; case 'H': /* BSD convention */ bsdtar->symlink_mode = 'H'; break; diff --git a/tar/bsdtar.h b/tar/bsdtar.h index 80e922ea2..a21be3d0d 100644 --- a/tar/bsdtar.h +++ b/tar/bsdtar.h @@ -120,6 +120,7 @@ enum { OPTION_FORMAT, OPTION_GID, OPTION_GNAME, + OPTION_GRZIP, OPTION_HELP, OPTION_INCLUDE, OPTION_KEEP_NEWER_FILES, diff --git a/tar/cmdline.c b/tar/cmdline.c index 684e28bfd..e658ec867 100644 --- a/tar/cmdline.c +++ b/tar/cmdline.c @@ -88,6 +88,7 @@ static const struct bsdtar_option { { "format", 1, OPTION_FORMAT }, { "gid", 1, OPTION_GID }, { "gname", 1, OPTION_GNAME }, + { "grzip", 0, OPTION_GRZIP }, { "gunzip", 0, 'z' }, { "gzip", 0, 'z' }, { "help", 0, OPTION_HELP }, diff --git a/tar/test/CMakeLists.txt b/tar/test/CMakeLists.txt index c14baf0a8..1f6c5ca50 100644 --- a/tar/test/CMakeLists.txt +++ b/tar/test/CMakeLists.txt @@ -14,6 +14,7 @@ IF(ENABLE_TAR AND ENABLE_TEST) test_empty_mtree.c test_extract_tar_Z.c test_extract_tar_bz2.c + test_extract_tar_grz.c test_extract_tar_gz.c test_extract_tar_lrz.c test_extract_tar_lz.c @@ -33,6 +34,7 @@ IF(ENABLE_TAR AND ENABLE_TEST) test_option_b64encode.c test_option_exclude.c test_option_gid_gname.c + test_option_grzip.c test_option_k.c test_option_keep_newer_files.c test_option_lrzip.c diff --git a/tar/test/main.c b/tar/test/main.c index 28275065a..ccf83ba20 100644 --- a/tar/test/main.c +++ b/tar/test/main.c @@ -1887,6 +1887,21 @@ canGunzip(void) return (value); } +/* + * Can this platform run the grzip program? + */ +int +canGrzip(void) +{ + static int tested = 0, value = 0; + if (!tested) { + tested = 1; + if (systemf("grzip -V %s", redirectArgs) == 0) + value = 1; + } + return (value); +} + /* * Can this platform run the lrzip program? */ diff --git a/tar/test/test.h b/tar/test/test.h index 49fe9d97f..36ff42e08 100644 --- a/tar/test/test.h +++ b/tar/test/test.h @@ -277,6 +277,9 @@ int canGzip(void); /* Return true if this platform can run the "gunzip" program. */ int canGunzip(void); +/* Return true if this platform can run the "grzip" program. */ +int canGrzip(void); + /* Return true if this platform can run the "lrzip" program. */ int canLrzip(void); diff --git a/tar/test/test_extract.tar.grz.uu b/tar/test/test_extract.tar.grz.uu new file mode 100644 index 000000000..44651e116 --- /dev/null +++ b/tar/test/test_extract.tar.grz.uu @@ -0,0 +1,7 @@ +begin 644 test_extract.tar.grz +M1U)::7!)20`"!#HI``P``*P,``#U````SP```'<````[-=0OM"R^UP#^C?Z< +MFGU0]I:>SW7]H01)1\WY:59("M_=V4[N[R*'`H&:'E=O@5B(?T,0?@)%-:_D +M;EUP)!JVN)@V_:ABYS3+[[6/R(NU,-::]'X&;,]:,HR[*3#R!@:W)IGC`,&G +8L+IZ7]FP=8U_R?CZ2XPO)"H-ME3@P]$` +` +end diff --git a/tar/test/test_extract_tar_grz.c b/tar/test/test_extract_tar_grz.c new file mode 100644 index 000000000..9c0615e98 --- /dev/null +++ b/tar/test/test_extract_tar_grz.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2012 Michihiro 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$"); + +DEFINE_TEST(test_extract_tar_grz) +{ + const char *reffile = "test_extract.tar.grz"; + int f; + + extract_reference_file(reffile); + f = systemf("%s -tf %s >test.out 2>test.err", testprog, reffile); + if (f == 0 || canGrzip()) { + assertEqualInt(0, systemf("%s -xf %s >test.out 2>test.err", + testprog, reffile)); + + assertFileExists("file1"); + assertTextFileContents("contents of file1.\n", "file1"); + assertFileExists("file2"); + assertTextFileContents("contents of file2.\n", "file2"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + } else { + skipping("It seems grzip is not supported on this platform"); + } +} diff --git a/tar/test/test_option_grzip.c b/tar/test/test_option_grzip.c new file mode 100644 index 000000000..5132eeec2 --- /dev/null +++ b/tar/test/test_option_grzip.c @@ -0,0 +1,52 @@ +/*- + * 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 + * 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$"); + +DEFINE_TEST(test_option_grzip) +{ + char *p; + size_t s; + + if (!canGrzip()) { + skipping("grzip is not supported on this platform"); + return; + } + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Archive it with grzip compression. */ + assertEqualInt(0, + systemf("%s -cf - --grzip f >archive.out 2>archive.err", + testprog)); + p = slurpfile(&s, "archive.err"); + p[s] = '\0'; + /* Check that the archive file has an grzip signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "GRZipII\x00\x02\x04:)", 12); +} diff --git a/tar/write.c b/tar/write.c index b6e1c58ff..077f3625d 100644 --- a/tar/write.c +++ b/tar/write.c @@ -174,6 +174,9 @@ tar_mode_c(struct bsdtar *bsdtar) case 0: r = ARCHIVE_OK; break; + case OPTION_GRZIP: + r = archive_write_add_filter_grzip(a); + break; case 'j': case 'y': r = archive_write_add_filter_bzip2(a); break;