]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Add RPM filter.
authorMichihiro NAKAJIMA <ggcueroad@gmail.com>
Mon, 23 Nov 2009 08:40:03 +0000 (03:40 -0500)
committerMichihiro NAKAJIMA <ggcueroad@gmail.com>
Mon, 23 Nov 2009 08:40:03 +0000 (03:40 -0500)
SVN-Revision: 1677

Makefile.am
libarchive/CMakeLists.txt
libarchive/archive.h
libarchive/archive_read_support_compression_all.c
libarchive/archive_read_support_compression_rpm.c [new file with mode: 0644]
libarchive/test/CMakeLists.txt
libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c [new file with mode: 0644]
libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.rpm.uu [new file with mode: 0644]
libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c [new file with mode: 0644]
libarchive/test/test_read_format_cpio_svr4_gzip_rpm.rpm.uu [new file with mode: 0644]

index 9f7387cf4a8dc599218483a389284ae607e18a55..bdc8547df04c7dbe5351c885d0c6662bfc00d6ce 100644 (file)
@@ -123,6 +123,7 @@ libarchive_la_SOURCES=                                              \
        libarchive/archive_read_support_compression_gzip.c      \
        libarchive/archive_read_support_compression_none.c      \
        libarchive/archive_read_support_compression_program.c   \
+       libarchive/archive_read_support_compression_rpm.c       \
        libarchive/archive_read_support_compression_uu.c        \
        libarchive/archive_read_support_compression_xz.c        \
        libarchive/archive_read_support_format_all.c            \
@@ -257,7 +258,9 @@ libarchive_test_SOURCES=                                    \
        libarchive/test/test_read_format_cpio_bin_lzma.c        \
        libarchive/test/test_read_format_cpio_bin_xz.c          \
        libarchive/test/test_read_format_cpio_odc.c             \
+       libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c  \
        libarchive/test/test_read_format_cpio_svr4_gzip.c       \
+       libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c   \
        libarchive/test/test_read_format_cpio_svr4c_Z.c         \
        libarchive/test/test_read_format_empty.c                \
        libarchive/test/test_read_format_gtar_gz.c              \
@@ -349,6 +352,8 @@ libarchive_test_EXTRA_DIST=\
        libarchive/test/test_pax_filename_encoding.tar.uu               \
        libarchive/test/test_read_format_ar.ar.uu                       \
        libarchive/test/test_read_format_cpio_bin_be.cpio.uu            \
+       libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.rpm.uu     \
+       libarchive/test/test_read_format_cpio_svr4_gzip_rpm.rpm.uu      \
        libarchive/test/test_read_format_gtar_sparse_1_13.tar.uu        \
        libarchive/test/test_read_format_gtar_sparse_1_17.tar.uu        \
        libarchive/test/test_read_format_gtar_sparse_1_17_posix00.tar.uu \
index af7dab72bb416cd4a1a878d5b37bdea72b4bae62..ce3451ad286c51ddba50fa02cbd818d640949750 100644 (file)
@@ -43,6 +43,7 @@ SET(libarchive_SOURCES
   archive_read_support_compression_gzip.c
   archive_read_support_compression_none.c
   archive_read_support_compression_program.c
+  archive_read_support_compression_rpm.c
   archive_read_support_compression_uu.c
   archive_read_support_compression_xz.c
   archive_read_support_format_all.c
index 6bd1b34b277ad4134cb56eb6c7f7e3c8ba80d603..6db0242dd5276cceac88aaf0d05fc2b9d2818658 100644 (file)
@@ -244,6 +244,7 @@ typedef int archive_close_callback(struct archive *, void *_client_data);
 #define        ARCHIVE_COMPRESSION_LZMA        5
 #define        ARCHIVE_COMPRESSION_XZ          6
 #define        ARCHIVE_COMPRESSION_UU          7
+#define        ARCHIVE_COMPRESSION_RPM         8
 
 /*
  * Codes returned by archive_format.
@@ -319,6 +320,7 @@ __LA_DECL int                archive_read_support_compression_program_signature
                                (struct archive *, const char *,
                                    const void * /* match */, size_t);
 
