]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Add basic archive read and write filter support for lrzip.
authorCon Kolivas <kernel@kolivas.org>
Mon, 23 Apr 2012 01:03:39 +0000 (11:03 +1000)
committerCon Kolivas <kernel@kolivas.org>
Mon, 23 Apr 2012 01:03:39 +0000 (11:03 +1000)
Makefile.am
libarchive/archive.h
libarchive/archive_read_support_filter_lrzip.c [new file with mode: 0644]
libarchive/archive_write_add_filter_lrzip.c [new file with mode: 0644]
libarchive/test/test_compat_lrzip.c [new file with mode: 0644]
libarchive/test/test_compat_lrzip.tar.lrz.uu [new file with mode: 0644]
libarchive/test/test_write_compress_lrzip.c [new file with mode: 0644]

index fd4028f347c8fdbe5192d7e92a4d66ac638a59e6..2a67c406c360cc18d44462c2557451c49d0316c6 100644 (file)
@@ -134,6 +134,7 @@ libarchive_la_SOURCES=                                              \
        libarchive/archive_read_support_filter_bzip2.c          \
        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_none.c           \
        libarchive/archive_read_support_filter_program.c        \
        libarchive/archive_read_support_filter_rpm.c            \
@@ -173,6 +174,7 @@ libarchive_la_SOURCES=                                              \
        libarchive/archive_write_add_filter_bzip2.c     \
        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_none.c              \
        libarchive/archive_write_add_filter_program.c   \
        libarchive/archive_write_add_filter_xz.c                \
@@ -291,6 +293,7 @@ libarchive_test_SOURCES=                                    \
        libarchive/test/test_compat_cpio.c                      \
        libarchive/test/test_compat_gtar.c                      \
        libarchive/test/test_compat_gzip.c                      \
+       libarchive/test/test_compat_lrzip.c                     \
        libarchive/test/test_compat_lzip.c                      \
        libarchive/test/test_compat_lzma.c                      \
        libarchive/test/test_compat_mac.c                       \
@@ -388,6 +391,7 @@ libarchive_test_SOURCES=                                    \
        libarchive/test/test_write_compress.c                   \
        libarchive/test/test_write_compress_bzip2.c             \
        libarchive/test/test_write_compress_gzip.c              \
+       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_program.c           \
@@ -438,7 +442,7 @@ libarchive_test_LDADD= $(LTLIBICONV)
 libarchive/test/list.h: Makefile
        cat $(top_srcdir)/libarchive/test/test_*.c | grep DEFINE_TEST > libarchive/test/list.h
 
-libarchive_TESTS_ENVIRONMENT= LIBARCHIVE_TEST_FILES=`cd $(top_srcdir);/bin/pwd`/libarchive/test
+libarchive_TESTS_ENVIRONMENT= LIBARCHIVE_TEST_FILES=`cd $(top_srcdir);/bin/pwd`/libarchive/test LRZIP=NOCONFIG
 
 libarchive_test_EXTRA_DIST=\
        libarchive/test/list.h          \
