From: Michihiro NAKAJIMA Date: Fri, 19 Oct 2012 04:14:32 +0000 (+0900) Subject: Use liblzo2 for the lzop reader filter if available. X-Git-Tag: v3.1.0~40^2~26 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6b29a1cc6c6969a742c683d566cde3bc61611b13;p=thirdparty%2Flibarchive.git Use liblzo2 for the lzop reader filter if available. --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 04b823495..8b4aaca2e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -366,6 +366,30 @@ ELSEIF(LZMADEC_FOUND) INCLUDE_DIRECTORIES(${LZMADEC_INCLUDE_DIR}) LIST(APPEND ADDITIONAL_LIBS ${LZMADEC_LIBRARIES}) ENDIF(LZMA_FOUND) +# +# Find LZO2 +# +IF (LZO2_INCLUDE_DIR) + # Already in cache, be silent + SET(LZO2_FIND_QUIETLY TRUE) +ENDIF (LZO2_INCLUDE_DIR) + +FIND_PATH(LZO2_INCLUDE_DIR lzo/lzoconf.h) +FIND_LIBRARY(LZO2_LIBRARY NAMES lzo2 liblzo2) +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZO2 DEFAULT_MSG LZO2_LIBRARY LZO2_INCLUDE_DIR) +IF(LZO2_FOUND) + SET(HAVE_LIBLZO2 1) + SET(HAVE_LZO_LZOCONF_H 1) + SET(HAVE_LZO_LZO1X_H 1) + INCLUDE_DIRECTORIES(${LZO2_INCLUDE_DIR}) + LIST(APPEND ADDITIONAL_LIBS ${LZO2_LIBRARY}) + # + # TODO: test for static library. + # +ENDIF(LZO2_FOUND) +MARK_AS_ADVANCED(CLEAR LZO2_INCLUDE_DIR) +MARK_AS_ADVANCED(CLEAR LZO2_LIBRARY) # # Check headers diff --git a/Makefile.am b/Makefile.am index 7d42fc3ce..dab07f686 100644 --- a/Makefile.am +++ b/Makefile.am @@ -312,6 +312,7 @@ libarchive_test_SOURCES= \ libarchive/test/test_compat_gzip.c \ libarchive/test/test_compat_lzip.c \ libarchive/test/test_compat_lzma.c \ + libarchive/test/test_compat_lzop.c \ libarchive/test/test_compat_mac.c \ libarchive/test/test_compat_pax_libarchive_2x.c \ libarchive/test/test_compat_solaris_tar_acl.c \ @@ -342,6 +343,7 @@ libarchive_test_SOURCES= \ 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_lzop_multiple_parts.c \ libarchive/test/test_read_filter_program.c \ libarchive/test/test_read_filter_program_signature.c \ libarchive/test/test_read_filter_uudecode.c \ @@ -489,6 +491,9 @@ libarchive_test_EXTRA_DIST=\ libarchive/test/test_compat_lzma_1.tlz.uu \ libarchive/test/test_compat_lzma_2.tlz.uu \ libarchive/test/test_compat_lzma_3.tlz.uu \ + libarchive/test/test_compat_lzop_1.tar.lzo.uu \ + libarchive/test/test_compat_lzop_2.tar.lzo.uu \ + libarchive/test/test_compat_lzop_3.tar.lzo.uu \ libarchive/test/test_compat_mac-1.tar.Z.uu \ libarchive/test/test_compat_mac-2.tar.Z.uu \ libarchive/test/test_compat_pax_libarchive_2x.tar.Z.uu \ @@ -520,6 +525,7 @@ libarchive_test_EXTRA_DIST=\ 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_filter_lzop_multiple_parts.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 \ diff --git a/build/cmake/config.h.in b/build/cmake/config.h.in index 8c40654e5..ab2ef2f18 100644 --- a/build/cmake/config.h.in +++ b/build/cmake/config.h.in @@ -585,6 +585,9 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the `lzmadec' library (-llzmadec). */ #cmakedefine HAVE_LIBLZMADEC 1 +/* Define to 1 if you have the `lzo2' library (-llzo2). */ +#cmakedefine HAVE_LIBLZO2 1 + /* Define to 1 if you have the `xml2' library (-lxml2). */ #cmakedefine HAVE_LIBXML2 1 @@ -664,6 +667,12 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the header file. */ #cmakedefine HAVE_LZMA_H 1 +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LZO_LZO1X_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LZO_LZOCONF_H 1 + /* Define to 1 if you have the `mbrtowc' function. */ #cmakedefine HAVE_MBRTOWC 1 diff --git a/configure.ac b/configure.ac index 64e09a5af..8cffa5dd7 100644 --- a/configure.ac +++ b/configure.ac @@ -285,6 +285,14 @@ if test "x$with_lzma" != "xno"; then AC_CHECK_LIB(lzma,lzma_stream_decoder) fi +AC_ARG_WITH([lzo2], + AS_HELP_STRING([--without-lzo2], [Don't build support for lzop through liblzo2])) + +if test "x$with_lzo2" != "xno"; then + AC_CHECK_HEADERS([lzo/lzoconf.h lzo/lzo1x.h]) + AC_CHECK_LIB(lzo2,lzo1x_decompress_safe) +fi + AC_ARG_WITH([nettle], AS_HELP_STRING([--without-nettle], [Don't build with crypto support from Nettle])) AC_ARG_WITH([openssl], diff --git a/libarchive/archive_read_support_filter_lzop.c b/libarchive/archive_read_support_filter_lzop.c index ed427d59a..c0b9abe67 100644 --- a/libarchive/archive_read_support_filter_lzop.c +++ b/libarchive/archive_read_support_filter_lzop.c @@ -28,7 +28,9 @@ __FBSDID("$FreeBSD$"); - +#undef HAVE_ZLIB_H +#include +#include #ifdef HAVE_ERRNO_H #include #endif @@ -41,18 +43,61 @@ __FBSDID("$FreeBSD$"); #ifdef HAVE_UNISTD_H #include #endif +#ifdef HAVE_LZO_LZOCONF_H +#include +#endif +#ifdef HAVE_LZO_LZO1X_H +#include +#endif +#ifdef HAVE_ZLIB_H +#include /* for crc32 and adler32 */ +#endif #include "archive.h" +#ifndef HAVE_ZLIB_H +#include "archive_crc32.h" +#endif +#include "archive_endian.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 +#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) +struct read_lzop { + unsigned char *out_block; + size_t out_block_size; + int64_t total_out; + int flags; + uint32_t compressed_cksum; + uint32_t uncompressed_cksum; + size_t compressed_size; + size_t uncompressed_size; + size_t unconsumed_bytes; + char in_stream; + char eof; /* True = found end of compressed data. */ +}; + +#define FILTER 0x0800 +#define CRC32_HEADER 0x1000 +#define EXTRA_FIELD 0x0040 +#define ADLER32_UNCOMPRESSED 0x0001 +#define ADLER32_COMPRESSED 0x0002 +#define CRC32_UNCOMPRESSED 0x0100 +#define CRC32_COMPRESSED 0x0200 +#define MAX_BLOCK_SIZE (64 * 1024 * 1024) + +static ssize_t lzop_filter_read(struct archive_read_filter *, const void **); +static int lzop_filter_close(struct archive_read_filter *); +#endif + 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 *); +#ifndef HAVE_ZLIB_H +static unsigned long adler32(unsigned long, const void *, size_t); +#endif int archive_read_support_filter_lzop(struct archive *_a) @@ -70,18 +115,16 @@ archive_read_support_filter_lzop(struct archive *_a) reader->bid = lzop_bidder_bid; reader->init = lzop_bidder_init; reader->options = NULL; - reader->free = lzop_reader_free; + reader->free = NULL; + /* Signal the extent of lzop support with the return value here. */ +#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) + return (ARCHIVE_OK); +#else /* Return ARCHIVE_WARN since this always uses an external program. */ archive_set_error(_a, ARCHIVE_ERRNO_MISC, "Using external lzop program for lzop decompression"); return (ARCHIVE_WARN); -} - -static int -lzop_reader_free(struct archive_read_filter_bidder *self) -{ - (void)self; /* UNUSED */ - return (ARCHIVE_OK); +#endif } /* @@ -106,6 +149,12 @@ lzop_bidder_bid(struct archive_read_filter_bidder *self, return (LZOP_HEADER_MAGIC_LEN * 8); } +#if !defined(HAVE_LZO_LZOCONF_H) || !defined(HAVE_LZO_LZO1X_H) +/* + * If we don't have the library on this system, we can't do the + * decompression directly. We can, however, try to run "lzop -d" + * in case that's available. + */ static int lzop_bidder_init(struct archive_read_filter *self) { @@ -119,3 +168,356 @@ lzop_bidder_init(struct archive_read_filter *self) self->name = "lzop"; return (r); } +#else +/* + * Initialize the filter object. + */ +static int +lzop_bidder_init(struct archive_read_filter *self) +{ + struct read_lzop *state; + + self->code = ARCHIVE_FILTER_LZOP; + self->name = "lzop"; + + state = (struct read_lzop *)calloc(sizeof(*state), 1); + if (state == NULL) { + archive_set_error(&self->archive->archive, ENOMEM, + "Can't allocate data for lzop decompression"); + return (ARCHIVE_FATAL); + } + + self->data = state; + self->read = lzop_filter_read; + self->skip = NULL; /* not supported */ + self->close = lzop_filter_close; + + return (ARCHIVE_OK); +} + +static int +consume_header(struct archive_read_filter *self) +{ + struct read_lzop *state = (struct read_lzop *)self->data; + const unsigned char *p, *_p; + unsigned checksum, flags, len, method, version; + + /* + * Check LZOP magic code. + */ + p = __archive_read_filter_ahead(self->upstream, + LZOP_HEADER_MAGIC_LEN, NULL); + if (p == NULL) + return (ARCHIVE_EOF); + + if (memcmp(p, LZOP_HEADER_MAGIC, LZOP_HEADER_MAGIC_LEN)) + return (ARCHIVE_EOF); + __archive_read_filter_consume(self->upstream, + LZOP_HEADER_MAGIC_LEN); + + p = __archive_read_filter_ahead(self->upstream, 29, NULL); + if (p == NULL) + goto truncated; + _p = p; + version = archive_be16dec(p); + p += 4;/* version(2 bytes) + library version(2 bytes) */ + + if (version >= 0x940) { + unsigned reqversion = archive_be16dec(p); p += 2; + if (reqversion < 0x900) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, "Invalid required version"); + return (ARCHIVE_FAILED); + } + } + + method = *p++; + if (method < 1 || method > 3) { + archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, + "Unsupported method"); + return (ARCHIVE_FAILED); + } + + if (version >= 0x940) { + unsigned level = *p++; + if (method == 1 && level == 0) level = 3; + if (method == 2 && level == 0) level = 1; + if (method == 3 && level == 0) level = 9; + if (level < 1 && level > 9) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, "Invalid level"); + return (ARCHIVE_FAILED); + } + } + + flags = archive_be32dec(p); p += 4; + + if (flags & FILTER) + p += 4; /* Skip filter */ + p += 4; /* Skip mode */ + if (version >= 0x940) + p += 8; /* Skip mtime */ + else + p += 4; /* Skip mtime */ + len = *p++; /* Read filename length */ + len += p - _p; + /* Make sure we have all bytes we need to calculate checksum. */ + p = __archive_read_filter_ahead(self->upstream, len + 4, NULL); + if (p == NULL) + goto truncated; + if (flags & CRC32_HEADER) + checksum = crc32(crc32(0, NULL, 0), p, len); + else + checksum = adler32(adler32(0, NULL, 0), p, len); + if (archive_be32dec(p + len) != checksum) + goto corrupted; + __archive_read_filter_consume(self->upstream, len + 4); + if (flags & EXTRA_FIELD) { + /* Skip extra field */ + p = __archive_read_filter_ahead(self->upstream, 4, NULL); + if (p == NULL) + goto truncated; + len = archive_be32dec(p); + __archive_read_filter_consume(self->upstream, len + 4 + 4); + } + state->flags = flags; + state->in_stream = 1; + return (ARCHIVE_OK); +truncated: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data"); + return (ARCHIVE_FAILED); +corrupted: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Corrupted lzop header"); + return (ARCHIVE_FAILED); +} + +static int +consume_block_info(struct archive_read_filter *self) +{ + struct read_lzop *state = (struct read_lzop *)self->data; + const unsigned char *p; + unsigned flags = state->flags; + + p = __archive_read_filter_ahead(self->upstream, 4, NULL); + if (p == NULL) + goto truncated; + state->uncompressed_size = archive_be32dec(p); + __archive_read_filter_consume(self->upstream, 4); + if (state->uncompressed_size == 0) + return (ARCHIVE_EOF); + if (state->uncompressed_size > MAX_BLOCK_SIZE) + goto corrupted; + + p = __archive_read_filter_ahead(self->upstream, 4, NULL); + if (p == NULL) + goto truncated; + state->compressed_size = archive_be32dec(p); + __archive_read_filter_consume(self->upstream, 4); + if (state->compressed_size > state->uncompressed_size) + goto corrupted; + + if (flags & (CRC32_UNCOMPRESSED | ADLER32_UNCOMPRESSED)) { + p = __archive_read_filter_ahead(self->upstream, 4, NULL); + if (p == NULL) + goto truncated; + state->compressed_cksum = state->uncompressed_cksum = + archive_be32dec(p); + __archive_read_filter_consume(self->upstream, 4); + } + if ((flags & (CRC32_COMPRESSED | ADLER32_COMPRESSED)) && + state->compressed_size < state->uncompressed_size) { + p = __archive_read_filter_ahead(self->upstream, 4, NULL); + if (p == NULL) + goto truncated; + state->compressed_cksum = archive_be32dec(p); + __archive_read_filter_consume(self->upstream, 4); + } + return (ARCHIVE_OK); +truncated: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data"); + return (ARCHIVE_FAILED); +corrupted: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Corrupted lzop header"); + return (ARCHIVE_FAILED); +} + +static ssize_t +lzop_filter_read(struct archive_read_filter *self, const void **p) +{ + struct read_lzop *state = (struct read_lzop *)self->data; + const void *b; + lzo_uint out_size; + uint32_t cksum; + int ret, r; + + if (state->unconsumed_bytes) { + __archive_read_filter_consume(self->upstream, + state->unconsumed_bytes); + state->unconsumed_bytes = 0; + } + if (state->eof) + return (0); + + for (;;) { + if (!state->in_stream) { + ret = consume_header(self); + if (ret < ARCHIVE_OK) + return (ret); + if (ret == ARCHIVE_EOF) { + state->eof = 1; + return (0); + } + } + ret = consume_block_info(self); + if (ret < ARCHIVE_OK) + return (ret); + if (ret == ARCHIVE_EOF) + state->in_stream = 0; + else + break; + } + + if (state->out_block == NULL || + state->out_block_size < state->uncompressed_size) { + void *new_block; + + new_block = realloc(state->out_block, state->uncompressed_size); + if (new_block == NULL) { + archive_set_error(&self->archive->archive, ENOMEM, + "Can't allocate data for lzop decompression"); + return (ARCHIVE_FATAL); + } + state->out_block = new_block; + state->out_block_size = state->uncompressed_size; + } + + b = __archive_read_filter_ahead(self->upstream, + state->compressed_size, NULL); + if (b == NULL) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data"); + return (ARCHIVE_FATAL); + } + if (state->flags & CRC32_COMPRESSED) + cksum = crc32(crc32(0, NULL, 0), b, state->compressed_size); + else if (state->flags & ADLER32_COMPRESSED) + cksum = adler32(adler32(0, NULL, 0), b, state->compressed_size); + else + cksum = state->compressed_cksum; + if (cksum != state->compressed_cksum) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, "Corrupted data"); + return (ARCHIVE_FATAL); + } + + /* + * If the both uncompressed size and compressed size are the same, + * we do not decompress this block. + */ + if (state->uncompressed_size == state->compressed_size) { + *p = b; + state->total_out += state->compressed_size; + state->unconsumed_bytes = state->compressed_size; + return ((ssize_t)state->uncompressed_size); + } + + /* + * Drive lzo uncompresison. + */ + out_size = (lzo_uint)state->uncompressed_size; + r = lzo1x_decompress_safe(b, (lzo_uint)state->compressed_size, + state->out_block, &out_size, NULL); + switch (r) { + case LZO_E_OK: + if (out_size == state->uncompressed_size) + break; + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, "Corrupted data"); + return (ARCHIVE_FATAL); + case LZO_E_OUT_OF_MEMORY: + archive_set_error(&self->archive->archive, ENOMEM, + "lzop decompression failed: out of memory"); + return (ARCHIVE_FATAL); + default: + archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, + "lzop decompression failed: %d", r); + return (ARCHIVE_FATAL); + } + + if (state->flags & CRC32_UNCOMPRESSED) + cksum = crc32(crc32(0, NULL, 0), state->out_block, + state->uncompressed_size); + else if (state->flags & ADLER32_UNCOMPRESSED) + cksum = adler32(adler32(0, NULL, 0), state->out_block, + state->uncompressed_size); + else + cksum = state->uncompressed_cksum; + if (cksum != state->uncompressed_cksum) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, "Corrupted data"); + return (ARCHIVE_FATAL); + } + + __archive_read_filter_consume(self->upstream, state->compressed_size); + *p = state->out_block; + state->total_out += out_size; + return ((ssize_t)out_size); +} + +/* + * Clean up the decompressor. + */ +static int +lzop_filter_close(struct archive_read_filter *self) +{ + struct read_lzop *state = (struct read_lzop *)self->data; + + free(state->out_block); + free(state); + return (ARCHIVE_OK); +} + +#ifndef HAVE_ZLIB_H +static unsigned long +adler32(unsigned long adler, const void *_p, size_t len) +{ + const unsigned char *p; + uint32_t a, b; + + if (_p == NULL) + return (1); + p = (const unsigned char *)_p; + a = adler & 0xffff; + b = (adler >> 16) & 0xffff; + while (len) { + size_t xlen, tlen = (len > 4096)? 4096: len; + len -= tlen; + xlen = tlen >> 4; + tlen &= 0x0f; + while (xlen--) { + a += p[0]; b += a; a += p[1]; b += a; + a += p[2]; b += a; a += p[3]; b += a; + a += p[4]; b += a; a += p[5]; b += a; + a += p[6]; b += a; a += p[7]; b += a; + a += p[8]; b += a; a += p[9]; b += a; + a += p[10]; b += a; a += p[11]; b += a; + a += p[12]; b += a; a += p[13]; b += a; + a += p[14]; b += a; a += p[15]; b += a; + p += 16; + } + while (tlen--) { + a += *p++; + b += a; + } + a %= 65521; + b %= 65521; + } + return ((b << 16) | a); +} +#endif + +#endif diff --git a/libarchive/test/CMakeLists.txt b/libarchive/test/CMakeLists.txt index a9fd1ba24..b2f67b056 100644 --- a/libarchive/test/CMakeLists.txt +++ b/libarchive/test/CMakeLists.txt @@ -49,6 +49,7 @@ IF(ENABLE_TEST) test_compat_gzip.c test_compat_lzip.c test_compat_lzma.c + test_compat_lzop.c test_compat_mac.c test_compat_pax_libarchive_2x.c test_compat_solaris_tar_acl.c @@ -79,6 +80,7 @@ IF(ENABLE_TEST) test_read_filter_grzip.c test_read_filter_lrzip.c test_read_filter_lzop.c + test_read_filter_lzop_multiple_parts.c test_read_filter_program.c test_read_filter_program_signature.c test_read_filter_uudecode.c diff --git a/libarchive/test/test_compat_lzop.c b/libarchive/test/test_compat_lzop.c new file mode 100644 index 000000000..cd43afcf3 --- /dev/null +++ b/libarchive/test/test_compat_lzop.c @@ -0,0 +1,131 @@ +/*- + * 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" +__FBSDID("$FreeBSD$"); + +/* + * Verify our ability to read sample files compatibly with lzop. + * + * In particular: + * * lzop will stop at the end of a stream if the following data + * doesn't start with a lzop signature. + * + */ + +DEFINE_TEST(test_compat_lzop) +{ + const char *sample1 = "test_compat_lzop_1.tar.lzo"; + const char *sample2 = "test_compat_lzop_2.tar.lzo"; + const char *sample3 = "test_compat_lzop_3.tar.lzo"; + struct archive_entry *ae; + struct archive *a; + int r; + + /* + * Test1: tar ball compressed in one block. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + r = archive_read_support_filter_lzop(a); + if (r == ARCHIVE_WARN) { + skipping("lzop reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + extract_reference_file(sample1); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, sample1, 2)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("INSTALL", 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_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)); + + /* + * Test2: tar ball compressed in multi blocks. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + extract_reference_file(sample2); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, sample2, 2)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("file1", archive_entry_pathname(ae)); + assertEqualInt(19, archive_entry_size(ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("file2", archive_entry_pathname(ae)); + assertEqualInt(262144, archive_entry_size(ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("file3", archive_entry_pathname(ae)); + assertEqualInt(19, archive_entry_size(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_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)); + + /* + * Test3: tar ball compressed in one block with junk data. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + extract_reference_file(sample3); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, sample3, 2)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("INSTALL", 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_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_compat_lzop_1.tar.lzo.uu b/libarchive/test/test_compat_lzop_1.tar.lzo.uu new file mode 100644 index 000000000..9eeca6a6c --- /dev/null +++ b/libarchive/test/test_compat_lzop_1.tar.lzo.uu @@ -0,0 +1,30 @@ +begin 664 test_compat_lzop_1.tar.lzo +MB4Q:3P`-"AH*$#`@8`E``04#```!``"!M%"`FEX`````%G1E2`H82?@"@-F'4"+"!T;PJL!`-W:71H(%AH +M;6!T!$UA8R!/4RQT%@$@8V%N)X`&+',,86YDO#.4(0(@+4<@(H0(`2(@?B\H +M;`D`#2UD;W=N;&]A9"UD:7(O"E1H92!R97-U;'0@=VEL;"!P=01P<')O<')I +M8"A\(I0F`BP@?!\#('1O;VPND!`!9&5F8780;VXP.Q$@:7-L +M*<0K`V4@36%K98P.=!)U(@IW(F%L2`H82?@"@-F'4"+"!T;PJL!`-W:71H(%AH +M;6!T!$UA8R!/4RQT%@$@8V%N)X`&+',,86YDO#.4(0(@+4<@(H0(`2(@?B\H +M;`D`#2UD;W=N;&]A9"UD:7(O"E1H92!R97-U;'0@=VEL;"!P=01P<')O<')I +M8"A\(I0F`BP@?!\#('1O;VPND!`!9&5F8780;VXP.Q$@:7-L +M*<0K`V4@36%K98P.=!)U(@IW(F%L?S4W(`!&_`\@/N@'(``````` +M`````````````````````````````````````)!X`0X````````````````` +M`````!$```````")3%I/``T*&@H0,"!@"4`!!0,```$``(&T4("O>``````+ +M=&5S=%]L>F]P86)^0`CR```H`````$DH```!`@``````(``````````````` +M`````````````````````````````````````.X0```!```````````````` +M`````````!$```````")3%I/``T*&@H0,"!@"4`!!0,```$``(&T4("O>``` +M```+=&5S=%]L>F]P86-^00CS```H`````$DH```!`@``````(``````````` +M`````````````````````````````````````````.X0```!```````````` +M`````````````!$```````")3%I/``T*&@H0,"!@"4`!!0,```$``(&T4("O +M>``````+=&5S=%]L>F]P861^0@CT```H`````$DH```!`@``````(``````` +M`````````````````````````````````````````````.X0```!```````` +M`````````````````!$```````")3%I/``T*&@H0,"!@"4`!!0,```$``(&T +M4("O>``````+=&5S=%]L>F]P865^0PCU```H`````$DH```!`@``````(``` +M`````````````````````````````````````````````````.X0```!```` +M`````````````````````!$```````")3%I/``T*&@H0,"!@"4`!!0,```$` +M`(&T4("O>``````+=&5S=%]L>F]P869^1`CV```H`````$DH```!`@`````` +M(````````````````````````````````````````````````````.X0```! +M`````````````````````````!$```````")3%I/``T*&@H0,"!@"4`!!0,` +M``$``(&T4("O>``````+=&5S=%]L>F]P86=^10CW```H`````$DH```!`@`` +M````(````````````````````````````````````````````````````.X0 +M```!`````````````````````````!$```````")3%I/``T*&@H0,"!@"4`! +M!0,```$``(&T4("O>``````+=&5S=%]L>F]P86A^1@CX```H`````$DH```! +M`@``````(``````````````````````````````````````````````````` +M`.X0```!`````````````````````````!$```````")3%I/``T*&@H0,"!@ +M"4`!!0,```$``(&T4("O>``````+=&5S=%]L>F]P86E^1PCY```H`````$DH +M```!`@``````(``````````````````````````````````````````````` +M`````.X0```!`````````````````````````!$```````")3%I/``T*&@H0 +M,"!@"4`!!0,```$``(&T4("O>``````+=&5S=%]L>F]P86I^2`CZ```H```` +M`$DH```!`@``````(``````````````````````````````````````````` +M`````````.X0```!`````````````````````````!$```````")3%I/``T* +M&@H0,"!@"4`!!0,```$``(&T4("O>``````+=&5S=%]L>F]P86M^20C[```H +M`````$DH```!`@``````(``````````````````````````````````````` +M`````````````.X0```!`````````````````````````!$```````")3%I/ +M``T*&@H0,"!@"4`!!0,```$``(&T4("O>``````+=&5S=%]L>F]P86Q^2@C\ +M```H`````$DH```!`@``````(``````````````````````````````````` +M`````````````````.X0```!`````````````````````````!$```````") +M3%I/``T*&@H0,"!@"4`!!0,```$``(&T4("O>``````+=&5S=%]L>F]P86U^ +M2PC]```H`````$DH```!`@``````(``````````````````````````````` +M`````````````````````.X0```!`````````````````````````!$````` +M``")3%I/``T*&@H0,"!@"4`!!0,```$``(&T4("O>``````+=&5S=%]L>F]P +M86Y^3`C^```H`````$DH```!`@``````(``````````````````````````` +M`````````````````````````.X0```!`````````````````````````!$` +M``````")3%I/``T*&@H0,"!@"4`!!0,```$``(&T4("O>``````+=&5S=%]L +M>F]P86]^30C_```H`````$DH```!`@``````(``````````````````````` +M`````````````````````````````.X0```!```````````````````````` +M`!$```````")3%I/``T*&@H0,"!@"4`!!0,```$``(&T4("O>``````+=&5S +M=%]L>F]P87!^3@D````H`````$DH```!`@``````(``````````````````` +M`````````````````````````````````.X0```!```````````````````` +M`````!$```````")3%I/``T*&@H0,"!@"4`!!0,```$``(&T4("O>``````+ +M=&5S=%]L>F]P87%^3PD!```H`````$DH```!`@``````(``````````````` +M`````````````````````````````````````.X0```!```````````````` +M`````````!$```````")3%I/``T*&@H0,"!@"4`!!0,```$``(&T4("O>``` +M```+=&5S=%]L>F]P87)^4`D"```H`````$DH```!`@``````(``````````` +M`````````````````````````````````````````.X0```!```````````` +M`````````````!$```````")3%I/``T*&@H0,"!@"4`!!0,```$``(&T4("O +M>``````+=&5S=%]L>F]P87-^40D#```H`````$DH```!`@``````(``````` +M`````````````````````````````````````````````.X0```!```````` +M`````````````````!$```````")3%I/``T*&@H0,"!@"4`!!0,```$``(&T +M4("O>``````+=&5S=%]L>F]P871^4@D$```H`````$DH```!`@``````(``` +M`````````````````````````````````````````````````.X0```!```` +M`````````````````````!$```````")3%I/``T*&@H0,"!@"4`!!0,```$` +M`(&T4("O>``````+=&5S=%]L>F]P875^4PD%```H`````$DH```!`@`````` +M(````````````````````````````````````````````````````.X0```! +M`````````````````````````!$```````")3%I/``T*&@H0,"!@"4`!!0,` +M``$``(&T4("O>``````+=&5S=%]L>F]P879^5`D&```H`````$DH```!`@`` +M````(````````````````````````````````````````````````````.X0 +M```!`````````````````````````!$```````")3%I/``T*&@H0,"!@"4`! +M!0,```$``(&T4("O>``````+=&5S=%]L>F]P87=^50D'```H`````$DH```! +M`@``````(``````````````````````````````````````````````````` +M`.X0```!`````````````````````````!$```````")3%I/``T*&@H0,"!@ +M"4`!!0,```$``(&T4("O>``````+=&5S=%]L>F]P87A^5@D(```H`````$DH +M```!`@``````(``````````````````````````````````````````````` +M`````.X0```!`````````````````````````!$```````")3%I/``T*&@H0 +M,"!@"4`!!0,```$``(&T4("O>``````+=&5S=%]L>F]P87E^5PD)```H```` +M`$DH```!`@``````(``````````````````````````````````````````` +M`````````.X0```!`````````````````````````!$```````")3%I/``T* +M&@H0,"!@"4`!!0,```$``(&T4("O>``````+=&5S=%]L>F]P87I^6`D*```F +M`````+OSXAG6`@``````(``````````````````````````````````````` +M]Q```F9I;&4S(#[\=PLP,#`V-C0@`#`P,3