+__LA_DECL int           archive_read_support_compression_rpm(struct archive *);
 __LA_DECL int           archive_read_support_compression_uu(struct archive *);
 __LA_DECL int           archive_read_support_compression_xz(struct archive *);
 
index f4708ca8102a39a7941b279de1444d0e2dbf8bc5..6cff93dd35137a10dc61142d5bf7a3582b604a84 100644 (file)
@@ -46,6 +46,8 @@ archive_read_support_compression_all(struct archive *a)
        archive_read_support_compression_xz(a);
        /* The decode code doesn't use an outside library. */
        archive_read_support_compression_uu(a);
+       /* The decode code doesn't use an outside library. */
+       archive_read_support_compression_rpm(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_compression_rpm.c b/libarchive/archive_read_support_compression_rpm.c
new file mode 100644 (file)
index 0000000..57e6e78
--- /dev/null
@@ -0,0 +1,287 @@
+/*-
+ * Copyright (c) 2009 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"
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include "archive.h"
+#include "archive_endian.h"
+#include "archive_private.h"
+#include "archive_read_private.h"
+
+struct rpm {
+       int64_t          total_in;
+       size_t           hpos;
+       size_t           hlen;
+       unsigned char    header[16];
+       enum {
+               ST_LEAD,        /* Skipping 'Lead' section. */
+               ST_HEADER,      /* Reading 'Header' section;
+                                * first 16 bytes. */
+               ST_HEADER_DATA, /* Skipping 'Header' section. */
+               ST_PADDING,     /* Skipping padding data after the
+                                * 'Header' section. */
+               ST_ARCHIVE      /* Reading 'Archive' section. */
+       }                state;
+       int              first_header;
+};
+#define RPM_LEAD_SIZE  96      /* Size of 'Lead' section. */
+
+static int     rpm_bidder_bid(struct archive_read_filter_bidder *,
+                   struct archive_read_filter *);
+static int     rpm_bidder_init(struct archive_read_filter *);
+
+static ssize_t rpm_filter_read(struct archive_read_filter *,
+                   const void **);
+static int     rpm_filter_close(struct archive_read_filter *);
+
+int
+archive_read_support_compression_rpm(struct archive *_a)
+{
+       struct archive_read *a = (struct archive_read *)_a;
+       struct archive_read_filter_bidder *bidder;
+
+       bidder = __archive_read_get_bidder(a);
+       archive_clear_error(_a);
+       if (bidder == NULL)
+               return (ARCHIVE_FATAL);
+
+       bidder->data = NULL;
+       bidder->bid = rpm_bidder_bid;
+       bidder->init = rpm_bidder_init;
+       bidder->options = NULL;
+       bidder->free = NULL;
+       return (ARCHIVE_OK);
+}
+
+static int
+rpm_bidder_bid(struct archive_read_filter_bidder *self,
+    struct archive_read_filter *filter)
+{
+       const unsigned char *b;
+       ssize_t avail;
+       int bits_checked;
+
+       (void)self; /* UNUSED */
+
+       b = __archive_read_filter_ahead(filter, 8, &avail);
+       if (b == NULL)
+               return (0);
+
+       bits_checked = 0;
+       /*
+        * Verify Header Magic Bytes : 0xed 0xab 0xee 0xdb
+        */
+       if (b[0] != 0xed)
+               return (0);
+       bits_checked += 8;
+       if (b[1] != 0xab)
+               return (0);
+       bits_checked += 8;
+       if (b[2] != 0xee)
+               return (0);
+       bits_checked += 8;
+       if (b[3] != 0xdb)
+               return (0);
+       bits_checked += 8;
+       /*
+        * Check major version.
+        */
+       if (b[4] != 3 && b[4] != 4)
+               return (0);
+       bits_checked += 8;
+       /*
+        * Check package type; binary or source.
+        */
+       if (b[6] != 0)
+               return (0);
+       bits_checked += 8;
+       if (b[7] != 0 && b[7] != 1)
+               return (0);
+       bits_checked += 8;
+
+       return (bits_checked);
+}
+
+static int
+rpm_bidder_init(struct archive_read_filter *self)
+{
+       struct rpm   *rpm;
+
+       self->code = ARCHIVE_COMPRESSION_RPM;
+       self->name = "rpm";
+       self->read = rpm_filter_read;
+       self->skip = NULL; /* not supported */
+       self->close = rpm_filter_close;
+
+       rpm = (struct rpm *)calloc(sizeof(*rpm), 1);
+       if (rpm == NULL) {
+               archive_set_error(&self->archive->archive, ENOMEM,
+                   "Can't allocate data for rpm");
+               return (ARCHIVE_FATAL);
+       }
+
+       self->data = rpm;
+       rpm->state = ST_LEAD;
+
+       return (ARCHIVE_OK);
+}
+
+static ssize_t
+rpm_filter_read(struct archive_read_filter *self, const void **buff)
+{
+       struct rpm *rpm;
+       const unsigned char *b;
+       ssize_t avail_in, total;
+       size_t used, n;
+       uint32_t section;
+       uint32_t bytes;
+
+       rpm = (struct rpm *)self->data;
+       *buff = NULL;
+       total = avail_in = 0;
+       b = NULL;
+       used = 0;
+       do {
+               if (b == NULL) {
+                       b = __archive_read_filter_ahead(self->upstream, 1,
+                           &avail_in);
+                       if (b == NULL) {
+                               if (avail_in < 0)
+                                       return (ARCHIVE_FATAL);
+                               else
+                                       break;
+                       }
+               }
+
+               switch (rpm->state) {
+               case ST_LEAD:
+                       if (rpm->total_in + avail_in < RPM_LEAD_SIZE)
+                               used += avail_in;
+                       else {
+                               n = RPM_LEAD_SIZE - rpm->total_in;
+                               used += n;
+                               b += n;
+                               rpm->state = ST_HEADER;
+                               rpm->hpos = 0;
+                               rpm->hlen = 0;
+                               rpm->first_header = 1;
+                       }
+                       break;
+               case ST_HEADER:
+                       n = 16 - rpm->hpos;
+                       if (n > avail_in - used)
+                               n = avail_in - used;
+                       memcpy(rpm->header+rpm->hpos, b, n);
+                       b += n;
+                       used += n;
+                       rpm->hpos += n;
+
+                       if (rpm->hpos == 16) {
+                               if (rpm->header[0] != 0x8e ||
+                                   rpm->header[1] != 0xad ||
+                                   rpm->header[2] != 0xe8 ||
+                                   rpm->header[3] != 0x01) {
+                                       if (rpm->first_header) {
+                                               archive_set_error(
+                                                   &self->archive->archive,
+                                                   ARCHIVE_ERRNO_FILE_FORMAT,
+                                                   "Unrecoginized rpm header");
+                                               return (ARCHIVE_FATAL);
+                                       }
+                                       rpm->state = ST_ARCHIVE;
+                                       *buff = rpm->header;
+                                       total = rpm->hpos;
+                                       break;
+                               }
+                               /* Calculate 'Header' length. */
+                               section = archive_be32dec(rpm->header+8);
+                               bytes = archive_be32dec(rpm->header+12);
+                               rpm->hlen = 16 + section * 16 + bytes;
+                               rpm->state = ST_HEADER_DATA;
+                               rpm->first_header = 0;
+                       }
+                       break;
+               case ST_HEADER_DATA:
+                       n = rpm->hlen - rpm->hpos;
+                       if (n > avail_in - used)
+                               n = avail_in - used;
+                       b += n;
+                       used += n;
+                       rpm->hpos += n;
+                       if (rpm->hpos == rpm->hlen)
+                               rpm->state = ST_PADDING;
+                       break;
+               case ST_PADDING:
+                       while (used < (size_t)avail_in) {
+                               if (*b != 0) {
+                                       /* Read next header. */
+                                       rpm->state = ST_HEADER;
+                                       rpm->hpos = 0;
+                                       rpm->hlen = 0;
+                                       break;
+                               }
+                               b++;
+                               used++;
+                       }
+                       break;
+               case ST_ARCHIVE:
+                       *buff = b;
+                       total = avail_in;
+                       used = avail_in;
+                       break;
+               }
+               if (used == avail_in) {
+                       rpm->total_in += used;
+                       __archive_read_filter_consume(self->upstream, used);
+                       b = NULL;
+                       used = 0;
+               }
+       } while (total == 0 && avail_in > 0);
+
+       if (used > 0 && b != NULL) {
+               rpm->total_in += used;
+               __archive_read_filter_consume(self->upstream, used);
+       }
+       return (total);
+}
+
+static int
+rpm_filter_close(struct archive_read_filter *self)
+{
+       struct rpm *rpm;
+
+       rpm = (struct rpm *)self->data;
+       free(rpm);
+
+       return (ARCHIVE_OK);
+}
+
index 69f494ccbbd33afb8c8a94dc0b91bb4b730acd0c..86afba358311f543196df1557bde7786128f59e5 100644 (file)
@@ -51,7 +51,9 @@ IF(ENABLE_TEST)
     test_read_format_cpio_bin_lzma.c
     test_read_format_cpio_bin_xz.c
     test_read_format_cpio_odc.c