index 48b5d54620c7600b253ce573afa42398dc7cec4d..c39df9851058a5e1a9220a481f7fbf03718783e2 100644 (file)
@@ -214,6 +214,7 @@ typedef int archive_switch_callback(struct archive *, void *_client_data1,
 #define        ARCHIVE_FILTER_UU       7
 #define        ARCHIVE_FILTER_RPM      8
 #define        ARCHIVE_FILTER_LZIP     9
+#define        ARCHIVE_FILTER_LRZIP    10
 
 #if ARCHIVE_VERSION_NUMBER < 4000000
 #define        ARCHIVE_COMPRESSION_NONE        ARCHIVE_FILTER_NONE
@@ -226,6 +227,7 @@ typedef int archive_switch_callback(struct archive *, void *_client_data1,
 #define        ARCHIVE_COMPRESSION_UU          ARCHIVE_FILTER_UU
 #define        ARCHIVE_COMPRESSION_RPM         ARCHIVE_FILTER_RPM
 #define        ARCHIVE_COMPRESSION_LZIP        ARCHIVE_FILTER_LZIP
+#define        ARCHIVE_COMPRESSION_LRZIP       ARCHIVE_FILTER_LRZIP
 #endif
 
 /*
@@ -320,6 +322,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_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_none(struct archive *);
@@ -576,6 +579,7 @@ __LA_DECL int archive_write_set_skip_file(struct archive *,
 __LA_DECL int archive_write_set_compression_bzip2(struct archive *);
 __LA_DECL int archive_write_set_compression_compress(struct archive *);
 __LA_DECL int archive_write_set_compression_gzip(struct archive *);
+__LA_DECL int archive_write_set_compression_lrzip(struct archive *);
 __LA_DECL int archive_write_set_compression_lzip(struct archive *);
 __LA_DECL int archive_write_set_compression_lzma(struct archive *);
 __LA_DECL int archive_write_set_compression_none(struct archive *);
@@ -589,6 +593,7 @@ __LA_DECL int archive_write_add_filter(struct archive *, int filter_code);
 __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_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_none(struct archive *);
diff --git a/libarchive/archive_read_support_filter_lrzip.c b/libarchive/archive_read_support_filter_lrzip.c
new file mode 100644 (file)
index 0000000..0272bf6
--- /dev/null
@@ -0,0 +1,127 @@
+/*-
+ * 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$");
+
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "archive.h"
+#include "archive_private.h"
+#include "archive_read_private.h"
+
+#define LRZIP_HEADER_MAGIC "LRZI"
+#define LRZIP_HEADER_MAGIC_LEN 4
+
+static int     lrzip_bidder_bid(struct archive_read_filter_bidder *, struct archive_read_filter *);
+static int     lrzip_bidder_init(struct archive_read_filter *);
+
+
+static int
+lrzip_reader_free(struct archive_read_filter_bidder *self)
+{
+       (void)self; /* UNUSED */
+       return (ARCHIVE_OK);
+}
+
+
+int
+archive_read_support_filter_lrzip(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, __func__);
+
+       if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK)
+               return (ARCHIVE_FATAL);
+
+       reader->data = NULL;
+       reader->bid = lrzip_bidder_bid;
+       reader->init = lrzip_bidder_init;
+       reader->options = NULL;
+       reader->free = lrzip_reader_free;
+       return (ARCHIVE_OK);
+}
+
+/*
+ * Bidder just verifies the header and returns the number of verified bits.
+ */
+static int
+lrzip_bidder_bid(struct archive_read_filter_bidder *self, struct archive_read_filter *filter)
+{
+       const unsigned char *p;
+       ssize_t avail, len;
+       int i;
+
+       (void)self; /* UNUSED */
+       /* Start by looking at the first six bytes of the header, which
+        * is all fixed layout. */
+       len = 6;
+       p = __archive_read_filter_ahead(filter, len, &avail);
+       if (p == NULL || avail == 0)
+               return (0);
+
+       if (memcmp(p, LRZIP_HEADER_MAGIC, LRZIP_HEADER_MAGIC_LEN))
+               return (0);
+
+       /* current major version is always 0, verify this */
+       if (p[LRZIP_HEADER_MAGIC_LEN])
+               return 0;
+       /* support only v0.6+ lrzip for sanity */
+       i = p[LRZIP_HEADER_MAGIC_LEN + 1];
+       if ((i < 6) || (i > 10))
+               return 0;
+
+       return len;
+}
+
+static int
+lrzip_bidder_init(struct archive_read_filter *self)
+{
+       int r;
+
+       r = __archive_read_program(self, "lrunzip");
+       /* Note: We set the format here even if __archive_read_program()
+        * above fails.  We do, after all, know what the format is
+        * even if we weren't able to read it. */
+       self->code = ARCHIVE_COMPRESSION_LRZIP;
+       self->name = "lrzip";
+       return (r);
+}
diff --git a/libarchive/archive_write_add_filter_lrzip.c b/libarchive/archive_write_add_filter_lrzip.c
new file mode 100644 (file)
index 0000000..6a8af99
--- /dev/null
@@ -0,0 +1,59 @@
+/*-
+ * 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: head/lib/libarchive/archive_write_set_compression_lrzip.c 201081 2009-12-28 02:04:42Z kientzle $");
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#include <time.h>
+
+#include "archive.h"
+#include "archive_private.h"
+#include "archive_write_private.h"
+
+
+#if ARCHIVE_VERSION_NUMBER < 4000000
+int
+archive_write_set_compression_lrzip(struct archive *a)
+{
+       __archive_write_filters_free(a);
+       return (archive_write_add_filter_lrzip(a));
+}
+#endif
+
+int
+archive_write_add_filter_lrzip(struct archive *a)
+{
+       return archive_write_add_filter_program(a, "lrzip");
+}
diff --git a/libarchive/test/test_compat_lrzip.c b/libarchive/test/test_compat_lrzip.c
new file mode 100644 (file)
index 0000000..0f182df
--- /dev/null
@@ -0,0 +1,77 @@
+/*-
+ * 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"
+
+static void
+verify(const char *name)
+{
+       /* lrzip tracks directories as files, ensure that we list everything */
+       const char *n[] = { "d1/", "d1/f1", "d1/f2", "d1/f3", "f1", "f2", "f3", NULL };
+       struct archive_entry *ae;
+       struct archive *a;
+       int i, r;
+
+       assert((a = archive_read_new()) != NULL);
+       r = archive_read_support_filter_lrzip(a);
+       if (r == ARCHIVE_WARN) {
+               skipping("lrzip reading not fully supported on this platform");
+               assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+               return;
+       }
+       assertEqualIntA(a, ARCHIVE_OK, r);
+       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; i < 7; ++i) {
+               failure("Could not read file %d (%s) from %s", i, n[i], name);
+               assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+               if (r != ARCHIVE_OK) {
+                       archive_read_free(a);
+                       return;
+               }
+               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_compression(a), ARCHIVE_COMPRESSION_LRZIP);
+       assertEqualString(archive_compression_name(a), "lrzip");
+       assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_GNUTAR);
+
+       assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+       assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
+
+
+DEFINE_TEST(test_compat_lrzip)
+{
+       verify("test_compat_lrzip.tar.lrz");
+}
+
+
diff --git a/libarchive/test/test_compat_lrzip.tar.lrz.uu b/libarchive/test/test_compat_lrzip.tar.lrz.uu
new file mode 100644 (file)
index 0000000..1248088
--- /dev/null
@@ -0,0 +1,10 @@
+begin 644 test_compat_lrzip.tar.lrz.uu
+M3%):20`&`"@``````````%T````!`0```@$`*`,`````#@`#`````&4`!E``
+MAP``````*(%=%O"2=0L1MCAA@GB4H1+_)V=!8=DS/0JC4Z+Q&5I0A'\SJ-#.
+M$U<4K-:^%:G^C3$B/80>END]NJE=5AP+]64N7$3):G02EKP>+AD`!IH`HQ(`
+M```R#$'@#E`G"/SW..;YC%X%73G3%U_;&GA#Y7N&P\[%?V!^'>:#?(>JQW**
+M1]!%JV?=U`TD.@:H85S[7D\VH/]%6JQ<D/18:FO<&V(OV/D=4^5^62X5NA'.
+MO*Q*>>/;HI.E&)I2N1_M4BU:942T`-IN<9%AZFZVY]'A)5%EY;Y0S/4MGN]Y
+D9.U/9Y/!R!PQ$O_\1>]J_8\^I0",9(YV]K_!A:WK9='*J7,1
+`
+end
diff --git a/libarchive/test/test_write_compress_lrzip.c b/libarchive/test/test_write_compress_lrzip.c
new file mode 100644 (file)
index 0000000..57fd3d4
--- /dev/null
@@ -0,0 +1,135 @@
+/*-
+ * Copyright (c) 2007 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "test.h"
+
+/*
+ * A basic exercise of lrzip reading and writing.
+ */
+
+DEFINE_TEST(test_write_compress_lrzip)
+{
+       struct archive_entry *ae;
+       struct archive* a;
+       char *buff, *data;
+       size_t buffsize, datasize;
+       char path[16];
+       size_t used1, used2;
+       int i, r;
+
+       buffsize = 2000000;
+       assert(NULL != (buff = (char *)malloc(buffsize)));
+
+       datasize = 10000;
+       assert(NULL != (data = (char *)malloc(datasize)));
+       memset(data, 0, datasize);
+
+       /*
+        * Write 100 files and read them all back.
+        */
+       assert((a = archive_write_new()) != NULL);
+       assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_gnutar(a));
+       assertEqualIntA(a, ARCHIVE_OK,
+           archive_write_set_compression_compress(a));
+       r = archive_write_set_compression_lrzip(a);
+       if (r == ARCHIVE_FATAL) {
+               skipping("lrzip writing not supported on this platform");
+               assertEqualInt(ARCHIVE_OK, archive_write_free(a));
+               return;
+       }
+       assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_per_block(a, 10));
+       assertEqualInt(ARCHIVE_COMPRESSION_PROGRAM, archive_compression(a));
+       assertEqualString("Program: lrzip", archive_compression_name(a));
+       assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used1));
+       assertEqualInt(ARCHIVE_COMPRESSION_PROGRAM, archive_compression(a));
+       assertEqualString("Program: lrzip", archive_compression_name(a));
+       assert((ae = archive_entry_new()) != NULL);
+       archive_entry_set_filetype(ae, AE_IFREG);
+       archive_entry_set_size(ae, datasize);
+       for (i = 0; i < 100; i++) {
+               sprintf(path, "file%03d", i);
+               archive_entry_copy_pathname(ae, path);
+               assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
+               assertA(datasize
+                   == (size_t)archive_write_data(a, data, datasize));
+       }
+       archive_entry_free(ae);
+       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));
+       r = archive_read_support_filter_lrzip(a);
+       if (r == ARCHIVE_WARN) {
+               skipping("Can't verify lrzip writing by reading back;"
+                   " lrzip reading not fully supported on this platform");
+       } else {
+               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_OK, archive_write_set_compression_lrzip(a));
+       assertEqualInt(ARCHIVE_OK, archive_write_free(a));
+
+       assert((a = archive_write_new()) != NULL);
+       assertEqualIntA(a, ARCHIVE_OK, archive_write_set_compression_lrzip(a));
+       assertEqualInt(ARCHIVE_OK, archive_write_close(a));
+       assertEqualInt(ARCHIVE_OK, archive_write_free(a));
+
+       assert((a = archive_write_new()) != NULL);
+       assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
+       assertEqualIntA(a, ARCHIVE_OK, archive_write_set_compression_lrzip(a));
+       assertEqualInt(ARCHIVE_OK, archive_write_close(a));
+       assertEqualInt(ARCHIVE_OK, archive_write_free(a));
+
+       assert((a = archive_write_new()) != NULL);
+       assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
+       assertEqualIntA(a, ARCHIVE_OK, archive_write_set_compression_lrzip(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);
+}