From: Michihiro NAKAJIMA Date: Sun, 7 Oct 2012 02:08:12 +0000 (+0900) Subject: Add support for lzop. X-Git-Tag: v3.1.0~40^2~94 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f51924bbd48594fef8b0d0beed87284eed40e7d0;p=thirdparty%2Flibarchive.git Add support for lzop. --- diff --git a/Makefile.am b/Makefile.am index 43e6180cb..a1310d6d3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -135,6 +135,7 @@ libarchive_la_SOURCES= \ libarchive/archive_read_support_filter_compress.c \ libarchive/archive_read_support_filter_gzip.c \ libarchive/archive_read_support_filter_lrzip.c \ + libarchive/archive_read_support_filter_lzop.c \ libarchive/archive_read_support_filter_none.c \ libarchive/archive_read_support_filter_program.c \ libarchive/archive_read_support_filter_rpm.c \ @@ -176,6 +177,7 @@ libarchive_la_SOURCES= \ libarchive/archive_write_add_filter_compress.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_xz.c \ @@ -333,6 +335,7 @@ libarchive_test_SOURCES= \ 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_lzop.c \ libarchive/test/test_read_format_7zip.c \ libarchive/test/test_read_format_ar.c \ libarchive/test/test_read_format_cab.c \ @@ -403,6 +406,7 @@ libarchive_test_SOURCES= \ libarchive/test/test_write_compress_lrzip.c \ libarchive/test/test_write_compress_lzip.c \ libarchive/test/test_write_compress_lzma.c \ + libarchive/test/test_write_compress_lzop.c \ libarchive/test/test_write_compress_program.c \ libarchive/test/test_write_compress_xz.c \ libarchive/test/test_write_disk.c \ @@ -502,6 +506,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_lzop.tar.lzo.uu \ libarchive/test/test_read_format_7zip_bcj_bzip2.7z.uu \ libarchive/test/test_read_format_7zip_bcj_copy.7z.uu \ libarchive/test/test_read_format_7zip_bcj_deflate.7z.uu \ @@ -720,6 +725,7 @@ bsdtar_test_SOURCES= \ tar/test/test_option_gid_gname.c \ tar/test/test_option_k.c \ tar/test/test_option_keep_newer_files.c \ + tar/test/test_option_lzop.c \ tar/test/test_option_n.c \ tar/test/test_option_newer_than.c \ tar/test/test_option_nodump.c \ @@ -841,6 +847,7 @@ bsdcpio_test_SOURCES= \ cpio/test/test_option_help.c \ cpio/test/test_option_l.c \ cpio/test/test_option_lzma.c \ + cpio/test/test_option_lzop.c \ cpio/test/test_option_m.c \ cpio/test/test_option_t.c \ cpio/test/test_option_u.c \ diff --git a/cpio/bsdcpio.1 b/cpio/bsdcpio.1 index 5611b20e9..05f79d26c 100644 --- a/cpio/bsdcpio.1 +++ b/cpio/bsdcpio.1 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 24, 2011 +.Dd October 7, 2012 .Dt CPIO 1 .Os .Sh NAME @@ -181,6 +181,11 @@ instead of copying. Compress the file with lzma-compatible compression before writing it. In input mode, this option is ignored; lzma compression is recognized automatically on input. +.It Fl Fl lzop +(o mode only) +Compress the resulting archive with +.Xr lzop 1 . +In input mode, this option is ignored. .It Fl m , Fl Fl preserve-modification-time (i and p modes) Set file modification time on created files to match diff --git a/cpio/cmdline.c b/cpio/cmdline.c index 438c27cf6..91f6e1c48 100644 --- a/cpio/cmdline.c +++ b/cpio/cmdline.c @@ -71,6 +71,7 @@ static const struct option { { "link", 0, 'l' }, { "list", 0, 't' }, { "lzma", 0, OPTION_LZMA }, + { "lzop", 0, OPTION_LZOP }, { "make-directories", 0, 'd' }, { "no-preserve-owner", 0, OPTION_NO_PRESERVE_OWNER }, { "null", 0, '0' }, diff --git a/cpio/cpio.c b/cpio/cpio.c index 21c77d0b1..db342318b 100644 --- a/cpio/cpio.c +++ b/cpio/cpio.c @@ -266,6 +266,7 @@ main(int argc, char *argv[]) cpio->option_link = 1; break; case OPTION_LZMA: /* GNU tar, others */ + case OPTION_LZOP: /* GNU tar, others */ cpio->compress = opt; break; case 'm': /* POSIX 1997 */ @@ -523,6 +524,9 @@ mode_out(struct cpio *cpio) case OPTION_LZMA: r = archive_write_set_compression_lzma(cpio->archive); break; + case OPTION_LZOP: + r = archive_write_add_filter_lzop(cpio->archive); + break; case 'j': case 'y': r = archive_write_set_compression_bzip2(cpio->archive); break; diff --git a/cpio/cpio.h b/cpio/cpio.h index 7e276bdba..af7ef8a89 100644 --- a/cpio/cpio.h +++ b/cpio/cpio.h @@ -98,6 +98,7 @@ const char *owner_parse(const char *, int *, int *); enum { OPTION_INSECURE = 1, OPTION_LZMA, + OPTION_LZOP, OPTION_NO_PRESERVE_OWNER, OPTION_PRESERVE_OWNER, OPTION_QUIET, diff --git a/cpio/test/CMakeLists.txt b/cpio/test/CMakeLists.txt index 662316425..30aa9766e 100644 --- a/cpio/test/CMakeLists.txt +++ b/cpio/test/CMakeLists.txt @@ -28,6 +28,7 @@ IF(ENABLE_CPIO AND ENABLE_TEST) test_option_help.c test_option_l.c test_option_lzma.c + test_option_lzop.c test_option_m.c test_option_t.c test_option_u.c diff --git a/cpio/test/main.c b/cpio/test/main.c index 36867725a..12dc0cebd 100644 --- a/cpio/test/main.c +++ b/cpio/test/main.c @@ -1932,6 +1932,21 @@ canUnlzma(void) return (value); } +/* + * Can this platform run the lzop program? + */ +int +canLzop(void) +{ + static int tested = 0, value = 0; + if (!tested) { + tested = 1; + if (systemf("lzop -V %s", redirectArgs) == 0) + value = 1; + } + return (value); +} + /* * Can this platform run the unxz program? */ diff --git a/cpio/test/test.h b/cpio/test/test.h index 350eb3344..01f902ef2 100644 --- a/cpio/test/test.h +++ b/cpio/test/test.h @@ -284,6 +284,9 @@ int canLunzip(void); /* Return true if this platform can run the "unlzma" program. */ int canUnlzma(void); +/* Return true if this platform can run the "lzop" program. */ +int canLzop(void); + /* Return true if this platform can run the "unxz" program. */ int canUnxz(void); diff --git a/cpio/test/test_option_lzop.c b/cpio/test/test_option_lzop.c new file mode 100644 index 000000000..a1812d3c7 --- /dev/null +++ b/cpio/test/test_option_lzop.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_lzop) +{ + char *p; + size_t s; + + if (!canLzop()) { + skipping("lzop is not supported on this platform"); + return; + } + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Archive it with lzop compression. */ + assertEqualInt(0, + systemf("echo f | %s -o --lzop >archive.out 2>archive.err", + testprog)); + p = slurpfile(&s, "archive.err"); + p[s] = '\0'; + /* Check that the archive file has an lzma signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a", 9); +} diff --git a/libarchive/CMakeLists.txt b/libarchive/CMakeLists.txt index cbb867281..df7185011 100644 --- a/libarchive/CMakeLists.txt +++ b/libarchive/CMakeLists.txt @@ -59,6 +59,7 @@ SET(libarchive_SOURCES archive_read_support_filter_compress.c archive_read_support_filter_gzip.c archive_read_support_filter_lrzip.c + archive_read_support_filter_lzop.c archive_read_support_filter_none.c archive_read_support_filter_program.c archive_read_support_filter_rpm.c diff --git a/libarchive/archive.h b/libarchive/archive.h index d914ed43c..b4da85ef9 100644 --- a/libarchive/archive.h +++ b/libarchive/archive.h @@ -215,6 +215,7 @@ typedef int archive_switch_callback(struct archive *, void *_client_data1, #define ARCHIVE_FILTER_RPM 8 #define ARCHIVE_FILTER_LZIP 9 #define ARCHIVE_FILTER_LRZIP 10 +#define ARCHIVE_FILTER_LZOP 11 #if ARCHIVE_VERSION_NUMBER < 4000000 #define ARCHIVE_COMPRESSION_NONE ARCHIVE_FILTER_NONE @@ -325,6 +326,7 @@ __LA_DECL int archive_read_support_filter_gzip(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 *); +__LA_DECL int archive_read_support_filter_lzop(struct archive *); __LA_DECL int archive_read_support_filter_none(struct archive *); __LA_DECL int archive_read_support_filter_program(struct archive *, const char *command); @@ -611,6 +613,7 @@ __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 *); __LA_DECL int archive_write_add_filter_lzma(struct archive *); +__LA_DECL int archive_write_add_filter_lzop(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); diff --git a/libarchive/archive_read_private.h b/libarchive/archive_read_private.h index 9f580c94d..2dc9645ca 100644 --- a/libarchive/archive_read_private.h +++ b/libarchive/archive_read_private.h @@ -163,7 +163,7 @@ struct archive_read { struct archive_read_client client; /* Registered filter bidders. */ - struct archive_read_filter_bidder bidders[10]; + struct archive_read_filter_bidder bidders[14]; /* Last filter in chain */ struct archive_read_filter *filter; diff --git a/libarchive/archive_read_support_filter_all.c b/libarchive/archive_read_support_filter_all.c index 637533288..dcd770325 100644 --- a/libarchive/archive_read_support_filter_all.c +++ b/libarchive/archive_read_support_filter_all.c @@ -65,6 +65,8 @@ archive_read_support_filter_all(struct archive *a) archive_read_support_filter_rpm(a); /* The decode code always uses "lrzip -d" command-line. */ archive_read_support_filter_lrzip(a); + /* The decode code always uses "lzop -d" command-line. */ + archive_read_support_filter_lzop(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_lzop.c b/libarchive/archive_read_support_filter_lzop.c new file mode 100644 index 000000000..4c8e0e0d2 --- /dev/null +++ b/libarchive/archive_read_support_filter_lzop.c @@ -0,0 +1,119 @@ +/*- + * 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 "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" + +#define LZOP_HEADER_MAGIC "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a" +#define LZOP_HEADER_MAGIC_LEN 9 + +static int lzop_bidder_bid(struct archive_read_filter_bidder *, + struct archive_read_filter *); +static int lzop_bidder_init(struct archive_read_filter *); +static int lzop_reader_free(struct archive_read_filter_bidder *); + +int +archive_read_support_filter_lzop(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_lzop"); + + if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + reader->data = NULL; + reader->bid = lzop_bidder_bid; + reader->init = lzop_bidder_init; + reader->options = NULL; + reader->free = lzop_reader_free; + /* Return ARCHIVE_WARN since this always uses an external program. */ + return (ARCHIVE_WARN); +} + +static int +lzop_reader_free(struct archive_read_filter_bidder *self) +{ + (void)self; /* UNUSED */ + return (ARCHIVE_OK); +} + +/* + * Bidder just verifies the header and returns the number of verified bits. + */ +static int +lzop_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, LZOP_HEADER_MAGIC_LEN, &avail); + if (p == NULL || avail == 0) + return (0); + + if (memcmp(p, LZOP_HEADER_MAGIC, LZOP_HEADER_MAGIC_LEN)) + return (0); + + return (LZOP_HEADER_MAGIC_LEN * 8); +} + +static int +lzop_bidder_init(struct archive_read_filter *self) +{ + int r; + + r = __archive_read_programl(self, "lzop", "lzop", "-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_LZOP; + self->name = "lzop"; + return (r); +} diff --git a/libarchive/archive_write_add_filter_lzop.c b/libarchive/archive_write_add_filter_lzop.c new file mode 100644 index 000000000..3b963d83b --- /dev/null +++ b/libarchive/archive_write_add_filter_lzop.c @@ -0,0 +1,41 @@ +/*- + * 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$"); + +#include "archive.h" + +int +archive_write_add_filter_lzop(struct archive *a) +{ + int r; + r = archive_write_add_filter_programl(a, "lzop", "lzop", NULL); + /* Return ARCHIVE_WARN since this always uses an external program. */ + if (r == ARCHIVE_OK) + r = ARCHIVE_WARN; + return (r); +} diff --git a/libarchive/test/CMakeLists.txt b/libarchive/test/CMakeLists.txt index f13adc9f3..3de15e2b2 100644 --- a/libarchive/test/CMakeLists.txt +++ b/libarchive/test/CMakeLists.txt @@ -78,6 +78,7 @@ IF(ENABLE_TEST) test_read_filter_program.c test_read_filter_program_signature.c test_read_filter_uudecode.c + test_read_filter_lzop.c test_read_format_7zip.c test_read_format_ar.c test_read_format_cab.c @@ -148,6 +149,7 @@ IF(ENABLE_TEST) test_write_compress_lrzip.c test_write_compress_lzip.c test_write_compress_lzma.c + test_write_compress_lzop.c test_write_compress_program.c test_write_compress_xz.c test_write_disk.c diff --git a/libarchive/test/main.c b/libarchive/test/main.c index 8ad8a782f..1f2a733de 100644 --- a/libarchive/test/main.c +++ b/libarchive/test/main.c @@ -1930,6 +1930,21 @@ canUnlzma(void) return (value); } +/* + * Can this platform run the lzop program? + */ +int +canLzop(void) +{ + static int tested = 0, value = 0; + if (!tested) { + tested = 1; + if (systemf("lzop -V %s", redirectArgs) == 0) + value = 1; + } + return (value); +} + /* * Can this platform run the unxz program? */ diff --git a/libarchive/test/test.h b/libarchive/test/test.h index 457346b79..bdd10672f 100644 --- a/libarchive/test/test.h +++ b/libarchive/test/test.h @@ -284,6 +284,9 @@ int canLunzip(void); /* Return true if this platform can run the "unlzma" program. */ int canUnlzma(void); +/* Return true if this platform can run the "lzop" program. */ +int canLzop(void); + /* Return true if this platform can run the "unxz" program. */ int canUnxz(void); diff --git a/libarchive/test/test_read_filter_lzop.c b/libarchive/test/test_read_filter_lzop.c new file mode 100644 index 000000000..885fbae91 --- /dev/null +++ b/libarchive/test/test_read_filter_lzop.c @@ -0,0 +1,69 @@ +/*- + * Copyright (c) 2003-2008 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" + +DEFINE_TEST(test_read_filter_lzop) +{ + const char *reference = "test_read_filter_lzop.tar.lzo"; + /* lrzip tracks directories as files, ensure that we list everything */ + const char *n[] = { + "d1/", "d1/f2", "d1/f3", "d1/f1", "f1", "f2", "f3", NULL }; + struct archive_entry *ae; + struct archive *a; + int i; + + if (!canLzop()) { + skipping("lzop command-line program not found"); + } + + extract_reference_file(reference); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_WARN, archive_read_support_filter_lzop(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, reference, 10240)); + + /* 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], reference); + 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_count(a), 2); + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_LZOP); + assertEqualString(archive_filter_name(a, 0), "lzop"); + 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_lzop.tar.lzo.uu b/libarchive/test/test_read_filter_lzop.tar.lzo.uu new file mode 100644 index 000000000..d5fcc3026 --- /dev/null +++ b/libarchive/test/test_read_filter_lzop.tar.lzo.uu @@ -0,0 +1,11 @@ +begin 664 test_read_filter_lzop.tar.lzo +MB4Q:3P`-"AH*$#`@8`E``04#```!``"!M%!PQ.T`````&71E`V0Q+P```"`]```+,#`P +M-S@'A`L@%/T',"``1OT'9B`_\P<````@#?T'-W__-C8V(`!'_`<@ +M/_`?(!?]!S<@`$?\!R`_\!\@%OT'-R``1_P7@/0@````RA````$````````` +3````````````````$0`````````` +` +end diff --git a/libarchive/test/test_write_compress_lzop.c b/libarchive/test/test_write_compress_lzop.c new file mode 100644 index 000000000..d984b8138 --- /dev/null +++ b/libarchive/test/test_write_compress_lzop.c @@ -0,0 +1,135 @@ +/*- + * 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 + * 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" + +/* + * A basic exercise of lzop reading and writing. + */ + +DEFINE_TEST(test_write_compress_lzop) +{ + struct archive_entry *ae; + struct archive* a; + char *buff, *data; + size_t buffsize, datasize; + char path[16]; + size_t used1, used2; + int blocksize = 1024; + int i; + + if (!canLzop()) { + skipping("lzop command-line program not found"); + return; + } + + buffsize = 2000000; + assert(NULL != (buff = (char *)malloc(buffsize))); + + datasize = 10000; + assert(NULL != (data = (char *)malloc(datasize))); + memset(data, 0, datasize); + + /* + * Write 100 files and read them all back. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_WARN, archive_write_add_filter_lzop(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_per_block(a, blocksize)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_in_last_block(a, blocksize)); + assertEqualInt(blocksize, archive_write_get_bytes_in_last_block(a)); + assertEqualInt(ARCHIVE_FILTER_PROGRAM, archive_filter_code(a, 0)); + assertEqualString("Program: lzop lzop", archive_filter_name(a, 0)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used1)); + assertEqualInt(blocksize, archive_write_get_bytes_in_last_block(a)); + + for (i = 0; i < 100; i++) { + sprintf(path, "file%03d", i); + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_size(ae, datasize); + archive_entry_copy_pathname(ae, path); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertA(datasize + == (size_t)archive_write_data(a, data, datasize)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_WARN, archive_read_support_filter_lzop(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_free(a)); + + /* + * Test various premature shutdown scenarios to make sure we + * don't crash or leak memory. + */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_WARN, archive_write_add_filter_lzop(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_WARN, archive_write_add_filter_lzop(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_WARN, archive_write_add_filter_lzop(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_WARN, archive_write_add_filter_lzop(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)); + + /* + * Clean up. + */ + free(data); + free(buff); +} diff --git a/tar/bsdtar.1 b/tar/bsdtar.1 index efa55c874..cd3e8fbce 100644 --- a/tar/bsdtar.1 +++ b/tar/bsdtar.1 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd October 3, 2012 +.Dd October 7, 2012 .Dt TAR 1 .Os .Sh NAME @@ -295,6 +295,15 @@ Note that, unlike other .Nm tar implementations, this implementation recognizes LZMA compression automatically when reading archives. +.It Fl Fl lzop +(c mode only) +Compress the resulting archive with +.Xr lzop 1 . +In extract or list modes, this option is ignored. +Note that, unlike other +.Nm tar +implementations, this implementation recognizes lzop compression +automatically when reading archives. .It Fl m , Fl Fl modification-time (x mode only) Do not extract modification time. diff --git a/tar/bsdtar.c b/tar/bsdtar.c index 2c83d0bf7..f8e7e5d87 100644 --- a/tar/bsdtar.c +++ b/tar/bsdtar.c @@ -374,6 +374,7 @@ main(int argc, char **argv) break; case OPTION_LZIP: /* GNU tar beginning with 1.23 */ case OPTION_LZMA: /* GNU tar beginning with 1.20 */ + case OPTION_LZOP: /* GNU tar beginning with 1.21 */ if (bsdtar->create_compression != '\0') lafe_errc(1, 0, "Can't specify both -%c and -%c", opt, diff --git a/tar/bsdtar.h b/tar/bsdtar.h index 8a11b1e16..810ddc390 100644 --- a/tar/bsdtar.h +++ b/tar/bsdtar.h @@ -123,6 +123,7 @@ enum { OPTION_KEEP_NEWER_FILES, OPTION_LZIP, OPTION_LZMA, + OPTION_LZOP, OPTION_NEWER_CTIME, OPTION_NEWER_CTIME_THAN, OPTION_NEWER_MTIME, diff --git a/tar/cmdline.c b/tar/cmdline.c index 329d8e5c7..3ee00e098 100644 --- a/tar/cmdline.c +++ b/tar/cmdline.c @@ -98,6 +98,7 @@ static const struct bsdtar_option { { "list", 0, 't' }, { "lzip", 0, OPTION_LZIP }, { "lzma", 0, OPTION_LZMA }, + { "lzop", 0, OPTION_LZOP }, { "modification-time", 0, 'm' }, { "newer", 1, OPTION_NEWER_CTIME }, { "newer-ctime", 1, OPTION_NEWER_CTIME }, diff --git a/tar/test/CMakeLists.txt b/tar/test/CMakeLists.txt index ffa8dcd11..22568d525 100644 --- a/tar/test/CMakeLists.txt +++ b/tar/test/CMakeLists.txt @@ -32,6 +32,7 @@ IF(ENABLE_TAR AND ENABLE_TEST) test_option_gid_gname.c test_option_k.c test_option_keep_newer_files.c + test_option_lzop.c test_option_n.c test_option_newer_than.c test_option_nodump.c diff --git a/tar/test/main.c b/tar/test/main.c index caf75e958..28275065a 100644 --- a/tar/test/main.c +++ b/tar/test/main.c @@ -1932,6 +1932,21 @@ canUnlzma(void) return (value); } +/* + * Can this platform run the lzop program? + */ +int +canLzop(void) +{ + static int tested = 0, value = 0; + if (!tested) { + tested = 1; + if (systemf("lzop -V %s", redirectArgs) == 0) + value = 1; + } + return (value); +} + /* * Can this platform run the unxz program? */ diff --git a/tar/test/test.h b/tar/test/test.h index e5463e1ea..49fe9d97f 100644 --- a/tar/test/test.h +++ b/tar/test/test.h @@ -286,6 +286,9 @@ int canLunzip(void); /* Return true if this platform can run the "unlzma" program. */ int canUnlzma(void); +/* Return true if this platform can run the "lzop" program. */ +int canLzop(void); + /* Return true if this platform can run the "unxz" program. */ int canUnxz(void); diff --git a/tar/test/test_option_lzop.c b/tar/test/test_option_lzop.c new file mode 100644 index 000000000..cf4f8a079 --- /dev/null +++ b/tar/test/test_option_lzop.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_lzop) +{ + char *p; + size_t s; + + if (!canLzop()) { + skipping("lzop is not supported on this platform"); + return; + } + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Archive it with lzop compression. */ + assertEqualInt(0, + systemf("%s -cf - --lzop f >archive.out 2>archive.err", + testprog)); + p = slurpfile(&s, "archive.err"); + p[s] = '\0'; + /* Check that the archive file has an lzma signature. */ + p = slurpfile(&s, "archive.out"); + assert(s > 2); + assertEqualMem(p, "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a", 9); +} diff --git a/tar/write.c b/tar/write.c index 659b412ce..25aaa184e 100644 --- a/tar/write.c +++ b/tar/write.c @@ -184,6 +184,9 @@ tar_mode_c(struct bsdtar *bsdtar) case OPTION_LZMA: r = archive_write_set_compression_lzma(a); break; + case OPTION_LZOP: + r = archive_write_add_filter_lzop(a); + break; case 'z': r = archive_write_set_compression_gzip(a); break; @@ -195,7 +198,7 @@ tar_mode_c(struct bsdtar *bsdtar) "Unrecognized compression option -%c", bsdtar->create_compression); } - if (r != ARCHIVE_OK) { + if (r < ARCHIVE_WARN) { lafe_errc(1, 0, "Unsupported compression option -%c", bsdtar->create_compression);