+    test_read_format_cpio_svr4_bzip2_rpm.c
     test_read_format_cpio_svr4_gzip.c
+    test_read_format_cpio_svr4_gzip_rpm.c
     test_read_format_cpio_svr4c_Z.c
     test_read_format_empty.c
     test_read_format_gtar_gz.c
diff --git a/libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c b/libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c
new file mode 100644 (file)
index 0000000..3b4170c
--- /dev/null
@@ -0,0 +1,127 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2009 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"
+
+/*
+Execute the following command to rebuild the data for this program:
+   tail -n +32 test_read_format_cpio_svr4_bzip2_rpm.c | /bin/sh
+
+F=test_read_format_cpio_svr4_bzip2_rpm.rpm
+NAME=rpmsample
+TMPRPM=/tmp/rpm
+rm -rf ${TMPRPM}
+mkdir -p ${TMPRPM}/BUILD
+mkdir -p ${TMPRPM}/RPMS
+mkdir -p ${TMPRPM}/SOURCES
+mkdir -p ${TMPRPM}/SPECS
+mkdir -p ${TMPRPM}/SRPMS
+echo "hello" > ${TMPRPM}/BUILD/file1
+echo "hello" > ${TMPRPM}/BUILD/file2
+echo "hello" > ${TMPRPM}/BUILD/file3
+cat > ${TMPRPM}/SPECS/${NAME}.spec <<END
+##
+%define _topdir ${TMPRPM}
+%define _binary_payload w9.bzdio
+
+Summary: Sample data of RPM filter of libarchive
+Name: ${NAME}
+Version: 1.0.0
+Release: 1
+License: BSD
+URL: http://code.google.com/p/libarchive
+BuildArch: noarch
+BuildRoot: %{_tmppath}/%{name}-%{version}-root
+
+%install
+rm -rf \$RPM_BUILD_ROOT
+
+mkdir -p \$RPM_BUILD_ROOT%{_sysconfdir}
+install -m 644 file1 \$RPM_BUILD_ROOT%{_sysconfdir}/file1
+install -m 644 file2 \$RPM_BUILD_ROOT%{_sysconfdir}/file2
+install -m 644 file3 \$RPM_BUILD_ROOT%{_sysconfdir}/file3
+TZ=utc touch -afm -t 197001020000.01 \$RPM_BUILD_ROOT%{_sysconfdir}/file1
+TZ=utc touch -afm -t 197001020000.01 \$RPM_BUILD_ROOT%{_sysconfdir}/file2
+TZ=utc touch -afm -t 197001020000.01 \$RPM_BUILD_ROOT%{_sysconfdir}/file3
+
+%files
+%{_sysconfdir}/file1
+%{_sysconfdir}/file2
+%{_sysconfdir}/file3
+
+%description
+Sample data.
+END
+#
+rpmbuild -bb ${TMPRPM}/SPECS/${NAME}.spec
+uuencode ${F} < ${TMPRPM}/RPMS/noarch/${NAME}-1.0.0-1.noarch.rpm > ${F}.uu
+
+rm -rf ${TMPRPM}
+exit 1
+*/
+
+DEFINE_TEST(test_read_format_cpio_svr4_bzip2_rpm)
+{
+       struct archive_entry *ae;
+       struct archive *a;
+       const char *name = "test_read_format_cpio_svr4_bzip2_rpm.rpm";
+       int r;
+
+       assert((a = archive_read_new()) != NULL);
+        r = archive_read_support_compression_bzip2(a);
+       if (r == ARCHIVE_WARN) {
+               skipping("bzip2 reading not fully supported on this platform");
+               assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
+               return;
+        }
+       assertEqualIntA(a, ARCHIVE_OK, r);
+       assertEqualIntA(a, ARCHIVE_OK,
+           archive_read_support_compression_rpm(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, 2));
+
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+       assertEqualString("./etc/file1", archive_entry_pathname(ae));
+       assertEqualInt(86401, archive_entry_mtime(ae));
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+       assertEqualString("./etc/file2", archive_entry_pathname(ae));
+       assertEqualInt(86401, archive_entry_mtime(ae));
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+       assertEqualString("./etc/file3", archive_entry_pathname(ae));
+       assertEqualInt(86401, archive_entry_mtime(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_BZIP2);
+       assertEqualString(archive_compression_name(a), "bzip2");
+       assertEqualInt(archive_format(a), ARCHIVE_FORMAT_CPIO_SVR4_NOCRC);
+       assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+       assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
+}
+
diff --git a/libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.rpm.uu b/libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.rpm.uu
new file mode 100644 (file)
index 0000000..884ca94
--- /dev/null
@@ -0,0 +1,47 @@
+begin 644 test_read_format_cpio_svr4_bzip2_rpm.rpm
+M[:ONVP,``````7)P;7-A;7!L92TQ+C`N,"TQ````````````````````````
+M```````````````````````````````````````````!``4`````````````
+M````````CJWH`0`````````%````5````#X````'````1````!````$-````
+M!@`````````!```#Z`````0````L`````0```^P````'````,````!````/O
+M````!````$`````!,F4X-3)F-39E,#,W83EE.61A9C<W8V(Q,&0P8S4T-65E
+M9&8S-6$U8@````````:<A,!!LG.$S/]SK-(FA0BH6@```@@````^````!___
+M_[`````0`````(ZMZ`$`````````,0```NP````_````!P```MP````0````
+M9`````@``````````0```^@````&`````@````$```/I````!@````P````!
+M```#Z@````8````2`````0```^P````)````%`````$```/M````"0```#P`
+M```!```#[@````0```!,`````0```^\````&````4`````$```/Q````!```
+M`%P````!```#]@````8```!@`````0```_@````)````9`````$```/\````
+M!@```'`````!```#_0````8```"4`````0```_X````&````F@````$```0$
+M````!````*0````#```$!@````,```"P`````P``!`D````#````M@````,`
+M``0*````!````+P````#```$"P````@```#(`````P``!`P````(```!*P``
+M``,```0-````!````3`````#```$#P````@```$\`````P``!!`````(```!
+M2P````,```04````!@```5H````!```$%0````0```%T`````P``!!<````(
+M```!@`````$```08````!````8P````#```$&0````@```&8`````P``!!H`
+M```(```!Z@````,```0H````!@```@`````!```$1P````0```((`````P``
+M!$@````$```"%`````,```1)````"````B`````#```$6`````0```(D````
+M`0``!%D````(```"*`````$```1<````!````C`````#```$70````@```(\
+M`````P``!%X````(```"3@````$```1B````!@```E0````!```$9`````8`
+M``)S`````0``!&4````&```">`````$```1F````!@```GX````!```$;```
+M``8```*``````0``!'0````$```"E`````,```1U````!````J`````#```$
+M=@````@```*L`````P``!'<````$```"Q`````,```1X````!````M`````#
+M0P!R<&US86UP;&4`,2XP+C``,0!386UP;&4@9&%T82!O9B!24$T@9FEL=&5R
+M(&]F(&QI8F%R8VAI=F4`4V%M<&QE(&1A=&$N`````$L)MWQC=64M9&5S:W1O
+M<``````20E-$`%5N<W!E8VEF:65D`&AT='`Z+R]C;V1E+F=O;V=L92YC;VTO
+M<"]L:6)A<F-H:79E`&QI;G5X`&YO87)C:``````````&````!@````:!I(&D
+M@:0``````````5&!``%1@0`!48%B,3DT-F%C.3(T.3)D,C,T-V,V,C,U8C1D
+M,C8Q,3$X-`!B,3DT-F%C.3(T.3)D,C,T-V,V,C,U8C1D,C8Q,3$X-`!B,3DT
+M-F%C.3(T.3)D,C,T-V,V,C,U8C1D,C8Q,3$X-```````````````````````
+M`')O;W0`<F]O=`!R;V]T`')O;W0`<F]O=`!R;V]T`')P;7-A;7!L92TQ+C`N
+M,"TQ+G-R8RYR<&T`________________<G!M<V%M<&QE`````0``2@$``$H!
+M``!*<G!M;&EB*$-O;7!R97-S961&:6QE3F%M97,I`')P;6QI8BA087EL;V%D
+M1FEL97-(879E4')E9FEX*0!R<&UL:6(H4&%Y;&]A9$ES0GII<#(I`#,N,"XT
+M+3$`-"XP+3$`,RXP+C4M,0`T+C<N,```````"`$```@!```(`0``*H<``"J(
+M```JB0`````````(,2XP+C`M,0````````````````!F:6QE,0!F:6QE,@!F
+M:6QE,P`O971C+P`M3S(@+6<@+6UA<F-H/6DS.#8@+6UT=6YE/6DV.#8`8W!I
+M;P!B>FEP,@`Y`&YO87)C:"UR<&TM;&EN=7@`````````````````````````
+M`0````$````!`$%30TE)('1E>'0`9&ER96-T;W)Y````````````````````
+M````````````````````/P````?___SP````$$)::#DQ05DF4UFX89DX``!=
+M?X!,$`@`*`'_X"(D%``[9(0`(`"2B/50T#0#0`](9!%(C1,0&GJ`R`M@PQRG
+M<PN0PPC]8&X[2P=KHS%0Q<^=89M6CI5L`O2\("`W!K-V.;*M63U;6ES%CQI6
+E4,1$DE)B@G&.7I5?NT46(XB0/D,B!$Z-!A_B[DBG"A(7##,G````
+`
+end
diff --git a/libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c b/libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c
new file mode 100644 (file)
index 0000000..eb8a38d
--- /dev/null
@@ -0,0 +1,127 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2009 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"
+
+/*
+Execute the following command to rebuild the data for this program:
+   tail -n +32 test_read_format_cpio_svr4_gzip_rpm.c | /bin/sh
+
+F=test_read_format_cpio_svr4_gzip_rpm.rpm
+NAME=rpmsample
+TMPRPM=/tmp/rpm
+rm -rf ${TMPRPM}
+mkdir -p ${TMPRPM}/BUILD
+mkdir -p ${TMPRPM}/RPMS
+mkdir -p ${TMPRPM}/SOURCES
+mkdir -p ${TMPRPM}/SPECS
+mkdir -p ${TMPRPM}/SRPMS
+echo "hello" > ${TMPRPM}/BUILD/file1
+echo "hello" > ${TMPRPM}/BUILD/file2
+echo "hello" > ${TMPRPM}/BUILD/file3
+cat > ${TMPRPM}/SPECS/${NAME}.spec <<END
+##
+%define _topdir ${TMPRPM}
+%define _binary_payload w9.gzdio
+
+Summary: Sample data of RPM filter of libarchive
+Name: ${NAME}
+Version: 1.0.0
+Release: 1
+License: BSD
+URL: http://code.google.com/p/libarchive
+BuildArch: noarch
+BuildRoot: %{_tmppath}/%{name}-%{version}-root
+
+%install
+rm -rf \$RPM_BUILD_ROOT
+
+mkdir -p \$RPM_BUILD_ROOT%{_sysconfdir}
+install -m 644 file1 \$RPM_BUILD_ROOT%{_sysconfdir}/file1
+install -m 644 file2 \$RPM_BUILD_ROOT%{_sysconfdir}/file2
+install -m 644 file3 \$RPM_BUILD_ROOT%{_sysconfdir}/file3
+TZ=utc touch -afm -t 197001020000.01 \$RPM_BUILD_ROOT%{_sysconfdir}/file1
+TZ=utc touch -afm -t 197001020000.01 \$RPM_BUILD_ROOT%{_sysconfdir}/file2
+TZ=utc touch -afm -t 197001020000.01 \$RPM_BUILD_ROOT%{_sysconfdir}/file3
+
+%files
+%{_sysconfdir}/file1
+%{_sysconfdir}/file2
+%{_sysconfdir}/file3
+
+%description
+Sample data.
+END
+#
+rpmbuild -bb ${TMPRPM}/SPECS/${NAME}.spec
+uuencode ${F} < ${TMPRPM}/RPMS/noarch/${NAME}-1.0.0-1.noarch.rpm > ${F}.uu
+
+rm -rf ${TMPRPM}
+exit 1
+*/
+
+DEFINE_TEST(test_read_format_cpio_svr4_gzip_rpm)
+{
+       struct archive_entry *ae;
+       struct archive *a;
+       const char *name = "test_read_format_cpio_svr4_gzip_rpm.rpm";
+       int r;
+
+       assert((a = archive_read_new()) != NULL);
+        r = archive_read_support_compression_gzip(a);
+       if (r == ARCHIVE_WARN) {
+               skipping("gzip reading not fully supported on this platform");
+               assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
+               return;
+        }
+       assertEqualIntA(a, ARCHIVE_OK, r);
+       assertEqualIntA(a, ARCHIVE_OK,
+           archive_read_support_compression_rpm(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, 2));
+
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+       assertEqualString("./etc/file1", archive_entry_pathname(ae));
+       assertEqualInt(86401, archive_entry_mtime(ae));
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+       assertEqualString("./etc/file2", archive_entry_pathname(ae));
+       assertEqualInt(86401, archive_entry_mtime(ae));
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+       assertEqualString("./etc/file3", archive_entry_pathname(ae));
+       assertEqualInt(86401, archive_entry_mtime(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_GZIP);
+       assertEqualString(archive_compression_name(a), "gzip");
+       assertEqualInt(archive_format(a), ARCHIVE_FORMAT_CPIO_SVR4_NOCRC);
+       assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+       assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
+}
+
diff --git a/libarchive/test/test_read_format_cpio_svr4_gzip_rpm.rpm.uu b/libarchive/test/test_read_format_cpio_svr4_gzip_rpm.rpm.uu
new file mode 100644 (file)
index 0000000..54d305b
--- /dev/null
@@ -0,0 +1,46 @@
+begin 644 test_read_format_cpio_svr4_gzip_rpm.rpm
+M[:ONVP,``````7)P;7-A;7!L92TQ+C`N,"TQ````````````````````````
+M```````````````````````````````````````````!``4`````````````
+M````````CJWH`0`````````%````5````#X````'````1````!````$-````
+M!@`````````!```#Z`````0````L`````0```^P````'````,````!````/O
+M````!````$`````!9&9E8V,W,#4T,C@X,V1D-&8P-6%E.#4Y,S<S,&1F,V)D
+M,#$Q,S0V80````````9=A5.[L^@5U91731!5GLHZC0```@@````^````!___
+M_[`````0`````(ZMZ`$`````````,0```L0````_````!P```K0````0````
+M9`````@``````````0```^@````&`````@````$```/I````!@````P````!
+M```#Z@````8````2`````0```^P````)````%`````$```/M````"0```#P`
+M```!```#[@````0```!,`````0```^\````&````4`````$```/Q````!```
+M`%P````!```#]@````8```!@`````0```_@````)````9`````$```/\````
+M!@```'`````!```#_0````8```"4`````0```_X````&````F@````$```0$
+M````!````*0````#```$!@````,```"P`````P``!`D````#````M@````,`
+M``0*````!````+P````#```$"P````@```#(`````P``!`P````(```!*P``
+M``,```0-````!````3`````#```$#P````@```$\`````P``!!`````(```!
+M2P````,```04````!@```5H````!```$%0````0```%T`````P``!!<````(
+M```!@`````$```08````!````8P````"```$&0````@```&4`````@``!!H`
+M```(```!SP````(```0H````!@```=T````!```$1P````0```'D`````P``
+M!$@````$```!\`````,```1)````"````?P````#```$6`````0```(`````
+M`0``!%D````(```"!`````$```1<````!````@P````#```$70````@```(8
+M`````P``!%X````(```"*@````$```1B````!@```C`````!```$9`````8`
+M``)/`````0``!&4````&```"5`````$```1F````!@```ED````!```$;```
+M``8```);`````0``!'0````$```";`````,```1U````!````G@````#```$
+M=@````@```*$`````P``!'<````$```"G`````,```1X````!````J@````#
+M0P!R<&US86UP;&4`,2XP+C``,0!386UP;&4@9&%T82!O9B!24$T@9FEL=&5R
+M(&]F(&QI8F%R8VAI=F4`4V%M<&QE(&1A=&$N`````$L)MAUC=64M9&5S:W1O
+M<``````20E-$`%5N<W!E8VEF:65D`&AT='`Z+R]C;V1E+F=O;V=L92YC;VTO
+M<"]L:6)A<F-H:79E`&QI;G5X`&YO87)C:``````````&````!@````:!I(&D
+M@:0``````````5&!``%1@0`!48%B,3DT-F%C.3(T.3)D,C,T-V,V,C,U8C1D
+M,C8Q,3$X-`!B,3DT-F%C.3(T.3)D,C,T-V,V,C,U8C1D,C8Q,3$X-`!B,3DT
+M-F%C.3(T.3)D,C,T-V,V,C,U8C1D,C8Q,3$X-```````````````````````
+M`')O;W0`<F]O=`!R;V]T`')O;W0`<F]O=`!R;V]T`')P;7-A;7!L92TQ+C`N
+M,"TQ+G-R8RYR<&T`________________<G!M<V%M<&QE`````0``2@$``$IR
+M<&UL:6(H0V]M<')E<W-E9$9I;&5.86UE<RD`<G!M;&EB*%!A>6QO861&:6QE
+M<TAA=F50<F5F:7@I`#,N,"XT+3$`-"XP+3$`-"XW+C``````"`$```@!```(
+M`0``*H<``"J(```JB0`````````(,2XP+C`M,0````````````````!F:6QE
+M,0!F:6QE,@!F:6QE,P`O971C+P`M3S(@+6<@+6UA<F-H/6DS.#8@+6UT=6YE
+M/6DV.#8`8W!I;P!G>FEP`#D`;F]A<F-H+7)P;2UL:6YU>```````````````
+M```````!`````0````$`05-#24D@=&5X=`!D:7)E8W1O<GD`````````````
+M```````````````````````````_````!____/`````0'XL(```````"`S,P
+M-S`W,#0``J-$"W,0;6&8:&*`'8#4&9H:6AA"^690V@))'AM(AC'T]%-+DO73
+M,G-2#1D8&#)2<W+RN1@8#)#=8$$_-QCA<H,E_=Q@C-4-1`!BU:&#)!@C),C1
+3T\<U2%%1$>@$!@"1O'?9"`(`````
+`
+end