Import libarchive-2.8.4.
authorPeter Avalos <pavalos@dragonflybsd.org>
Wed, 15 Dec 2010 08:07:20 +0000 (22:07 -1000)
committerPeter Avalos <pavalos@dragonflybsd.org>
Wed, 15 Dec 2010 08:51:20 +0000 (22:51 -1000)
115 files changed:
contrib/libarchive/COPYING
contrib/libarchive/NEWS
contrib/libarchive/README
contrib/libarchive/README.DELETED
contrib/libarchive/build/version
contrib/libarchive/cpio/bsdcpio.1
contrib/libarchive/cpio/cmdline.c
contrib/libarchive/cpio/cpio.c
contrib/libarchive/cpio/cpio.h
contrib/libarchive/cpio/cpio_platform.h
contrib/libarchive/libarchive/COPYING [deleted file]
contrib/libarchive/libarchive/README [deleted file]
contrib/libarchive/libarchive/archive.h
contrib/libarchive/libarchive/archive_check_magic.c
contrib/libarchive/libarchive/archive_endian.h
contrib/libarchive/libarchive/archive_entry.c
contrib/libarchive/libarchive/archive_entry.h
contrib/libarchive/libarchive/archive_entry_copy_bhfi.c [copied from contrib/libarchive/libarchive/archive_virtual.c with 51% similarity]
contrib/libarchive/libarchive/archive_entry_copy_stat.c
contrib/libarchive/libarchive/archive_entry_link_resolver.c
contrib/libarchive/libarchive/archive_entry_private.h
contrib/libarchive/libarchive/archive_entry_stat.c
contrib/libarchive/libarchive/archive_entry_xattr.c [new file with mode: 0644]
contrib/libarchive/libarchive/archive_hash.h [new file with mode: 0644]
contrib/libarchive/libarchive/archive_platform.h
contrib/libarchive/libarchive/archive_private.h
contrib/libarchive/libarchive/archive_read.3
contrib/libarchive/libarchive/archive_read.c
contrib/libarchive/libarchive/archive_read_disk.3
contrib/libarchive/libarchive/archive_read_disk.c
contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c
contrib/libarchive/libarchive/archive_read_disk_private.h
contrib/libarchive/libarchive/archive_read_disk_set_standard_lookup.c
contrib/libarchive/libarchive/archive_read_open_fd.c
contrib/libarchive/libarchive/archive_read_open_file.c
contrib/libarchive/libarchive/archive_read_open_filename.c
contrib/libarchive/libarchive/archive_read_private.h
contrib/libarchive/libarchive/archive_read_support_compression_all.c
contrib/libarchive/libarchive/archive_read_support_compression_bzip2.c
contrib/libarchive/libarchive/archive_read_support_compression_compress.c
contrib/libarchive/libarchive/archive_read_support_compression_gzip.c
contrib/libarchive/libarchive/archive_read_support_compression_none.c
contrib/libarchive/libarchive/archive_read_support_compression_program.c
contrib/libarchive/libarchive/archive_read_support_compression_rpm.c [new file with mode: 0644]
contrib/libarchive/libarchive/archive_read_support_compression_uu.c [new file with mode: 0644]
contrib/libarchive/libarchive/archive_read_support_compression_xz.c
contrib/libarchive/libarchive/archive_read_support_format_all.c
contrib/libarchive/libarchive/archive_read_support_format_ar.c
contrib/libarchive/libarchive/archive_read_support_format_cpio.c
contrib/libarchive/libarchive/archive_read_support_format_empty.c
contrib/libarchive/libarchive/archive_read_support_format_iso9660.c
contrib/libarchive/libarchive/archive_read_support_format_mtree.c
contrib/libarchive/libarchive/archive_read_support_format_raw.c [new file with mode: 0644]
contrib/libarchive/libarchive/archive_read_support_format_tar.c
contrib/libarchive/libarchive/archive_read_support_format_xar.c [new file with mode: 0644]
contrib/libarchive/libarchive/archive_read_support_format_zip.c
contrib/libarchive/libarchive/archive_string.c
contrib/libarchive/libarchive/archive_string.h
contrib/libarchive/libarchive/archive_string_sprintf.c
contrib/libarchive/libarchive/archive_util.3
contrib/libarchive/libarchive/archive_util.c
contrib/libarchive/libarchive/archive_virtual.c
contrib/libarchive/libarchive/archive_write.3
contrib/libarchive/libarchive/archive_write.c
contrib/libarchive/libarchive/archive_write_disk.c
contrib/libarchive/libarchive/archive_write_disk_private.h
contrib/libarchive/libarchive/archive_write_disk_set_standard_lookup.c
contrib/libarchive/libarchive/archive_write_open_fd.c
contrib/libarchive/libarchive/archive_write_open_filename.c
contrib/libarchive/libarchive/archive_write_private.h
contrib/libarchive/libarchive/archive_write_set_compression_bzip2.c
contrib/libarchive/libarchive/archive_write_set_compression_compress.c
contrib/libarchive/libarchive/archive_write_set_compression_gzip.c
contrib/libarchive/libarchive/archive_write_set_compression_none.c
contrib/libarchive/libarchive/archive_write_set_compression_program.c
contrib/libarchive/libarchive/archive_write_set_compression_xz.c
contrib/libarchive/libarchive/archive_write_set_format.c
contrib/libarchive/libarchive/archive_write_set_format_ar.c
contrib/libarchive/libarchive/archive_write_set_format_by_name.c
contrib/libarchive/libarchive/archive_write_set_format_cpio.c
contrib/libarchive/libarchive/archive_write_set_format_cpio_newc.c
contrib/libarchive/libarchive/archive_write_set_format_mtree.c
contrib/libarchive/libarchive/archive_write_set_format_pax.c
contrib/libarchive/libarchive/archive_write_set_format_shar.c
contrib/libarchive/libarchive/archive_write_set_format_ustar.c
contrib/libarchive/libarchive/archive_write_set_format_zip.c [new file with mode: 0644]
contrib/libarchive/libarchive/filter_fork.c
contrib/libarchive/libarchive/filter_fork.h
contrib/libarchive/libarchive/libarchive-formats.5
contrib/libarchive/libarchive/libarchive_internals.3
contrib/libarchive/libarchive/tar.5
contrib/libarchive/libarchive_fe/err.c [copied from contrib/libarchive/cpio/err.c with 85% similarity]
contrib/libarchive/libarchive_fe/err.h [copied from contrib/libarchive/libarchive/filter_fork.h with 75% similarity]
contrib/libarchive/libarchive_fe/lafe_platform.h [moved from contrib/libarchive/cpio/err.c with 63% similarity]
contrib/libarchive/libarchive_fe/line_reader.c [new file with mode: 0644]
contrib/libarchive/libarchive_fe/line_reader.h [copied from contrib/libarchive/cpio/matching.h with 76% similarity]
contrib/libarchive/libarchive_fe/matching.c [moved from contrib/libarchive/cpio/matching.c with 63% similarity]
contrib/libarchive/libarchive_fe/matching.h [moved from contrib/libarchive/cpio/matching.h with 69% similarity]
contrib/libarchive/libarchive_fe/pathmatch.c [moved from contrib/libarchive/cpio/pathmatch.c with 94% similarity]
contrib/libarchive/libarchive_fe/pathmatch.h [moved from contrib/libarchive/cpio/pathmatch.h with 91% similarity]
contrib/libarchive/tar/COPYING [deleted file]
contrib/libarchive/tar/bsdtar.1
contrib/libarchive/tar/bsdtar.c
contrib/libarchive/tar/bsdtar.h
contrib/libarchive/tar/bsdtar_platform.h
contrib/libarchive/tar/cmdline.c
contrib/libarchive/tar/getdate.c
contrib/libarchive/tar/matching.c [deleted file]
contrib/libarchive/tar/read.c
contrib/libarchive/tar/siginfo.c [deleted file]
contrib/libarchive/tar/subst.c
contrib/libarchive/tar/tree.c
contrib/libarchive/tar/tree.h
contrib/libarchive/tar/util.c
contrib/libarchive/tar/write.c

index ec7d6c4..9dbf49d 100644 (file)
@@ -22,7 +22,7 @@ the actual statements in the files are controlling.
    tar/matching.c
 
 * The following source files are in the public domain:
-   tar/getdate.y
+   tar/getdate.c
 
 * The build files---including Makefiles, configure scripts,
   and auxiliary scripts used as part of the compile process---have
@@ -35,7 +35,7 @@ do use the license below.  The varying licensing of the build scripts
 seems to be an unavoidable mess.
 
 
-Copyright (c) 2003-2008 <author(s)>
+Copyright (c) 2003-2009 <author(s)>
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
index 68700b7..b1d83e3 100644 (file)
@@ -1,6 +1,35 @@
+Jun 30, 2010: libarchive 2.8.4 released
+Jun 30, 2010: Improved reliability of hash function detection
+Jun 30, 2010: Fix issues on ancient FreeBSD, QNX, ancient NetBSD and Minux
 
-Aug 04, 2009: libarchive 2.7.1 released
+Mar 14, 2010: libarchive 2.8.3 released
+Mar 14, 2010: Symlink dereference fix for Linux broke the build there; corrected.
+
+Mar 14, 2010: libarchive 2.8.2 released
+Mar 12, 2010: Fix NULL deference for short self-extracting zip archives.
+Mar 12, 2010: Don't dereference symlinks on Linux when reading ACLs.
+Mar 07, 2010: Better detection of SHA2 support for old OpenSSL versions.
+Mar 07, 2010: Fix parsing of input files for bsdtar -T.
+Mar 07, 2010: Do not leak setup_xattr into the global namespace.
+
+Mar 06, 2010: libarchive 2.8.1 released
+Mar 06, 2010: Fix build when an older libarchive is already installed
+Mar 03, 2010: Use O_BINARY opening files in bsdtar
+Mar 02, 2010: Include missing archive_crc32.h
+Mar 01, 2010: Correctly include iconv.h required by libxml2.
+
+Feb 04, 2010: libarchive 2.8.0 released
+Jan 17, 2010: Fix error handling for 'echo nonexistent | cpio -o'
+Jan 17, 2010: Don't use futimes() on Cygwin
 
+Jan 02, 2010: libarchive 2.7.902a released (test release for 2.8)
+Jan 02, 2010: Fix tar/test/test_windows on MinGW
+Jan 02, 2010: Fix memory leaks in libarchive tests
+Jan 01, 2010: Fix memory leak when filter startup fails
+
+Dec 27, 2009: libarchive 2.7.901a released (test release for 2.8)
+
+Aug 04, 2009: libarchive 2.7.1 released
 Jul 20, 2009: Suppress bogus warning about unxz
 Jul 19, 2009: Support Cygwin 1.7
 Jun 11, 2009: Support lzma/xz files compressed with larger buffer sizes.
index 07fb359..03e47e8 100644 (file)
@@ -6,7 +6,6 @@ Questions?  Issues?
      documentation, and links to the libarchive mailing lists.
 
 This distribution bundle includes the following components:
-
    * libarchive: a library for reading and writing streaming archives
    * tar: the 'bsdtar' program is a full-featured 'tar'
           replacement built on libarchive
@@ -29,7 +28,6 @@ The top-level directory contains the following information files:
 
 The following files in the top-level directory are used by the
 'configure' script:
-
    * Makefile.am, aclocal.m4, configure.ac
        - used to build this distribution, only needed by maintainers
    * Makefile.in, config.h.in
@@ -39,19 +37,22 @@ Guide to Documentation installed by this system:
  * bsdtar.1 explains the use of the bsdtar program
  * bsdcpio.1 explains the use of the bsdcpio program
  * libarchive.3 gives an overview of the library as a whole
- * archive_read.3, archive_write.3, and archive_write_disk.3 provide
-   detailed calling sequences for the read and write APIs
+ * archive_read.3, archive_write.3, archive_write_disk.3, and
+   archive_read_disk.3 provide detailed calling sequences for the read
+   and write APIs
  * archive_entry.3 details the "struct archive_entry" utility class
  * archive_internals.3 provides some insight into libarchive's
    internal structure and operation.
  * libarchive-formats.5 documents the file formats supported by the library
- * cpio.5, mtree.5, and tar.5 provide detailed information about a
-   variety of different archive formats, including hard-to-find details
-   about modern cpio and tar variants.
+ * cpio.5, mtree.5, and tar.5 provide detailed information about these
+   popular archive formats, including hard-to-find details about
+   modern cpio and tar variants.
+The manual pages above are provided in the 'doc' directory in
+a number of different formats.
 
-You should also read the copious comments in "archive.h" and the source
-code for the sample "bsdtar" program for more details.  Please let me know
-about any errors or omissions you find.
+You should also read the copious comments in "archive.h" and the
+source code for the sample programs for more details.  Please let me
+know about any errors or omissions you find.
 
 Currently, the library automatically detects and reads the following:
   * gzip compression
@@ -66,6 +67,7 @@ Currently, the library automatically detects and reads the following:
   * POSIX pax interchange format
   * POSIX octet-oriented cpio
   * SVR4 ASCII cpio
+  * POSIX octet-oriented cpio
   * Binary cpio (big-endian or little-endian)
   * ISO9660 CD-ROM images (with optional Rockridge or Joliet extensions)
   * ZIP archives (with uncompressed or "deflate" compressed entries)
@@ -84,20 +86,20 @@ The library can write:
   * POSIX octet-oriented cpio
   * SVR4 "newc" cpio
   * shar archives
+  * ZIP archives (with uncompressed or "deflate" compressed entries)
   * GNU and BSD 'ar' archives
   * 'mtree' format
 
 Notes about the library architecture:
 
  * This is a heavily stream-oriented system.  There is no direct
-   support for in-place modification or random access and no intention
-   of ever adding such support.  Adding such support would require
-   sacrificing a lot of other features, so don't bother asking.
+   support for in-place modification or random access.
 
  * The library is designed to be extended with new compression and
    archive formats.  The only requirement is that the format be
    readable or writable as a stream and that each archive entry be
-   independent.
+   independent.  There are articles on the libarchive Wiki explaining
+   how to extend libarchive.
 
  * On read, compression and format are always detected automatically.
 
index 409636e..7886d32 100644 (file)
@@ -2,12 +2,13 @@ CMakeLists.txt
 INSTALL
 Makefile.am
 Makefile.in
-PROJECTS
 aclocal.m4
 build/autoconf/
 build/autogen.sh
+build/bump-version.sh
+build/clean.sh
 build/cmake/
-build/release.sh
+build/pkgconfig/
 build/windows/
 config.h.in
 configure
@@ -15,23 +16,19 @@ configure.ac
 contrib/
 cpio/CMakeLists.txt
 cpio/config_freebsd.h
-cpio/cpio_cygwin.c
-cpio/cpio_cygwin.h
 cpio/cpio_windows.c
 cpio/cpio_windows.h
 cpio/test/
 doc/
 examples/
 libarchive/CMakeLists.txt
+libarchive/archive_crc32.h
 libarchive/archive_windows.c
 libarchive/archive_windows.h
 libarchive/config_freebsd.h
-libarchive/config_windows.h
 libarchive/filter_fork_windows.c
 libarchive/test/
 tar/CMakeLists.txt
-tar/bsdtar_cygwin.c
-tar/bsdtar_cygwin.h
 tar/bsdtar_windows.c
 tar/bsdtar_windows.h
 tar/config_freebsd.h
index 81b3462..79b6997 100644 (file)
@@ -80,6 +80,9 @@ specified directory.
 Unless specifically stated otherwise, options are applicable in
 all operating modes.
 .Bl -tag -width indent
+.It Fl 0
+Read filenames separated by NUL characters instead of newlines.
+This is necessary if any of the filenames being read might contain newlines.
 .It Fl A
 (o mode only)
 Append to the specified archive.
@@ -142,6 +145,11 @@ for more complete information about the
 formats currently supported by the underlying
 .Xr libarchive 3
 library.
+.It Fl H Ar format
+Synonym for
+.Fl -format .
+.It Fl h , Fl -help
+Print usage information.
 .It Fl I Ar file
 Read archive from
 .Ar file .
@@ -154,6 +162,14 @@ Disable security checks during extraction or copying.
 This allows extraction via symbolic links and path names containing
 .Sq ..
 in the name.
+.It Fl J
+(o mode only)
+Compress the file with xz-compatible compression before writing it.
+In input mode, this option is ignored; xz compression is recognized
+automatically on input.
+.It Fl j
+Synonym for
+.Fl y .
 .It Fl L
 (o and p modes)
 All symbolic links will be followed.
@@ -163,6 +179,11 @@ With this option, the target of the link will be archived or copied instead.
 (p mode only)
 Create links from the target directory to the original files,
 instead of copying.
+.It Fl lzma
+(o mode only)
+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 m
 (i and p modes)
 Set file modification time on created files to match
@@ -176,6 +197,10 @@ By default,
 displays the user and group names when they are provided in the
 archive, or looks up the user and group names in the system
 password database.
+.It Fl no-preserve-owner
+(i mode only)
+Do not attempt to restore file ownership.
+This is the default when run by non-root users.
 .It Fl O Ar file
 Write archive to
 .Ar file .
@@ -185,6 +210,10 @@ See above for description.
 .It Fl p
 Pass-through mode.
 See above for description.
+.It Fl preserve-owner
+(i mode only)
+Restore file ownership.
+This is the default when run by the root user.
 .It Fl -quiet
 Suppress unnecessary messages.
 .It Fl R Oo user Oc Ns Oo : Oc Ns Oo group Oc
index edcd8ba..2223798 100644 (file)
@@ -46,11 +46,12 @@ __FBSDID("$FreeBSD: src/usr.bin/cpio/cmdline.c,v 1.5 2008/12/06 07:30:40 kientzl
 #endif
 
 #include "cpio.h"
+#include "err.h"
 
 /*
  * Short options for cpio.  Please keep this sorted.
  */
-static const char *short_options = "0AaBC:F:O:cdE:f:H:hI:ijLlmnopR:rtuvW:yZz";
+static const char *short_options = "0AaBC:cdE:F:f:H:hI:iJjLlmnO:opR:rtuvW:yZz";
 
 /*
  * Long options for cpio.  Please keep this sorted.
@@ -68,6 +69,7 @@ static const struct option {
        { "insecure",                   0, OPTION_INSECURE },
        { "link",                       0, 'l' },
        { "list",                       0, 't' },
+       { "lzma",                       0, OPTION_LZMA },
        { "make-directories",           0, 'd' },
        { "no-preserve-owner",          0, OPTION_NO_PRESERVE_OWNER },
        { "null",                       0, '0' },
@@ -75,10 +77,12 @@ static const struct option {
        { "owner",                      1, 'R' },
        { "pass-through",               0, 'p' },
        { "preserve-modification-time", 0, 'm' },
+       { "preserve-owner",             0, OPTION_PRESERVE_OWNER },
        { "quiet",                      0, OPTION_QUIET },
        { "unconditional",              0, 'u' },
        { "verbose",                    0, 'v' },
        { "version",                    0, OPTION_VERSION },
+       { "xz",                         0, 'J' },
        { NULL, 0, 0 }
 };
 
@@ -171,7 +175,7 @@ cpio_getopt(struct cpio *cpio)
                                /* Otherwise, pick up the next word. */
                                opt_word = *cpio->argv;
                                if (opt_word == NULL) {
-                                       cpio_warnc(0,
+                                       lafe_warnc(0,
                                            "Option -%c requires an argument",
                                            opt);
                                        return ('?');
@@ -222,13 +226,13 @@ cpio_getopt(struct cpio *cpio)
 
                /* Fail if there wasn't a unique match. */
                if (match == NULL) {
-                       cpio_warnc(0,
+                       lafe_warnc(0,
                            "Option %s%s is not supported",
                            long_prefix, opt_word);
                        return ('?');
                }
                if (match2 != NULL) {
-                       cpio_warnc(0,
+                       lafe_warnc(0,
                            "Ambiguous option %s%s (matches --%s and --%s)",
                            long_prefix, opt_word, match->name, match2->name);
                        return ('?');
@@ -240,7 +244,7 @@ cpio_getopt(struct cpio *cpio)
                        if (cpio->optarg == NULL) {
                                cpio->optarg = *cpio->argv;
                                if (cpio->optarg == NULL) {
-                                       cpio_warnc(0,
+                                       lafe_warnc(0,
                                            "Option %s%s requires an argument",
                                            long_prefix, match->name);
                                        return ('?');
@@ -251,7 +255,7 @@ cpio_getopt(struct cpio *cpio)
                } else {
                        /* Argument forbidden: fail if there is one. */
                        if (cpio->optarg != NULL) {
-                               cpio_warnc(0,
+                               lafe_warnc(0,
                                    "Option %s%s does not allow an argument",
                                    long_prefix, match->name);
                                return ('?');
@@ -268,24 +272,35 @@ cpio_getopt(struct cpio *cpio)
  * Parse the argument to the -R or --owner flag.
  *
  * The format is one of the following:
- *   <user>    - Override user but not group
- *   <user>:   - Override both, group is user's default group
- *   <user>:<group> - Override both
- *   :<group>  - Override group but not user
+ *   <username|uid>    - Override user but not group
+ *   <username>:   - Override both, group is user's default group
+ *   <uid>:    - Override user but not group
+ *   <username|uid>:<groupname|gid> - Override both
+ *   :<groupname|gid>  - Override group but not user
+ *
+ * Where uid/gid are decimal representations and groupname/username
+ * are names to be looked up in system database.  Note that we try
+ * to look up an argument as a name first, then try numeric parsing.
  *
  * A period can be used instead of the colon.
  *
- * Sets uid/gid as appropriate, -1 indicates uid/gid not specified.
+ * Sets uid/gid return as appropriate, -1 indicates uid/gid not specified.
+ *
+ * Returns NULL if no error, otherwise returns error string for display.
  *
  */
-int
+const char *
 owner_parse(const char *spec, int *uid, int *gid)
 {
+       static char errbuff[128];
        const char *u, *ue, *g;
 
        *uid = -1;
        *gid = -1;
 
+       if (spec[0] == '\0')
+               return ("Invalid empty user/group spec");
+
        /*
         * Split spec into [user][:.][group]
         *  u -> first char of username, NULL if no username
@@ -312,31 +327,43 @@ owner_parse(const char *spec, int *uid, int *gid)
                struct passwd *pwent;
 
                user = (char *)malloc(ue - u + 1);
-               if (user == NULL) {
-                       cpio_warnc(errno, "Couldn't allocate memory");
-                       return (1);
-               }
+               if (user == NULL)
+                       return ("Couldn't allocate memory");
                memcpy(user, u, ue - u);
                user[ue - u] = '\0';
-               pwent = getpwnam(user);
-               if (pwent == NULL) {
-                       cpio_warnc(errno, "Couldn't lookup user ``%s''", user);
-                       return (1);
+               if ((pwent = getpwnam(user)) != NULL) {
+                       *uid = pwent->pw_uid;
+                       if (*ue != '\0')
+                               *gid = pwent->pw_gid;
+               } else {
+                       char *end;
+                       errno = 0;
+                       *uid = strtoul(user, &end, 10);
+                       if (errno || *end != '\0') {
+                               snprintf(errbuff, sizeof(errbuff),
+                                   "Couldn't lookup user ``%s''", user);
+                               errbuff[sizeof(errbuff) - 1] = '\0';
+                               return (errbuff);
+                       }
                }
                free(user);
-               *uid = pwent->pw_uid;
-               if (*ue != '\0' && *g == '\0')
-                       *gid = pwent->pw_gid;
        }
+
        if (*g != '\0') {
                struct group *grp;
-               grp = getgrnam(g);
-               if (grp != NULL)
+               if ((grp = getgrnam(g)) != NULL) {
                        *gid = grp->gr_gid;
-               else {
-                       cpio_warnc(errno, "Couldn't look up group ``%s''", g);
-                       return (1);
+               } else {
+                       char *end;
+                       errno = 0;
+                       *gid = strtoul(g, &end, 10);
+                       if (errno || *end != '\0') {
+                               snprintf(errbuff, sizeof(errbuff),
+                                   "Couldn't lookup group ``%s''", g);
+                               errbuff[sizeof(errbuff) - 1] = '\0';
+                               return (errbuff);
+                       }
                }
        }
-       return (0);
+       return (NULL);
 }
index e5b40c9..7d5031b 100644 (file)
@@ -56,6 +56,9 @@ __FBSDID("$FreeBSD: src/usr.bin/cpio/cpio.c,v 1.15 2008/12/06 07:30:40 kientzle
 #ifdef HAVE_STDARG_H
 #include <stdarg.h>
 #endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
 #include <stdio.h>
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
@@ -74,11 +77,17 @@ __FBSDID("$FreeBSD: src/usr.bin/cpio/cpio.c,v 1.15 2008/12/06 07:30:40 kientzle
 #endif
 
 #include "cpio.h"
+#include "err.h"
+#include "line_reader.h"
 #include "matching.h"
 
 /* Fixed size of uname/gname caches. */
 #define        name_cache_size 101
 
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
 struct name_cache {
        int     probes;
        int     hits;
@@ -89,7 +98,8 @@ struct name_cache {
        } cache[name_cache_size];
 };
 
-static int     copy_data(struct archive *, struct archive *);
+static int     extract_data(struct archive *, struct archive *);
+const char *   cpio_i64toa(int64_t);
 static const char *cpio_rename(const char *name);
 static int     entry_to_archive(struct cpio *, struct archive_entry *);
 static int     file_to_archive(struct cpio *, const char *);
@@ -117,6 +127,7 @@ main(int argc, char *argv[])
        static char buff[16384];
        struct cpio _cpio; /* Allocated on stack. */
        struct cpio *cpio;
+       const char *errmsg;
        int uid, gid;
        int opt;
 
@@ -124,33 +135,26 @@ main(int argc, char *argv[])
        memset(cpio, 0, sizeof(*cpio));
        cpio->buff = buff;
        cpio->buff_size = sizeof(buff);
-#if defined(_WIN32) && !defined(__CYGWIN__)
-       /* Make sure open() function will be used with a binary mode. */
-       /* on cygwin, we need something similar, but instead link against */
-       /* a special startup object, binmode.o */
-       _set_fmode(_O_BINARY);
-#endif
 
-       /* Need cpio_progname before calling cpio_warnc. */
+       /* Need lafe_progname before calling lafe_warnc. */
        if (*argv == NULL)
-               cpio_progname = "bsdcpio";
+               lafe_progname = "bsdcpio";
        else {
 #if defined(_WIN32) && !defined(__CYGWIN__)
-               cpio_progname = strrchr(*argv, '\\');
+               lafe_progname = strrchr(*argv, '\\');
 #else
-               cpio_progname = strrchr(*argv, '/');
+               lafe_progname = strrchr(*argv, '/');
 #endif
-               if (cpio_progname != NULL)
-                       cpio_progname++;
+               if (lafe_progname != NULL)
+                       lafe_progname++;
                else
-                       cpio_progname = *argv;
+                       lafe_progname = *argv;
        }
 
        cpio->uid_override = -1;
        cpio->gid_override = -1;
        cpio->argv = argv;
        cpio->argc = argc;
-       cpio->line_separator = '\n';
        cpio->mode = '\0';
        cpio->verbose = 0;
        cpio->compress = '\0';
@@ -161,19 +165,17 @@ main(int argc, char *argv[])
        cpio->extract_flags |= ARCHIVE_EXTRACT_PERM;
        cpio->extract_flags |= ARCHIVE_EXTRACT_FFLAGS;
        cpio->extract_flags |= ARCHIVE_EXTRACT_ACL;
-#if defined(_WIN32) || defined(__CYGWIN__)
-       if (bsdcpio_is_privileged())
-#else
+#if !defined(_WIN32) && !defined(__CYGWIN__)
        if (geteuid() == 0)
-#endif
                cpio->extract_flags |= ARCHIVE_EXTRACT_OWNER;
+#endif
        cpio->bytes_per_block = 512;
        cpio->filename = NULL;
 
        while ((opt = cpio_getopt(cpio)) != -1) {
                switch (opt) {
                case '0': /* GNU convention: --null, -0 */
-                       cpio->line_separator = '\0';
+                       cpio->option_null = 1;
                        break;
                case 'A': /* NetBSD/OpenBSD */
                        cpio->option_append = 1;
@@ -187,7 +189,7 @@ main(int argc, char *argv[])
                case 'C': /* NetBSD/OpenBSD */
                        cpio->bytes_per_block = atoi(cpio->optarg);
                        if (cpio->bytes_per_block <= 0)
-                               cpio_errc(1, 0, "Invalid blocksize %s", cpio->optarg);
+                               lafe_errc(1, 0, "Invalid blocksize %s", cpio->optarg);
                        break;
                case 'c': /* POSIX 1997 */
                        cpio->format = "odc";
@@ -196,13 +198,14 @@ main(int argc, char *argv[])
                        cpio->extract_flags &= ~ARCHIVE_EXTRACT_NO_AUTODIR;
                        break;
                case 'E': /* NetBSD/OpenBSD */
-                       include_from_file(cpio, cpio->optarg);
+                       lafe_include_from_file(&cpio->matching,
+                           cpio->optarg, cpio->option_null);
                        break;
                case 'F': /* NetBSD/OpenBSD/GNU cpio */
                        cpio->filename = cpio->optarg;
                        break;
                case 'f': /* POSIX 1997 */
-                       exclude(cpio, cpio->optarg);
+                       lafe_exclude(&cpio->matching, cpio->optarg);
                        break;
                case 'H': /* GNU cpio (also --format) */
                        cpio->format = cpio->optarg;
@@ -215,10 +218,16 @@ main(int argc, char *argv[])
                        break;
                case 'i': /* POSIX 1997 */
                        if (cpio->mode != '\0')
-                               cpio_errc(1, 0,
+                               lafe_errc(1, 0,
                                    "Cannot use both -i and -%c", cpio->mode);
                        cpio->mode = opt;
                        break;
+               case 'J': /* GNU tar, others */
+                       cpio->compress = opt;
+                       break;
+               case 'j': /* GNU tar, others */
+                       cpio->compress = opt;
+                       break;
                case OPTION_INSECURE:
                        cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_SYMLINKS;
                        cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_NODOTDOT;
@@ -229,6 +238,9 @@ main(int argc, char *argv[])
                case 'l': /* POSIX 1997 */
                        cpio->option_link = 1;
                        break;
+               case OPTION_LZMA: /* GNU tar, others */
+                       cpio->compress = opt;
+                       break;
                case 'm': /* POSIX 1997 */
                        cpio->extract_flags |= ARCHIVE_EXTRACT_TIME;
                        break;
@@ -243,23 +255,29 @@ main(int argc, char *argv[])
                        break;
                case 'o': /* POSIX 1997 */
                        if (cpio->mode != '\0')
-                               cpio_errc(1, 0,
+                               lafe_errc(1, 0,
                                    "Cannot use both -o and -%c", cpio->mode);
                        cpio->mode = opt;
                        break;
                case 'p': /* POSIX 1997 */
                        if (cpio->mode != '\0')
-                               cpio_errc(1, 0,
+                               lafe_errc(1, 0,
                                    "Cannot use both -p and -%c", cpio->mode);
                        cpio->mode = opt;
                        cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_NODOTDOT;
                        break;
+               case OPTION_PRESERVE_OWNER:
+                       cpio->extract_flags |= ARCHIVE_EXTRACT_OWNER;
+                       break;
                case OPTION_QUIET: /* GNU cpio */
                        cpio->quiet = 1;
                        break;
                case 'R': /* GNU cpio, also --owner */
-                       if (owner_parse(cpio->optarg, &uid, &gid))
+                       errmsg = owner_parse(cpio->optarg, &uid, &gid);
+                       if (errmsg) {
+                               lafe_warnc(-1, "%s", errmsg);
                                usage();
+                       }
                        if (uid != -1)
                                cpio->uid_override = uid;
                        if (gid != -1)
@@ -290,23 +308,13 @@ main(int argc, char *argv[])
                        break;
 #endif
                case 'y': /* tar convention */
-#if HAVE_LIBBZ2
                        cpio->compress = opt;
-#else
-                       cpio_warnc(0, "bzip2 compression not supported by "
-                           "this version of bsdcpio");
-#endif
                        break;
                case 'Z': /* tar convention */
                        cpio->compress = opt;
                        break;
                case 'z': /* tar convention */
-#if HAVE_LIBZ
                        cpio->compress = opt;
-#else
-                       cpio_warnc(0, "gzip compression not supported by "
-                           "this version of bsdcpio");
-#endif
                        break;
                default:
                        usage();
@@ -321,16 +329,16 @@ main(int argc, char *argv[])
                cpio->mode = 'i';
        /* -t requires -i */
        if (cpio->option_list && cpio->mode != 'i')
-               cpio_errc(1, 0, "Option -t requires -i", cpio->mode);
+               lafe_errc(1, 0, "Option -t requires -i");
        /* -n requires -it */
        if (cpio->option_numeric_uid_gid && !cpio->option_list)
-               cpio_errc(1, 0, "Option -n requires -it");
+               lafe_errc(1, 0, "Option -n requires -it");
        /* Can only specify format when writing */
        if (cpio->format != NULL && cpio->mode != 'o')
-               cpio_errc(1, 0, "Option --format requires -o");
+               lafe_errc(1, 0, "Option --format requires -o");
        /* -l requires -p */
        if (cpio->option_link && cpio->mode != 'p')
-               cpio_errc(1, 0, "Option -l requires -p");
+               lafe_errc(1, 0, "Option -l requires -p");
        /* TODO: Flag other nonsensical combinations. */
 
        switch (cpio->mode) {
@@ -344,7 +352,7 @@ main(int argc, char *argv[])
                break;
        case 'i':
                while (*cpio->argv != NULL) {
-                       include(cpio, *cpio->argv);
+                       lafe_include(&cpio->matching, *cpio->argv);
                        --cpio->argc;
                        ++cpio->argv;
                }
@@ -355,26 +363,26 @@ main(int argc, char *argv[])
                break;
        case 'p':
                if (*cpio->argv == NULL || **cpio->argv == '\0')
-                       cpio_errc(1, 0,
+                       lafe_errc(1, 0,
                            "-p mode requires a target directory");
                mode_pass(cpio, *cpio->argv);
                break;
        default:
-               cpio_errc(1, 0,
+               lafe_errc(1, 0,
                    "Must specify at least one of -i, -o, or -p");
        }
 
        free_cache(cpio->gname_cache);
        free_cache(cpio->uname_cache);
-       return (0);
+       return (cpio->return_value);
 }
 
-void
+static void
 usage(void)
 {
        const char      *p;
 
-       p = cpio_progname;
+       p = lafe_progname;
 
        fprintf(stderr, "Brief Usage:\n");
        fprintf(stderr, "  List:    %s -it < archive\n", p);
@@ -390,12 +398,7 @@ static const char *long_help_msg =
        "Common Options:\n"
        "  -v    Verbose\n"
        "Create: %p -o [options]  < [list of files] > [archive]\n"
-#ifdef HAVE_BZLIB_H
-       "  -y  Compress archive with bzip2\n"
-#endif
-#ifdef HAVE_ZLIB_H
-       "  -z  Compress archive with gzip\n"
-#endif
+       "  -J,-y,-z,--lzma  Compress archive with xz/bzip2/gzip/lzma\n"
        "  --format {odc|newc|ustar}  Select archive format\n"
        "List: %p -it < [archive]\n"
        "Extract: %p -i [options] < [archive]\n";
@@ -417,7 +420,7 @@ long_help(void)
        const char      *prog;
        const char      *p;
 
-       prog = cpio_progname;
+       prog = lafe_progname;
 
        fflush(stderr);
 
@@ -449,50 +452,66 @@ version(void)
 static void
 mode_out(struct cpio *cpio)
 {
-       unsigned long blocks;
        struct archive_entry *entry, *spare;
-       struct line_reader *lr;
+       struct lafe_line_reader *lr;
        const char *p;
        int r;
 
        if (cpio->option_append)
-               cpio_errc(1, 0, "Append mode not yet supported.");
+               lafe_errc(1, 0, "Append mode not yet supported.");
+
+       cpio->archive_read_disk = archive_read_disk_new();
+       if (cpio->archive_read_disk == NULL)
+               lafe_errc(1, 0, "Failed to allocate archive object");
+       if (cpio->option_follow_links)
+               archive_read_disk_set_symlink_logical(cpio->archive_read_disk);
+       else
+               archive_read_disk_set_symlink_physical(cpio->archive_read_disk);
+       archive_read_disk_set_standard_lookup(cpio->archive_read_disk);
+
        cpio->archive = archive_write_new();
        if (cpio->archive == NULL)
-               cpio_errc(1, 0, "Failed to allocate archive object");
+               lafe_errc(1, 0, "Failed to allocate archive object");
        switch (cpio->compress) {
-#ifdef HAVE_BZLIB_H
+       case 'J':
+               r = archive_write_set_compression_xz(cpio->archive);
+               break;
+       case OPTION_LZMA:
+               r = archive_write_set_compression_lzma(cpio->archive);
+               break;
        case 'j': case 'y':
-               archive_write_set_compression_bzip2(cpio->archive);
+               r = archive_write_set_compression_bzip2(cpio->archive);
                break;
-#endif
-#ifdef HAVE_ZLIB_H
        case 'z':
-               archive_write_set_compression_gzip(cpio->archive);
+               r = archive_write_set_compression_gzip(cpio->archive);
                break;
-#endif
        case 'Z':
-               archive_write_set_compression_compress(cpio->archive);
+               r = archive_write_set_compression_compress(cpio->archive);
                break;
        default:
-               archive_write_set_compression_none(cpio->archive);
+               r = archive_write_set_compression_none(cpio->archive);
                break;
        }
+       if (r < ARCHIVE_WARN)
+               lafe_errc(1, 0, "Requested compression not available");
        r = archive_write_set_format_by_name(cpio->archive, cpio->format);
        if (r != ARCHIVE_OK)
-               cpio_errc(1, 0, archive_error_string(cpio->archive));
+               lafe_errc(1, 0, "%s", archive_error_string(cpio->archive));
        archive_write_set_bytes_per_block(cpio->archive, cpio->bytes_per_block);
        cpio->linkresolver = archive_entry_linkresolver_new();
        archive_entry_linkresolver_set_strategy(cpio->linkresolver,
            archive_format(cpio->archive));
 
+       /*
+        * The main loop:  Copy each file into the output archive.
+        */
        r = archive_write_open_file(cpio->archive, cpio->filename);
        if (r != ARCHIVE_OK)
-               cpio_errc(1, 0, archive_error_string(cpio->archive));
-       lr = process_lines_init("-", cpio->line_separator);
-       while ((p = process_lines_next(lr)) != NULL)
+               lafe_errc(1, 0, "%s", archive_error_string(cpio->archive));
+       lr = lafe_line_reader("-", cpio->option_null);
+       while ((p = lafe_line_reader_next(lr)) != NULL)
                file_to_archive(cpio, p);
-       process_lines_free(lr);
+       lafe_line_reader_free(lr);
 
        /*
         * The hardlink detection may have queued up a couple of entries
@@ -509,12 +528,13 @@ mode_out(struct cpio *cpio)
 
        r = archive_write_close(cpio->archive);
        if (r != ARCHIVE_OK)
-               cpio_errc(1, 0, archive_error_string(cpio->archive));
+               lafe_errc(1, 0, "%s", archive_error_string(cpio->archive));
 
        if (!cpio->quiet) {
-               blocks = (archive_position_uncompressed(cpio->archive) + 511)
-                             / 512;
-               fprintf(stderr, "%lu %s\n", blocks,
+               int64_t blocks =
+                       (archive_position_uncompressed(cpio->archive) + 511)
+                       / 512;
+               fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
                    blocks == 1 ? "block" : "blocks");
        }
        archive_write_finish(cpio->archive);
@@ -528,57 +548,37 @@ mode_out(struct cpio *cpio)
 static int
 file_to_archive(struct cpio *cpio, const char *srcpath)
 {
-       struct stat st;
        const char *destpath;
        struct archive_entry *entry, *spare;
        size_t len;
        const char *p;
-#if !defined(_WIN32) || defined(__CYGWIN__)
-       int lnklen;
-#endif
        int r;
 
        /*
         * Create an archive_entry describing the source file.
         *
-        * XXX TODO: rework to use archive_read_disk_entry_from_file()
         */
        entry = archive_entry_new();
        if (entry == NULL)
-               cpio_errc(1, 0, "Couldn't allocate entry");
+               lafe_errc(1, 0, "Couldn't allocate entry");
        archive_entry_copy_sourcepath(entry, srcpath);
-
-       /* Get stat information. */
-       if (cpio->option_follow_links)
-               r = stat(srcpath, &st);
-       else
-               r = lstat(srcpath, &st);
-       if (r != 0) {
-               cpio_warnc(errno, "Couldn't stat \"%s\"", srcpath);
-               archive_entry_free(entry);
-               return (0);
+       r = archive_read_disk_entry_from_file(cpio->archive_read_disk,
+           entry, -1, NULL);
+       if (r < ARCHIVE_FAILED)
+               lafe_errc(1, 0, "%s",
+                   archive_error_string(cpio->archive_read_disk));
+       if (r < ARCHIVE_OK)
+               lafe_warnc(0, "%s",
+                   archive_error_string(cpio->archive_read_disk));
+       if (r <= ARCHIVE_FAILED) {
+               cpio->return_value = 1;
+               return (r);
        }
 
        if (cpio->uid_override >= 0)
-               st.st_uid = cpio->uid_override;
+               archive_entry_set_uid(entry, cpio->uid_override);
        if (cpio->gid_override >= 0)
-               st.st_gid = cpio->uid_override;
-       archive_entry_copy_stat(entry, &st);
-
-#if !defined(_WIN32) || defined(__CYGWIN__)
-       /* If its a symlink, pull the target. */
-       if (S_ISLNK(st.st_mode)) {
-               lnklen = readlink(srcpath, cpio->buff, cpio->buff_size);
-               if (lnklen < 0) {
-                       cpio_warnc(errno,
-                           "%s: Couldn't read symbolic link", srcpath);
-                       archive_entry_free(entry);
-                       return (0);
-               }
-               cpio->buff[lnklen] = 0;
-               archive_entry_set_symlink(entry, cpio->buff);
-       }
-#endif
+               archive_entry_set_gid(entry, cpio->gid_override);
 
        /*
         * Generate a destination path for this entry.
@@ -597,7 +597,7 @@ file_to_archive(struct cpio *cpio, const char *srcpath)
                        free(cpio->pass_destpath);
                        cpio->pass_destpath = malloc(cpio->pass_destpath_alloc);
                        if (cpio->pass_destpath == NULL)
-                               cpio_errc(1, ENOMEM,
+                               lafe_errc(1, ENOMEM,
                                    "Can't allocate path buffer");
                }
                strcpy(cpio->pass_destpath, cpio->destdir);
@@ -618,18 +618,18 @@ file_to_archive(struct cpio *cpio, const char *srcpath)
         */
        spare = NULL;
        if (cpio->linkresolver != NULL
-           && !S_ISDIR(st.st_mode)) {
+           && archive_entry_filetype(entry) != AE_IFDIR) {
                archive_entry_linkify(cpio->linkresolver, &entry, &spare);
        }
 
        if (entry != NULL) {
                r = entry_to_archive(cpio, entry);
                archive_entry_free(entry);
-       }
-       if (spare != NULL) {
-               if (r == 0)
-                       r = entry_to_archive(cpio, spare);
-               archive_entry_free(spare);
+               if (spare != NULL) {
+                       if (r == 0)
+                               r = entry_to_archive(cpio, spare);
+                       archive_entry_free(spare);
+               }
        }
        return (r);
 }
@@ -663,7 +663,7 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
                /* Save the original entry in case we need it later. */
                t = archive_entry_clone(entry);
                if (t == NULL)
-                       cpio_errc(1, ENOMEM, "Can't create link");
+                       lafe_errc(1, ENOMEM, "Can't create link");
                /* Note: link(2) doesn't create parent directories,
                 * so we use archive_write_header() instead as a
                 * convenience. */
@@ -673,15 +673,15 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
                r = archive_write_header(cpio->archive, t);
                archive_entry_free(t);
                if (r != ARCHIVE_OK)
-                       cpio_warnc(archive_errno(cpio->archive),
-                           archive_error_string(cpio->archive));
+                       lafe_warnc(archive_errno(cpio->archive),
+                           "%s", archive_error_string(cpio->archive));
                if (r == ARCHIVE_FATAL)
                        exit(1);
 #ifdef EXDEV
                if (r != ARCHIVE_OK && archive_errno(cpio->archive) == EXDEV) {
                        /* Cross-device link:  Just fall through and use
                         * the original entry to copy the file over. */
-                       cpio_warnc(0, "Copying file instead");
+                       lafe_warnc(0, "Copying file instead");
                } else
 #endif
                return (0);
@@ -693,9 +693,9 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
         */
        if (archive_entry_filetype(entry) == AE_IFREG) {
                if (archive_entry_size(entry) > 0) {
-                       fd = open(srcpath, O_RDONLY);
+                       fd = open(srcpath, O_RDONLY | O_BINARY);
                        if (fd < 0) {
-                               cpio_warnc(errno,
+                               lafe_warnc(errno,
                                    "%s: could not open file", srcpath);
                                goto cleanup;
                        }
@@ -707,7 +707,7 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
        r = archive_write_header(cpio->archive, entry);
 
        if (r != ARCHIVE_OK)
-               cpio_warnc(archive_errno(cpio->archive),
+               lafe_warnc(archive_errno(cpio->archive),
                    "%s: %s",
                    srcpath,
                    archive_error_string(cpio->archive));
@@ -721,10 +721,10 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
                        r = archive_write_data(cpio->archive,
                            cpio->buff, bytes_read);
                        if (r < 0)
-                               cpio_errc(1, archive_errno(cpio->archive),
-                                   archive_error_string(cpio->archive));
+                               lafe_errc(1, archive_errno(cpio->archive),
+                                   "%s", archive_error_string(cpio->archive));
                        if (r < bytes_read) {
-                               cpio_warnc(0,
+                               lafe_warnc(0,
                                    "Truncated write; file may have grown while being archived.");
                        }
                        bytes_read = read(fd, cpio->buff, cpio->buff_size);
@@ -753,7 +753,7 @@ restore_time(struct cpio *cpio, struct archive_entry *entry,
        (void)name; /* UNUSED */
 
        if (!warned)
-               cpio_warnc(0, "Can't restore access times on this platform");
+               lafe_warnc(0, "Can't restore access times on this platform");
        warned = 1;
        return (fd);
 #else
@@ -772,7 +772,7 @@ restore_time(struct cpio *cpio, struct archive_entry *entry,
         times[0].tv_sec = archive_entry_atime(entry);
         times[0].tv_usec = archive_entry_atime_nsec(entry) / 1000;
 
-#ifdef HAVE_FUTIMES
+#if defined(HAVE_FUTIMES) && !defined(__CYGWIN__)
         if (fd >= 0 && futimes(fd, times) == 0)
                return (fd);
 #endif
@@ -788,9 +788,10 @@ restore_time(struct cpio *cpio, struct archive_entry *entry,
 #ifdef HAVE_LUTIMES
         if (lutimes(name, times) != 0)
 #else
-        if (!S_ISLNK(archive_entry_mode(entry)) && utimes(name, times) != 0)
+        if ((AE_IFLNK != archive_entry_filetype(entry))
+                       && utimes(name, times) != 0)
 #endif
-                cpio_warnc(errno, "Can't update time for %s", name);
+                lafe_warnc(errno, "Can't update time for %s", name);
 #endif
        return (fd);
 }
@@ -803,33 +804,32 @@ mode_in(struct cpio *cpio)
        struct archive_entry *entry;
        struct archive *ext;
        const char *destpath;
-       unsigned long blocks;
        int r;
 
        ext = archive_write_disk_new();
        if (ext == NULL)
-               cpio_errc(1, 0, "Couldn't allocate restore object");
+               lafe_errc(1, 0, "Couldn't allocate restore object");
        r = archive_write_disk_set_options(ext, cpio->extract_flags);
        if (r != ARCHIVE_OK)
-               cpio_errc(1, 0, archive_error_string(ext));
+               lafe_errc(1, 0, "%s", archive_error_string(ext));
        a = archive_read_new();
        if (a == NULL)
-               cpio_errc(1, 0, "Couldn't allocate archive object");
+               lafe_errc(1, 0, "Couldn't allocate archive object");
        archive_read_support_compression_all(a);
        archive_read_support_format_all(a);
 
        if (archive_read_open_file(a, cpio->filename, cpio->bytes_per_block))
-               cpio_errc(1, archive_errno(a),
-                   archive_error_string(a));
+               lafe_errc(1, archive_errno(a),
+                   "%s", archive_error_string(a));
        for (;;) {
                r = archive_read_next_header(a, &entry);
                if (r == ARCHIVE_EOF)
                        break;
                if (r != ARCHIVE_OK) {
-                       cpio_errc(1, archive_errno(a),
-                           archive_error_string(a));
+                       lafe_errc(1, archive_errno(a),
+                           "%s", archive_error_string(a));
                }
-               if (excluded(cpio, archive_entry_pathname(entry)))
+               if (lafe_excluded(cpio->matching, archive_entry_pathname(entry)))
                        continue;
                if (cpio->option_rename) {
                        destpath = cpio_rename(archive_entry_pathname(entry));
@@ -850,28 +850,34 @@ mode_in(struct cpio *cpio)
                            archive_entry_pathname(entry),
                            archive_error_string(ext));
                } else if (archive_entry_size(entry) > 0) {
-                       r = copy_data(a, ext);
+                       r = extract_data(a, ext);
+                       if (r != ARCHIVE_OK)
+                               cpio->return_value = 1;
                }
        }
        r = archive_read_close(a);
        if (r != ARCHIVE_OK)
-               cpio_errc(1, 0, archive_error_string(a));
+               lafe_errc(1, 0, "%s", archive_error_string(a));
        r = archive_write_close(ext);
        if (r != ARCHIVE_OK)
-               cpio_errc(1, 0, archive_error_string(ext));
+               lafe_errc(1, 0, "%s", archive_error_string(ext));
        if (!cpio->quiet) {
-               blocks = (archive_position_uncompressed(a) + 511)
+               int64_t blocks = (archive_position_uncompressed(a) + 511)
                              / 512;
-               fprintf(stderr, "%lu %s\n", blocks,
+               fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
                    blocks == 1 ? "block" : "blocks");
        }
        archive_read_finish(a);
        archive_write_finish(ext);
-       exit(0);
+       exit(cpio->return_value);
 }
 
+/*
+ * Exits if there's a fatal error.  Returns ARCHIVE_OK
+ * if everything is kosher.
+ */
 static int
-copy_data(struct archive *ar, struct archive *aw)
+extract_data(struct archive *ar, struct archive *aw)
 {
        int r;
        size_t size;
@@ -883,14 +889,14 @@ copy_data(struct archive *ar, struct archive *aw)
                if (r == ARCHIVE_EOF)
                        return (ARCHIVE_OK);
                if (r != ARCHIVE_OK) {
-                       cpio_warnc(archive_errno(ar),
+                       lafe_warnc(archive_errno(ar),
                            "%s", archive_error_string(ar));
-                       return (r);
+                       exit(1);
                }
                r = archive_write_data_block(aw, block, size, offset);
                if (r != ARCHIVE_OK) {
-                       cpio_warnc(archive_errno(aw),
-                           archive_error_string(aw));
+                       lafe_warnc(archive_errno(aw),
+                           "%s", archive_error_string(aw));
                        return (r);
                }
        }
@@ -901,27 +907,26 @@ mode_list(struct cpio *cpio)
 {
        struct archive *a;
        struct archive_entry *entry;
-       unsigned long blocks;
        int r;
 
        a = archive_read_new();
        if (a == NULL)
-               cpio_errc(1, 0, "Couldn't allocate archive object");
+               lafe_errc(1, 0, "Couldn't allocate archive object");
        archive_read_support_compression_all(a);
        archive_read_support_format_all(a);
 
        if (archive_read_open_file(a, cpio->filename, cpio->bytes_per_block))
-               cpio_errc(1, archive_errno(a),
-                   archive_error_string(a));
+               lafe_errc(1, archive_errno(a),
+                   "%s", archive_error_string(a));
        for (;;) {
                r = archive_read_next_header(a, &entry);
                if (r == ARCHIVE_EOF)
                        break;
                if (r != ARCHIVE_OK) {
-                       cpio_errc(1, archive_errno(a),
-                           archive_error_string(a));
+                       lafe_errc(1, archive_errno(a),
+                           "%s", archive_error_string(a));
                }
-               if (excluded(cpio, archive_entry_pathname(entry)))
+               if (lafe_excluded(cpio->matching, archive_entry_pathname(entry)))
                        continue;
                if (cpio->verbose)
                        list_item_verbose(cpio, entry);
@@ -930,11 +935,11 @@ mode_list(struct cpio *cpio)
        }
        r = archive_read_close(a);
        if (r != ARCHIVE_OK)
-               cpio_errc(1, 0, archive_error_string(a));
+               lafe_errc(1, 0, "%s", archive_error_string(a));
        if (!cpio->quiet) {
-               blocks = (archive_position_uncompressed(a) + 511)
+               int64_t blocks = (archive_position_uncompressed(a) + 511)
                              / 512;
-               fprintf(stderr, "%lu %s\n", blocks,
+               fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
                    blocks == 1 ? "block" : "blocks");
        }
        archive_read_finish(a);
@@ -957,23 +962,18 @@ list_item_verbose(struct cpio *cpio, struct archive_entry *entry)
        char                     uids[16], gids[16];
        const char              *uname, *gname;
        FILE                    *out = stdout;
-       const struct stat       *st;
        const char              *fmt;
-       time_t                   tim;
+       time_t                   mtime;
        static time_t            now;
 
-       st = archive_entry_stat(entry);
-
        if (!now)
                time(&now);
 
        if (cpio->option_numeric_uid_gid) {
                /* Format numeric uid/gid for display. */
-               snprintf(uids, sizeof(uids), "%d",
-                   (int)archive_entry_uid(entry));
+               strcpy(uids, cpio_i64toa(archive_entry_uid(entry)));
                uname = uids;
-               snprintf(gids, sizeof(gids), "%d",
-                   (int)archive_entry_gid(entry));
+               strcpy(gids, cpio_i64toa(archive_entry_gid(entry)));
                gname = gids;
        } else {
                /* Use uname if it's present, else lookup name from uid. */
@@ -987,30 +987,31 @@ list_item_verbose(struct cpio *cpio, struct archive_entry *entry)
        }
 
        /* Print device number or file size. */
-       if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) {
+       if (archive_entry_filetype(entry) == AE_IFCHR
+           || archive_entry_filetype(entry) == AE_IFBLK) {
                snprintf(size, sizeof(size), "%lu,%lu",
-                   (unsigned long)major(st->st_rdev),
-                   (unsigned long)minor(st->st_rdev)); /* ls(1) also casts here. */
+                   (unsigned long)archive_entry_rdevmajor(entry),
+                   (unsigned long)archive_entry_rdevminor(entry));
        } else {
-               snprintf(size, sizeof(size), CPIO_FILESIZE_PRINTF,
-                   (CPIO_FILESIZE_TYPE)st->st_size);
+               strcpy(size, cpio_i64toa(archive_entry_size(entry)));
        }
 
        /* Format the time using 'ls -l' conventions. */
-       tim = (time_t)st->st_mtime;
+       mtime = archive_entry_mtime(entry);
 #if defined(_WIN32) && !defined(__CYGWIN__)
        /* Windows' strftime function does not support %e format. */
-       if (abs(tim - now) > (365/2)*86400)
+       if (mtime - now > 365*86400/2
+               || mtime - now < -365*86400/2)
                fmt = cpio->day_first ? "%d %b  %Y" : "%b %d  %Y";
        else
                fmt = cpio->day_first ? "%d %b %H:%M" : "%b %d %H:%M";
 #else
-       if (abs(tim - now) > (365/2)*86400)
+       if (abs(mtime - now) > (365/2)*86400)
                fmt = cpio->day_first ? "%e %b  %Y" : "%b %e  %Y";
        else
                fmt = cpio->day_first ? "%e %b %H:%M" : "%b %e %H:%M";
 #endif
-       strftime(date, sizeof(date), fmt, localtime(&tim));
+       strftime(date, sizeof(date), fmt, localtime(&mtime));
 
        fprintf(out, "%s%3d %-8s %-8s %8s %12s %s",
            archive_entry_strmode(entry),
@@ -1029,8 +1030,7 @@ list_item_verbose(struct cpio *cpio, struct archive_entry *entry)
 static void
 mode_pass(struct cpio *cpio, const char *destdir)
 {
-       unsigned long blocks;
-       struct line_reader *lr;
+       struct lafe_line_reader *lr;
        const char *p;
        int r;
 
@@ -1042,26 +1042,37 @@ mode_pass(struct cpio *cpio, const char *destdir)
 
        cpio->archive = archive_write_disk_new();
        if (cpio->archive == NULL)
-               cpio_errc(1, 0, "Failed to allocate archive object");
+               lafe_errc(1, 0, "Failed to allocate archive object");
        r = archive_write_disk_set_options(cpio->archive, cpio->extract_flags);
        if (r != ARCHIVE_OK)
-               cpio_errc(1, 0, archive_error_string(cpio->archive));
+               lafe_errc(1, 0, "%s", archive_error_string(cpio->archive));
        cpio->linkresolver = archive_entry_linkresolver_new();
        archive_write_disk_set_standard_lookup(cpio->archive);
-       lr = process_lines_init("-", cpio->line_separator);
-       while ((p = process_lines_next(lr)) != NULL)
+
+       cpio->archive_read_disk = archive_read_disk_new();
+       if (cpio->archive_read_disk == NULL)
+               lafe_errc(1, 0, "Failed to allocate archive object");
+       if (cpio->option_follow_links)
+               archive_read_disk_set_symlink_logical(cpio->archive_read_disk);
+       else
+               archive_read_disk_set_symlink_physical(cpio->archive_read_disk);
+       archive_read_disk_set_standard_lookup(cpio->archive_read_disk);
+
+       lr = lafe_line_reader("-", cpio->option_null);
+       while ((p = lafe_line_reader_next(lr)) != NULL)
                file_to_archive(cpio, p);
-       process_lines_free(lr);
+       lafe_line_reader_free(lr);
 
        archive_entry_linkresolver_free(cpio->linkresolver);
        r = archive_write_close(cpio->archive);
        if (r != ARCHIVE_OK)
-               cpio_errc(1, 0, archive_error_string(cpio->archive));
+               lafe_errc(1, 0, "%s", archive_error_string(cpio->archive));
 
        if (!cpio->quiet) {
-               blocks = (archive_position_uncompressed(cpio->archive) + 511)
-                             / 512;
-               fprintf(stderr, "%lu %s\n", blocks,
+               int64_t blocks =
+                       (archive_position_uncompressed(cpio->archive) + 511)
+                       / 512;
+               fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
                    blocks == 1 ? "block" : "blocks");
        }
 
@@ -1111,130 +1122,6 @@ cpio_rename(const char *name)
        return (ret);
 }
 
-
-/*
- * Read lines from file and do something with each one.  If option_null
- * is set, lines are terminated with zero bytes; otherwise, they're
- * terminated with newlines.
- *
- * This uses a self-sizing buffer to handle arbitrarily-long lines.
- */
-struct line_reader {
-       FILE *f;
-       char *buff, *buff_end, *line_start, *line_end, *p;
-       char *pathname;
-       size_t buff_length;
-       int separator;
-       int ret;
-};
-
-struct line_reader *
-process_lines_init(const char *pathname, char separator)
-{
-       struct line_reader *lr;
-
-       lr = calloc(1, sizeof(*lr));
-       if (lr == NULL)
-               cpio_errc(1, ENOMEM, "Can't open %s", pathname);
-
-       lr->separator = separator;
-       lr->pathname = strdup(pathname);
-
-       if (strcmp(pathname, "-") == 0)
-               lr->f = stdin;
-       else
-               lr->f = fopen(pathname, "r");
-       if (lr->f == NULL)
-               cpio_errc(1, errno, "Couldn't open %s", pathname);
-       lr->buff_length = 8192;
-       lr->buff = malloc(lr->buff_length);
-       if (lr->buff == NULL)
-               cpio_errc(1, ENOMEM, "Can't read %s", pathname);
-       lr->line_start = lr->line_end = lr->buff_end = lr->buff;
-
-       return (lr);
-}
-
-const char *
-process_lines_next(struct line_reader *lr)
-{
-       size_t bytes_wanted, bytes_read, new_buff_size;
-       char *line_start, *p;
-
-       for (;;) {
-               /* If there's a line in the buffer, return it immediately. */
-               while (lr->line_end < lr->buff_end) {
-                       if (*lr->line_end == lr->separator) {
-                               *lr->line_end = '\0';
-                               line_start = lr->line_start;
-                               lr->line_start = lr->line_end + 1;
-                               lr->line_end = lr->line_start;
-                               return (line_start);
-                       } else
-                               lr->line_end++;
-               }
-
-               /* If we're at end-of-file, process the final data. */
-               if (lr->f == NULL) {
-                       /* If there's more text, return one last line. */
-                       if (lr->line_end > lr->line_start) {
-                               *lr->line_end = '\0';
-                               line_start = lr->line_start;
-                               lr->line_start = lr->line_end + 1;
-                               lr->line_end = lr->line_start;
-                               return (line_start);
-                       }
-                       /* Otherwise, we're done. */
-                       return (NULL);
-               }
-
-               /* Buffer only has part of a line. */
-               if (lr->line_start > lr->buff) {
-                       /* Move a leftover fractional line to the beginning. */
-                       memmove(lr->buff, lr->line_start,
-                           lr->buff_end - lr->line_start);
-                       lr->buff_end -= lr->line_start - lr->buff;
-                       lr->line_end -= lr->line_start - lr->buff;
-                       lr->line_start = lr->buff;
-               } else {
-                       /* Line is too big; enlarge the buffer. */
-                       new_buff_size = lr->buff_length * 2;
-                       if (new_buff_size <= lr->buff_length)
-                               cpio_errc(1, ENOMEM,
-                                   "Line too long in %s", lr->pathname);
-                       lr->buff_length = new_buff_size;
-                       p = realloc(lr->buff, new_buff_size);
-                       if (p == NULL)
-                               cpio_errc(1, ENOMEM,
-                                   "Line too long in %s", lr->pathname);
-                       lr->buff_end = p + (lr->buff_end - lr->buff);
-                       lr->line_end = p + (lr->line_end - lr->buff);
-                       lr->line_start = lr->buff = p;
-               }
-
-               /* Get some more data into the buffer. */
-               bytes_wanted = lr->buff + lr->buff_length - lr->buff_end;
-               bytes_read = fread(lr->buff_end, 1, bytes_wanted, lr->f);
-               lr->buff_end += bytes_read;
-
-               if (ferror(lr->f))
-                       cpio_errc(1, errno, "Can't read %s", lr->pathname);
-               if (feof(lr->f)) {
-                       if (lr->f != stdin)
-                               fclose(lr->f);
-                       lr->f = NULL;
-               }
-       }
-}
-
-void
-process_lines_free(struct line_reader *lr)
-{
-       free(lr->buff);
-       free(lr->pathname);
-       free(lr);
-}
-
 static void
 free_cache(struct name_cache *cache)
 {
@@ -1263,7 +1150,7 @@ lookup_name(struct cpio *cpio, struct name_cache **name_cache_variable,
        if (*name_cache_variable == NULL) {
                *name_cache_variable = malloc(sizeof(struct name_cache));
                if (*name_cache_variable == NULL)
-                       cpio_errc(1, ENOMEM, "No more memory");
+                       lafe_errc(1, ENOMEM, "No more memory");
                memset(*name_cache_variable, 0, sizeof(struct name_cache));
                (*name_cache_variable)->size = name_cache_size;
        }
@@ -1319,8 +1206,8 @@ lookup_uname_helper(struct cpio *cpio, const char **name, id_t id)
        pwent = getpwuid((uid_t)id);
        if (pwent == NULL) {
                *name = NULL;
-               if (errno != 0)
-                       cpio_warnc(errno, "getpwuid(%d) failed", id);
+               if (errno != 0 && errno != ENOENT)
+                       lafe_warnc(errno, "getpwuid(%d) failed", id);
                return (errno);
        }
 
@@ -1347,10 +1234,34 @@ lookup_gname_helper(struct cpio *cpio, const char **name, id_t id)
        if (grent == NULL) {
                *name = NULL;
                if (errno != 0)
-                       cpio_warnc(errno, "getgrgid(%d) failed", id);
+                       lafe_warnc(errno, "getgrgid(%d) failed", id);
                return (errno);
        }
 
        *name = grent->gr_name;
        return (0);
 }
+
+/*
+ * It would be nice to just use printf() for formatting large numbers,
+ * but the compatibility problems are a big headache.  Hence the
+ * following simple utility function.
+ */
+const char *
+cpio_i64toa(int64_t n0)
+{
+       // 2^64 =~ 1.8 * 10^19, so 20 decimal digits suffice.
+       // We also need 1 byte for '-' and 1 for '\0'.
+       static char buff[22];
+       int64_t n = n0 < 0 ? -n0 : n0;
+       char *p = buff + sizeof(buff);
+
+       *--p = '\0';
+       do {
+               *--p = '0' + (int)(n % 10);
+               n /= 10;
+       } while (n > 0);
+       if (n0 < 0)
+               *--p = '-';
+       return p;
+}
index 79b2223..3eed834 100644 (file)
@@ -31,7 +31,7 @@
 #include "cpio_platform.h"
 #include <stdio.h>
 
-#define        DEFAULT_BYTES_PER_BLOCK (20*512)
+#include "matching.h"
 
 /*
  * The internal state for the "cpio" program.
@@ -56,12 +56,12 @@ struct cpio {
        int               extract_flags; /* Flags for extract operation */
        char              symlink_mode; /* H or L, per BSD conventions */
        const char       *compress_program;
-       char              line_separator; /* --null ? '\0' : '\n' */
        int               option_append; /* -A, only relevant for -o */
        int               option_atime_restore; /* -a */
        int               option_follow_links; /* -L */
        int               option_link; /* -l */
        int               option_list; /* -t */
+       char              option_null; /* --null */
        int               option_numeric_uid_gid; /* -n */
        int               option_rename; /* -r */
        char             *destdir;
@@ -76,6 +76,7 @@ struct cpio {
 
        /* Miscellaneous state information */
        struct archive   *archive;
+       struct archive   *archive_read_disk;
        int               argc;
        char            **argv;
        int               return_value; /* Value returned by main() */
@@ -85,35 +86,24 @@ struct cpio {
        struct name_cache *gname_cache;
 
        /* Work data. */
-       struct matching  *matching;
+       struct lafe_matching  *matching;
        char             *buff;
        size_t            buff_size;
 };
 
-/* Name of this program; used in error reporting, initialized in main(). */
-const char *cpio_progname;
-
-void   cpio_errc(int _eval, int _code, const char *fmt, ...) __LA_DEAD;
-void   cpio_warnc(int _code, const char *fmt, ...);
-
-int    owner_parse(const char *, int *, int *);
+const char *owner_parse(const char *, int *, int *);
 
 
 /* Fake short equivalents for long options that otherwise lack them. */
 enum {
        OPTION_INSECURE = 1,
+       OPTION_LZMA,
        OPTION_NO_PRESERVE_OWNER,
+       OPTION_PRESERVE_OWNER,
        OPTION_QUIET,
        OPTION_VERSION
 };
 
-struct line_reader;
-
-struct line_reader *process_lines_init(const char *, char separator);
-const char *process_lines_next(struct line_reader *);
-void   process_lines_free(struct line_reader *);
-
 int    cpio_getopt(struct cpio *cpio);
-int    include_from_file(struct cpio *, const char *);
 
 #endif
index 8ade731..31d9a73 100644 (file)
 #if defined(PLATFORM_CONFIG_H)
 /* Use hand-built config.h in environments that need it. */
 #include PLATFORM_CONFIG_H
-#elif defined(HAVE_CONFIG_H)
-/* Most POSIX platforms use the 'configure' script to build config.h */
-#include "config.h"
 #else
-/* Warn if cpio hasn't been (automatically or manually) configured. */
-#error Oops: No config.h and no built-in configuration in cpio_platform.h.
-#endif /* !HAVE_CONFIG_H */
+/* Read config.h or die trying. */
+#include "config.h"
+#endif
 
-/* No non-FreeBSD platform will have __FBSDID, so just define it here. */
-#ifdef __FreeBSD__
-#include <sys/cdefs.h>  /* For __FBSDID */
-#elif !defined(__FBSDID)
-/* Just leaving this macro replacement empty leads to a dangling semicolon. */
+/* Get a real definition for __FBSDID if we can */
+#if HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+
+/* If not, define it so as to avoid dangling semicolons. */
+#ifndef __FBSDID
 #define        __FBSDID(a)     struct _undefined_hack
 #endif
 
 #include "archive_entry.h"
 #endif
 
-/*
- * We need to be able to display a filesize using printf().  The type
- * and format string here must be compatible with one another and
- * large enough for any file.
- */
-#if HAVE_UINTMAX_T
-#define        CPIO_FILESIZE_TYPE      uintmax_t
-#define        CPIO_FILESIZE_PRINTF    "%ju"
-#else
-#if HAVE_UNSIGNED_LONG_LONG
-#define        CPIO_FILESIZE_TYPE      unsigned long long
-#define        CPIO_FILESIZE_PRINTF    "%llu"
-#else
-#define        CPIO_FILESIZE_TYPE      unsigned long
-#define        CPIO_FILESIZE_PRINTF    "%lu"
-#endif
-#endif
-
 /* How to mark functions that don't return. */
 #if defined(__GNUC__) && (__GNUC__ > 2 || \
                           (__GNUC__ == 2 && __GNUC_MINOR__ >= 5))
@@ -89,9 +70,7 @@
 #define __LA_DEAD
 #endif
 
-#if defined(__CYGWIN__)
-#include "cpio_cygwin.h"
-#elif defined(_WIN32)  /* && !__CYGWIN__ */
+#if defined(_WIN32) && !defined(__CYGWIN__)
 #include "cpio_windows.h"
 #endif
 
diff --git a/contrib/libarchive/libarchive/COPYING b/contrib/libarchive/libarchive/COPYING
deleted file mode 100644 (file)
index 90ef954..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-All of the C source code, header files, and documentation in this
-package are covered by the following:
-
-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.
-
-===========================================================================
-
-Shell scripts, makefiles, and certain other files may be covered by
-other licenses.  In particular, some distributions of this library
-contain Makefiles and/or shell scripts that are generated
-automatically by GNU autoconf and GNU automake.  Those generated files
-are controlled by the relevant licenses.
-
-$FreeBSD: src/lib/libarchive/COPYING,v 1.3 2007/01/09 08:05:54 kientzle Exp $
-
diff --git a/contrib/libarchive/libarchive/README b/contrib/libarchive/libarchive/README
deleted file mode 100644 (file)
index df62c23..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-$FreeBSD: src/lib/libarchive/README,v 1.5 2007/03/03 07:37:35 kientzle Exp $
-
-libarchive: a library for reading and writing streaming archives
-
-This is all under a BSD license.  Use, enjoy, but don't blame me if it breaks!
-
-Documentation:
- * libarchive.3 gives an overview of the library as a whole
- * archive_read.3, archive_write.3, and archive_write_disk.3 provide
-   detailed calling sequences for the read and write APIs
- * archive_entry.3 details the "struct archive_entry" utility class
- * libarchive-formats.5 documents the file formats supported by the library
- * tar.5 provides some detailed information about a variety of different
-   "tar" formats.
-
-You should also read the copious comments in "archive.h" and the source
-code for the sample "bsdtar" and "minitar" programs for more details.
-Please let me know about any errors or omissions you find.
-
-Currently, the library automatically detects and reads the following:
-  * gzip compression
-  * bzip2 compression
-  * compress/LZW compression
-  * GNU tar format (including GNU long filenames, long link names, and
-    sparse files)
-  * Solaris 9 extended tar format (including ACLs)
-  * Old V7 tar archives
-  * POSIX ustar
-  * POSIX pax interchange format
-  * POSIX octet-oriented cpio
-  * SVR4 ASCII cpio
-  * Binary cpio (big-endian or little-endian)
-  * ISO9660 CD-ROM images (with optional Rockridge extensions)
-  * ZIP archives (with uncompressed or "deflate" compressed entries)
-
-The library can write:
-  * gzip compression
-  * bzip2 compression
-  * POSIX ustar
-  * POSIX pax interchange format
-  * "restricted" pax format, which will create ustar archives except for
-    entries that require pax extensions (for long filenames, ACLs, etc).
-  * POSIX octet-oriented cpio
-  * shar archives
-
-Notes:
- * This is a heavily stream-oriented system.  There is no direct
-   support for in-place modification or random access and no intention
-   of ever adding such support.  Adding such support would require
-   sacrificing a lot of other features, so don't bother asking.
-
- * The library is designed to be extended with new compression and
-   archive formats.  The only requirement is that the format be
-   readable or writable as a stream and that each archive entry be
-   independent.
-
- * On read, compression and format are always detected automatically.
-
- * I've attempted to minimize static link pollution.  If you don't
-   explicitly invoke a particular feature (such as support for a
-   particular compression or format), it won't get pulled in.
-   In particular, if you don't explicitly enable a particular
-   compression or decompression support, you won't need to link
-   against the corresponding compression or decompression libraries.
-   This also reduces the size of statically-linked binaries in
-   environments where that matters.
-
- * On read, the library accepts whatever blocks you hand it.
-   Your read callback is free to pass the library a byte at a time
-   or mmap the entire archive and give it to the library at once.
-   On write, the library always produces correctly-blocked
-   output.
-
- * The object-style approach allows you to have multiple archive streams
-   open at once.  bsdtar uses this in its "@archive" extension.
-
- * The archive itself is read/written using callback functions.
-   You can read an archive directly from an in-memory buffer or
-   write it to a socket, if you wish.  There are some utility
-   functions to provide easy-to-use "open file," etc, capabilities.
-
- * The read/write APIs are designed to allow individual entries
-   to be read or written to any data source:  You can create
-   a block of data in memory and add it to a tar archive without
-   first writing a temporary file.  You can also read an entry from
-   an archive and write the data directly to a socket.  If you want
-   to read/write entries to disk, the archive_write_disk interface
-   treats a directory as if it were an archive so you can copy
-   from archive->disk using the same code you use for archive->archive
-   transfers.
-
- * Note: "pax interchange format" is really an extended tar format,
-   despite what the name says.
index 917c19a..5ca28eb 100644 (file)
  * this header!  If you must conditionalize, use predefined compiler and/or
  * platform macros.
  */
+#if defined(__BORLANDC__) && __BORLANDC__ >= 0x560
+# define __LA_STDINT_H <stdint.h>
+#elif !defined(__WATCOMC__) && !defined(_MSC_VER) && !defined(__INTERIX) && !defined(__BORLANDC__)
+# define __LA_STDINT_H <inttypes.h>
+#endif
 
 #include <sys/stat.h>
 #include <sys/types.h>  /* Linux requires this for off_t */
-#if !defined(__WATCOMC__) && !defined(_MSC_VER) && !defined(__INTERIX)
-/* Header unavailable on Watcom C or MS Visual C++ or SFU. */
-#include <inttypes.h> /* int64_t, etc. */
+#ifdef __LA_STDINT_H
+# include __LA_STDINT_H /* int64_t, etc. */
 #endif
 #include <stdio.h> /* For FILE * */
 
 /* These should match the types used in 'struct stat' */
 #if defined(_WIN32) && !defined(__CYGWIN__)
 #define        __LA_INT64_T    __int64
-# if   defined(_WIN64)
+# if defined(_SSIZE_T_DEFINED)
+#  define      __LA_SSIZE_T    ssize_t
+# elif defined(_WIN64)
 #  define      __LA_SSIZE_T    __int64
 # else
 #  define      __LA_SSIZE_T    long
 # endif
-#define        __LA_UID_T      unsigned int
-#define        __LA_GID_T      unsigned int
+# if defined(__BORLANDC__)
+#  define      __LA_UID_T      uid_t
+#  define      __LA_GID_T      gid_t
+# else
+#  define      __LA_UID_T      short
+#  define      __LA_GID_T      short
+# endif
 #else
 #include <unistd.h>  /* ssize_t, uid_t, and gid_t */
 #define        __LA_INT64_T    int64_t
@@ -118,13 +129,13 @@ extern "C" {
  *             (ARCHIVE_API_VERSION * 1000000 + ARCHIVE_API_FEATURE * 1000)
  * #endif
  */
-#define        ARCHIVE_VERSION_NUMBER 2007001
+#define        ARCHIVE_VERSION_NUMBER 2008004
 __LA_DECL int          archive_version_number(void);
 
 /*
  * Textual name/version of the library, useful for version displays.
  */
-#define        ARCHIVE_VERSION_STRING "libarchive 2.7.1"
+#define        ARCHIVE_VERSION_STRING "libarchive 2.8.4"
 __LA_DECL const char * archive_version_string(void);
 
 #if ARCHIVE_VERSION_NUMBER < 3000000
@@ -232,6 +243,8 @@ typedef int archive_close_callback(struct archive *, void *_client_data);
 #define        ARCHIVE_COMPRESSION_PROGRAM     4
 #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.
@@ -272,6 +285,8 @@ typedef int archive_close_callback(struct archive *, void *_client_data);
 #define        ARCHIVE_FORMAT_AR_GNU                   (ARCHIVE_FORMAT_AR | 1)
 #define        ARCHIVE_FORMAT_AR_BSD                   (ARCHIVE_FORMAT_AR | 2)
 #define        ARCHIVE_FORMAT_MTREE                    0x80000
+#define        ARCHIVE_FORMAT_RAW                      0x90000
+#define        ARCHIVE_FORMAT_XAR                      0xA0000
 
 /*-
  * Basic outline for reading an archive:
@@ -306,6 +321,8 @@ __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 *);
 
 __LA_DECL int           archive_read_support_format_all(struct archive *);
@@ -315,7 +332,9 @@ __LA_DECL int                archive_read_support_format_empty(struct archive *);
 __LA_DECL int           archive_read_support_format_gnutar(struct archive *);
 __LA_DECL int           archive_read_support_format_iso9660(struct archive *);
 __LA_DECL int           archive_read_support_format_mtree(struct archive *);
+__LA_DECL int           archive_read_support_format_raw(struct archive *);
 __LA_DECL int           archive_read_support_format_tar(struct archive *);
+__LA_DECL int           archive_read_support_format_xar(struct archive *);
 __LA_DECL int           archive_read_support_format_zip(struct archive *);
 
 
@@ -527,6 +546,7 @@ __LA_DECL int                archive_write_set_format_pax_restricted(struct archive *);
 __LA_DECL int           archive_write_set_format_shar(struct archive *);
 __LA_DECL int           archive_write_set_format_shar_dump(struct archive *);
 __LA_DECL int           archive_write_set_format_ustar(struct archive *);
+__LA_DECL int           archive_write_set_format_zip(struct archive *);
 __LA_DECL int           archive_write_open(struct archive *, void *,
                     archive_open_callback *, archive_write_callback *,
                     archive_close_callback *);
@@ -702,6 +722,7 @@ __LA_DECL void               archive_set_error(struct archive *, int _err,
                            const char *fmt, ...);
 __LA_DECL void          archive_copy_error(struct archive *dest,
                            struct archive *src);
+__LA_DECL int           archive_file_count(struct archive *);
 
 #ifdef __cplusplus
 }
index 7a19087..e27e5d8 100644 (file)
@@ -24,7 +24,7 @@
  */
 
 #include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_check_magic.c,v 1.9 2008/12/06 05:52:01 kientzle Exp $");
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_check_magic.c 201089 2009-12-28 02:20:23Z kientzle $");
 
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
@@ -50,7 +50,16 @@ __FBSDID("$FreeBSD: src/lib/libarchive/archive_check_magic.c,v 1.9 2008/12/06 05
 static void
 errmsg(const char *m)
 {
-       write(2, m, strlen(m));
+       size_t s = strlen(m);
+       ssize_t written;
+
+       while (s > 0) {
+               written = write(2, m, strlen(m));
+               if (written <= 0)
+                       return;
+               m += written;
+               s -= written;
+       }
 }
 
 static void
@@ -60,8 +69,7 @@ diediedie(void)
        /* Cause a breakpoint exception  */
        DebugBreak();
 #endif
-       *(char *)0 = 1; /* Deliberately segfault and force a coredump. */
-       _exit(1);       /* If that didn't work, just exit with an error. */
+       abort();        /* Terminate the program abnormally. */
 }
 
 static const char *
@@ -85,7 +93,7 @@ write_all_states(unsigned int states)
        unsigned int lowbit;
 
        /* A trick for computing the lowest set bit. */
-       while ((lowbit = states & (-states)) != 0) {
+       while ((lowbit = states & (1 + ~states)) != 0) {
                states &= ~lowbit;              /* Clear the low bit. */
                errmsg(state_name(lowbit));
                if (states != 0)
index 3c62fbf..edc90ee 100644 (file)
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/lib/libarchive/archive_endian.h,v 1.4 2008/12/06 06:12:24 kientzle Exp $
+ * $FreeBSD: head/lib/libarchive/archive_endian.h 201085 2009-12-28 02:17:15Z kientzle $
  *
  * Borrowed from FreeBSD's <sys/endian.h>
  */
 
+#ifndef __LIBARCHIVE_BUILD
+#error This header is only to be used internally to libarchive.
+#endif
+
 /* Note:  This is a purely internal header! */
 /* Do not use this outside of libarchive internal code! */
 
@@ -41,7 +45,7 @@
  * - SGI MIPSpro
  * - Microsoft Visual C++ 6.0 (supposedly newer versions too)
  */
-#if defined(__WATCOMC__) || defined(__sgi)
+#if defined(__WATCOMC__) || defined(__sgi) || defined(__hpux) || defined(__BORLANDC__)
 #define        inline
 #elif defined(_MSC_VER)
 #define inline __inline
index ffbd92f..f734b8c 100644 (file)
@@ -24,7 +24,7 @@
  */
 
 #include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_entry.c,v 1.55 2008/12/23 05:01:43 kientzle Exp $");
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_entry.c 201096 2009-12-28 02:41:27Z kientzle $");
 
 #ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
@@ -32,12 +32,12 @@ __FBSDID("$FreeBSD: src/lib/libarchive/archive_entry.c,v 1.55 2008/12/23 05:01:4
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
 #endif
-#ifdef MAJOR_IN_MKDEV
+#if MAJOR_IN_MKDEV
 #include <sys/mkdev.h>
-#else
-#ifdef MAJOR_IN_SYSMACROS
+#define HAVE_MAJOR
+#elif MAJOR_IN_SYSMACROS
 #include <sys/sysmacros.h>
-#endif
+#define HAVE_MAJOR
 #endif
 #ifdef HAVE_LIMITS_H
 #include <limits.h>
@@ -75,6 +75,13 @@ __FBSDID("$FreeBSD: src/lib/libarchive/archive_entry.c,v 1.55 2008/12/23 05:01:4
 #undef max
 #define        max(a, b)       ((a)>(b)?(a):(b))
 
+#if !defined(HAVE_MAJOR) && !defined(major)
+/* Replacement for major/minor/makedev. */
+#define        major(x) ((int)(0x00ff & ((x) >> 8)))
+#define        minor(x) ((int)(0xffff00ff & (x)))
+#define        makedev(maj,min) ((0xff00 & ((maj)<<8)) | (0xffff00ff & (min)))
+#endif
+
 /* Play games to come up with a suitable makedev() definition. */
 #ifdef __QNXNTO__
 /* QNX.  <sigh> */
@@ -115,6 +122,7 @@ static int  acl_special(struct archive_entry *entry,
 static struct ae_acl *acl_new_entry(struct archive_entry *entry,
                    int type, int permset, int tag, int id);
 static int     isint_w(const wchar_t *start, const wchar_t *end, int *result);
+static int     ismode_w(const wchar_t *start, const wchar_t *end, int *result);
 static void    next_field_w(const wchar_t **wp, const wchar_t **start,
                    const wchar_t **end, wchar_t *sep);
 static int     prefix_w(const wchar_t *start, const wchar_t *end,
@@ -214,7 +222,7 @@ static const wchar_t *
 aes_get_wcs(struct aes *aes)
 {
        wchar_t *w;
-       int r;
+       size_t r;
 
        /* Return WCS form if we already have it. */
        if (aes->aes_set & AES_SET_WCS)
@@ -232,7 +240,7 @@ aes_get_wcs(struct aes *aes)
                if (w == NULL)
                        __archive_errx(1, "No memory for aes_get_wcs()");
                r = mbstowcs(w, aes->aes_mbs.s, wcs_length);
-               if (r > 0) {
+               if (r != (size_t)-1 && r != 0) {
                        w[r] = 0;
                        aes->aes_set |= AES_SET_WCS;
                        return (aes->aes_wcs = w);
@@ -617,6 +625,12 @@ archive_entry_ino(struct archive_entry *entry)
        return (entry->ae_stat.aest_ino);
 }
 
+int64_t
+archive_entry_ino64(struct archive_entry *entry)
+{
+       return (entry->ae_stat.aest_ino);
+}
+
 mode_t
 archive_entry_mode(struct archive_entry *entry)
 {
@@ -816,6 +830,13 @@ archive_entry_set_ino(struct archive_entry *entry, unsigned long ino)
        entry->ae_stat.aest_ino = ino;
 }
 
+void
+archive_entry_set_ino64(struct archive_entry *entry, int64_t ino)
+{
+       entry->stat_valid = 0;
+       entry->ae_stat.aest_ino = ino;
+}
+
 void
 archive_entry_set_hardlink(struct archive_entry *entry, const char *target)
 {
@@ -846,6 +867,16 @@ archive_entry_copy_hardlink_w(struct archive_entry *entry, const wchar_t *target
                entry->ae_set &= ~AE_SET_HARDLINK;
 }
 
+int
+archive_entry_update_hardlink_utf8(struct archive_entry *entry, const char *target)
+{
+       if (target != NULL)
+               entry->ae_set |= AE_SET_HARDLINK;
+       else
+               entry->ae_set &= ~AE_SET_HARDLINK;
+       return (aes_update_utf8(&entry->ae_hardlink, target));
+}
+
 void
 archive_entry_set_atime(struct archive_entry *entry, time_t t, long ns)
 {
@@ -1094,6 +1125,16 @@ archive_entry_copy_symlink_w(struct archive_entry *entry, const wchar_t *linknam
                entry->ae_set &= ~AE_SET_SYMLINK;
 }
 
+int
+archive_entry_update_symlink_utf8(struct archive_entry *entry, const char *linkname)
+{
+       if (linkname != NULL)
+               entry->ae_set |= AE_SET_SYMLINK;
+       else
+               entry->ae_set &= ~AE_SET_SYMLINK;
+       return (aes_update_utf8(&entry->ae_symlink, linkname));
+}
+
 void
 archive_entry_set_uid(struct archive_entry *entry, uid_t u)
 {
@@ -1185,7 +1226,7 @@ archive_entry_acl_add_entry_w(struct archive_entry *entry,
        archive_entry_acl_add_entry_w_len(entry, type, permset, tag, id, name, wcslen(name));
 }
 
-void
+static void
 archive_entry_acl_add_entry_w_len(struct archive_entry *entry,
     int type, int permset, int tag, int id, const wchar_t *name, size_t len)
 {
@@ -1238,7 +1279,7 @@ static struct ae_acl *
 acl_new_entry(struct archive_entry *entry,
     int type, int permset, int tag, int id)
 {
-       struct ae_acl *ap;
+       struct ae_acl *ap, *aq;
 
        if (type != ARCHIVE_ENTRY_ACL_TYPE_ACCESS &&
            type != ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)
@@ -1251,20 +1292,26 @@ acl_new_entry(struct archive_entry *entry,
        /* XXX TODO: More sanity-checks on the arguments XXX */
 
        /* If there's a matching entry already in the list, overwrite it. */
-       for (ap = entry->acl_head; ap != NULL; ap = ap->next) {
+       ap = entry->acl_head;
+       aq = NULL;
+       while (ap != NULL) {
                if (ap->type == type && ap->tag == tag && ap->id == id) {
                        ap->permset = permset;
                        return (ap);
                }
+               aq = ap;
+               ap = ap->next;
        }
 
-       /* Add a new entry to the list. */
+       /* Add a new entry to the end of the list. */
        ap = (struct ae_acl *)malloc(sizeof(*ap));
        if (ap == NULL)
                return (NULL);
        memset(ap, 0, sizeof(*ap));
-       ap->next = entry->acl_head;
-       entry->acl_head = ap;
+       if (aq == NULL)
+               entry->acl_head = ap;
+       else
+               aq->next = ap;
        ap->type = type;
        ap->tag = tag;
        ap->id = id;
@@ -1586,11 +1633,10 @@ __archive_entry_acl_parse_w(struct archive_entry *entry,
        struct {
                const wchar_t *start;
                const wchar_t *end;
-       } field[4];
+       } field[4], name;
 
-       int fields;
+       int fields, n;
        int type, tag, permset, id;
-       const wchar_t *p;
        wchar_t sep;
 
        while (text != NULL  &&  *text != L'\0') {
@@ -1609,8 +1655,9 @@ __archive_entry_acl_parse_w(struct archive_entry *entry,
                        ++fields;
                } while (sep == L':');
 
-               if (fields < 3)
-                       return (ARCHIVE_WARN);
+               /* Set remaining fields to blank. */
+               for (n = fields; n < 4; ++n)
+                       field[n].start = field[n].end = NULL;
 
                /* Check for a numeric ID in field 1 or 3. */
                id = -1;
@@ -1619,54 +1666,58 @@ __archive_entry_acl_parse_w(struct archive_entry *entry,
                if (id == -1 && fields > 3)
                        isint_w(field[3].start, field[3].end, &id);
 
-               /* Parse the permissions from field 2. */
-               permset = 0;
-               p = field[2].start;
-               while (p < field[2].end) {
-                       switch (*p++) {
-                       case 'r': case 'R':
-                               permset |= ARCHIVE_ENTRY_ACL_READ;
-                               break;
-                       case 'w': case 'W':
-                               permset |= ARCHIVE_ENTRY_ACL_WRITE;
-                               break;
-                       case 'x': case 'X':
-                               permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
-                               break;
-                       case '-':
-                               break;
-                       default:
-                               return (ARCHIVE_WARN);
-                       }
-               }
-
                /*
                 * Solaris extension:  "defaultuser::rwx" is the
                 * default ACL corresponding to "user::rwx", etc.
                 */
-               if (field[0].end-field[0].start > 7
+               if (field[0].end - field[0].start > 7
                    && wmemcmp(field[0].start, L"default", 7) == 0) {
                        type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
                        field[0].start += 7;
                } else
                        type = default_type;
 
+               name.start = name.end = NULL;
                if (prefix_w(field[0].start, field[0].end, L"user")) {
-                       if (id != -1 || field[1].start < field[1].end)
+                       if (!ismode_w(field[2].start, field[2].end, &permset))
+                               return (ARCHIVE_WARN);
+                       if (id != -1 || field[1].start < field[1].end) {
                                tag = ARCHIVE_ENTRY_ACL_USER;
-                       else
+                               name = field[1];
+                       } else
                                tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
                } else if (prefix_w(field[0].start, field[0].end, L"group")) {
-                       if (id != -1 || field[1].start < field[1].end)
+                       if (!ismode_w(field[2].start, field[2].end, &permset))
+                               return (ARCHIVE_WARN);
+                       if (id != -1 || field[1].start < field[1].end) {
                                tag = ARCHIVE_ENTRY_ACL_GROUP;
-                       else
+                               name = field[1];
+                       } else
                                tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
                } else if (prefix_w(field[0].start, field[0].end, L"other")) {
-                       if (id != -1 || field[1].start < field[1].end)
+                       if (fields == 2
+                           && field[1].start < field[1].end
+                           && ismode_w(field[1].start, field[1].end, &permset)) {
+                               /* This is Solaris-style "other:rwx" */
+                       } else if (fields == 3
+                           && field[1].start == field[1].end
+                           && field[2].start < field[2].end
+                           && ismode_w(field[2].start, field[2].end, &permset)) {
+                               /* This is FreeBSD-style "other::rwx" */
+                       } else
                                return (ARCHIVE_WARN);
                        tag = ARCHIVE_ENTRY_ACL_OTHER;
                } else if (prefix_w(field[0].start, field[0].end, L"mask")) {
-                       if (id != -1 || field[1].start < field[1].end)
+                       if (fields == 2
+                           && field[1].start < field[1].end
+                           && ismode_w(field[1].start, field[1].end, &permset)) {
+                               /* This is Solaris-style "mask:rwx" */
+                       } else if (fields == 3
+                           && field[1].start == field[1].end
+                           && field[2].start < field[2].end
+                           && ismode_w(field[2].start, field[2].end, &permset)) {
+                               /* This is FreeBSD-style "mask::rwx" */
+                       } else
                                return (ARCHIVE_WARN);
                        tag = ARCHIVE_ENTRY_ACL_MASK;
                } else
@@ -1674,103 +1725,11 @@ __archive_entry_acl_parse_w(struct archive_entry *entry,
 
                /* Add entry to the internal list. */
                archive_entry_acl_add_entry_w_len(entry, type, permset,
-                   tag, id, field[1].start, field[1].end - field[1].start);
+                   tag, id, name.start, name.end - name.start);
        }
        return (ARCHIVE_OK);
 }
 
-/*
- * extended attribute handling
- */
-
-void
-archive_entry_xattr_clear(struct archive_entry *entry)
-{
-       struct ae_xattr *xp;
-
-       while (entry->xattr_head != NULL) {
-               xp = entry->xattr_head->next;
-               free(entry->xattr_head->name);
-               free(entry->xattr_head->value);
-               free(entry->xattr_head);
-               entry->xattr_head = xp;
-       }
-
-       entry->xattr_head = NULL;
-}
-
-void
-archive_entry_xattr_add_entry(struct archive_entry *entry,
-       const char *name, const void *value, size_t size)
-{
-       struct ae_xattr *xp;
-
-       for (xp = entry->xattr_head; xp != NULL; xp = xp->next)
-               ;
-
-       if ((xp = (struct ae_xattr *)malloc(sizeof(struct ae_xattr))) == NULL)
-               /* XXX Error XXX */
-               return;
-
-       xp->name = strdup(name);
-       if ((xp->value = malloc(size)) != NULL) {
-               memcpy(xp->value, value, size);
-               xp->size = size;
-       } else
-               xp->size = 0;
-
-       xp->next = entry->xattr_head;
-       entry->xattr_head = xp;
-}
-
-
-/*
- * returns number of the extended attribute entries
- */
-int
-archive_entry_xattr_count(struct archive_entry *entry)
-{
-       struct ae_xattr *xp;
-       int count = 0;
-
-       for (xp = entry->xattr_head; xp != NULL; xp = xp->next)
-               count++;
-
-       return count;
-}
-
-int
-archive_entry_xattr_reset(struct archive_entry * entry)
-{
-       entry->xattr_p = entry->xattr_head;
-
-       return archive_entry_xattr_count(entry);
-}
-
-int
-archive_entry_xattr_next(struct archive_entry * entry,
-       const char **name, const void **value, size_t *size)
-{
-       if (entry->xattr_p) {
-               *name = entry->xattr_p->name;
-               *value = entry->xattr_p->value;
-               *size = entry->xattr_p->size;
-
-               entry->xattr_p = entry->xattr_p->next;
-
-               return (ARCHIVE_OK);
-       } else {
-               *name = NULL;
-               *value = NULL;
-               *size = (size_t)0;
-               return (ARCHIVE_WARN);
-       }
-}
-
-/*
- * end of xattr handling
- */
-
 /*
  * Parse a string to a positive decimal integer.  Returns true if
  * the string is non-empty and consists only of decimal digits,
@@ -1797,6 +1756,40 @@ isint_w(const wchar_t *start, const wchar_t *end, int *result)
        return (1);
 }
 
+/*
+ * Parse a string as a mode field.  Returns true if
+ * the string is non-empty and consists only of mode characters,
+ * false otherwise.
+ */
+static int
+ismode_w(const wchar_t *start, const wchar_t *end, int *permset)
+{
+       const wchar_t *p;
+
+       if (start >= end)
+               return (0);
+       p = start;
+       *permset = 0;
+       while (p < end) {
+               switch (*p++) {
+               case 'r': case 'R':
+                       *permset |= ARCHIVE_ENTRY_ACL_READ;
+                       break;
+               case 'w': case 'W':
+                       *permset |= ARCHIVE_ENTRY_ACL_WRITE;
+                       break;
+               case 'x': case 'X':
+                       *permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
+                       break;
+               case '-':
+                       break;
+               default:
+                       return (0);
+               }
+       }
+       return (1);
+}
+
 /*
  * Match "[:whitespace:]*(.*)[:whitespace:]*[:,\n]".  *wp is updated
  * to point to just after the separator.  *start points to the first
@@ -1949,6 +1942,18 @@ static struct flag {
        { "nouunlnk",   L"nouunlnk",            UF_NOUNLINK,    0 },
        { "nouunlink",  L"nouunlink",           UF_NOUNLINK,    0 },
 #endif
+#ifdef EXT2_UNRM_FL
+        { "nouunlink", L"nouunlink",           EXT2_UNRM_FL,   0},
+#endif
+
+#ifdef EXT2_BTREE_FL
+        { "nobtree",   L"nobtree",             EXT2_BTREE_FL,  0 },
+#endif
+
+#ifdef EXT2_ECOMPR_FL
+        { "nocomperr", L"nocomperr",           EXT2_ECOMPR_FL, 0 },
+#endif
+
 #ifdef EXT2_COMPR_FL                           /* 'c' */
         { "nocompress",        L"nocompress",          EXT2_COMPR_FL,  0 },
 #endif
@@ -1956,6 +1961,46 @@ static struct flag {
 #ifdef EXT2_NOATIME_FL                         /* 'A' */
         { "noatime",   L"noatime",             0,              EXT2_NOATIME_FL},
 #endif
+
+#ifdef EXT2_DIRTY_FL
+        { "nocompdirty",L"nocompdirty",                EXT2_DIRTY_FL,          0},
+#endif
+
+#ifdef EXT2_COMPRBLK_FL
+#ifdef EXT2_NOCOMPR_FL
+        { "nocomprblk",        L"nocomprblk",          EXT2_COMPRBLK_FL, EXT2_NOCOMPR_FL},
+#else
+        { "nocomprblk",        L"nocomprblk",          EXT2_COMPRBLK_FL,       0},
+#endif
+#endif
+#ifdef EXT2_DIRSYNC_FL
+        { "nodirsync", L"nodirsync",           EXT2_DIRSYNC_FL,        0},
+#endif
+#ifdef EXT2_INDEX_FL
+        { "nohashidx", L"nohashidx",           EXT2_INDEX_FL,          0},
+#endif
+#ifdef EXT2_IMAGIC_FL
+        { "noimagic",  L"noimagic",            EXT2_IMAGIC_FL,         0},
+#endif
+#ifdef EXT3_JOURNAL_DATA_FL
+        { "nojournal", L"nojournal",           EXT3_JOURNAL_DATA_FL,   0},
+#endif
+#ifdef EXT2_SECRM_FL
+        { "nosecuredeletion",L"nosecuredeletion",EXT2_SECRM_FL,                0},
+#endif
+#ifdef EXT2_SYNC_FL
+        { "nosync",    L"nosync",              EXT2_SYNC_FL,           0},
+#endif
+#ifdef EXT2_NOTAIL_FL
+        { "notail",    L"notail",              0,              EXT2_NOTAIL_FL},
+#endif
+#ifdef EXT2_TOPDIR_FL
+        { "notopdir",  L"notopdir",            EXT2_TOPDIR_FL,         0},
+#endif
+#ifdef EXT2_RESERVED_FL
+        { "noreserved",        L"noreserved",          EXT2_RESERVED_FL,       0},
+#endif
+
        { NULL,         NULL,                   0,              0 }
 };
 
index 52fcc4a..d572817 100644 (file)
@@ -22,7 +22,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD: src/lib/libarchive/archive_entry.h,v 1.31 2008/12/06 06:18:46 kientzle Exp $
+ * $FreeBSD: head/lib/libarchive/archive_entry.h 201096 2009-12-28 02:41:27Z kientzle $
  */
 
 #ifndef ARCHIVE_ENTRY_H_INCLUDED
 #include <stddef.h>  /* for wchar_t */
 #include <time.h>
 
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#include <windows.h>
+#endif
+
 /* Get appropriate definitions of standard POSIX-style types. */
 /* These should match the types used in 'struct stat' */
 #if defined(_WIN32) && !defined(__CYGWIN__)
 #define        __LA_INT64_T    __int64
-#define        __LA_UID_T      unsigned int
-#define        __LA_GID_T      unsigned int
-#define        __LA_DEV_T      unsigned int
-#define        __LA_MODE_T     unsigned short
+# if defined(__BORLANDC__)
+#  define      __LA_UID_T      uid_t
+#  define      __LA_GID_T      gid_t
+#  define      __LA_DEV_T      dev_t
+#  define      __LA_MODE_T     mode_t
+# else
+#  define      __LA_UID_T      short
+#  define      __LA_GID_T      short
+#  define      __LA_DEV_T      unsigned int
+#  define      __LA_MODE_T     unsigned short
+# endif
 #else
 #include <unistd.h>
 #define        __LA_INT64_T    int64_t
@@ -194,6 +205,7 @@ __LA_DECL const wchar_t     *archive_entry_gname_w(struct archive_entry *);
 __LA_DECL const char   *archive_entry_hardlink(struct archive_entry *);
 __LA_DECL const wchar_t        *archive_entry_hardlink_w(struct archive_entry *);
 __LA_DECL __LA_INO_T    archive_entry_ino(struct archive_entry *);
+__LA_DECL __LA_INT64_T  archive_entry_ino64(struct archive_entry *);
 __LA_DECL __LA_MODE_T   archive_entry_mode(struct archive_entry *);
 __LA_DECL time_t        archive_entry_mtime(struct archive_entry *);
 __LA_DECL long          archive_entry_mtime_nsec(struct archive_entry *);
@@ -227,6 +239,10 @@ __LA_DECL const wchar_t    *archive_entry_uname_w(struct archive_entry *);
 
 __LA_DECL void archive_entry_set_atime(struct archive_entry *, time_t, long);
 __LA_DECL void  archive_entry_unset_atime(struct archive_entry *);
+#if defined(_WIN32) && !defined(__CYGWIN__)
+__LA_DECL void archive_entry_copy_bhfi(struct archive_entry *,
+                                                                          BY_HANDLE_FILE_INFORMATION *);
+#endif
 __LA_DECL void archive_entry_set_birthtime(struct archive_entry *, time_t, long);
 __LA_DECL void  archive_entry_unset_birthtime(struct archive_entry *);
 __LA_DECL void archive_entry_set_ctime(struct archive_entry *, time_t, long);
@@ -251,7 +267,14 @@ __LA_DECL int      archive_entry_update_gname_utf8(struct archive_entry *, const char
 __LA_DECL void archive_entry_set_hardlink(struct archive_entry *, const char *);
 __LA_DECL void archive_entry_copy_hardlink(struct archive_entry *, const char *);
 __LA_DECL void archive_entry_copy_hardlink_w(struct archive_entry *, const wchar_t *);
+__LA_DECL int  archive_entry_update_hardlink_utf8(struct archive_entry *, const char *);
+#if ARCHIVE_VERSION_NUMBER >= 3000000
+/* Starting with libarchive 3.0, this will be synonym for ino64. */
+__LA_DECL void archive_entry_set_ino(struct archive_entry *, __LA_INT64_T);
+#else
 __LA_DECL void archive_entry_set_ino(struct archive_entry *, unsigned long);
+#endif
+__LA_DECL void archive_entry_set_ino64(struct archive_entry *, __LA_INT64_T);
 __LA_DECL void archive_entry_set_link(struct archive_entry *, const char *);
 __LA_DECL void archive_entry_copy_link(struct archive_entry *, const char *);
 __LA_DECL void archive_entry_copy_link_w(struct archive_entry *, const wchar_t *);
@@ -274,6 +297,7 @@ __LA_DECL void      archive_entry_copy_sourcepath(struct archive_entry *, const char
 __LA_DECL void archive_entry_set_symlink(struct archive_entry *, const char *);
 __LA_DECL void archive_entry_copy_symlink(struct archive_entry *, const char *);
 __LA_DECL void archive_entry_copy_symlink_w(struct archive_entry *, const wchar_t *);
+__LA_DECL int  archive_entry_update_symlink_utf8(struct archive_entry *, const char *);
 __LA_DECL void archive_entry_set_uid(struct archive_entry *, __LA_UID_T);
 __LA_DECL void archive_entry_set_uname(struct archive_entry *, const char *);
 __LA_DECL void archive_entry_copy_uname(struct archive_entry *, const char *);
  */
 
 #include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_virtual.c,v 1.1 2007/03/03 07:37:36 kientzle Exp $");
+__FBSDID("$FreeBSD$");
 
-#include "archive.h"
-#include "archive_entry.h"
 #include "archive_private.h"
+#include "archive_entry.h"
 
-int
-archive_write_close(struct archive *a)
-{
-       return ((a->vtable->archive_close)(a));
-}
+#if defined(_WIN32) && !defined(__CYGWIN__)
 
-int
-archive_read_close(struct archive *a)
-{
-       return ((a->vtable->archive_close)(a));
-}
+#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
 
-#if ARCHIVE_API_VERSION > 1
-int
-archive_write_finish(struct archive *a)
+__inline static void
+fileTimeToUtc(const FILETIME *filetime, time_t *time, long *ns)
 {
-       return ((a->vtable->archive_finish)(a));
-}
-#else
-/* Temporarily allow library to compile with either 1.x or 2.0 API. */
-void
-archive_write_finish(struct archive *a)
-{
-       (void)(a->vtable->archive_finish)(a);
-}
-#endif
+       ULARGE_INTEGER utc;
 
-int
-archive_read_finish(struct archive *a)
-{
-       return ((a->vtable->archive_finish)(a));
+       utc.HighPart = filetime->dwHighDateTime;
+       utc.LowPart  = filetime->dwLowDateTime;
+       if (utc.QuadPart >= EPOC_TIME) {
+               utc.QuadPart -= EPOC_TIME;
+               *time = (time_t)(utc.QuadPart / 10000000);      /* milli seconds base */
+               *ns = (long)(utc.QuadPart % 10000000) * 100;/* nano seconds base */
+       } else {
+               *time = 0;
+               *ns = 0;
+       }
 }
 
-int
-archive_write_header(struct archive *a, struct archive_entry *entry)
+void
+archive_entry_copy_bhfi(struct archive_entry *entry,
+                       BY_HANDLE_FILE_INFORMATION *bhfi)
 {
-       return ((a->vtable->archive_write_header)(a, entry));
-}
+       time_t secs;
+       long nsecs;
 
-int
-archive_write_finish_entry(struct archive *a)
-{
-       return ((a->vtable->archive_write_finish_entry)(a));
+       fileTimeToUtc(&bhfi->ftLastAccessTime, &secs, &nsecs);
+       archive_entry_set_atime(entry, secs, nsecs);
+       fileTimeToUtc(&bhfi->ftLastWriteTime, &secs, &nsecs);
+       archive_entry_set_mtime(entry, secs, nsecs);
+       fileTimeToUtc(&bhfi->ftCreationTime, &secs, &nsecs);
+       archive_entry_set_birthtime(entry, secs, nsecs);
+       archive_entry_set_dev(entry, bhfi->dwVolumeSerialNumber);
+       archive_entry_set_ino64(entry, (((int64_t)bhfi->nFileIndexHigh) << 32)
+               + bhfi->nFileIndexLow);
+       archive_entry_set_nlink(entry, bhfi->nNumberOfLinks);
+       archive_entry_set_size(entry, (((int64_t)bhfi->nFileSizeHigh) << 32)
+               + bhfi->nFileSizeLow);
+//     archive_entry_set_mode(entry, st->st_mode);
 }
-
-#if ARCHIVE_API_VERSION > 1
-ssize_t
-#else
-/* Temporarily allow library to compile with either 1.x or 2.0 API. */
-int
 #endif
-archive_write_data(struct archive *a, const void *buff, size_t s)
-{
-       return ((a->vtable->archive_write_data)(a, buff, s));
-}
-
-ssize_t
-archive_write_data_block(struct archive *a, const void *buff, size_t s, off_t o)
-{
-       return ((a->vtable->archive_write_data_block)(a, buff, s, o));
-}
index 3f624fc..ef59a5e 100644 (file)
@@ -24,7 +24,7 @@
  */
 
 #include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_entry_copy_stat.c,v 1.2 2008/09/30 03:53:03 kientzle Exp $");
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_entry_copy_stat.c 189466 2009-03-07 00:52:02Z kientzle $");
 
 #ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
index 9300fe3..3b13e19 100644 (file)
@@ -24,7 +24,7 @@
  */
 
 #include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_entry_link_resolver.c,v 1.4 2008/09/05 06:15:25 kientzle Exp $");
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_entry_link_resolver.c 201100 2009-12-28 03:05:31Z kientzle $");
 
 #ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
@@ -181,8 +181,10 @@ archive_entry_linkify(struct archive_entry_linkresolver *res,
        /* If it has only one link, then we're done. */
        if (archive_entry_nlink(*e) == 1)
                return;
-       /* Directories never have hardlinks. */
-       if (archive_entry_filetype(*e) == AE_IFDIR)
+       /* Directories, devices never have hardlinks. */
+       if (archive_entry_filetype(*e) == AE_IFDIR
+           || archive_entry_filetype(*e) == AE_IFBLK
+           || archive_entry_filetype(*e) == AE_IFCHR)
                return;
 
        switch (res->strategy) {
@@ -249,7 +251,7 @@ find_entry(struct archive_entry_linkresolver *res,
        struct links_entry      *le;
        int                      hash, bucket;
        dev_t                    dev;
-       ino_t                    ino;
+       int64_t                  ino;
 
        /* Free a held entry. */
        if (res->spare != NULL) {
@@ -264,15 +266,15 @@ find_entry(struct archive_entry_linkresolver *res,
                return (NULL);
 
        dev = archive_entry_dev(entry);
-       ino = archive_entry_ino(entry);
-       hash = dev ^ ino;
+       ino = archive_entry_ino64(entry);
+       hash = (int)(dev ^ ino);
 
        /* Try to locate this entry in the links cache. */
        bucket = hash % res->number_buckets;
        for (le = res->buckets[bucket]; le != NULL; le = le->next) {
                if (le->hash == hash
                    && dev == archive_entry_dev(le->canonical)
-                   && ino == archive_entry_ino(le->canonical)) {
+                   && ino == archive_entry_ino64(le->canonical)) {
                        /*
                         * Decrement link count each time and release
                         * the entry if it hits zero.  This saves
@@ -350,7 +352,7 @@ insert_entry(struct archive_entry_linkresolver *res,
        if (res->number_entries > res->number_buckets * 2)
                grow_hash(res);
 
-       hash = archive_entry_dev(entry) ^ archive_entry_ino(entry);
+       hash = archive_entry_dev(entry) ^ archive_entry_ino64(entry);
        bucket = hash % res->number_buckets;
 
        /* If we could allocate the entry, record it. */
index a4317de..5ab4f75 100644 (file)
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD: src/lib/libarchive/archive_entry_private.h,v 1.6 2008/09/30 03:53:03 kientzle Exp $
+ * $FreeBSD: head/lib/libarchive/archive_entry_private.h 201096 2009-12-28 02:41:27Z kientzle $
  */
 
+#ifndef __LIBARCHIVE_BUILD
+#error This header is only to be used internally to libarchive.
+#endif
+
 #ifndef ARCHIVE_ENTRY_PRIVATE_H_INCLUDED
 #define        ARCHIVE_ENTRY_PRIVATE_H_INCLUDED
 
@@ -115,7 +119,7 @@ struct archive_entry {
                int64_t         aest_birthtime;
                uint32_t        aest_birthtime_nsec;
                gid_t           aest_gid;
-               ino_t           aest_ino;
+               int64_t         aest_ino;
                mode_t          aest_mode;
                uint32_t        aest_nlink;
                uint64_t        aest_size;
index 315d5cf..ad772c9 100644 (file)
@@ -24,7 +24,7 @@
  */
 
 #include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_entry_stat.c,v 1.2 2008/09/30 03:53:03 kientzle Exp $");
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_entry_stat.c 201100 2009-12-28 03:05:31Z kientzle $");
 
 #ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
@@ -72,7 +72,7 @@ archive_entry_stat(struct archive_entry *entry)
        st->st_dev = archive_entry_dev(entry);
        st->st_gid = archive_entry_gid(entry);
        st->st_uid = archive_entry_uid(entry);
-       st->st_ino = archive_entry_ino(entry);
+       st->st_ino = archive_entry_ino64(entry);
        st->st_nlink = archive_entry_nlink(entry);
        st->st_rdev = archive_entry_rdev(entry);
        st->st_size = archive_entry_size(entry);
diff --git a/contrib/libarchive/libarchive/archive_entry_xattr.c b/contrib/libarchive/libarchive/archive_entry_xattr.c
new file mode 100644 (file)
index 0000000..a3efe7c
--- /dev/null
@@ -0,0 +1,158 @@
+/*-
+ * 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_entry_xattr.c 201096 2009-12-28 02:41:27Z kientzle $");
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifdef HAVE_LINUX_FS_H
+#include <linux/fs.h>  /* for Linux file flags */
+#endif
+/*
+ * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h.
+ * As the include guards don't agree, the order of include is important.
+ */
+#ifdef HAVE_LINUX_EXT2_FS_H
+#include <linux/ext2_fs.h>     /* for Linux file flags */
+#endif
+#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)
+#include <ext2fs/ext2_fs.h>    /* for Linux file flags */
+#endif
+#include <stddef.h>
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_WCHAR_H
+#include <wchar.h>
+#endif
+
+#include "archive.h"
+#include "archive_entry.h"
+#include "archive_private.h"
+#include "archive_entry_private.h"
+
+/*
+ * extended attribute handling
+ */
+
+void
+archive_entry_xattr_clear(struct archive_entry *entry)
+{
+       struct ae_xattr *xp;
+
+       while (entry->xattr_head != NULL) {
+               xp = entry->xattr_head->next;
+               free(entry->xattr_head->name);
+               free(entry->xattr_head->value);
+               free(entry->xattr_head);
+               entry->xattr_head = xp;
+       }
+
+       entry->xattr_head = NULL;
+}
+
+void
+archive_entry_xattr_add_entry(struct archive_entry *entry,
+       const char *name, const void *value, size_t size)
+{
+       struct ae_xattr *xp;
+
+       for (xp = entry->xattr_head; xp != NULL; xp = xp->next)
+               ;
+
+       if ((xp = (struct ae_xattr *)malloc(sizeof(struct ae_xattr))) == NULL)
+               /* XXX Error XXX */
+               return;
+
+       xp->name = strdup(name);
+       if ((xp->value = malloc(size)) != NULL) {
+               memcpy(xp->value, value, size);
+               xp->size = size;
+       } else
+               xp->size = 0;
+
+       xp->next = entry->xattr_head;
+       entry->xattr_head = xp;
+}
+
+
+/*
+ * returns number of the extended attribute entries
+ */
+int
+archive_entry_xattr_count(struct archive_entry *entry)
+{
+       struct ae_xattr *xp;
+       int count = 0;
+
+       for (xp = entry->xattr_head; xp != NULL; xp = xp->next)
+               count++;
+
+       return count;
+}
+
+int
+archive_entry_xattr_reset(struct archive_entry * entry)
+{
+       entry->xattr_p = entry->xattr_head;
+
+       return archive_entry_xattr_count(entry);
+}
+
+int
+archive_entry_xattr_next(struct archive_entry * entry,
+       const char **name, const void **value, size_t *size)
+{
+       if (entry->xattr_p) {
+               *name = entry->xattr_p->name;
+               *value = entry->xattr_p->value;
+               *size = entry->xattr_p->size;
+
+               entry->xattr_p = entry->xattr_p->next;
+
+               return (ARCHIVE_OK);
+       } else {
+               *name = NULL;
+               *value = NULL;
+               *size = (size_t)0;
+               return (ARCHIVE_WARN);
+       }
+}
+
+/*
+ * end of xattr handling
+ */
diff --git a/contrib/libarchive/libarchive/archive_hash.h b/contrib/libarchive/libarchive/archive_hash.h
new file mode 100644 (file)
index 0000000..b180da6
--- /dev/null
@@ -0,0 +1,281 @@
+/*-
+ * Copyright (c) 2009 Joerg Sonnenberger
+ * 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.
+ *
+ * $FreeBSD: head/lib/libarchive/archive_hash.h 201171 2009-12-29 06:39:07Z kientzle $
+ */
+
+#ifndef __LIBARCHIVE_BUILD
+#error This header is only to be used internally to libarchive.
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+/*
+ * Hash function support in various Operating Systems:
+ *
+ * NetBSD:
+ * - MD5 and SHA1 in libc: without _ after algorithm name
+ * - SHA2 in libc: with _ after algorithm name
+ *
+ * OpenBSD:
+ * - MD5, SHA1 and SHA2 in libc: without _ after algorithm name
+ * - OpenBSD 4.4 and earlier have SHA2 in libc with _ after algorithm name
+ *
+ * DragonFly and FreeBSD (XXX not used yet):
+ * - MD5 and SHA1 in libmd: without _ after algorithm name
+ * - SHA256: with _ after algorithm name
+ *
+ * Mac OS X (10.4 and later):
+ * - MD5, SHA1 and SHA2 in libSystem: with CC_ prefix and _ after algorithm name
+ *
+ * OpenSSL:
+ * - MD5, SHA1 and SHA2 in libcrypto: with _ after algorithm name
+ *
+ * Windows:
+ * - MD5, SHA1 and SHA2 in archive_windows.c: without algorithm name
+ *   and with __la_ prefix.
+ */
+#if defined(ARCHIVE_HASH_MD5_WIN)    ||\
+      defined(ARCHIVE_HASH_SHA1_WIN)   || defined(ARCHIVE_HASH_SHA256_WIN) ||\
+      defined(ARCHIVE_HASH_SHA384_WIN) || defined(ARCHIVE_HASH_SHA512_WIN)
+#include <wincrypt.h>
+typedef struct {
+       int             valid;
+       HCRYPTPROV      cryptProv;
+       HCRYPTHASH      hash;
+} Digest_CTX;
+extern void __la_hash_Init(Digest_CTX *, ALG_ID);
+extern void __la_hash_Final(unsigned char *, size_t, Digest_CTX *);
+extern void __la_hash_Update(Digest_CTX *, const unsigned char *, size_t);
+#endif
+
+#if defined(ARCHIVE_HASH_MD5_LIBC)
+#  include <md5.h>
+#  define ARCHIVE_HAS_MD5
+typedef MD5_CTX archive_md5_ctx;
+#  define archive_md5_init(ctx)                        MD5Init(ctx)
+#  define archive_md5_final(ctx, buf)          MD5Final(buf, ctx)
+#  define archive_md5_update(ctx, buf, n)      MD5Update(ctx, buf, n)
+#elif defined(ARCHIVE_HASH_MD5_LIBSYSTEM)
+#  include <CommonCrypto/CommonDigest.h>
+#  define ARCHIVE_HAS_MD5
+typedef CC_MD5_CTX archive_md5_ctx;
+#  define archive_md5_init(ctx)                        CC_MD5_Init(ctx)
+#  define archive_md5_final(ctx, buf)          CC_MD5_Final(buf, ctx)
+#  define archive_md5_update(ctx, buf, n)      CC_MD5_Update(ctx, buf, n)
+#elif defined(ARCHIVE_HASH_MD5_OPENSSL)
+#  include <openssl/md5.h>
+#  define ARCHIVE_HAS_MD5
+typedef MD5_CTX archive_md5_ctx;
+#  define archive_md5_init(ctx)                        MD5_Init(ctx)
+#  define archive_md5_final(ctx, buf)          MD5_Final(buf, ctx)
+#  define archive_md5_update(ctx, buf, n)      MD5_Update(ctx, buf, n)
+#elif defined(ARCHIVE_HASH_MD5_WIN)
+#  define ARCHIVE_HAS_MD5
+#  define MD5_DIGEST_LENGTH    16
+typedef Digest_CTX archive_md5_ctx;
+#  define archive_md5_init(ctx)                        __la_hash_Init(ctx, CALG_MD5)
+#  define archive_md5_final(ctx, buf)          __la_hash_Final(buf, MD5_DIGEST_LENGTH, ctx)
+#  define archive_md5_update(ctx, buf, n)      __la_hash_Update(ctx, buf, n)
+#endif
+
+#if defined(ARCHIVE_HASH_RMD160_LIBC)
+#  include <rmd160.h>
+#  define ARCHIVE_HAS_RMD160
+typedef RMD160_CTX archive_rmd160_ctx;
+#  define archive_rmd160_init(ctx)             RMD160Init(ctx)
+#  define archive_rmd160_final(ctx, buf)       RMD160Final(buf, ctx)
+#  define archive_rmd160_update(ctx, buf, n)   RMD160Update(ctx, buf, n)
+#elif defined(ARCHIVE_HASH_RMD160_OPENSSL)
+#  include <openssl/ripemd.h>
+#  define ARCHIVE_HAS_RMD160
+typedef RIPEMD160_CTX archive_rmd160_ctx;
+#  define archive_rmd160_init(ctx)             RIPEMD160_Init(ctx)
+#  define archive_rmd160_final(ctx, buf)       RIPEMD160_Final(buf, ctx)
+#  define archive_rmd160_update(ctx, buf, n)   RIPEMD160_Update(ctx, buf, n)
+#endif
+
+#if defined(ARCHIVE_HASH_SHA1_LIBC)
+#  include <sha1.h>
+#  define ARCHIVE_HAS_SHA1
+typedef SHA1_CTX archive_sha1_ctx;
+#  define archive_sha1_init(ctx)               SHA1Init(ctx)
+#  define archive_sha1_final(ctx, buf)         SHA1Final(buf, ctx)
+#  define archive_sha1_update(ctx, buf, n)     SHA1Update(ctx, buf, n)
+#elif defined(ARCHIVE_HASH_SHA1_LIBSYSTEM)
+#  include <CommonCrypto/CommonDigest.h>
+#  define ARCHIVE_HAS_SHA1
+typedef CC_SHA1_CTX archive_sha1_ctx;
+#  define archive_sha1_init(ctx)               CC_SHA1_Init(ctx)
+#  define archive_sha1_final(ctx, buf)         CC_SHA1_Final(buf, ctx)
+#  define archive_sha1_update(ctx, buf, n)     CC_SHA1_Update(ctx, buf, n)
+#elif defined(ARCHIVE_HASH_SHA1_OPENSSL)
+#  include <openssl/sha.h>
+#  define ARCHIVE_HAS_SHA1
+typedef SHA_CTX archive_sha1_ctx;
+#  define archive_sha1_init(ctx)               SHA1_Init(ctx)
+#  define archive_sha1_final(ctx, buf)         SHA1_Final(buf, ctx)
+#  define archive_sha1_update(ctx, buf, n)     SHA1_Update(ctx, buf, n)
+#elif defined(ARCHIVE_HASH_SHA1_WIN)
+#  define ARCHIVE_HAS_SHA1
+#  define SHA1_DIGEST_LENGTH   20
+typedef Digest_CTX archive_sha1_ctx;
+#  define archive_sha1_init(ctx)               __la_hash_Init(ctx, CALG_SHA1)
+#  define archive_sha1_final(ctx, buf)         __la_hash_Final(buf, SHA1_DIGEST_LENGTH, ctx)
+#  define archive_sha1_update(ctx, buf, n)     __la_hash_Update(ctx, buf, n)
+#endif
+
+#if defined(ARCHIVE_HASH_SHA256_LIBC)
+#  include <sha2.h>
+#  define ARCHIVE_HAS_SHA256
+typedef SHA256_CTX archive_sha256_ctx;
+#  define archive_sha256_init(ctx)             SHA256_Init(ctx)
+#  define archive_sha256_final(ctx, buf)       SHA256_Final(buf, ctx)
+#  define archive_sha256_update(ctx, buf, n)   SHA256_Update(ctx, buf, n)
+#elif defined(ARCHIVE_HASH_SHA256_LIBC2)
+#  include <sha2.h>
+#  define ARCHIVE_HAS_SHA256
+typedef SHA256_CTX archive_sha256_ctx;
+#  define archive_sha256_init(ctx)             SHA256Init(ctx)
+#  define archive_sha256_final(ctx, buf)       SHA256Final(buf, ctx)
+#  define archive_sha256_update(ctx, buf, n)   SHA256Update(ctx, buf, n)
+#elif defined(ARCHIVE_HASH_SHA256_LIBC3)
+#  include <sha2.h>
+#  define ARCHIVE_HAS_SHA256
+typedef SHA2_CTX archive_sha256_ctx;
+#  define archive_sha256_init(ctx)             SHA256Init(ctx)
+#  define archive_sha256_final(ctx, buf)       SHA256Final(buf, ctx)
+#  define archive_sha256_update(ctx, buf, n)   SHA256Update(ctx, buf, n)
+#elif defined(ARCHIVE_HASH_SHA256_LIBSYSTEM)
+#  include <CommonCrypto/CommonDigest.h>
+#  define ARCHIVE_HAS_SHA256
+typedef CC_SHA256_CTX archive_shs256_ctx;
+#  define archive_shs256_init(ctx)             CC_SHA256_Init(ctx)
+#  define archive_shs256_final(ctx, buf)       CC_SHA256_Final(buf, ctx)
+#  define archive_shs256_update(ctx, buf, n)   CC_SHA256_Update(ctx, buf, n)
+#elif defined(ARCHIVE_HASH_SHA256_OPENSSL)
+#  include <openssl/sha.h>
+#  define ARCHIVE_HAS_SHA256
+typedef SHA256_CTX archive_sha256_ctx;
+#  define archive_sha256_init(ctx)             SHA256_Init(ctx)
+#  define archive_sha256_final(ctx, buf)       SHA256_Final(buf, ctx)
+#  define archive_sha256_update(ctx, buf, n)   SHA256_Update(ctx, buf, n)
+#elif defined(ARCHIVE_HASH_SHA256_WIN)
+#  define ARCHIVE_HAS_SHA256
+#  define SHA256_DIGEST_LENGTH 32
+typedef Digest_CTX archive_sha256_ctx;
+#  define archive_sha256_init(ctx)             __la_hash_Init(ctx, CALG_SHA_256)
+#  define archive_sha256_final(ctx, buf)       __la_hash_Final(buf, SHA256_DIGEST_LENGTH, ctx)
+#  define archive_sha256_update(ctx, buf, n)   __la_hash_Update(ctx, buf, n)
+#endif
+
+#if defined(ARCHIVE_HASH_SHA384_LIBC)
+#  include <sha2.h>
+#  define ARCHIVE_HAS_SHA384
+typedef SHA384_CTX archive_sha384_ctx;
+#  define archive_sha384_init(ctx)             SHA384_Init(ctx)
+#  define archive_sha384_final(ctx, buf)       SHA384_Final(buf, ctx)
+#  define archive_sha384_update(ctx, buf, n)   SHA384_Update(ctx, buf, n)
+#elif defined(ARCHIVE_HASH_SHA384_LIBC2)
+#  include <sha2.h>
+#  define ARCHIVE_HAS_SHA384
+typedef SHA384_CTX archive_sha384_ctx;
+#  define archive_sha384_init(ctx)             SHA384Init(ctx)
+#  define archive_sha384_final(ctx, buf)       SHA384Final(buf, ctx)
+#  define archive_sha384_update(ctx, buf, n)   SHA384Update(ctx, buf, n)
+#elif defined(ARCHIVE_HASH_SHA384_LIBC3)
+#  include <sha2.h>
+#  define ARCHIVE_HAS_SHA384
+typedef SHA2_CTX archive_sha384_ctx;
+#  define archive_sha384_init(ctx)             SHA384Init(ctx)
+#  define archive_sha384_final(ctx, buf)       SHA384Final(buf, ctx)
+#  define archive_sha384_update(ctx, buf, n)   SHA384Update(ctx, buf, n)
+#elif defined(ARCHIVE_HASH_SHA384_LIBSYSTEM)
+#  include <CommonCrypto/CommonDigest.h>
+#  define ARCHIVE_HAS_SHA384
+typedef CC_SHA512_CTX archive_shs384_ctx;
+#  define archive_shs384_init(ctx)             CC_SHA384_Init(ctx)
+#  define archive_shs384_final(ctx, buf)       CC_SHA384_Final(buf, ctx)
+#  define archive_shs384_update(ctx, buf, n)   CC_SHA384_Update(ctx, buf, n)
+#elif defined(ARCHIVE_HASH_SHA384_OPENSSL)
+#  include <openssl/sha.h>
+#  define ARCHIVE_HAS_SHA384
+typedef SHA512_CTX archive_sha384_ctx;
+#  define archive_sha384_init(ctx)             SHA384_Init(ctx)
+#  define archive_sha384_final(ctx, buf)       SHA384_Final(buf, ctx)
+#  define archive_sha384_update(ctx, buf, n)   SHA384_Update(ctx, buf, n)
+#elif defined(ARCHIVE_HASH_SHA384_WIN)
+#  define ARCHIVE_HAS_SHA384
+#  define SHA384_DIGEST_LENGTH 48
+typedef Digest_CTX archive_sha384_ctx;
+#  define archive_sha384_init(ctx)             __la_hash_Init(ctx, CALG_SHA_384)
+#  define archive_sha384_final(ctx, buf)       __la_hash_Final(buf, SHA384_DIGEST_LENGTH, ctx)
+#  define archive_sha384_update(ctx, buf, n)   __la_hash_Update(ctx, buf, n)
+#endif
+
+#if defined(ARCHIVE_HASH_SHA512_LIBC)
+#  include <sha2.h>
+#  define ARCHIVE_HAS_SHA512
+typedef SHA512_CTX archive_sha512_ctx;
+#  define archive_sha512_init(ctx)             SHA512_Init(ctx)
+#  define archive_sha512_final(ctx, buf)       SHA512_Final(buf, ctx)
+#  define archive_sha512_update(ctx, buf, n)   SHA512_Update(ctx, buf, n)
+#elif defined(ARCHIVE_HASH_SHA512_LIBC2)
+#  include <sha2.h>
+#  define ARCHIVE_HAS_SHA512
+typedef SHA512_CTX archive_sha512_ctx;
+#  define archive_sha512_init(ctx)             SHA512Init(ctx)
+#  define archive_sha512_final(ctx, buf)       SHA512Final(buf, ctx)
+#  define archive_sha512_update(ctx, buf, n)   SHA512Update(ctx, buf, n)
+#elif defined(ARCHIVE_HASH_SHA512_LIBC3)
+#  include <sha2.h>
+#  define ARCHIVE_HAS_SHA512
+typedef SHA2_CTX archive_sha512_ctx;
+#  define archive_sha512_init(ctx)             SHA512Init(ctx)
+#  define archive_sha512_final(ctx, buf)       SHA512Final(buf, ctx)
+#  define archive_sha512_update(ctx, buf, n)   SHA512Update(ctx, buf, n)
+#elif defined(ARCHIVE_HASH_SHA512_LIBSYSTEM)
+#  include <CommonCrypto/CommonDigest.h>
+#  define ARCHIVE_HAS_SHA512
+typedef CC_SHA512_CTX archive_shs512_ctx;
+#  define archive_shs512_init(ctx)             CC_SHA512_Init(ctx)
+#  define archive_shs512_final(ctx, buf)       CC_SHA512_Final(buf, ctx)
+#  define archive_shs512_update(ctx, buf, n)   CC_SHA512_Update(ctx, buf, n)
+#elif defined(ARCHIVE_HASH_SHA512_OPENSSL)
+#  include <openssl/sha.h>
+#  define ARCHIVE_HAS_SHA512
+typedef SHA512_CTX archive_sha512_ctx;
+#  define archive_sha512_init(ctx)             SHA512_Init(ctx)
+#  define archive_sha512_final(ctx, buf)       SHA512_Final(buf, ctx)
+#  define archive_sha512_update(ctx, buf, n)   SHA512_Update(ctx, buf, n)
+#elif defined(ARCHIVE_HASH_SHA512_WIN)
+#  define ARCHIVE_HAS_SHA512
+#  define SHA512_DIGEST_LENGTH 64
+typedef Digest_CTX archive_sha512_ctx;
+#  define archive_sha512_init(ctx)             __la_hash_Init(ctx, CALG_SHA_512)
+#  define archive_sha512_final(ctx, buf)       __la_hash_Final(buf, SHA512_DIGEST_LENGTH, ctx)
+#  define archive_sha512_update(ctx, buf, n)   __la_hash_Update(ctx, buf, n)
+#endif
index 763c296..ce2f482 100644 (file)
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD: src/lib/libarchive/archive_platform.h,v 1.32 2008/12/06 05:53:05 kientzle Exp $
+ * $FreeBSD: head/lib/libarchive/archive_platform.h 201090 2009-12-28 02:22:04Z kientzle $
  */
 
+/* !!ONLY FOR USE INTERNALLY TO LIBARCHIVE!! */
+
 /*
  * This header is the first thing included in any of the libarchive
  * source files.  As far as possible, platform-specific issues should
 #error Oops: No config.h and no pre-built configuration in archive_platform.h.
 #endif
 
+/* It should be possible to get rid of this by extending the feature-test
+ * macros to cover Windows API functions, probably along with non-trivial
+ * refactoring of code to find structures that sit more cleanly on top of
+ * either Windows or Posix APIs. */
+#if (defined(__WIN32__) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__)
+#include "archive_windows.h"
+#endif
+
 /*
  * The config files define a lot of feature macros.  The following
  * uses those macros to select/define replacements and include key
  * headers as required.
  */
 
-/* No non-FreeBSD platform will have __FBSDID, so just define it here. */
-#ifdef __FreeBSD__
-#include <sys/cdefs.h>  /* For __FBSDID */
-#else
-/* Just leaving this macro replacement empty leads to a dangling semicolon. */
+/* Get a real definition for __FBSDID if we can */
+#if HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+
+/* If not, define it so as to avoid dangling semicolons. */
+#ifndef __FBSDID
 #define        __FBSDID(a)     struct _undefined_hack
 #endif
 
 #include <stdint.h>
 #endif
 
+/* Borland warns about its own constants!  */
+#if defined(__BORLANDC__)
+# if HAVE_DECL_UINT64_MAX
+#  undef       UINT64_MAX
+#  undef       HAVE_DECL_UINT64_MAX
+# endif
+# if HAVE_DECL_UINT64_MIN
+#  undef       UINT64_MIN
+#  undef       HAVE_DECL_UINT64_MIN
+# endif
+# if HAVE_DECL_INT64_MAX
+#  undef       INT64_MAX
+#  undef       HAVE_DECL_INT64_MAX
+# endif
+# if HAVE_DECL_INT64_MIN
+#  undef       INT64_MIN
+#  undef       HAVE_DECL_INT64_MIN
+# endif
+#endif
+
 /* Some platforms lack the standard *_MAX definitions. */
 #if !HAVE_DECL_SIZE_MAX
 #define        SIZE_MAX (~(size_t)0)
index 698ad22..63384b8 100644 (file)
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD: src/lib/libarchive/archive_private.h,v 1.32 2008/12/06 06:23:37 kientzle Exp $
+ * $FreeBSD: head/lib/libarchive/archive_private.h 201098 2009-12-28 02:58:14Z kientzle $
  */
 
+#ifndef __LIBARCHIVE_BUILD
+#error This header is only to be used internally to libarchive.
+#endif
+
 #ifndef ARCHIVE_PRIVATE_H_INCLUDED
 #define        ARCHIVE_PRIVATE_H_INCLUDED
 
@@ -90,6 +94,8 @@ struct archive {
        int64_t           file_position;
        /* Position in COMPRESSED data stream. */
        int64_t           raw_position;
+       /* Number of file entries processed. */
+       int               file_count;
 
        int               archive_error_number;
        const char       *error;
@@ -107,4 +113,12 @@ int        __archive_parse_options(const char *p, const char *fn,
 
 #define        err_combine(a,b)        ((a) < (b) ? (a) : (b))
 
+#if defined(__BORLANDC__) || (defined(_MSC_VER) &&  _MSC_VER <= 1300)
+# define       ARCHIVE_LITERAL_LL(x)   x##i64
+# define       ARCHIVE_LITERAL_ULL(x)  x##ui64
+#else
+# define       ARCHIVE_LITERAL_LL(x)   x##ll
+# define       ARCHIVE_LITERAL_ULL(x)  x##ull
+#endif
+
 #endif
index d6d2c74..5d5f539 100644 (file)
@@ -22,9 +22,9 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD: src/lib/libarchive/archive_read.3,v 1.37 2008/05/26 17:00:22 kientzle Exp $
+.\" $FreeBSD: head/lib/libarchive/archive_read.3 191595 2009-04-27 20:13:13Z kientzle $
 .\"
-.Dd August 19, 2006
+.Dd April 13, 2009
 .Dt archive_read 3
 .Os
 .Sh NAME
 .Nm archive_read_support_compression_bzip2 ,
 .Nm archive_read_support_compression_compress ,
 .Nm archive_read_support_compression_gzip ,
+.Nm archive_read_support_compression_lzma ,
 .Nm archive_read_support_compression_none ,
+.Nm archive_read_support_compression_xz ,
 .Nm archive_read_support_compression_program ,
+.Nm archive_read_support_compression_program_signature ,
 .Nm archive_read_support_format_all ,
+.Nm archive_read_support_format_ar ,
 .Nm archive_read_support_format_cpio ,
 .Nm archive_read_support_format_empty ,
 .Nm archive_read_support_format_iso9660 ,
+.Nm archive_read_support_format_mtree,
+.Nm archive_read_support_format_raw,
 .Nm archive_read_support_format_tar ,
 .Nm archive_read_support_format_zip ,
 .Nm archive_read_open ,
 .Ft int
 .Fn archive_read_support_compression_gzip "struct archive *"
 .Ft int
+.Fn archive_read_support_compression_lzma "struct archive *"
+.Ft int
 .Fn archive_read_support_compression_none "struct archive *"
 .Ft int
+.Fn archive_read_support_compression_xz "struct archive *"
+.Ft int
 .Fo archive_read_support_compression_program
 .Fa "struct archive *"
 .Fa "const char *cmd"
 .Fc
 .Ft int
+.Fo archive_read_support_compression_program_signature
+.Fa "struct archive *"
+.Fa "const char *cmd"
+.Fa "const void *signature"
+.Fa "size_t signature_length"
+.Fc
+.Ft int
 .Fn archive_read_support_format_all "struct archive *"
 .Ft int
+.Fn archive_read_support_format_ar "struct archive *"
+.Ft int
 .Fn archive_read_support_format_cpio "struct archive *"
 .Ft int
 .Fn archive_read_support_format_empty "struct archive *"
 .Ft int
 .Fn archive_read_support_format_iso9660 "struct archive *"
 .Ft int
+.Fn archive_read_support_format_mtree "struct archive *"
+.Ft int
+.Fn archive_read_support_format_raw "struct archive *"
+.Ft int
 .Fn archive_read_support_format_tar "struct archive *"
 .Ft int
 .Fn archive_read_support_format_zip "struct archive *"
@@ -189,30 +212,43 @@ Allocates and initializes a
 .Tn struct archive
 object suitable for reading from an archive.
 .It Xo
-.Fn archive_read_support_compression_all ,
 .Fn archive_read_support_compression_bzip2 ,
 .Fn archive_read_support_compression_compress ,
 .Fn archive_read_support_compression_gzip ,
-.Fn archive_read_support_compression_none
+.Fn archive_read_support_compression_lzma ,
+.Fn archive_read_support_compression_none ,
+.Fn archive_read_support_compression_xz
 .Xc
 Enables auto-detection code and decompression support for the
 specified compression.
+Returns
+.Cm ARCHIVE_OK
+if the compression is fully supported, or
+.Cm ARCHIVE_WARN
+if the compression is supported only through an external program.
+Note that decompression using an external program is usually slower than
+decompression through built-in libraries.
 Note that
 .Dq none
 is always enabled by default.
-For convenience,
-.Fn archive_read_support_compression_all
-enables all available decompression code.
+.It Fn archive_read_support_compression_all
+Enables all available decompression filters.
 .It Fn archive_read_support_compression_program
 Data is fed through the specified external program before being dearchived.
 Note that this disables automatic detection of the compression format,
 so it makes no sense to specify this in conjunction with any other
 decompression option.
+.It Fn archive_read_support_compression_program_signature
+This feeds data through the specified external program
+but only if the initial bytes of the data match the specified
+signature value.
 .It Xo
 .Fn archive_read_support_format_all ,
+.Fn archive_read_support_format_ar ,
 .Fn archive_read_support_format_cpio ,
 .Fn archive_read_support_format_empty ,
 .Fn archive_read_support_format_iso9660 ,
+.Fn archive_read_support_format_mtree ,
 .Fn archive_read_support_format_tar ,
 .Fn archive_read_support_format_zip
 .Xc
@@ -226,6 +262,17 @@ For convenience,
 .Fn archive_read_support_format_all
 enables support for all available formats.
 Only empty archives are supported by default.
+.It Fn archive_read_support_format_raw
+The
+.Dq raw
+format handler allows libarchive to be used to read arbitrary data.
+It treats any data stream as an archive with a single entry.
+The pathname of this entry is
+.Dq data ;
+all other entry fields are unset.
+This is not enabled by
+.Fn archive_read_support_format_all
+in order to avoid erroneous handling of damaged archives.
 .It Xo
 .Fn archive_read_set_filter_options ,
 .Fn archive_read_set_format_options ,
@@ -322,9 +369,9 @@ a
 .Tn struct archive_entry .
 This is a convenience wrapper around
 .Fn archive_read_next_header2
-that uses an internal
+that reuses an internal
 .Tn struct archive_entry
-object.
+object for each request.
 .It Fn archive_read_next_header2
 Read the header for the next entry and populate the provided
 .Tn struct archive_entry .
@@ -550,7 +597,7 @@ list_archive(const char *name)
   archive_read_support_format_all(a);
   archive_read_open(a, mydata, myopen, myread, myclose);
   while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
-    printf("%s\\n",archive_entry_pathname(entry));
+    printf("%s\en",archive_entry_pathname(entry));
     archive_read_data_skip(a);
   }
   archive_read_finish(a);
index e88b90f..f39f5ce 100644 (file)
@@ -32,7 +32,7 @@
  */
 
 #include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_read.c,v 1.39 2008/12/06 06:45:15 kientzle Exp $");
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_read.c 201157 2009-12-29 05:30:23Z kientzle $");
 
 #ifdef HAVE_ERRNO_H
 #include <errno.h>
@@ -57,6 +57,7 @@ __FBSDID("$FreeBSD: src/lib/libarchive/archive_read.c,v 1.39 2008/12/06 06:45:15
 
 static int     build_stream(struct archive_read *);
 static int     choose_format(struct archive_read *);
+static int     cleanup_filters(struct archive_read *);
 static struct archive_vtable *archive_read_vtable(void);
 static int     _archive_read_close(struct archive *);
 static int     _archive_read_finish(struct archive *);
@@ -121,6 +122,9 @@ archive_read_set_format_options(struct archive *_a, const char *s)
        size_t i;
        int len, r;
 
+       __archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
+           "archive_read_set_format_options");
+
        if (s == NULL || *s == '\0')
                return (ARCHIVE_OK);
        a = (struct archive_read *)_a;
@@ -165,12 +169,14 @@ archive_read_set_filter_options(struct archive *_a, const char *s)
        char key[64], val[64];
        int len, r;
 
+       __archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
+           "archive_read_set_filter_options");
+
        if (s == NULL || *s == '\0')
                return (ARCHIVE_OK);
        a = (struct archive_read *)_a;
        __archive_check_magic(&a->archive, ARCHIVE_READ_MAGIC,
            ARCHIVE_STATE_NEW, "archive_read_set_filter_options");
-       filter = a->filter;
        len = 0;
        for (filter = a->filter; filter != NULL; filter = filter->upstream) {
                bidder = filter->bidder;
@@ -206,6 +212,10 @@ archive_read_set_options(struct archive *_a, const char *s)
 {
        int r;
 
+       __archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
+           "archive_read_set_options");
+       archive_clear_error(_a);
+
        r = archive_read_set_format_options(_a, s);
        if (r != ARCHIVE_OK)
                return (r);
@@ -290,6 +300,7 @@ archive_read_open2(struct archive *_a, void *client_data,
 
        __archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
            "archive_read_open");
+       archive_clear_error(&a->archive);
 
        if (client_reader == NULL)
                __archive_errx(1,
@@ -344,6 +355,7 @@ build_stream(struct archive_read *a)
        int number_bidders, i, bid, best_bid;
        struct archive_read_filter_bidder *bidder, *best_bidder;
        struct archive_read_filter *filter;
+       ssize_t avail;
        int r;
 
        for (;;) {
@@ -383,6 +395,12 @@ build_stream(struct archive_read *a)
                        return (r);
                }
                a->filter = filter;
+               /* Verify the filter by asking it for some data. */
+               __archive_read_filter_ahead(filter, 1, &avail);
+               if (avail < 0) {
+                       cleanup_filters(a);
+                       return (ARCHIVE_FATAL);
+               }
        }
 }
 
@@ -399,6 +417,7 @@ archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
            ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
            "archive_read_next_header");
 
+       ++_a->file_count;
        archive_entry_clear(entry);
        archive_clear_error(&a->archive);
 
@@ -719,18 +738,10 @@ _archive_read_close(struct archive *_a)
 
        /* TODO: Clean up the formatters. */
 
-       /* Clean up the filter pipeline. */
-       while (a->filter != NULL) {
-               struct archive_read_filter *t = a->filter->upstream;
-               if (a->filter->close != NULL) {
-                       r1 = (a->filter->close)(a->filter);
-                       if (r1 < r)
-                               r = r1;
-               }
-               free(a->filter->buffer);
-               free(a->filter);
-               a->filter = t;
-       }
+       /* Release the filter objects. */
+       r1 = cleanup_filters(a);
+       if (r1 < r)
+               r = r1;
 
        /* Release the bidder objects. */
        n = sizeof(a->bidders)/sizeof(a->bidders[0]);
@@ -745,10 +756,29 @@ _archive_read_close(struct archive *_a)
        return (r);
 }
 
+static int
+cleanup_filters(struct archive_read *a)
+{
+       int r = ARCHIVE_OK;
+       /* Clean up the filter pipeline. */
+       while (a->filter != NULL) {
+               struct archive_read_filter *t = a->filter->upstream;
+               if (a->filter->close != NULL) {
+                       int r1 = (a->filter->close)(a->filter);
+                       if (r1 < r)
+                               r = r1;
+               }
+               free(a->filter->buffer);
+               free(a->filter);
+               a->filter = t;
+       }
+       return r;
+}
+
 /*
  * Release memory and other resources.
  */
-int
+static int
 _archive_read_finish(struct archive *_a)
 {
        struct archive_read *a = (struct archive_read *)_a;
@@ -941,9 +971,12 @@ __archive_read_filter_ahead(struct archive_read_filter *filter,
        for (;;) {
 
                /*
-                * If we can satisfy from the copy buffer, we're done.
+                * If we can satisfy from the copy buffer (and the
+                * copy buffer isn't empty), we're done.  In particular,
+                * note that min == 0 is a perfectly well-defined
+                * request.
                 */
-               if (filter->avail >= min) {
+               if (filter->avail >= min && filter->avail > 0) {
                        if (avail != NULL)
                                *avail = filter->avail;
                        return (filter->next);
@@ -1126,7 +1159,26 @@ __archive_read_filter_consume(struct archive_read_filter * filter,
 int64_t
 __archive_read_skip(struct archive_read *a, int64_t request)
 {
-       return (__archive_read_filter_skip(a->filter, request));
+       int64_t skipped = __archive_read_skip_lenient(a, request);
+       if (skipped == request)
+               return (skipped);
+       /* We hit EOF before we satisfied the skip request. */
+       if (skipped < 0)  // Map error code to 0 for error message below.
+               skipped = 0;
+       archive_set_error(&a->archive,
+           ARCHIVE_ERRNO_MISC,
+           "Truncated input file (needed %jd bytes, only %jd available)",
+           (intmax_t)request, (intmax_t)skipped);
+       return (ARCHIVE_FATAL);
+}
+
+int64_t
+__archive_read_skip_lenient(struct archive_read *a, int64_t request)
+{
+       int64_t skipped = __archive_read_filter_skip(a->filter, request);
+       if (skipped > 0)
+               a->archive.file_position += skipped;
+       return (skipped);
 }
 
 int64_t
@@ -1142,13 +1194,13 @@ __archive_read_filter_skip(struct archive_read_filter *filter, int64_t request)
         */
        if (filter->avail > 0) {
                min = minimum(request, (off_t)filter->avail);
-               bytes_skipped = __archive_read_consume(filter->archive, min);
+               bytes_skipped = __archive_read_filter_consume(filter, min);
                request -= bytes_skipped;
                total_bytes_skipped += bytes_skipped;
        }
        if (filter->client_avail > 0) {
                min = minimum(request, (int64_t)filter->client_avail);
-               bytes_skipped = __archive_read_consume(filter->archive, min);
+               bytes_skipped = __archive_read_filter_consume(filter, min);
                request -= bytes_skipped;
                total_bytes_skipped += bytes_skipped;
        }
@@ -1169,7 +1221,6 @@ __archive_read_filter_skip(struct archive_read_filter *filter, int64_t request)
                        filter->fatal = 1;
                        return (bytes_skipped);
                }
-               filter->archive->archive.file_position += bytes_skipped;
                total_bytes_skipped += bytes_skipped;
                request -= bytes_skipped;
                filter->client_next = filter->client_buff;
@@ -1182,22 +1233,15 @@ __archive_read_filter_skip(struct archive_read_filter *filter, int64_t request)
         * have to use ordinary reads to finish out the request.
         */
        while (request > 0) {
-               const void* dummy_buffer;
                ssize_t bytes_read;
-               dummy_buffer = __archive_read_ahead(filter->archive,
-                   1, &bytes_read);
+               (void)__archive_read_filter_ahead(filter, 1, &bytes_read);
                if (bytes_read < 0)
                        return (bytes_read);
                if (bytes_read == 0) {
-                       /* We hit EOF before we satisfied the skip request. */
-                       archive_set_error(&filter->archive->archive,
-                           ARCHIVE_ERRNO_MISC,
-                           "Truncated input file (need to skip %jd bytes)",
-                           (intmax_t)request);
-                       return (ARCHIVE_FATAL);
+                       return (total_bytes_skipped);
                }
                min = (size_t)(minimum(bytes_read, request));
-               bytes_read = __archive_read_consume(filter->archive, min);
+               bytes_read = __archive_read_filter_consume(filter, min);
                total_bytes_skipped += bytes_read;
                request -= bytes_read;
        }
index fd53095..b3a09b5 100644 (file)
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD$
+.\" $FreeBSD: head/lib/libarchive/archive_read_disk.3 190957 2009-04-12 05:04:02Z kientzle $
 .\"
 .Dd March 10, 2009
 .Dt archive_read_disk 3
index 3c0b815..8fad7f1 100644 (file)
@@ -25,7 +25,7 @@
  */
 
 #include "archive_platform.h"
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk.c 189429 2009-03-06 04:35:31Z kientzle $");
 
 #include "archive.h"
 #include "archive_string.h"
index 8f90191..7473c50 100644 (file)
@@ -24,7 +24,7 @@
  */
 
 #include "archive_platform.h"
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 201084 2009-12-28 02:14:09Z kientzle $");
 
 #ifdef HAVE_SYS_TYPES_H
 /* Mac OSX requires sys/types.h before sys/acl.h. */
@@ -103,7 +103,7 @@ archive_read_disk_entry_from_file(struct archive *_a,
         * open file descriptor which we can use in the subsequent lookups. */
        if ((S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) {
                if (fd < 0)
-                       fd = open(pathname, O_RDONLY | O_NONBLOCK);
+                       fd = open(pathname, O_RDONLY | O_NONBLOCK | O_BINARY);
                if (fd >= 0) {
                        unsigned long stflags;
                        int r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags);
@@ -114,20 +114,34 @@ archive_read_disk_entry_from_file(struct archive *_a,
 #endif
 
        if (st == NULL) {
+               /* TODO: On Windows, use GetFileInfoByHandle() here.
+                * Using Windows stat() call is badly broken, but
+                * even the stat() wrapper has problems because
+                * 'struct stat' is broken on Windows.
+                */
 #if HAVE_FSTAT
                if (fd >= 0) {
-                       if (fstat(fd, &s) != 0)
-                               return (ARCHIVE_FATAL);
+                       if (fstat(fd, &s) != 0) {
+                               archive_set_error(&a->archive, errno,
+                                   "Can't fstat");
+                               return (ARCHIVE_FAILED);
+                       }
                } else
 #endif
 #if HAVE_LSTAT
                if (!a->follow_symlinks) {
-                       if (lstat(path, &s) != 0)
-                               return (ARCHIVE_FATAL);
+                       if (lstat(path, &s) != 0) {
+                               archive_set_error(&a->archive, errno,
+                                   "Can't lstat %s", path);
+                               return (ARCHIVE_FAILED);
+                       }
                } else
 #endif
-               if (stat(path, &s) != 0)
-                       return (ARCHIVE_FATAL);
+               if (stat(path, &s) != 0) {
+                       archive_set_error(&a->archive, errno,
+                           "Can't lstat %s", path);
+                       return (ARCHIVE_FAILED);
+               }
                st = &s;
        }
        archive_entry_copy_stat(entry, st);
@@ -154,7 +168,7 @@ archive_read_disk_entry_from_file(struct archive *_a,
                if (lnklen < 0) {
                        archive_set_error(&a->archive, errno,
                            "Couldn't read link data");
-                       return (ARCHIVE_WARN);
+                       return (ARCHIVE_FAILED);
                }
                linkbuffer[lnklen] = 0;
                archive_entry_set_symlink(entry, linkbuffer);
@@ -194,6 +208,12 @@ setup_acls_posix1e(struct archive_read_disk *a,
 #if HAVE_ACL_GET_LINK_NP
        else if (!a->follow_symlinks)
                acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS);
+#else
+       else if ((!a->follow_symlinks)
+           && (archive_entry_filetype(entry) == AE_IFLNK))
+               /* We can't get the ACL of a symlink, so we assume it can't
+                  have one. */
+               acl = NULL;
 #endif
        else
                acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
@@ -405,7 +425,8 @@ setup_xattrs(struct archive_read_disk *a,
        return (ARCHIVE_OK);
 }
 
-#elif HAVE_EXTATTR_GET_FILE && HAVE_EXTATTR_LIST_FILE
+#elif HAVE_EXTATTR_GET_FILE && HAVE_EXTATTR_LIST_FILE && \
+    HAVE_DECL_EXTATTR_NAMESPACE_USER
 
 /*
  * FreeBSD extattr interface.
@@ -416,11 +437,11 @@ setup_xattrs(struct archive_read_disk *a,
  * to not include the system extattrs that hold ACLs; we handle
  * those separately.
  */
-int
+static int
 setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
     int namespace, const char *name, const char *fullname, int fd);
 
-int
+static int
 setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
     int namespace, const char *name, const char *fullname, int fd)
 {
index fd385a6..b674b71 100644 (file)
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD$
+ * $FreeBSD: head/lib/libarchive/archive_read_disk_private.h 201105 2009-12-28 03:20:54Z kientzle $
  */
 
+#ifndef __LIBARCHIVE_BUILD
+#error This header is only to be used internally to libarchive.
+#endif
+
 #ifndef ARCHIVE_READ_DISK_PRIVATE_H_INCLUDED
 #define ARCHIVE_READ_DISK_PRIVATE_H_INCLUDED
 
index 60054f9..97a568e 100644 (file)
@@ -24,7 +24,7 @@
  */
 
 #include "archive_platform.h"
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_set_standard_lookup.c 201109 2009-12-28 03:30:31Z kientzle $");
 
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
@@ -182,6 +182,7 @@ lookup_uname(void *data, uid_t uid)
                    &lookup_uname_helper, (id_t)uid));
 }
 
+#if HAVE_GETPWUID_R
 static const char *
 lookup_uname_helper(struct name_cache *cache, id_t id)
 {
@@ -195,6 +196,7 @@ lookup_uname_helper(struct name_cache *cache, id_t id)
        if (cache->buff == NULL)
                return (NULL);
        for (;;) {
+               result = &pwent; /* Old getpwuid_r ignores last arg. */
                r = getpwuid_r((uid_t)id, &pwent,
                               cache->buff, cache->buff_size, &result);
                if (r == 0)
@@ -221,6 +223,20 @@ lookup_uname_helper(struct name_cache *cache, id_t id)
 
        return strdup(result->pw_name);
 }
+#else
+static const char *
+lookup_uname_helper(struct name_cache *cache, id_t id)
+{
+       struct passwd   *result;
+
+       result = getpwuid((uid_t)id);
+
+       if (result == NULL)
+               return (NULL);
+
+       return strdup(result->pw_name);
+}
+#endif
 
 static const char *
 lookup_gname(void *data, gid_t gid)
@@ -230,6 +246,7 @@ lookup_gname(void *data, gid_t gid)
                    &lookup_gname_helper, (id_t)gid));
 }
 
+#if HAVE_GETGRGID_R
 static const char *
 lookup_gname_helper(struct name_cache *cache, id_t id)
 {
@@ -243,6 +260,7 @@ lookup_gname_helper(struct name_cache *cache, id_t id)
        if (cache->buff == NULL)
                return (NULL);
        for (;;) {
+               result = &grent; /* Old getgrgid_r ignores last arg. */
                r = getgrgid_r((gid_t)id, &grent,
                               cache->buff, cache->buff_size, &result);
                if (r == 0)
@@ -267,4 +285,19 @@ lookup_gname_helper(struct name_cache *cache, id_t id)
 
        return strdup(result->gr_name);
 }
+#else
+static const char *
+lookup_gname_helper(struct name_cache *cache, id_t id)
+{
+       struct group    *result;
+
+       result = getgrgid((gid_t)id);
+
+       if (result == NULL)
+               return (NULL);
+
+       return strdup(result->gr_name);
+}
+#endif
+
 #endif /* ! (_WIN32 && !__CYGWIN__) */
index c7f9d69..9660da8 100644 (file)
@@ -24,7 +24,7 @@
  */
 
 #include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_open_fd.c,v 1.13 2007/06/26 03:06:48 kientzle Exp $");
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_open_fd.c 201103 2009-12-28 03:13:49Z kientzle $");
 
 #ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
@@ -32,6 +32,12 @@ __FBSDID("$FreeBSD: src/lib/libarchive/archive_read_open_fd.c,v 1.13 2007/06/26
 #ifdef HAVE_ERRNO_H
 #include <errno.h>
 #endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
 #endif
@@ -66,6 +72,7 @@ archive_read_open_fd(struct archive *a, int fd, size_t block_size)
        struct read_fd_data *mine;
        void *b;
 
+       archive_clear_error(a);
        if (fstat(fd, &st) != 0) {
                archive_set_error(a, errno, "Can't stat fd %d", fd);
                return (ARCHIVE_FATAL);
@@ -94,6 +101,9 @@ archive_read_open_fd(struct archive *a, int fd, size_t block_size)
                mine->can_skip = 1;
        } else
                mine->can_skip = 0;
+#if defined(__CYGWIN__) || defined(_WIN32)
+       setmode(mine->fd, O_BINARY);
+#endif
 
        return (archive_read_open2(a, mine,
                NULL, file_read, file_skip, file_close));
@@ -106,11 +116,15 @@ file_read(struct archive *a, void *client_data, const void **buff)
        ssize_t bytes_read;
 
        *buff = mine->buffer;
-       bytes_read = read(mine->fd, mine->buffer, mine->block_size);
-       if (bytes_read < 0) {
-               archive_set_error(a, errno, "Error reading fd %d", mine->fd);
+       for (;;) {
+               bytes_read = read(mine->fd, mine->buffer, mine->block_size);
+               if (bytes_read < 0) {
+                       if (errno == EINTR)
+                               continue;
+                       archive_set_error(a, errno, "Error reading fd %d", mine->fd);
+               }
+               return (bytes_read);
        }
-       return (bytes_read);
 }
 
 #if ARCHIVE_API_VERSION < 2
index bcc13b1..095ae6e 100644 (file)
@@ -24,7 +24,7 @@
  */
 
 #include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_open_file.c,v 1.20 2007/06/26 03:06:48 kientzle Exp $");
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_open_file.c 201093 2009-12-28 02:28:44Z kientzle $");
 
 #ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
@@ -35,6 +35,9 @@ __FBSDID("$FreeBSD: src/lib/libarchive/archive_read_open_file.c,v 1.20 2007/06/2
 #ifdef HAVE_FCNTL_H
 #include <fcntl.h>
 #endif
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
 #endif
@@ -70,6 +73,7 @@ archive_read_open_FILE(struct archive *a, FILE *f)
        size_t block_size = 128 * 1024;
        void *b;
 
+       archive_clear_error(a);
        mine = (struct read_FILE_data *)malloc(sizeof(*mine));
        b = malloc(block_size);
        if (mine == NULL || b == NULL) {
@@ -93,6 +97,10 @@ archive_read_open_FILE(struct archive *a, FILE *f)
        } else
                mine->can_skip = 0;
 
+#if defined(__CYGWIN__) || defined(_WIN32)
+       setmode(fileno(mine->f), O_BINARY);
+#endif
+
        return (archive_read_open2(a, mine, NULL, file_read,
                    file_skip, file_close));
 }
index deac47b..74f3e60 100644 (file)
@@ -24,7 +24,7 @@
  */
 
 #include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_open_filename.c,v 1.21 2008/02/19 06:10:48 kientzle Exp $");
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_open_filename.c 201093 2009-12-28 02:28:44Z kientzle $");
 
 #ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
@@ -35,6 +35,9 @@ __FBSDID("$FreeBSD: src/lib/libarchive/archive_read_open_filename.c,v 1.21 2008/
 #ifdef HAVE_FCNTL_H
 #include <fcntl.h>
 #endif
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
 #endif
@@ -84,6 +87,7 @@ archive_read_open_filename(struct archive *a, const char *filename,
        void *b;
        int fd;
 
+       archive_clear_error(a);
        if (filename == NULL || filename[0] == '\0') {
                /* We used to invoke archive_read_open_fd(a,0,block_size)
                 * here, but that doesn't (and shouldn't) handle the
@@ -95,6 +99,9 @@ archive_read_open_filename(struct archive *a, const char *filename,
                 */
                filename = ""; /* Normalize NULL to "" */
                fd = 0;
+#if defined(__CYGWIN__) || defined(_WIN32)
+               setmode(0, O_BINARY);
+#endif
        } else {
                fd = open(filename, O_RDONLY | O_BINARY);
                if (fd < 0) {
@@ -153,15 +160,19 @@ file_read(struct archive *a, void *client_data, const void **buff)
        ssize_t bytes_read;
 
        *buff = mine->buffer;
-       bytes_read = read(mine->fd, mine->buffer, mine->block_size);
-       if (bytes_read < 0) {
-               if (mine->filename[0] == '\0')
-                       archive_set_error(a, errno, "Error reading stdin");
-               else
-                       archive_set_error(a, errno, "Error reading '%s'",
-                           mine->filename);
+       for (;;) {
+               bytes_read = read(mine->fd, mine->buffer, mine->block_size);
+               if (bytes_read < 0) {
+                       if (errno == EINTR)
+                               continue;
+                       else if (mine->filename[0] == '\0')
+                               archive_set_error(a, errno, "Error reading stdin");
+                       else
+                               archive_set_error(a, errno, "Error reading '%s'",
+                                   mine->filename);
+               }
+               return (bytes_read);
        }
-       return (bytes_read);
 }
 
 #if ARCHIVE_API_VERSION < 2
index 10def72..5a85018 100644 (file)
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD: src/lib/libarchive/archive_read_private.h,v 1.7 2008/12/06 06:45:15 kientzle Exp $
+ * $FreeBSD: head/lib/libarchive/archive_read_private.h 201088 2009-12-28 02:18:55Z kientzle $
  */
 
+#ifndef __LIBARCHIVE_BUILD
+#error This header is only to be used internally to libarchive.
+#endif
+
 #ifndef ARCHIVE_READ_PRIVATE_H_INCLUDED
 #define        ARCHIVE_READ_PRIVATE_H_INCLUDED
 
@@ -160,7 +164,7 @@ struct archive_read {
                int     (*read_data)(struct archive_read *, const void **, size_t *, off_t *);
                int     (*read_data_skip)(struct archive_read *);
                int     (*cleanup)(struct archive_read *);
-       }       formats[8];
+       }       formats[9];
        struct archive_format_descriptor        *format; /* Active format. */
 
        /*
@@ -189,6 +193,7 @@ const void *__archive_read_filter_ahead(struct archive_read_filter *,
 ssize_t        __archive_read_consume(struct archive_read *, size_t);
 ssize_t        __archive_read_filter_consume(struct archive_read_filter *, size_t);
 int64_t        __archive_read_skip(struct archive_read *, int64_t);
+int64_t        __archive_read_skip_lenient(struct archive_read *, int64_t);
 int64_t        __archive_read_filter_skip(struct archive_read_filter *, int64_t);
 int __archive_read_program(struct archive_read_filter *, const char *);
 #endif
index dcd6a31..a6db736 100644 (file)
@@ -24,7 +24,7 @@
  */
 
 #include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_compression_all.c,v 1.7 2008/12/06 06:45:15 kientzle Exp $");
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_compression_all.c 201248 2009-12-30 06:12:03Z kientzle $");
 
 #include "archive.h"
 
@@ -44,6 +44,10 @@ archive_read_support_compression_all(struct archive *a)
        archive_read_support_compression_lzma(a);
        /* Xz falls back to "unxz" command-line program. */
        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
index 082cf49..8381c9a 100644 (file)
@@ -25,7 +25,7 @@
 
 #include "archive_platform.h"
 
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_compression_bzip2.c,v 1.19 2008/12/06 06:45:15 kientzle Exp $");
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_compression_bzip2.c 201108 2009-12-28 03:28:21Z kientzle $");
 
 #ifdef HAVE_ERRNO_H
 #include <errno.h>
@@ -48,7 +48,7 @@ __FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_compression_bzip2.c,
 #include "archive_private.h"
 #include "archive_read_private.h"
 
-#if HAVE_BZLIB_H
+#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
 struct private_data {
        bz_stream        stream;
        char            *out_block;
@@ -86,7 +86,7 @@ archive_read_support_compression_bzip2(struct archive *_a)
        reader->init = bzip2_reader_init;
        reader->options = NULL;
        reader->free = bzip2_reader_free;
-#if HAVE_BZLIB_H
+#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
        return (ARCHIVE_OK);
 #else
        archive_set_error(_a, ARCHIVE_ERRNO_MISC,
@@ -146,7 +146,7 @@ bzip2_reader_bid(struct archive_read_filter_bidder *self, struct archive_read_fi
        return (bits_checked);
 }
 
-#ifndef HAVE_BZLIB_H
+#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR)
 
 /*
  * If we don't have the library on this system, we can't actually do the
@@ -210,12 +210,11 @@ static ssize_t
 bzip2_filter_read(struct archive_read_filter *self, const void **p)
 {
        struct private_data *state;
-       size_t read_avail, decompressed;
+       size_t decompressed;
        const char *read_buf;
        ssize_t ret;
 
        state = (struct private_data *)self->data;
-       read_avail = 0;
 
        if (state->eof) {
                *p = NULL;
@@ -348,7 +347,7 @@ bzip2_filter_close(struct archive_read_filter *self)
 
        free(state->out_block);
        free(state);
-       return (ARCHIVE_OK);
+       return (ret);
 }
 
-#endif /* HAVE_BZLIB_H */
+#endif /* HAVE_BZLIB_H && BZ_CONFIG_ERROR */
index 752ddda..2461975 100644 (file)
@@ -64,7 +64,7 @@
 
 
 #include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_compression_compress.c,v 1.11 2008/12/06 06:45:15 kientzle Exp $");
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_compression_compress.c 201094 2009-12-28 02:29:21Z kientzle $");
 
 #ifdef HAVE_ERRNO_H
 #include <errno.h>
@@ -229,8 +229,8 @@ compress_bidder_init(struct archive_read_filter *self)
 
        /* XXX MOVE THE FOLLOWING OUT OF INIT() XXX */
 
-       code = getbits(self, 8); /* Skip first signature byte. */
-       code = getbits(self, 8); /* Skip second signature byte. */
+       (void)getbits(self, 8); /* Skip first signature byte. */
+       (void)getbits(self, 8); /* Skip second signature byte. */
 
        code = getbits(self, 8);
        state->maxcode_bits = code & 0x1f;
index cd21c61..8cc924c 100644 (file)
@@ -25,7 +25,7 @@
 
 #include "archive_platform.h"
 
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_compression_gzip.c,v 1.17 2008/12/06 06:45:15 kientzle Exp $");
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_compression_gzip.c 201082 2009-12-28 02:05:28Z kientzle $");
 
 
 #ifdef HAVE_ERRNO_H
@@ -411,6 +411,8 @@ gzip_filter_read(struct archive_read_filter *self, const void **p)
                        /* Consume the stream trailer; release the
                         * decompression library. */
                        ret = consume_trailer(self);
+                       if (ret < ARCHIVE_OK)
+                               return (ret);
                        break;
                default:
                        /* Return an error. */
index 2fddece..955d06d 100644 (file)
@@ -24,7 +24,7 @@
  */
 
 #include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_compression_none.c,v 1.20 2008/12/06 06:45:15 kientzle Exp $");
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_compression_none.c 185679 2008-12-06 06:45:15Z kientzle $");
 
 #include "archive.h"
 
index 11ee805..0c63f2e 100644 (file)
@@ -24,7 +24,7 @@
  */
 
 #include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_compression_program.c,v 1.6 2008/12/06 06:45:15 kientzle Exp $");
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_compression_program.c 201112 2009-12-28 06:59:35Z kientzle $");
 
 #ifdef HAVE_SYS_WAIT_H
 #  include <sys/wait.h>
@@ -205,7 +205,7 @@ program_bidder_bid(struct archive_read_filter_bidder *self,
                /* No match, so don't bid. */
                if (memcmp(p, state->signature, state->signature_len) != 0)
                        return (0);
-               return (state->signature_len * 8);
+               return ((int)state->signature_len * 8);
        }
 
        /* Otherwise, bid once and then never bid again. */
@@ -251,6 +251,7 @@ child_stop(struct archive_read_filter *self, struct program_filter *state)
                return (ARCHIVE_WARN);
        }
 
+#if !defined(_WIN32) || defined(__CYGWIN__)
        if (WIFSIGNALED(state->exit_status)) {
 #ifdef SIGPIPE
                /* If the child died because we stopped reading before
@@ -267,6 +268,7 @@ child_stop(struct archive_read_filter *self, struct program_filter *state)
                    WTERMSIG(state->exit_status));
                return (ARCHIVE_WARN);
        }
+#endif /* !_WIN32 || __CYGWIN__ */
 
        if (WIFEXITED(state->exit_status)) {
                if (WEXITSTATUS(state->exit_status) == 0)
diff --git a/contrib/libarchive/libarchive/archive_read_support_compression_rpm.c b/contrib/libarchive/libarchive/archive_read_support_compression_rpm.c
new file mode 100644 (file)
index 0000000..051baa5
--- /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 == (size_t)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);
+}
+
diff --git a/contrib/libarchive/libarchive/archive_read_support_compression_uu.c b/contrib/libarchive/libarchive/archive_read_support_compression_uu.c
new file mode 100644 (file)
index 0000000..1e30520
--- /dev/null
@@ -0,0 +1,627 @@
+/*-
+ * 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"
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_compression_uu.c 201248 2009-12-30 06:12:03Z 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 "archive.h"
+#include "archive_private.h"
+#include "archive_read_private.h"
+
+struct uudecode {
+       int64_t          total;
+       unsigned char   *in_buff;
+#define IN_BUFF_SIZE   (1024)
+       int              in_cnt;
+       size_t           in_allocated;
+       unsigned char   *out_buff;
+#define OUT_BUFF_SIZE  (64 * 1024)
+       int              state;
+#define ST_FIND_HEAD   0
+#define ST_READ_UU     1
+#define ST_UUEND       2
+#define ST_READ_BASE64 3
+};
+
+static int     uudecode_bidder_bid(struct archive_read_filter_bidder *,
+                   struct archive_read_filter *filter);
+static int     uudecode_bidder_init(struct archive_read_filter *);
+
+static ssize_t uudecode_filter_read(struct archive_read_filter *,
+                   const void **);
+static int     uudecode_filter_close(struct archive_read_filter *);
+
+int
+archive_read_support_compression_uu(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 = uudecode_bidder_bid;
+       bidder->init = uudecode_bidder_init;
+       bidder->options = NULL;
+       bidder->free = NULL;
+       return (ARCHIVE_OK);
+}
+
+static const unsigned char ascii[256] = {
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\n', 0, 0, '\r', 0, 0, /* 00 - 0F */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */
+       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */
+       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 - 3F */
+       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
+       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */
+       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */
+       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* 70 - 7F */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */
+};
+
+static const unsigned char uuchar[256] = {
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 0F */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */
+       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */
+       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 - 3F */
+       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
+       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */
+       1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 6F */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 70 - 7F */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */
+};
+
+static const unsigned char base64[256] = {
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 0F */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, /* 20 - 2F */
+       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, /* 30 - 3F */
+       0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
+       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 50 - 5F */
+       0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */
+       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 70 - 7F */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */
+};
+
+static const int base64num[128] = {
+        0,  0,  0,  0,  0,  0,  0,  0,
+        0,  0,  0,  0,  0,  0,  0,  0, /* 00 - 0F */
+        0,  0,  0,  0,  0,  0,  0,  0,
+        0,  0,  0,  0,  0,  0,  0,  0, /* 10 - 1F */
+        0,  0,  0,  0,  0,  0,  0,  0,
+        0,  0,  0, 62,  0,  0,  0, 63, /* 20 - 2F */
+       52, 53, 54, 55, 56, 57, 58, 59,
+       60, 61,  0,  0,  0,  0,  0,  0, /* 30 - 3F */
+        0,  0,  1,  2,  3,  4,  5,  6,
+        7,  8,  9, 10, 11, 12, 13, 14, /* 40 - 4F */
+       15, 16, 17, 18, 19, 20, 21, 22,
+       23, 24, 25,  0,  0,  0,  0,  0, /* 50 - 5F */
+        0, 26, 27, 28, 29, 30, 31, 32,
+       33, 34, 35, 36, 37, 38, 39, 40, /* 60 - 6F */
+       41, 42, 43, 44, 45, 46, 47, 48,
+       49, 50, 51,  0,  0,  0,  0,  0, /* 70 - 7F */
+};
+
+static ssize_t
+get_line(const unsigned char *b, ssize_t avail, ssize_t *nlsize)
+{
+       ssize_t len;
+
+       len = 0;
+       while (len < avail) {
+               switch (ascii[*b]) {
+               case 0: /* Non-ascii character or control character. */
+                       if (nlsize != NULL)
+                               *nlsize = 0;
+                       return (-1);
+               case '\r':
+                       if (avail-len > 1 && b[1] == '\n') {
+                               if (nlsize != NULL)
+                                       *nlsize = 2;
+                               return (len+2);
+                       }
+                       /* FALL THROUGH */
+               case '\n':
+                       if (nlsize != NULL)
+                               *nlsize = 1;
+                       return (len+1);
+               case 1:
+                       b++;
+                       len++;
+                       break;
+               }
+       }
+       if (nlsize != NULL)
+               *nlsize = 0;
+       return (avail);
+}
+
+static ssize_t
+bid_get_line(struct archive_read_filter *filter,
+    const unsigned char **b, ssize_t *avail, ssize_t *ravail, ssize_t *nl)
+{
+       ssize_t len;
+       int quit;
+       
+       quit = 0;
+       if (*avail == 0) {
+               *nl = 0;
+               len = 0;
+       } else
+               len = get_line(*b, *avail, nl);
+       /*
+        * Read bytes more while it does not reach the end of line.
+        */
+       while (*nl == 0 && len == *avail && !quit) {
+               ssize_t diff = *ravail - *avail;
+
+               *b = __archive_read_filter_ahead(filter, 160 + *ravail, avail);
+               if (*b == NULL) {
+                       if (*ravail >= *avail)
+                               return (0);
+                       /* Reading bytes reaches the end of file. */
+                       *b = __archive_read_filter_ahead(filter, *avail, avail);
+                       quit = 1;
+               }
+               *ravail = *avail;
+               *b += diff;
+               *avail -= diff;
+               len = get_line(*b, *avail, nl);
+       }
+       return (len);
+}
+
+#define UUDECODE(c) (((c) - 0x20) & 0x3f)
+
+static int
+uudecode_bidder_bid(struct archive_read_filter_bidder *self,
+    struct archive_read_filter *filter)
+{
+       const unsigned char *b;
+       ssize_t avail, ravail;
+       ssize_t len, nl;
+       int l;
+       int firstline;
+
+       (void)self; /* UNUSED */
+
+       b = __archive_read_filter_ahead(filter, 1, &avail);
+       if (b == NULL)
+               return (0);
+
+       firstline = 20;
+       ravail = avail;
+       for (;;) {
+               len = bid_get_line(filter, &b, &avail, &ravail, &nl);
+               if (len < 0 || nl == 0)
+                       return (0);/* Binary data. */
+               if (memcmp(b, "begin ", 6) == 0 && len - nl >= 11)
+                       l = 6;
+               else if (memcmp(b, "begin-base64 ", 13) == 0 && len - nl >= 18)
+                       l = 13;
+               else
+                       l = 0;
+
+               if (l > 0 && (b[l] < '0' || b[l] > '7' ||
+                   b[l+1] < '0' || b[l+1] > '7' ||
+                   b[l+2] < '0' || b[l+2] > '7' || b[l+3] != ' '))
+                       l = 0;
+
+               b += len;
+               avail -= len;
+               if (l)
+                       break;
+               firstline = 0;
+       }
+       if (!avail)
+               return (0);
+       len = bid_get_line(filter, &b, &avail, &ravail, &nl);
+       if (len < 0 || nl == 0)
+               return (0);/* There are non-ascii characters. */
+       avail -= len;
+
+       if (l == 6) {
+               if (!uuchar[*b])
+                       return (0);
+               /* Get a length of decoded bytes. */
+               l = UUDECODE(*b++); len--;
+               if (l > 45)
+                       /* Normally, maximum length is 45(character 'M'). */
+                       return (0);
+               while (l && len-nl > 0) {
+                       if (l > 0) {
+                               if (!uuchar[*b++])
+                                       return (0);
+                               if (!uuchar[*b++])
+                                       return (0);
+                               len -= 2;
+                               --l;
+                       }
+                       if (l > 0) {
+                               if (!uuchar[*b++])
+                                       return (0);
+                               --len;
+                               --l;
+                       }
+                       if (l > 0) {
+                               if (!uuchar[*b++])
+                                       return (0);
+                               --len;
+                               --l;
+                       }
+               }
+               if (len-nl < 0)
+                       return (0);
+               if (len-nl == 1 &&
+                   (uuchar[*b] ||               /* Check sum. */
+                    (*b >= 'a' && *b <= 'z'))) {/* Padding data(MINIX). */
+                       ++b;
+                       --len;
+               }
+               b += nl;
+               if (avail && uuchar[*b])
+                       return (firstline+30);
+       }
+       if (l == 13) {
+               while (len-nl > 0) {
+                       if (!base64[*b++])
+                               return (0);
+                       --len;
+               }
+               b += nl;
+
+               if (avail >= 5 && memcmp(b, "====\n", 5) == 0)
+                       return (firstline+40);
+               if (avail >= 6 && memcmp(b, "====\r\n", 6) == 0)
+                       return (firstline+40);
+               if (avail > 0 && base64[*b])
+                       return (firstline+30);
+       }
+
+       return (0);
+}
+
+static int
+uudecode_bidder_init(struct archive_read_filter *self)
+{
+       struct uudecode   *uudecode;
+       void *out_buff;
+       void *in_buff;
+
+       self->code = ARCHIVE_COMPRESSION_UU;
+       self->name = "uu";
+       self->read = uudecode_filter_read;
+       self->skip = NULL; /* not supported */
+       self->close = uudecode_filter_close;
+
+       uudecode = (struct uudecode *)calloc(sizeof(*uudecode), 1);
+       out_buff = malloc(OUT_BUFF_SIZE);
+       in_buff = malloc(IN_BUFF_SIZE);
+       if (uudecode == NULL || out_buff == NULL || in_buff == NULL) {
+               archive_set_error(&self->archive->archive, ENOMEM,
+                   "Can't allocate data for uudecode");
+               free(uudecode);
+               free(out_buff);
+               free(in_buff);
+               return (ARCHIVE_FATAL);
+       }
+
+       self->data = uudecode;
+       uudecode->in_buff = in_buff;
+       uudecode->in_cnt = 0;
+       uudecode->in_allocated = IN_BUFF_SIZE;
+       uudecode->out_buff = out_buff;
+       uudecode->state = ST_FIND_HEAD;
+
+       return (ARCHIVE_OK);
+}
+
+static int
+ensure_in_buff_size(struct archive_read_filter *self,
+    struct uudecode *uudecode, size_t size)
+{
+
+       if (size > uudecode->in_allocated) {
+               unsigned char *ptr;
+               size_t newsize;
+
+               newsize = uudecode->in_allocated << 1;
+               ptr = malloc(newsize);
+               if (ptr == NULL ||
+                   newsize < uudecode->in_allocated) {
+                       free(ptr);
+                       archive_set_error(&self->archive->archive,
+                           ENOMEM,
+                           "Can't allocate data for uudecode");
+                       return (ARCHIVE_FATAL);
+               }
+               if (uudecode->in_cnt)
+                       memmove(ptr, uudecode->in_buff,
+                           uudecode->in_cnt);
+               free(uudecode->in_buff);
+               uudecode->in_buff = ptr;
+               uudecode->in_allocated = newsize;
+       }
+       return (ARCHIVE_OK);
+}
+
+static ssize_t
+uudecode_filter_read(struct archive_read_filter *self, const void **buff)
+{
+       struct uudecode *uudecode;
+       const unsigned char *b, *d;
+       unsigned char *out;
+       ssize_t avail_in, ravail;
+       ssize_t used;
+       ssize_t total;
+       ssize_t len, llen, nl;
+
+       uudecode = (struct uudecode *)self->data;
+
+read_more:
+       d = __archive_read_filter_ahead(self->upstream, 1, &avail_in);
+       if (d == NULL && avail_in < 0)
+               return (ARCHIVE_FATAL);
+       /* Quiet a code analyzer; make sure avail_in must be zero
+        * when d is NULL. */
+       if (d == NULL)
+               avail_in = 0;
+       used = 0;
+       total = 0;
+       out = uudecode->out_buff;
+       ravail = avail_in;
+       if (uudecode->in_cnt) {
+               /*
+                * If there is remaining data which is saved by
+                * previous calling, use it first.
+                */
+               if (ensure_in_buff_size(self, uudecode,
+                   avail_in + uudecode->in_cnt) != ARCHIVE_OK)
+                       return (ARCHIVE_FATAL);
+               memcpy(uudecode->in_buff + uudecode->in_cnt,
+                   d, avail_in);
+               d = uudecode->in_buff;
+               avail_in += uudecode->in_cnt;
+               uudecode->in_cnt = 0;
+       }
+       for (;used < avail_in; d += llen, used += llen) {
+               int l, body;
+
+               b = d;
+               len = get_line(b, avail_in - used, &nl);
+               if (len < 0) {
+                       /* Non-ascii character is found. */
+                       archive_set_error(&self->archive->archive,
+                           ARCHIVE_ERRNO_MISC,
+                           "Insufficient compressed data");
+                       return (ARCHIVE_FATAL);
+               }
+               llen = len;
+               if (nl == 0) {
+                       /*
+                        * Save remaining data which does not contain
+                        * NL('\n','\r').
+                        */
+                       if (ensure_in_buff_size(self, uudecode, len)
+                           != ARCHIVE_OK)
+                               return (ARCHIVE_FATAL);
+                       if (uudecode->in_buff != b)
+                               memmove(uudecode->in_buff, b, len);
+                       uudecode->in_cnt = len;
+                       if (total == 0) {
+                               /* Do not return 0; it means end-of-file.
+                                * We should try to read bytes more. */
+                               __archive_read_filter_consume(
+                                   self->upstream, ravail);
+                               goto read_more;
+                       }
+                       break;
+               }
+               if (total + len * 2 > OUT_BUFF_SIZE)
+                       break;
+               switch (uudecode->state) {
+               default:
+               case ST_FIND_HEAD:
+                       if (len - nl > 13 && memcmp(b, "begin ", 6) == 0)
+                               l = 6;
+                       else if (len - nl > 18 &&
+                           memcmp(b, "begin-base64 ", 13) == 0)
+                               l = 13;
+                       else
+                               l = 0;
+                       if (l != 0 && b[l] >= '0' && b[l] <= '7' &&
+                           b[l+1] >= '0' && b[l+1] <= '7' &&
+                           b[l+2] >= '0' && b[l+2] <= '7' && b[l+3] == ' ') {
+                               if (l == 6)
+                                       uudecode->state = ST_READ_UU;
+                               else
+                                       uudecode->state = ST_READ_BASE64;
+                       }
+                       break;
+               case ST_READ_UU:
+                       body = len - nl;
+                       if (!uuchar[*b] || body <= 0) {
+                               archive_set_error(&self->archive->archive,
+                                   ARCHIVE_ERRNO_MISC,
+                                   "Insufficient compressed data");
+                               return (ARCHIVE_FATAL);
+                       }
+                       /* Get length of undecoded bytes of curent line. */
+                       l = UUDECODE(*b++);
+                       body--;
+                       if (l > body) {
+                               archive_set_error(&self->archive->archive,
+                                   ARCHIVE_ERRNO_MISC,
+                                   "Insufficient compressed data");
+                               return (ARCHIVE_FATAL);
+                       }
+                       if (l == 0) {
+                               uudecode->state = ST_UUEND;
+                               break;
+                       }
+                       while (l > 0) {
+                               int n = 0;
+
+                               if (l > 0) {
+                                       if (!uuchar[b[0]] || !uuchar[b[1]])
+                                               break;
+                                       n = UUDECODE(*b++) << 18;
+                                       n |= UUDECODE(*b++) << 12;
+                                       *out++ = n >> 16; total++;
+                                       --l;
+                               }
+                               if (l > 0) {
+                                       if (!uuchar[b[0]])
+                                               break;
+                                       n |= UUDECODE(*b++) << 6;
+                                       *out++ = (n >> 8) & 0xFF; total++;
+                                       --l;
+                               }
+                               if (l > 0) {
+                                       if (!uuchar[b[0]])
+                                               break;
+                                       n |= UUDECODE(*b++);
+                                       *out++ = n & 0xFF; total++;
+                                       --l;
+                               }
+                       }
+                       if (l) {
+                               archive_set_error(&self->archive->archive,
+                                   ARCHIVE_ERRNO_MISC,
+                                   "Insufficient compressed data");
+                               return (ARCHIVE_FATAL);
+                       }
+                       break;
+               case ST_UUEND:
+                       if (len - nl == 3 && memcmp(b, "end ", 3) == 0)
+                               uudecode->state = ST_FIND_HEAD;
+                       else {
+                               archive_set_error(&self->archive->archive,
+                                   ARCHIVE_ERRNO_MISC,
+                                   "Insufficient compressed data");
+                               return (ARCHIVE_FATAL);
+                       }
+                       break;
+               case ST_READ_BASE64:
+                       l = len - nl;
+                       if (l >= 3 && b[0] == '=' && b[1] == '=' &&
+                           b[2] == '=') {
+                               uudecode->state = ST_FIND_HEAD;
+                               break;
+                       }
+                       while (l > 0) {
+                               int n = 0;
+
+                               if (l > 0) {
+                                       if (!base64[b[0]] || !base64[b[1]])
+                                               break;
+                                       n = base64num[*b++] << 18;
+                                       n |= base64num[*b++] << 12;
+                                       *out++ = n >> 16; total++;
+                                       l -= 2;
+                               }
+                               if (l > 0) {
+                                       if (*b == '=')
+                                               break;
+                                       if (!base64[*b])
+                                               break;
+                                       n |= base64num[*b++] << 6;
+                                       *out++ = (n >> 8) & 0xFF; total++;
+                                       --l;
+                               }
+                               if (l > 0) {
+                                       if (*b == '=')
+                                               break;
+                                       if (!base64[*b])
+                                               break;
+                                       n |= base64num[*b++];
+                                       *out++ = n & 0xFF; total++;
+                                       --l;
+                               }
+                       }
+                       if (l && *b != '=') {
+                               archive_set_error(&self->archive->archive,
+                                   ARCHIVE_ERRNO_MISC,
+                                   "Insufficient compressed data");
+                               return (ARCHIVE_FATAL);
+                       }
+                       break;
+               }
+       }
+
+       __archive_read_filter_consume(self->upstream, ravail);
+
+       *buff = uudecode->out_buff;
+       uudecode->total += total;
+       return (total);
+}
+
+static int
+uudecode_filter_close(struct archive_read_filter *self)
+{
+       struct uudecode *uudecode;
+
+       uudecode = (struct uudecode *)self->data;
+       free(uudecode->in_buff);
+       free(uudecode->out_buff);
+       free(uudecode);
+
+       return (ARCHIVE_OK);
+}
+
index 61d9d0c..28c4e2d 100644 (file)
@@ -26,7 +26,7 @@
 
 #include "archive_platform.h"
 
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_compression_xz.c 201167 2009-12-29 06:06:20Z kientzle $");
 
 #ifdef HAVE_ERRNO_H
 #include <errno.h>
@@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
 #endif
 
 #include "archive.h"
+#include "archive_endian.h"
 #include "archive_private.h"
 #include "archive_read_private.h"
 
@@ -100,6 +101,7 @@ archive_read_support_compression_xz(struct archive *_a)
        struct archive_read *a = (struct archive_read *)_a;
        struct archive_read_filter_bidder *bidder = __archive_read_get_bidder(a);
 
+       archive_clear_error(_a);
        if (bidder == NULL)
                return (ARCHIVE_FATAL);
 
@@ -123,6 +125,7 @@ archive_read_support_compression_lzma(struct archive *_a)
        struct archive_read *a = (struct archive_read *)_a;
        struct archive_read_filter_bidder *bidder = __archive_read_get_bidder(a);
 
+       archive_clear_error(_a);
        if (bidder == NULL)
                return (ARCHIVE_FATAL);
 
@@ -203,37 +206,100 @@ lzma_bidder_bid(struct archive_read_filter_bidder *self,
 {
        const unsigned char *buffer;
        ssize_t avail;
+       uint32_t dicsize;
+       uint64_t uncompressed_size;
        int bits_checked;
 
        (void)self; /* UNUSED */
 
-       buffer = __archive_read_filter_ahead(filter, 6, &avail);
+       buffer = __archive_read_filter_ahead(filter, 14, &avail);
        if (buffer == NULL)
                return (0);
 
-       /* First byte of raw LZMA stream is always 0x5d. */
+       /* First byte of raw LZMA stream is commonly 0x5d.
+        * The first byte is a special number, which consists of
+        * three parameters of LZMA compression, a number of literal
+        * context bits(which is from 0 to 8, default is 3), a number
+        * of literal pos bits(which is from 0 to 4, default is 0),
+        * a number of pos bits(which is from 0 to 4, default is 2).
+        * The first byte is made by
+        * (pos bits * 5 + literal pos bit) * 9 + * literal contest bit,
+        * and so the default value in this field is
+        * (2 * 5 + 0) * 9 + 3 = 0x5d.
+        * lzma of LZMA SDK has options to change those parameters.
+        * It means a range of this field is from 0 to 224. And lzma of
+        * XZ Utils with option -e records 0x5e in this field. */
+       /* NOTE: If this checking of the first byte increases false
+        * recognition, we should allow only 0x5d and 0x5e for the first
+        * byte of LZMA stream. */
        bits_checked = 0;
-       if (buffer[0] != 0x5d)
-               return (0);
-       bits_checked += 8;
-
-       /* Second through fifth bytes are dictionary code, stored in
-        * little-endian order.  The two least-significant bytes are
-        * always zero. */
-       if (buffer[1] != 0 || buffer[2] != 0)
+       if (buffer[0] > (4 * 5 + 4) * 9 + 8)
                return (0);
-       bits_checked += 16;
-
-       /* ??? TODO:  Fix this. ??? */
-       /* NSIS format check uses this, but I've seen tar.lzma
-        * archives where this byte is 0xff, not 0.  Can it
-        * ever be anything other than 0 or 0xff?
-        */
-#if 0
-       if (buffer[5] != 0)
+       /* Most likely value in the first byte of LZMA stream. */
+       if (buffer[0] == 0x5d || buffer[0] == 0x5e)
+               bits_checked += 8;
+
+       /* Sixth through fourteenth bytes are uncompressed size,
+        * stored in little-endian order. `-1' means uncompressed
+        * size is unknown and lzma of XZ Utils always records `-1'
+        * in this field. */
+       uncompressed_size = archive_le64dec(buffer+5);
+       if (uncompressed_size == (uint64_t)ARCHIVE_LITERAL_LL(-1))
+               bits_checked += 64;
+
+       /* Second through fifth bytes are dictionary size, stored in
+        * little-endian order. The minimum dictionary size is
+        * 1 << 12(4KiB) which the lzma of LZMA SDK uses with option
+        * -d12 and the maxinam dictionary size is 1 << 27(128MiB)
+        * which the one uses with option -d27.
+        * NOTE: A comment of LZMA SDK source code says this dictionary
+        * range is from 1 << 12 to 1 << 30. */
+       dicsize = archive_le32dec(buffer+1);
+       switch (dicsize) {
+       case 0x00001000:/* lzma of LZMA SDK option -d12. */
+       case 0x00002000:/* lzma of LZMA SDK option -d13. */
+       case 0x00004000:/* lzma of LZMA SDK option -d14. */
+       case 0x00008000:/* lzma of LZMA SDK option -d15. */
+       case 0x00010000:/* lzma of XZ Utils option -0 and -1.
+                        * lzma of LZMA SDK option -d16. */
+       case 0x00020000:/* lzma of LZMA SDK option -d17. */
+       case 0x00040000:/* lzma of LZMA SDK option -d18. */
+       case 0x00080000:/* lzma of XZ Utils option -2.
+                        * lzma of LZMA SDK option -d19. */
+       case 0x00100000:/* lzma of XZ Utils option -3.
+                        * lzma of LZMA SDK option -d20. */
+       case 0x00200000:/* lzma of XZ Utils option -4.
+                        * lzma of LZMA SDK option -d21. */
+       case 0x00400000:/* lzma of XZ Utils option -5.
+                        * lzma of LZMA SDK option -d22. */
+       case 0x00800000:/* lzma of XZ Utils option -6.
+                        * lzma of LZMA SDK option -d23. */
+       case 0x01000000:/* lzma of XZ Utils option -7.
+                        * lzma of LZMA SDK option -d24. */
+       case 0x02000000:/* lzma of XZ Utils option -8.
+                        * lzma of LZMA SDK option -d25. */
+       case 0x04000000:/* lzma of XZ Utils option -9.
+                        * lzma of LZMA SDK option -d26. */
+       case 0x08000000:/* lzma of LZMA SDK option -d27. */
+               bits_checked += 32;
+               break;
+       default:
+               /* If a memory usage for encoding was not enough on
+                * the platform where LZMA stream was made, lzma of
+                * XZ Utils automatically decreased the dictionary
+                * size to enough memory for encoding by 1Mi bytes
+                * (1 << 20).*/
+               if (dicsize <= 0x03F00000 && dicsize >= 0x00300000 &&
+                   (dicsize & ((1 << 20)-1)) == 0 &&
+                   bits_checked == 8 + 64) {
+                       bits_checked += 32;
+                       break;
+               }
+               /* Otherwise dictionary size is unlikely. But it is
+                * possible that someone makes lzma stream with
+                * liblzma/LZMA SDK in one's dictionary size. */
                return (0);
-       bits_checked += 8;
-#endif
+       }
 
        /* TODO: The above test is still very weak.  It would be
         * good to do better. */
index 24e31ef..9677838 100644 (file)
@@ -24,7 +24,7 @@
  */
 
 #include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_all.c,v 1.10 2007/12/30 04:58:21 kientzle Exp $");
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_all.c 174991 2007-12-30 04:58:22Z kientzle $");
 
 #include "archive.h"
 
@@ -37,6 +37,7 @@ archive_read_support_format_all(struct archive *a)
        archive_read_support_format_iso9660(a);
        archive_read_support_format_mtree(a);
        archive_read_support_format_tar(a);
+       archive_read_support_format_xar(a);
        archive_read_support_format_zip(a);
        return (ARCHIVE_OK);
 }
index 587aad2..7c1ca3a 100644 (file)
@@ -26,7 +26,7 @@
  */
 
 #include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_ar.c,v 1.12 2008/12/17 19:02:42 kientzle Exp $");
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_ar.c 201101 2009-12-28 03:06:27Z kientzle $");
 
 #ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
@@ -40,6 +40,9 @@ __FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_ar.c,v 1.12 2
 #ifdef HAVE_STRING_H
 #include <string.h>
 #endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
 
 #include "archive.h"
 #include "archive_entry.h"
@@ -134,7 +137,6 @@ archive_read_format_ar_cleanup(struct archive_read *a)
 static int
 archive_read_format_ar_bid(struct archive_read *a)
 {
-       struct ar *ar;
        const void *h;
 
        if (a->archive.archive_format != 0 &&
@@ -142,8 +144,6 @@ archive_read_format_ar_bid(struct archive_read *a)
            ARCHIVE_FORMAT_AR)
                return(0);
 
-       ar = (struct ar *)(a->format->data);
-
        /*
         * Verify the 8-byte file signature.
         * TODO: Do we need to check more than this?
index 56247dd..1def000 100644 (file)
@@ -24,7 +24,7 @@
  */
 
 #include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_cpio.c,v 1.27 2008/12/06 06:45:15 kientzle Exp $");
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_cpio.c 201163 2009-12-29 05:50:34Z kientzle $");
 
 #ifdef HAVE_ERRNO_H
 #include <errno.h>
@@ -92,7 +92,7 @@ struct links_entry {
         struct links_entry      *previous;
         int                      links;
         dev_t                    dev;
-        ino_t                    ino;
+        int64_t                  ino;
         char                    *name;
 };
 
@@ -257,6 +257,11 @@ archive_read_format_cpio_read_header(struct archive_read *a,
                cpio->entry_bytes_remaining = 0;
        }
 
+       /* XXX TODO: If the full mode is 0160200, then this is a Solaris
+        * ACL description for the following entry.  Read this body
+        * and parse it as a Solaris-style ACL, then read the next
+        * header.  XXX */
+
        /* Compare name to "TRAILER!!!" to test for end-of-archive. */
        if (namelength == 11 && strcmp((const char *)h, "TRAILER!!!") == 0) {
            /* TODO: Store file location of start of block. */
@@ -351,7 +356,7 @@ find_newc_header(struct archive_read *a)
                 * Scan ahead until we find something that looks
                 * like an odc header.
                 */
-               while (p + sizeof(struct cpio_newc_header) < q) {
+               while (p + sizeof(struct cpio_newc_header) <= q) {
                        switch (p[5]) {
                        case '1':
                        case '2':
@@ -485,7 +490,7 @@ find_odc_header(struct archive_read *a)
                 * Scan ahead until we find something that looks
                 * like an odc header.
                 */
-               while (p + sizeof(struct cpio_odc_header) < q) {
+               while (p + sizeof(struct cpio_odc_header) <= q) {
                        switch (p[5]) {
                        case '7':
                                if (memcmp("070707", p, 6) == 0
@@ -669,7 +674,7 @@ le4(const unsigned char *p)
 static int
 be4(const unsigned char *p)
 {
-       return (p[0] + (p[1]<<8) + (p[2]<<16) + (p[3]<<24));
+       return ((p[0]<<24) + (p[1]<<16) + (p[2]<<8) + (p[3]));
 }
 
 /*
@@ -722,48 +727,51 @@ atol16(const char *p, unsigned char_cnt)
 static void
 record_hardlink(struct cpio *cpio, struct archive_entry *entry)
 {
-        struct links_entry      *le;
+       struct links_entry      *le;
        dev_t dev;
-       ino_t ino;
+       int64_t ino;
+
+       if (archive_entry_nlink(entry) <= 1)
+               return;
 
        dev = archive_entry_dev(entry);
-       ino = archive_entry_ino(entry);
-
-        /*
-         * First look in the list of multiply-linked files.  If we've
-         * already dumped it, convert this entry to a hard link entry.
-         */
-        for (le = cpio->links_head; le; le = le->next) {
-                if (le->dev == dev && le->ino == ino) {
-                        archive_entry_copy_hardlink(entry, le->name);
-
-                        if (--le->links <= 0) {
-                                if (le->previous != NULL)
-                                        le->previous->next = le->next;
-                                if (le->next != NULL)
-                                        le->next->previous = le->previous;
-                                if (cpio->links_head == le)
-                                        cpio->links_head = le->next;
+       ino = archive_entry_ino64(entry);
+
+       /*
+        * First look in the list of multiply-linked files.  If we've
+        * already dumped it, convert this entry to a hard link entry.
+        */
+       for (le = cpio->links_head; le; le = le->next) {
+               if (le->dev == dev && le->ino == ino) {
+                       archive_entry_copy_hardlink(entry, le->name);
+
+                       if (--le->links <= 0) {
+                               if (le->previous != NULL)
+                                       le->previous->next = le->next;
+                               if (le->next != NULL)
+                                       le->next->previous = le->previous;
+                               if (cpio->links_head == le)
+                                       cpio->links_head = le->next;
                                free(le->name);
-                                free(le);
-                        }
+                               free(le);
+                       }
 
-                        return;
-                }
-        }
+                       return;
+               }
+       }
 
-        le = (struct links_entry *)malloc(sizeof(struct links_entry));
+       le = (struct links_entry *)malloc(sizeof(struct links_entry));
        if (le == NULL)
                __archive_errx(1, "Out of memory adding file to list");
-        if (cpio->links_head != NULL)
-                cpio->links_head->previous = le;
-        le->next = cpio->links_head;
-        le->previous = NULL;
-        cpio->links_head = le;
-        le->dev = dev;
-        le->ino = ino;
-        le->links = archive_entry_nlink(entry) - 1;
-        le->name = strdup(archive_entry_pathname(entry));
+       if (cpio->links_head != NULL)
+               cpio->links_head->previous = le;
+       le->next = cpio->links_head;
+       le->previous = NULL;
+       cpio->links_head = le;
+       le->dev = dev;
+       le->ino = ino;
+       le->links = archive_entry_nlink(entry) - 1;
+       le->name = strdup(archive_entry_pathname(entry));
        if (le->name == NULL)
                __archive_errx(1, "Out of memory adding file to list");
 }
index 583e5a3..518fdcb 100644 (file)
@@ -24,7 +24,7 @@
  */
 
 #include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_empty.c,v 1.4 2008/12/06 06:45:15 kientzle Exp $");
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_empty.c 191524 2009-04-26 18:24:14Z kientzle $");
 
 #include "archive.h"
 #include "archive_entry.h"
@@ -59,10 +59,9 @@ archive_read_support_format_empty(struct archive *_a)
 static int
 archive_read_format_empty_bid(struct archive_read *a)
 {
-       const void *h;
        ssize_t avail;
 
-       h = __archive_read_ahead(a, 1, &avail);
+       (void)__archive_read_ahead(a, 1, &avail);
        if (avail != 0)
                return (-1);
        return (1);
index 1921c58..0c640c8 100644 (file)
@@ -1,6 +1,7 @@
 /*-
  * Copyright (c) 2003-2007 Tim Kientzle
  * Copyright (c) 2009 Andreas Henriksson <andreas@fatal.se>
+ * Copyright (c) 2009 Michihiro NAKAJIMA
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -25,7 +26,7 @@
  */
 
 #include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_iso9660.c,v 1.30 2008/12/06 06:57:45 kientzle Exp $");
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_iso9660.c 201246 2009-12-30 05:30:35Z kientzle $");
 
 #ifdef HAVE_ERRNO_H
 #include <errno.h>
@@ -39,8 +40,12 @@ __FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_iso9660.c,v 1
 #include <string.h>
 #endif
 #include <time.h>
+#ifdef HAVE_ZLIB_H
+#include <zlib.h>
+#endif
 
 #include "archive.h"
+#include "archive_endian.h"
 #include "archive_entry.h"
 #include "archive_private.h"
 #include "archive_read_private.h"
@@ -73,6 +78,8 @@ __FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_iso9660.c,v 1
  * the file body.  This strategy allows us to read most compliant
  * CDs with a single pass through the data, as required by libarchive.
  */
+#define        LOGICAL_BLOCK_SIZE      2048
+#define        SYSTEM_AREA_BLOCK       16
 
 /* Structure of on-disk primary volume descriptor. */
 #define PVD_type_offset 0
@@ -158,6 +165,8 @@ __FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_iso9660.c,v 1
 #define SVD_version_offset (SVD_id_offset + SVD_id_size)
 #define SVD_version_size 1
 /* ... */
+#define SVD_reserved1_offset   72
+#define SVD_reserved1_size     8
 #define SVD_volume_space_size_offset 80
 #define SVD_volume_space_size_size 8
 #define SVD_escape_sequences_offset (SVD_volume_space_size_offset + SVD_volume_space_size_size)
@@ -165,9 +174,16 @@ __FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_iso9660.c,v 1
 /* ... */
 #define SVD_logical_block_size_offset 128
 #define SVD_logical_block_size_size 4
+#define SVD_type_L_path_table_offset 140
+#define SVD_type_M_path_table_offset 148
 /* ... */
 #define SVD_root_directory_record_offset 156
 #define SVD_root_directory_record_size 34
+#define SVD_file_structure_version_offset 881
+#define SVD_reserved2_offset   882
+#define SVD_reserved2_size     1
+#define SVD_reserved3_offset   1395
+#define SVD_reserved3_size     653
 /* ... */
 /* FIXME: validate correctness of last SVD entry offset. */
 
@@ -198,60 +214,146 @@ __FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_iso9660.c,v 1
 #define DR_name_len_size 1
 #define DR_name_offset 33
 
+#ifdef HAVE_ZLIB_H
+static const unsigned char zisofs_magic[8] = {
+       0x37, 0xE4, 0x53, 0x96, 0xC9, 0xDB, 0xD6, 0x07
+};
+
+struct zisofs {
+       /* Set 1 if this file compressed by paged zlib */
+       int              pz;
+       int              pz_log2_bs; /* Log2 of block size */
+       uint64_t         pz_uncompressed_size;
+
+       int              initialized;
+       unsigned char   *uncompressed_buffer;
+       size_t           uncompressed_buffer_size;
+
+       uint32_t         pz_offset;
+       unsigned char    header[16];
+       size_t           header_avail;
+       int              header_passed;
+       unsigned char   *block_pointers;
+       size_t           block_pointers_alloc;
+       size_t           block_pointers_size;
+       size_t           block_pointers_avail;
+       size_t           block_off;
+       uint32_t         block_avail;
+
+       z_stream         stream;
+       int              stream_valid;
+};
+#else
+struct zisofs {
+       /* Set 1 if this file compressed by paged zlib */
+       int              pz;
+};
+#endif
+
+struct content {
+       uint64_t         offset;/* Offset on disk.              */
+       uint64_t         size;  /* File size in bytes.          */
+       struct content  *next;
+};
+
 /* In-memory storage for a directory record. */
 struct file_info {
+       struct file_info        *use_next;
        struct file_info        *parent;
-       int              refcount;
-       uint64_t         offset;  /* Offset on disk. */
-       uint64_t         size;  /* File size in bytes. */
-       uint64_t         ce_offset; /* Offset of CE */
-       uint64_t         ce_size; /* Size of CE */
-       time_t           birthtime; /* File created time. */
-       time_t           mtime; /* File last modified time. */
-       time_t           atime; /* File last accessed time. */
-       time_t           ctime; /* File attribute change time. */
-       uint64_t         rdev; /* Device number */
+       struct file_info        *next;
+       int              subdirs;
+       uint64_t         key;           /* Heap Key.                    */
+       uint64_t         offset;        /* Offset on disk.              */
+       uint64_t         size;          /* File size in bytes.          */
+       uint32_t         ce_offset;     /* Offset of CE.                */
+       uint32_t         ce_size;       /* Size of CE.                  */
+       char             re;            /* Having RRIP "RE" extension.  */
+       uint64_t         cl_offset;     /* Having RRIP "CL" extension.  */
+       int              birthtime_is_set;
+       time_t           birthtime;     /* File created time.           */
+       time_t           mtime;         /* File last modified time.     */
+       time_t           atime;         /* File last accessed time.     */
+       time_t           ctime;         /* File attribute change time.  */
+       uint64_t         rdev;          /* Device number.               */
        mode_t           mode;
        uid_t            uid;
        gid_t            gid;
-       ino_t            inode;
+       int64_t          number;
        int              nlinks;
        struct archive_string name; /* Pathname */
        char             name_continues; /* Non-zero if name continues */
        struct archive_string symlink;
        char             symlink_continues; /* Non-zero if link continues */
+       /* Set 1 if this file compressed by paged zlib(zisofs) */
+       int              pz;
+       int              pz_log2_bs; /* Log2 of block size */
+       uint64_t         pz_uncompressed_size;
+       /* Set 1 if this file is multi extent. */
+       int              multi_extent;
+       struct {
+               struct content  *first;
+               struct content  **last;
+       } contents;
+       char             exposed;
 };
 
+struct heap_queue {
+       struct file_info **files;
+       int              allocated;
+       int              used;
+};
 
 struct iso9660 {
        int     magic;
 #define ISO9660_MAGIC   0x96609660
 
-       int option_ignore_joliet;
+       int opt_support_joliet;
+       int opt_support_rockridge;
 
        struct archive_string pathname;
-       char    seenRockridge; /* Set true if RR extensions are used. */
-       unsigned char   suspOffset;
+       char    seenRockridge;  /* Set true if RR extensions are used. */
+       char    seenSUSP;       /* Set true if SUSP is beging used. */
        char    seenJoliet;
 
-       uint64_t        previous_offset;
-       uint64_t        previous_size;
+       unsigned char   suspOffset;
+       struct file_info *rr_moved;
+       struct heap_queue                re_dirs;
+       struct heap_queue                cl_files;
+       struct read_ce_queue {
+               struct read_ce_req {
+                       uint64_t         offset;/* Offset of CE on disk. */
+                       struct file_info *file;
+               }               *reqs;
+               int              cnt;
+               int              allocated;
+       }       read_ce_req;
+
+       int64_t         previous_number;
        struct archive_string previous_pathname;
 
-       /* TODO: Make this a heap for fast inserts and deletions. */
-       struct file_info **pending_files;
-       int     pending_files_allocated;
-       int     pending_files_used;
+       struct file_info                *use_files;
+       struct heap_queue                pending_files;
+       struct {
+               struct file_info        *first;
+               struct file_info        **last;
+       }       cache_files;
 
        uint64_t current_position;
        ssize_t logical_block_size;
        uint64_t volume_size; /* Total size of volume in bytes. */
+       int32_t  volume_block;/* Total size of volume in logical blocks. */
+
+       struct vd {
+               int             location;       /* Location of Extent.  */
+               uint32_t        size;
+       } primary, joliet;
 
        off_t   entry_sparse_offset;
        int64_t entry_bytes_remaining;
+       struct zisofs    entry_zisofs;
+       struct content  *entry_content;
 };
 
-static void    add_entry(struct iso9660 *iso9660, struct file_info *file);
 static int     archive_read_format_iso9660_bid(struct archive_read *);
 static int     archive_read_format_iso9660_options(struct archive_read *,
                    const char *, const char *);
@@ -268,25 +370,49 @@ static void       dump_isodirrec(FILE *, const unsigned char *isodirrec);
 static time_t  time_from_tm(struct tm *);
 static time_t  isodate17(const unsigned char *);
 static time_t  isodate7(const unsigned char *);
+static int     isBootRecord(struct iso9660 *, const unsigned char *);
+static int     isVolumePartition(struct iso9660 *, const unsigned char *);
+static int     isVDSetTerminator(struct iso9660 *, const unsigned char *);
 static int     isJolietSVD(struct iso9660 *, const unsigned char *);
+static int     isSVD(struct iso9660 *, const unsigned char *);
+static int     isEVD(struct iso9660 *, const unsigned char *);
 static int     isPVD(struct iso9660 *, const unsigned char *);
-static struct file_info *next_entry(struct iso9660 *);
+static struct file_info *next_cache_entry(struct iso9660 *iso9660);
 static int     next_entry_seek(struct archive_read *a, struct iso9660 *iso9660,
                    struct file_info **pfile);
 static struct file_info *
-               parse_file_info(struct iso9660 *iso9660,
+               parse_file_info(struct archive_read *a,
                    struct file_info *parent, const unsigned char *isodirrec);
-static void    parse_rockridge(struct iso9660 *iso9660,
+static int     parse_rockridge(struct archive_read *a,
                    struct file_info *file, const unsigned char *start,
                    const unsigned char *end);
+static int     register_CE(struct archive_read *a, int32_t location,
+                   struct file_info *file);
+static int     read_CE(struct archive_read *a, struct iso9660 *iso9660);
 static void    parse_rockridge_NM1(struct file_info *,
                    const unsigned char *, int);
 static void    parse_rockridge_SL1(struct file_info *,
                    const unsigned char *, int);
 static void    parse_rockridge_TF1(struct file_info *,
                    const unsigned char *, int);
-static void    release_file(struct iso9660 *, struct file_info *);
+static void    parse_rockridge_ZF1(struct file_info *,
+                   const unsigned char *, int);
+static void    register_file(struct iso9660 *, struct file_info *);
+static void    release_files(struct iso9660 *);
 static unsigned        toi(const void *p, int n);
+static inline void cache_add_entry(struct iso9660 *iso9660,
+                   struct file_info *file);
+static inline void cache_add_to_next_of_parent(struct iso9660 *iso9660,
+                   struct file_info *file);
+static inline struct file_info *cache_get_entry(struct iso9660 *iso9660);
+static void    heap_add_entry(struct heap_queue *heap,
+                   struct file_info *file, uint64_t key);
+static struct file_info *heap_get_entry(struct heap_queue *heap);
+
+#define add_entry(iso9660, file)       \
+       heap_add_entry(&((iso9660)->pending_files), file, file->offset)
+#define next_entry(iso9660)            \
+       heap_get_entry(&((iso9660)->pending_files))
 
 int
 archive_read_support_format_iso9660(struct archive *_a)
@@ -302,6 +428,12 @@ archive_read_support_format_iso9660(struct archive *_a)
        }
        memset(iso9660, 0, sizeof(*iso9660));
        iso9660->magic = ISO9660_MAGIC;
+       iso9660->cache_files.first = NULL;
+       iso9660->cache_files.last = &(iso9660->cache_files.first);
+       /* Enable to support Joliet extensions by default.      */
+       iso9660->opt_support_joliet = 1;
+       /* Enable to support Rock Ridge extensions by default.  */
+       iso9660->opt_support_rockridge = 1;
 
        r = __archive_read_register_format(a,
            iso9660,
@@ -325,10 +457,10 @@ static int
 archive_read_format_iso9660_bid(struct archive_read *a)
 {
        struct iso9660 *iso9660;
-       ssize_t bytes_read, brsvd;
+       ssize_t bytes_read;
        const void *h;
-       const unsigned char *p, *psvd;
-       int bid;
+       const unsigned char *p;
+       int seenTerminator;
 
        iso9660 = (struct iso9660 *)(a->format->data);
 
@@ -337,34 +469,56 @@ archive_read_format_iso9660_bid(struct archive_read *a)
         * 8 sectors of the volume descriptor table.  Of course,
         * if the I/O layer gives us more, we'll take it.
         */
-       h = __archive_read_ahead(a, 32768 + 8*2048, &bytes_read);
+#define RESERVED_AREA  (SYSTEM_AREA_BLOCK * LOGICAL_BLOCK_SIZE)
+       h = __archive_read_ahead(a,
+           RESERVED_AREA + 8 * LOGICAL_BLOCK_SIZE,
+           &bytes_read);
        if (h == NULL)
            return (-1);
        p = (const unsigned char *)h;
 
        /* Skip the reserved area. */
-       bytes_read -= 32768;
-       p += 32768;
-
-       /* Check each volume descriptor to locate possible SVD with Joliet. */
-       for (brsvd = bytes_read, psvd = p;
-                       !iso9660->option_ignore_joliet && brsvd > 2048;
-                       brsvd -= 2048, psvd += 2048) {
-               bid = isJolietSVD(iso9660, psvd);
-               if (bid > 0)
-                       return (bid);
-               if (*p == '\177') /* End-of-volume-descriptor marker. */
-                       break;
-       }
-
-       /* Check each volume descriptor to locate the PVD. */
-       for (; bytes_read > 2048; bytes_read -= 2048, p += 2048) {
-               bid = isPVD(iso9660, p);
-               if (bid > 0)
-                       return (bid);
-               if (*p == '\177') /* End-of-volume-descriptor marker. */
+       bytes_read -= RESERVED_AREA;
+       p += RESERVED_AREA;
+
+       /* Check each volume descriptor. */
+       seenTerminator = 0;
+       for (; bytes_read > LOGICAL_BLOCK_SIZE;
+           bytes_read -= LOGICAL_BLOCK_SIZE, p += LOGICAL_BLOCK_SIZE) {
+               /* Do not handle undefined Volume Descriptor Type. */
+               if (p[0] >= 4 && p[0] <= 254)
+                       return (0);
+               /* Standard Identifier must be "CD001" */
+               if (memcmp(p + 1, "CD001", 5) != 0)
+                       return (0);
+               if (!iso9660->primary.location) {
+                       if (isPVD(iso9660, p))
+                               continue;
+               }
+               if (!iso9660->joliet.location) {
+                       if (isJolietSVD(iso9660, p))
+                               continue;
+               }
+               if (isBootRecord(iso9660, p))
+                       continue;
+               if (isEVD(iso9660, p))
+                       continue;
+               if (isSVD(iso9660, p))
+                       continue;
+               if (isVolumePartition(iso9660, p))
+                       continue;
+               if (isVDSetTerminator(iso9660, p)) {
+                       seenTerminator = 1;
                        break;
+               }
+               return (0);
        }
+       /*
+        * ISO 9660 format must have Primary Volume Descriptor and
+        * Volume Descriptor Set Terminator.
+        */
+       if (seenTerminator && iso9660->primary.location > 16)
+               return (48);
 
        /* We didn't find a valid PVD; return a bid of zero. */
        return (0);
@@ -383,9 +537,14 @@ archive_read_format_iso9660_options(struct archive_read *a,
                                strcmp(val, "ignore") == 0 ||
                                strcmp(val, "disable") == 0 ||
                                strcmp(val, "0") == 0)
-                       iso9660->option_ignore_joliet = 1;
+                       iso9660->opt_support_joliet = 0;
                else
-                       iso9660->option_ignore_joliet = 0;
+                       iso9660->opt_support_joliet = 1;
+               return (ARCHIVE_OK);
+       }
+       if (strcmp(key, "rockridge") == 0 ||
+           strcmp(key, "Rockridge") == 0) {
+               iso9660->opt_support_rockridge = val != NULL;
                return (ARCHIVE_OK);
        }
 
@@ -396,17 +555,80 @@ archive_read_format_iso9660_options(struct archive_read *a,
 }
 
 static int
-isJolietSVD(struct iso9660 *iso9660, const unsigned char *h)
+isBootRecord(struct iso9660 *iso9660, const unsigned char *h)
 {
-       struct file_info *file;
-       const unsigned char *p;
+       (void)iso9660; /* UNUSED */
 
-       /* Type 2 means it's a SVD. */
-       if (h[SVD_type_offset] != 2)
+       /* Type of the Volume Descriptor Boot Record must be 0. */
+       if (h[0] != 0)
+               return (0);
+
+       /* Volume Descriptor Version must be 1. */
+       if (h[6] != 1)
+               return (0);
+
+       return (1);
+}
+
+static int
+isVolumePartition(struct iso9660 *iso9660, const unsigned char *h)
+{
+       int32_t location;
+
+       /* Type of the Volume Partition Descriptor must be 3. */
+       if (h[0] != 3)
+               return (0);
+
+       /* Volume Descriptor Version must be 1. */
+       if (h[6] != 1)
+               return (0);
+       /* Unused Field */
+       if (h[7] != 0)
                return (0);
 
-       /* ID must be "CD001" */
-       if (memcmp(h + SVD_id_offset, "CD001", 5) != 0)
+       location = archive_le32dec(h + 72);
+       if (location <= SYSTEM_AREA_BLOCK ||
+           location >= iso9660->volume_block)
+               return (0);
+       if ((uint32_t)location != archive_be32dec(h + 76))
+               return (0);
+
+       return (1);
+}
+
+static int
+isVDSetTerminator(struct iso9660 *iso9660, const unsigned char *h)
+{
+       int i;
+
+       (void)iso9660; /* UNUSED */
+
+       /* Type of the Volume Descriptor Set Terminator must be 255. */
+       if (h[0] != 255)
+               return (0);
+
+       /* Volume Descriptor Version must be 1. */
+       if (h[6] != 1)
+               return (0);
+
+       /* Reserved field must be 0. */
+       for (i = 7; i < 2048; ++i)
+               if (h[i] != 0)
+                       return (0);
+
+       return (1);
+}
+
+static int
+isJolietSVD(struct iso9660 *iso9660, const unsigned char *h)
+{
+       const unsigned char *p;
+       ssize_t logical_block_size;
+       int32_t volume_block;
+
+       /* Check if current sector is a kind of Supplementary Volume
+        * Descriptor. */
+       if (!isSVD(iso9660, h))
                return (0);
 
        /* FIXME: do more validations according to joliet spec. */
@@ -431,23 +653,160 @@ isJolietSVD(struct iso9660 *iso9660, const unsigned char *h)
        } else /* not joliet */
                return (0);
 
-       iso9660->logical_block_size = toi(h + SVD_logical_block_size_offset, 2);
-       if (iso9660->logical_block_size <= 0)
+       logical_block_size =
+           archive_le16dec(h + SVD_logical_block_size_offset);
+       volume_block = archive_le32dec(h + SVD_volume_space_size_offset);
+
+       iso9660->logical_block_size = logical_block_size;
+       iso9660->volume_block = volume_block;
+       iso9660->volume_size = logical_block_size * (uint64_t)volume_block;
+       /* Read Root Directory Record in Volume Descriptor. */
+       p = h + SVD_root_directory_record_offset;
+       iso9660->joliet.location = archive_le32dec(p + DR_extent_offset);
+       iso9660->joliet.size = archive_le32dec(p + DR_size_offset);
+
+       return (48);
+}
+
+static int
+isSVD(struct iso9660 *iso9660, const unsigned char *h)
+{
+       const unsigned char *p;
+       ssize_t logical_block_size;
+       int32_t volume_block;
+       int32_t location;
+       int i;
+
+       (void)iso9660; /* UNUSED */
+
+       /* Type 2 means it's a SVD. */
+       if (h[SVD_type_offset] != 2)
                return (0);
 
-       iso9660->volume_size = iso9660->logical_block_size
-           * (uint64_t)toi(h + SVD_volume_space_size_offset, 4);
+       /* Reserved field must be 0. */
+       for (i = 0; i < SVD_reserved1_size; ++i)
+               if (h[SVD_reserved1_offset + i] != 0)
+                       return (0);
+       for (i = 0; i < SVD_reserved2_size; ++i)
+               if (h[SVD_reserved2_offset + i] != 0)
+                       return (0);
+       for (i = 0; i < SVD_reserved3_size; ++i)
+               if (h[SVD_reserved3_offset + i] != 0)
+                       return (0);
+
+       /* File structure version must be 1 for ISO9660/ECMA119. */
+       if (h[SVD_file_structure_version_offset] != 1)
+               return (0);
 
-#if DEBUG
-       fprintf(stderr, "Joliet UCS-2 level %d with "
-                       "logical block size:%d, volume size:%d\n",
-                       iso9660->seenJoliet,
-                       iso9660->logical_block_size, iso9660->volume_size);
-#endif
+       logical_block_size =
+           archive_le16dec(h + SVD_logical_block_size_offset);
+       if (logical_block_size <= 0)
+               return (0);
+
+       volume_block = archive_le32dec(h + SVD_volume_space_size_offset);
+       if (volume_block <= SYSTEM_AREA_BLOCK+4)
+               return (0);
+
+       /* Location of Occurrence of Type L Path Table must be
+        * available location,
+        * > SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */
+       location = archive_le32dec(h+SVD_type_L_path_table_offset);
+       if (location <= SYSTEM_AREA_BLOCK+2 || location >= volume_block)
+               return (0);
+
+       /* Location of Occurrence of Type M Path Table must be
+        * available location,
+        * > SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */
+       location = archive_be32dec(h+SVD_type_M_path_table_offset);
+       if (location <= SYSTEM_AREA_BLOCK+2 || location >= volume_block)
+               return (0);
+
+       /* Read Root Directory Record in Volume Descriptor. */
+       p = h + SVD_root_directory_record_offset;
+       if (p[DR_length_offset] != 34)
+               return (0);
+
+       return (48);
+}
+
+static int
+isEVD(struct iso9660 *iso9660, const unsigned char *h)
+{
+       const unsigned char *p;
+       ssize_t logical_block_size;
+       int32_t volume_block;
+       int32_t location;
+       int i;
+
+       (void)iso9660; /* UNUSED */
+
+       /* Type of the Enhanced Volume Descriptor must be 2. */
+       if (h[PVD_type_offset] != 2)
+               return (0);
+
+       /* EVD version must be 2. */
+       if (h[PVD_version_offset] != 2)
+               return (0);
+
+       /* Reserved field must be 0. */
+       if (h[PVD_reserved1_offset] != 0)
+               return (0);
+
+       /* Reserved field must be 0. */
+       for (i = 0; i < PVD_reserved2_size; ++i)
+               if (h[PVD_reserved2_offset + i] != 0)
+                       return (0);
 
-       /* Store the root directory in the pending list. */
-       file = parse_file_info(iso9660, NULL, h + SVD_root_directory_record_offset);
-       add_entry(iso9660, file);
+       /* Reserved field must be 0. */
+       for (i = 0; i < PVD_reserved3_size; ++i)
+               if (h[PVD_reserved3_offset + i] != 0)
+                       return (0);
+
+       /* Logical block size must be > 0. */
+       /* I've looked at Ecma 119 and can't find any stronger
+        * restriction on this field. */
+       logical_block_size =
+           archive_le16dec(h + PVD_logical_block_size_offset);
+       if (logical_block_size <= 0)
+               return (0);
+
+       volume_block =
+           archive_le32dec(h + PVD_volume_space_size_offset);
+       if (volume_block <= SYSTEM_AREA_BLOCK+4)
+               return (0);
+
+       /* File structure version must be 2 for ISO9660:1999. */
+       if (h[PVD_file_structure_version_offset] != 2)
+               return (0);
+
+       /* Location of Occurrence of Type L Path Table must be
+        * available location,
+        * > SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */
+       location = archive_le32dec(h+PVD_type_1_path_table_offset);
+       if (location <= SYSTEM_AREA_BLOCK+2 || location >= volume_block)
+               return (0);
+
+       /* Location of Occurrence of Type M Path Table must be
+        * available location,
+        * > SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */
+       location = archive_be32dec(h+PVD_type_m_path_table_offset);
+       if (location <= SYSTEM_AREA_BLOCK+2 || location >= volume_block)
+               return (0);
+
+       /* Reserved field must be 0. */
+       for (i = 0; i < PVD_reserved4_size; ++i)
+               if (h[PVD_reserved4_offset + i] != 0)
+                       return (0);
+
+       /* Reserved field must be 0. */
+       for (i = 0; i < PVD_reserved5_size; ++i)
+               if (h[PVD_reserved5_offset + i] != 0)
+                       return (0);
+
+       /* Read Root Directory Record in Volume Descriptor. */
+       p = h + PVD_root_directory_record_offset;
+       if (p[DR_length_offset] != 34)
+               return (0);
 
        return (48);
 }
@@ -455,17 +814,16 @@ isJolietSVD(struct iso9660 *iso9660, const unsigned char *h)
 static int
 isPVD(struct iso9660 *iso9660, const unsigned char *h)
 {
-       struct file_info *file;
+       const unsigned char *p;
+       ssize_t logical_block_size;
+       int32_t volume_block;
+       int32_t location;
        int i;
 
        /* Type of the Primary Volume Descriptor must be 1. */
        if (h[PVD_type_offset] != 1)
                return (0);
 
-       /* ID must be "CD001" */
-       if (memcmp(h + PVD_id_offset, "CD001", 5) != 0)
-               return (0);
-
        /* PVD version must be 1. */
        if (h[PVD_version_offset] != 1)
                return (0);
@@ -487,17 +845,32 @@ isPVD(struct iso9660 *iso9660, const unsigned char *h)
        /* Logical block size must be > 0. */
        /* I've looked at Ecma 119 and can't find any stronger
         * restriction on this field. */
-       iso9660->logical_b