Import libarchive-3.2.0.
authorPeter Avalos <pavalos@dragonflybsd.org>
Thu, 12 May 2016 20:58:50 +0000 (13:58 -0700)
committerPeter Avalos <pavalos@dragonflybsd.org>
Thu, 12 May 2016 21:01:05 +0000 (14:01 -0700)
151 files changed:
contrib/libarchive/COPYING
contrib/libarchive/NEWS
contrib/libarchive/README
contrib/libarchive/README.DELETED
contrib/libarchive/build/version
contrib/libarchive/cat/bsdcat.1 [copied from contrib/libarchive/libarchive/archive_write_data.3 with 65% similarity]
contrib/libarchive/cat/bsdcat.c [new file with mode: 0644]
contrib/libarchive/cat/bsdcat.h [copied from contrib/libarchive/libarchive_fe/err.h with 66% similarity]
contrib/libarchive/cat/bsdcat_platform.h [copied from contrib/libarchive/cpio/cpio_platform.h with 80% similarity]
contrib/libarchive/cat/cmdline.c [copied from contrib/libarchive/tar/cmdline.c with 51% similarity]
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/archive.h
contrib/libarchive/libarchive/archive_cryptor.c [new file with mode: 0644]
contrib/libarchive/libarchive/archive_cryptor_private.h [new file with mode: 0644]
contrib/libarchive/libarchive/archive_digest.c [moved from contrib/libarchive/libarchive/archive_crypto.c with 99% similarity]
contrib/libarchive/libarchive/archive_digest_private.h [moved from contrib/libarchive/libarchive/archive_crypto_private.h with 93% similarity]
contrib/libarchive/libarchive/archive_endian.h
contrib/libarchive/libarchive/archive_entry.3
contrib/libarchive/libarchive/archive_entry.c
contrib/libarchive/libarchive/archive_entry.h
contrib/libarchive/libarchive/archive_entry_acl.3
contrib/libarchive/libarchive/archive_entry_copy_stat.c
contrib/libarchive/libarchive/archive_entry_paths.3
contrib/libarchive/libarchive/archive_entry_perms.3
contrib/libarchive/libarchive/archive_entry_private.h
contrib/libarchive/libarchive/archive_entry_sparse.c
contrib/libarchive/libarchive/archive_entry_stat.3
contrib/libarchive/libarchive/archive_entry_time.3
contrib/libarchive/libarchive/archive_entry_xattr.c
contrib/libarchive/libarchive/archive_getdate.c
contrib/libarchive/libarchive/archive_getdate.h [copied from contrib/libarchive/libarchive_fe/err.h with 66% similarity]
contrib/libarchive/libarchive/archive_hmac.c [new file with mode: 0644]
contrib/libarchive/libarchive/archive_hmac_private.h [new file with mode: 0644]
contrib/libarchive/libarchive/archive_match.c
contrib/libarchive/libarchive/archive_options.c
contrib/libarchive/libarchive/archive_pack_dev.c [new file with mode: 0644]
contrib/libarchive/libarchive/archive_pack_dev.h [new file with mode: 0644]
contrib/libarchive/libarchive/archive_pathmatch.c
contrib/libarchive/libarchive/archive_platform.h
contrib/libarchive/libarchive/archive_private.h
contrib/libarchive/libarchive/archive_random.c [new file with mode: 0644]
contrib/libarchive/libarchive/archive_random_private.h [copied from contrib/libarchive/libarchive_fe/err.h with 65% similarity]
contrib/libarchive/libarchive/archive_read.3
contrib/libarchive/libarchive/archive_read.c
contrib/libarchive/libarchive/archive_read_add_passphrase.3 [copied from contrib/libarchive/libarchive/archive_write_data.3 with 59% similarity]
contrib/libarchive/libarchive/archive_read_add_passphrase.c [new file with mode: 0644]
contrib/libarchive/libarchive/archive_read_append_filter.c
contrib/libarchive/libarchive/archive_read_data.3
contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c
contrib/libarchive/libarchive/archive_read_disk_posix.c
contrib/libarchive/libarchive/archive_read_disk_private.h
contrib/libarchive/libarchive/archive_read_disk_set_standard_lookup.c
contrib/libarchive/libarchive/archive_read_extract.c
contrib/libarchive/libarchive/archive_read_extract2.c [copied from contrib/libarchive/libarchive/archive_read_extract.c with 76% similarity]
contrib/libarchive/libarchive/archive_read_filter.3
contrib/libarchive/libarchive/archive_read_open.3
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_open_memory.c
contrib/libarchive/libarchive/archive_read_private.h
contrib/libarchive/libarchive/archive_read_set_options.3
contrib/libarchive/libarchive/archive_read_set_options.c
contrib/libarchive/libarchive/archive_read_support_filter_all.c
contrib/libarchive/libarchive/archive_read_support_filter_compress.c
contrib/libarchive/libarchive/archive_read_support_filter_lz4.c [new file with mode: 0644]
contrib/libarchive/libarchive/archive_read_support_filter_lzop.c
contrib/libarchive/libarchive/archive_read_support_filter_uu.c
contrib/libarchive/libarchive/archive_read_support_filter_xz.c
contrib/libarchive/libarchive/archive_read_support_format_7zip.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_cab.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_lha.c
contrib/libarchive/libarchive/archive_read_support_format_mtree.c
contrib/libarchive/libarchive/archive_read_support_format_rar.c
contrib/libarchive/libarchive/archive_read_support_format_raw.c
contrib/libarchive/libarchive/archive_read_support_format_tar.c
contrib/libarchive/libarchive/archive_read_support_format_warc.c [new file with mode: 0644]
contrib/libarchive/libarchive/archive_read_support_format_xar.c
contrib/libarchive/libarchive/archive_read_support_format_zip.c
contrib/libarchive/libarchive/archive_string.c
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_add_filter.c
contrib/libarchive/libarchive/archive_write_add_filter_by_name.c
contrib/libarchive/libarchive/archive_write_add_filter_bzip2.c
contrib/libarchive/libarchive/archive_write_add_filter_grzip.c
contrib/libarchive/libarchive/archive_write_add_filter_gzip.c
contrib/libarchive/libarchive/archive_write_add_filter_lrzip.c
contrib/libarchive/libarchive/archive_write_add_filter_lz4.c [new file with mode: 0644]
contrib/libarchive/libarchive/archive_write_add_filter_lzop.c
contrib/libarchive/libarchive/archive_write_add_filter_program.c
contrib/libarchive/libarchive/archive_write_add_filter_xz.c
contrib/libarchive/libarchive/archive_write_data.3
contrib/libarchive/libarchive/archive_write_disk.3
contrib/libarchive/libarchive/archive_write_disk_acl.c
contrib/libarchive/libarchive/archive_write_disk_posix.c
contrib/libarchive/libarchive/archive_write_disk_set_standard_lookup.c
contrib/libarchive/libarchive/archive_write_filter.3
contrib/libarchive/libarchive/archive_write_finish_entry.3
contrib/libarchive/libarchive/archive_write_format.3
contrib/libarchive/libarchive/archive_write_open.3
contrib/libarchive/libarchive/archive_write_open_filename.c
contrib/libarchive/libarchive/archive_write_private.h
contrib/libarchive/libarchive/archive_write_set_format.c
contrib/libarchive/libarchive/archive_write_set_format_7zip.c
contrib/libarchive/libarchive/archive_write_set_format_by_name.c
contrib/libarchive/libarchive/archive_write_set_format_filter_by_ext.c [new file with mode: 0644]
contrib/libarchive/libarchive/archive_write_set_format_gnutar.c
contrib/libarchive/libarchive/archive_write_set_format_iso9660.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_raw.c [new file with mode: 0644]
contrib/libarchive/libarchive/archive_write_set_format_shar.c
contrib/libarchive/libarchive/archive_write_set_format_warc.c [new file with mode: 0644]
contrib/libarchive/libarchive/archive_write_set_format_xar.c
contrib/libarchive/libarchive/archive_write_set_format_zip.c
contrib/libarchive/libarchive/archive_write_set_options.3
contrib/libarchive/libarchive/archive_write_set_passphrase.3 [copied from contrib/libarchive/libarchive/archive_write_data.3 with 60% similarity]
contrib/libarchive/libarchive/archive_write_set_passphrase.c [new file with mode: 0644]
contrib/libarchive/libarchive/archive_xxhash.h [copied from contrib/libarchive/libarchive_fe/err.h with 66% similarity]
contrib/libarchive/libarchive/libarchive-formats.5
contrib/libarchive/libarchive/libarchive.3
contrib/libarchive/libarchive/libarchive_internals.3
contrib/libarchive/libarchive/mtree.5
contrib/libarchive/libarchive/tar.5
contrib/libarchive/libarchive/xxhash.c [new file with mode: 0644]
contrib/libarchive/libarchive_fe/err.c
contrib/libarchive/libarchive_fe/err.h
contrib/libarchive/libarchive_fe/passphrase.c [new file with mode: 0644]
contrib/libarchive/libarchive_fe/passphrase.h [copied from contrib/libarchive/libarchive_fe/err.h with 65% similarity]
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/creation_set.c
contrib/libarchive/tar/read.c
contrib/libarchive/tar/subst.c
contrib/libarchive/tar/util.c
contrib/libarchive/tar/write.c

index b258806..93952b7 100644 (file)
@@ -17,12 +17,11 @@ the actual statements in the files are controlling.
   files for details:
    libarchive/archive_entry.c
    libarchive/archive_read_support_filter_compress.c
-   libarchive/archive_write_set_filter_compress.c
+   libarchive/archive_write_add_filter_compress.c
    libarchive/mtree.5
-   tar/matching.c
 
 * The following source files are in the public domain:
-   tar/getdate.c
+   libarchive/archive_getdate.c
 
 * The build files---including Makefiles, configure scripts,
   and auxiliary scripts used as part of the compile process---have
index 107d4da..5bf8776 100644 (file)
@@ -1,3 +1,35 @@
+Apr 09, 2016: libarchive 3.1.901a released
+    Another test release in preparation for 3.2.0
+
+Feb 13, 2016: libarchive 3.1.900a released
+    This is a test release in preparation for 3.2.0
+
+Oct 21, 2015: Preliminary port to OSF
+
+Apr 11, 2015: libarchive's issue tracker is now hosted at GitHub.
+    https://github.com/libarchive/libarchive/issues
+
+Early 2015:  Many fixes to crash and overflow bugs thanks to Hanno Boeck
+
+Oct 13, 2014: Zip encryption and decryption support
+
+Aug 13, 2014: Add support for lz4 compression.
+
+Jun 10, 2014: Add warc format support
+
+May  3, 2014: Add experimental Zip streaming extension
+
+Apr  6, 2014: Add bsdcat command-line tool
+
+Jan 12, 2014: Add Zip64 support
+
+Dec  1, 2013: Rewrite Zip write logic
+
+Jul  1, 2013: Add ability to detect encrypted entries for many formats
+     (This does not add the ability to *decrypt* those entries, however)
+
+Feb 23, 2013: "raw" write support added
+
 Feb 09, 2013: libarchive 3.1.2 released
 
 Jan 28, 2013: libarchive's new website moved to http://www.libarchive.org.
index 1c974fd..180d284 100644 (file)
@@ -5,7 +5,7 @@ Questions?  Issues?
      libarchive development, including documentation, and
      links to the libarchive mailing lists.
    * To report an issue, use the issue tracker at
-     http://code.google.com/p/libarchive/issues/list
+     https://github.com/libarchive/libarchive/issues
    * To submit an enhancement to libarchive, please submit
      a pull request via GitHub.
      https://github.com/libarchive/libarchive/pulls
@@ -13,9 +13,11 @@ Questions?  Issues?
 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
+          implementation built on libarchive
    * cpio: the 'bsdcpio' program is a different interface to
           essentially the same functionality
+   * cat: the 'bsdcat' program is a simple replacement tool for
+          zcat, bzcat, xzcat, and such
    * examples: Some small example programs that you may find useful.
    * examples/minitar: a compact sample demonstrating use of libarchive.
    * contrib:  Various items sent to me by third parties;
@@ -39,6 +41,7 @@ The following files in the top-level directory are used by the
 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
+ * bsdcat.1 explains the use of the bsdcat program
  * libarchive.3 gives an overview of the library as a whole
  * archive_read.3, archive_write.3, archive_write_disk.3, and
    archive_read_disk.3 provide detailed calling sequences for the read
@@ -84,6 +87,8 @@ The library also detects and handles any of the following before evaluating the
   * bzip2 compression
   * compress/LZW compression
   * lzma, lzip, and xz compression
+  * lz4 compression
+  * lzop compression
 
 The library can create archives in any of the following formats:
   * POSIX ustar
@@ -91,6 +96,7 @@ The library can create archives in any of the following formats:
   * "restricted" pax format, which will create ustar archives except for
     entries that require pax extensions (for long filenames, ACLs, etc).
   * Old GNU tar format
+  * Old V7 tar format
   * POSIX octet-oriented cpio
   * SVR4 "newc" cpio
   * shar archives
@@ -107,6 +113,8 @@ When creating archives, the result can be filtered with any of the following:
   * bzip2 compression
   * compress/LZW compression
   * lzma, lzip, and xz compression
+  * lz4 compression
+  * lzop compression
 
 Notes about the library architecture:
 
@@ -123,12 +131,12 @@ Notes about the library architecture:
 
  * 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.
+   particular compression or format), it won't get pulled in to
+   statically-linked programs.  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
index 6c5b48e..0996227 100644 (file)
@@ -9,6 +9,8 @@ build/bump-version.sh
 build/clean.sh
 build/cmake/
 build/pkgconfig/
+cat/CMakeLists.txt
+cat/test/
 config.h.in
 configure
 configure.ac
similarity index 65%
copy from contrib/libarchive/libarchive/archive_write_data.3
copy to contrib/libarchive/cat/bsdcat.1
index cfd5cd5..4f82b1e 100644 (file)
@@ -1,4 +1,4 @@
-.\" Copyright (c) 2003-2011 Tim Kientzle
+.\" Copyright (c) 2011-2014, Mike Kazantsev
 .\" All rights reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without
 .\"
 .\" $FreeBSD$
 .\"
-.Dd February 2, 2012
-.Dt ARCHIVE_WRITE_DATA 3
+.Dd March 1, 2014
+.Dt BSDCAT 1
 .Os
 .Sh NAME
-.Nm archive_write_data
-.Nd functions for creating archives
-.Sh LIBRARY
-Streaming Archive Library (libarchive, -larchive)
+.Nm bsdcat
+.Nd expand files to standard output
 .Sh SYNOPSIS
-.In archive.h
-.Ft ssize_t
-.Fn archive_write_data "struct archive *" "const void *" "size_t"
+.Nm
+.Op options
+.Op files
+.Pp
 .Sh DESCRIPTION
-Write data corresponding to the header just written.
-.\" .Sh EXAMPLE
-.\"
-.Sh RETURN VALUES
-This function returns the number of bytes actually written, or
-.Li -1
-on error.
-.\"
-.Sh ERRORS
-Detailed error codes and textual descriptions are available from the
-.Fn archive_errno
-and
-.Fn archive_error_string
-functions.
-.\"
+.Nm
+expands files to standard output.
+.Sh OPTIONS
+.Nm
+typically takes a filename as an argument or reads standard input when used in a
+pipe. In both cases decompressed data it written to standard output.
+.Sh EXAMPLES
+.Pp
+To decompress a file:
+.Pp
+.Dl bsdcat example.txt.gz > example.txt
+.Pp
+To decompress standard input in a pipe:
+.Pp
+.Dl cat example.txt.gz | bsdcat > example.txt
+.Pp
+Both examples achieve the same results - a decompressed file by redirecting
+output.
 .Sh SEE ALSO
-.Xr tar 1 ,
-.Xr libarchive 3 ,
-.Xr archive_write_finish_entry 3 ,
-.Xr archive_write_set_options 3 ,
-.Xr cpio 5 ,
-.Xr mtree 5 ,
-.Xr tar 5
+.Xr uncompress 1 ,
+.Xr zcat 1 ,
+.Xr bzcat 1 ,
+.Xr xzcat 1 ,
+.Xr libarchive-formats 5 ,
diff --git a/contrib/libarchive/cat/bsdcat.c b/contrib/libarchive/cat/bsdcat.c
new file mode 100644 (file)
index 0000000..af140e0
--- /dev/null
@@ -0,0 +1,146 @@
+/*-
+ * Copyright (c) 2011-2014, Mike Kazantsev
+ * 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 "bsdcat_platform.h"
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include "bsdcat.h"
+#include "err.h"
+
+#define        BYTES_PER_BLOCK (20*512)
+
+struct archive *a;
+struct archive_entry *ae;
+char *bsdcat_current_path;
+int exit_status = 0;
+
+
+void
+usage(FILE *stream, int eval)
+{
+       const char *p;
+       p = lafe_getprogname();
+       fprintf(stream,
+           "Usage: %s [-h] [--help] [--version] [--] [filenames...]\n", p);
+       exit(eval);
+}
+
+static void
+version(void)
+{
+       printf("bsdcat %s - %s\n",
+           BSDCAT_VERSION_STRING,
+           archive_version_details());
+       exit(0);
+}
+
+void
+bsdcat_next()
+{
+       a = archive_read_new();
+       archive_read_support_filter_all(a);
+       archive_read_support_format_empty(a);
+       archive_read_support_format_raw(a);
+}
+
+void
+bsdcat_print_error(void)
+{
+       lafe_warnc(0, "%s: %s",
+           bsdcat_current_path, archive_error_string(a));
+       exit_status = 1;
+}
+
+void
+bsdcat_read_to_stdout(char* filename)
+{
+       int r;
+
+       if (archive_read_open_filename(a, filename, BYTES_PER_BLOCK)
+           != ARCHIVE_OK)
+               bsdcat_print_error();
+       else if (r = archive_read_next_header(a, &ae),
+                r != ARCHIVE_OK && r != ARCHIVE_EOF)
+               bsdcat_print_error();
+       else if (r == ARCHIVE_EOF)
+               /* for empty payloads don't try and read data */
+               ;
+       else if (archive_read_data_into_fd(a, 1) != ARCHIVE_OK)
+               bsdcat_print_error();
+       if (archive_read_free(a) != ARCHIVE_OK)
+               bsdcat_print_error();
+}
+
+int
+main(int argc, char **argv)
+{
+       struct bsdcat *bsdcat, bsdcat_storage;
+       int c;
+
+       bsdcat = &bsdcat_storage;
+       memset(bsdcat, 0, sizeof(*bsdcat));
+
+       lafe_setprogname(*argv, "bsdcat");
+
+       bsdcat->argv = argv;
+       bsdcat->argc = argc;
+
+       while ((c = bsdcat_getopt(bsdcat)) != -1) {
+               switch (c) {
+               case 'h':
+                       usage(stdout, 0);
+                       break;
+               case OPTION_VERSION:
+                       version();
+                       break;
+               default:
+                       usage(stderr, 1);
+               }
+       }
+
+       bsdcat_next();
+       if (*bsdcat->argv == NULL) {
+               bsdcat_current_path = "<stdin>";
+               bsdcat_read_to_stdout(NULL);
+       } else
+               while (*bsdcat->argv) {
+                       bsdcat_current_path = *bsdcat->argv++;
+                       bsdcat_read_to_stdout(bsdcat_current_path);
+                       bsdcat_next();
+               }
+
+       exit(exit_status);
+}
similarity index 66%
copy from contrib/libarchive/libarchive_fe/err.h
copy to contrib/libarchive/cat/bsdcat.h
index ca1af35..ca603d3 100644 (file)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2009 Joerg Sonnenberger
+ * Copyright (c) 2014, Mike Kazantsev
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef LAFE_ERR_H
-#define LAFE_ERR_H
-
-#if defined(__GNUC__) && (__GNUC__ > 2 || \
-                          (__GNUC__ == 2 && __GNUC_MINOR__ >= 5))
-#define __LA_DEAD       __attribute__((__noreturn__))
+#if defined(PLATFORM_CONFIG_H)
+/* Use hand-built config.h in environments that need it. */
+#include PLATFORM_CONFIG_H
 #else
-#define __LA_DEAD
+/* Not having a config.h of some sort is a serious problem. */
+#include "config.h"
 #endif
 
-#if defined(__GNUC__) && (__GNUC__ > 2 || \
-                         (__GNUC__ == 2 && __GNUC_MINOR__ >= 7))
-#define        __LA_PRINTFLIKE(f,a)    __attribute__((__format__(__printf__, f, a)))
-#else
-#define        __LA_PRINTFLIKE(f,a)
-#endif
+#include <archive.h>
+#include <archive_entry.h>
 
-extern const char *lafe_progname;
+struct bsdcat {
+       /* Option parser state */
+       int               getopt_state;
+       char             *getopt_word;
 
-void   lafe_warnc(int code, const char *fmt, ...) __LA_PRINTFLIKE(2, 3);
-void   lafe_errc(int eval, int code, const char *fmt, ...) __LA_DEAD
-                 __LA_PRINTFLIKE(3, 4);
+       /* Miscellaneous state information */
+       int               argc;
+       char            **argv;
+       const char       *argument;
+};
 
-#endif
+enum {
+       OPTION_VERSION
+};
+
+int bsdcat_getopt(struct bsdcat *);
+void usage(FILE *stream, int eval);
+void bsdcat_next(void);
+void bsdcat_print_error(void);
+void bsdcat_read_to_stdout(char* filename);
similarity index 80%
copy from contrib/libarchive/cpio/cpio_platform.h
copy to contrib/libarchive/cat/bsdcat_platform.h
index 31d9a73..10b7113 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/usr.bin/cpio/cpio_platform.h,v 1.2 2008/12/06 07:15:42 kientzle Exp $
+ * $FreeBSD: src/usr.bin/tar/bsdtar_platform.h,v 1.26 2008/12/06 07:37:14 kientzle Exp $
  */
 
 /*
- * This header is the first thing included in any of the cpio
+ * This header is the first thing included in any of the bsdtar
  * source files.  As far as possible, platform-specific issues should
  * be dealt with here and not within individual source files.
  */
 
-#ifndef CPIO_PLATFORM_H_INCLUDED
-#define        CPIO_PLATFORM_H_INCLUDED
+#ifndef BSDCAT_PLATFORM_H_INCLUDED
+#define        BSDCAT_PLATFORM_H_INCLUDED
 
 #if defined(PLATFORM_CONFIG_H)
 /* Use hand-built config.h in environments that need it. */
 #include PLATFORM_CONFIG_H
 #else
-/* Read config.h or die trying. */
+/* Not having a config.h of some sort is a serious problem. */
 #include "config.h"
 #endif
 
 #endif
 
 /* How to mark functions that don't return. */
+/* This facilitates use of some newer static code analysis tools. */
+#undef __LA_DEAD
 #if defined(__GNUC__) && (__GNUC__ > 2 || \
-                          (__GNUC__ == 2 && __GNUC_MINOR__ >= 5))
-#define __LA_DEAD       __attribute__((__noreturn__))
+                         (__GNUC__ == 2 && __GNUC_MINOR__ >= 5))
+#define        __LA_DEAD       __attribute__((__noreturn__))
 #else
-#define __LA_DEAD
+#define        __LA_DEAD
 #endif
 
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#include "cpio_windows.h"
-#endif
-
-#endif /* !CPIO_PLATFORM_H_INCLUDED */
+#endif /* !BSDCAT_PLATFORM_H_INCLUDED */
similarity index 51%
copy from contrib/libarchive/tar/cmdline.c
copy to contrib/libarchive/cat/cmdline.c
index 4444b80..cae19be 100644 (file)
@@ -27,7 +27,7 @@
  * Command line parser for tar.
  */
 
-#include "bsdtar_platform.h"
+#include "bsdcat_platform.h"
 __FBSDID("$FreeBSD$");
 
 #ifdef HAVE_ERRNO_H
@@ -40,112 +40,30 @@ __FBSDID("$FreeBSD$");
 #include <string.h>
 #endif
 
-#include "bsdtar.h"
+#include "bsdcat.h"
 #include "err.h"
 
 /*
  * Short options for tar.  Please keep this sorted.
  */
-static const char *short_options
-       = "aBb:C:cf:HhI:JjkLlmnOoPpqrSs:T:tUuvW:wX:xyZz";
+static const char *short_options = "h";
 
 /*
  * Long options for tar.  Please keep this list sorted.
  *
  * The symbolic names for options that lack a short equivalent are
- * defined in bsdtar.h.  Also note that so far I've found no need
+ * defined in bsdcat.h.  Also note that so far I've found no need
  * to support optional arguments to long options.  That would be
  * a small change to the code below.
  */
 
-static const struct bsdtar_option {
+static const struct bsdcat_option {
        const char *name;
        int required;      /* 1 if this option requires an argument. */
        int equivalent;    /* Equivalent short option. */
 } tar_longopts[] = {
-       { "absolute-paths",       0, 'P' },
-       { "append",               0, 'r' },
-       { "auto-compress",        0, 'a' },
-       { "b64encode",            0, OPTION_B64ENCODE },
-       { "block-size",           1, 'b' },
-       { "bunzip2",              0, 'j' },
-       { "bzip",                 0, 'j' },
-       { "bzip2",                0, 'j' },
-       { "cd",                   1, 'C' },
-       { "check-links",          0, OPTION_CHECK_LINKS },
-       { "chroot",               0, OPTION_CHROOT },
-       { "compress",             0, 'Z' },
-       { "confirmation",         0, 'w' },
-       { "create",               0, 'c' },
-       { "dereference",          0, 'L' },
-       { "directory",            1, 'C' },
-       { "disable-copyfile",     0, OPTION_DISABLE_COPYFILE },
-       { "exclude",              1, OPTION_EXCLUDE },
-       { "exclude-from",         1, 'X' },
-       { "extract",              0, 'x' },
-       { "fast-read",            0, 'q' },
-       { "file",                 1, 'f' },
-       { "files-from",           1, 'T' },
-       { "format",               1, OPTION_FORMAT },
-       { "gid",                  1, OPTION_GID },
-       { "gname",                1, OPTION_GNAME },
-       { "grzip",                0, OPTION_GRZIP },
-       { "gunzip",               0, 'z' },
-       { "gzip",                 0, 'z' },
-       { "help",                 0, OPTION_HELP },
-       { "hfsCompression",       0, OPTION_HFS_COMPRESSION },
-       { "include",              1, OPTION_INCLUDE },
-       { "insecure",             0, 'P' },
-       { "interactive",          0, 'w' },
-       { "keep-newer-files",     0, OPTION_KEEP_NEWER_FILES },
-       { "keep-old-files",       0, 'k' },
-       { "list",                 0, 't' },
-       { "lrzip",                0, OPTION_LRZIP },
-       { "lzip",                 0, OPTION_LZIP },
-       { "lzma",                 0, OPTION_LZMA },
-       { "lzop",                 0, OPTION_LZOP },
-       { "modification-time",    0, 'm' },
-       { "newer",                1, OPTION_NEWER_CTIME },
-       { "newer-ctime",          1, OPTION_NEWER_CTIME },
-       { "newer-ctime-than",     1, OPTION_NEWER_CTIME_THAN },
-       { "newer-mtime",          1, OPTION_NEWER_MTIME },
-       { "newer-mtime-than",     1, OPTION_NEWER_MTIME_THAN },
-       { "newer-than",           1, OPTION_NEWER_CTIME_THAN },
-       { "no-recursion",         0, 'n' },
-       { "no-same-owner",        0, OPTION_NO_SAME_OWNER },
-       { "no-same-permissions",  0, OPTION_NO_SAME_PERMISSIONS },
-       { "nodump",               0, OPTION_NODUMP },
-       { "nopreserveHFSCompression",0, OPTION_NOPRESERVE_HFS_COMPRESSION },
-       { "norecurse",            0, 'n' },
-       { "null",                 0, OPTION_NULL },
-       { "numeric-owner",        0, OPTION_NUMERIC_OWNER },
-       { "older",                1, OPTION_OLDER_CTIME },
-       { "older-ctime",          1, OPTION_OLDER_CTIME },
-       { "older-ctime-than",     1, OPTION_OLDER_CTIME_THAN },
-       { "older-mtime",          1, OPTION_OLDER_MTIME },
-       { "older-mtime-than",     1, OPTION_OLDER_MTIME_THAN },
-       { "older-than",           1, OPTION_OLDER_CTIME_THAN },
-       { "one-file-system",      0, OPTION_ONE_FILE_SYSTEM },
-       { "options",              1, OPTION_OPTIONS },
-       { "posix",                0, OPTION_POSIX },
-       { "preserve-permissions", 0, 'p' },
-       { "read-full-blocks",     0, 'B' },
-       { "same-owner",           0, OPTION_SAME_OWNER },
-       { "same-permissions",     0, 'p' },
-       { "strip-components",     1, OPTION_STRIP_COMPONENTS },
-       { "to-stdout",            0, 'O' },
-       { "totals",               0, OPTION_TOTALS },
-       { "uid",                  1, OPTION_UID },
-       { "uname",                1, OPTION_UNAME },
-       { "uncompress",           0, 'Z' },
-       { "unlink",               0, 'U' },
-       { "unlink-first",         0, 'U' },
-       { "update",               0, 'u' },
-       { "use-compress-program", 1, OPTION_USE_COMPRESS_PROGRAM },
-       { "uuencode",             0, OPTION_UUENCODE },
-       { "verbose",              0, 'v' },
+       { "help",                 0, 'h' },
        { "version",              0, OPTION_VERSION },
-       { "xz",                   0, 'J' },
        { NULL, 0, 0 }
 };
 
@@ -154,7 +72,7 @@ static const struct bsdtar_option {
  * getopt_long() implementations lack.  Apart from those, it's a
  * straightforward option parser, considerably simplified by not
  * needing to support the wealth of exotic getopt_long() features.  It
- * has, of course, been shamelessly tailored for bsdtar.  (If you're
+ * has, of course, been shamelessly tailored for bsdcat.  (If you're
  * looking for a generic getopt_long() implementation for your
  * project, I recommend Gregory Pietsch's public domain getopt_long()
  * implementation.)  The two additional features are:
@@ -172,7 +90,7 @@ static const struct bsdtar_option {
  * -W long options: There's an obscure GNU convention (only rarely
  * supported even there) that allows "-W option=argument" as an
  * alternative way to support long options.  This was supported in
- * early bsdtar as a way to access long options on platforms that did
+ * early bsdcat as a way to access long options on platforms that did
  * not support getopt_long() and is preserved here for backwards
  * compatibility.  (Of course, if I'd started with a custom
  * command-line parser from the beginning, I would have had normal
@@ -183,7 +101,7 @@ static const struct bsdtar_option {
  * TODO: We should be able to use this to pull files and intermingled
  * options (such as -C) from the command line in write mode.  That
  * will require a little rethinking of the argument handling in
- * bsdtar.c.
+ * bsdcat.c.
  *
  * TODO: If we want to support arbitrary command-line options from -T
  * input (as GNU tar does), we may need to extend this to handle option
@@ -192,104 +110,70 @@ static const struct bsdtar_option {
  */
 
 int
-bsdtar_getopt(struct bsdtar *bsdtar)
+bsdcat_getopt(struct bsdcat *bsdcat)
 {
        enum { state_start = 0, state_old_tar, state_next_word,
               state_short, state_long };
 
-       const struct bsdtar_option *popt, *match = NULL, *match2 = NULL;
+       const struct bsdcat_option *popt, *match = NULL, *match2 = NULL;
        const char *p, *long_prefix = "--";
        size_t optlength;
        int opt = '?';
        int required = 0;
 
-       bsdtar->argument = NULL;
+       bsdcat->argument = NULL;
 
        /* First time through, initialize everything. */
-       if (bsdtar->getopt_state == state_start) {
+       if (bsdcat->getopt_state == state_start) {
                /* Skip program name. */
-               ++bsdtar->argv;
-               --bsdtar->argc;
-               if (*bsdtar->argv == NULL)
+               ++bsdcat->argv;
+               --bsdcat->argc;
+               if (*bsdcat->argv == NULL)
                        return (-1);
                /* Decide between "new style" and "old style" arguments. */
-               if (bsdtar->argv[0][0] == '-') {
-                       bsdtar->getopt_state = state_next_word;
-               } else {
-                       bsdtar->getopt_state = state_old_tar;
-                       bsdtar->getopt_word = *bsdtar->argv++;
-                       --bsdtar->argc;
-               }
-       }
-
-       /*
-        * We're parsing old-style tar arguments
-        */
-       if (bsdtar->getopt_state == state_old_tar) {
-               /* Get the next option character. */
-               opt = *bsdtar->getopt_word++;
-               if (opt == '\0') {
-                       /* New-style args can follow old-style. */
-                       bsdtar->getopt_state = state_next_word;
-               } else {
-                       /* See if it takes an argument. */
-                       p = strchr(short_options, opt);
-                       if (p == NULL)
-                               return ('?');
-                       if (p[1] == ':') {
-                               bsdtar->argument = *bsdtar->argv;
-                               if (bsdtar->argument == NULL) {
-                                       lafe_warnc(0,
-                                           "Option %c requires an argument",
-                                           opt);
-                                       return ('?');
-                               }
-                               ++bsdtar->argv;
-                               --bsdtar->argc;
-                       }
-               }
+               bsdcat->getopt_state = state_next_word;
        }
 
        /*
         * We're ready to look at the next word in argv.
         */
-       if (bsdtar->getopt_state == state_next_word) {
+       if (bsdcat->getopt_state == state_next_word) {
                /* No more arguments, so no more options. */
-               if (bsdtar->argv[0] == NULL)
+               if (bsdcat->argv[0] == NULL)
                        return (-1);
                /* Doesn't start with '-', so no more options. */
-               if (bsdtar->argv[0][0] != '-')
+               if (bsdcat->argv[0][0] != '-')
                        return (-1);
                /* "--" marks end of options; consume it and return. */
-               if (strcmp(bsdtar->argv[0], "--") == 0) {
-                       ++bsdtar->argv;
-                       --bsdtar->argc;
+               if (strcmp(bsdcat->argv[0], "--") == 0) {
+                       ++bsdcat->argv;
+                       --bsdcat->argc;
                        return (-1);
                }
                /* Get next word for parsing. */
-               bsdtar->getopt_word = *bsdtar->argv++;
-               --bsdtar->argc;
-               if (bsdtar->getopt_word[1] == '-') {
+               bsdcat->getopt_word = *bsdcat->argv++;
+               --bsdcat->argc;
+               if (bsdcat->getopt_word[1] == '-') {
                        /* Set up long option parser. */
-                       bsdtar->getopt_state = state_long;
-                       bsdtar->getopt_word += 2; /* Skip leading '--' */
+                       bsdcat->getopt_state = state_long;
+                       bsdcat->getopt_word += 2; /* Skip leading '--' */
                } else {
                        /* Set up short option parser. */
-                       bsdtar->getopt_state = state_short;
-                       ++bsdtar->getopt_word;  /* Skip leading '-' */
+                       bsdcat->getopt_state = state_short;
+                       ++bsdcat->getopt_word;  /* Skip leading '-' */
                }
        }
 
        /*
         * We're parsing a group of POSIX-style single-character options.
         */
-       if (bsdtar->getopt_state == state_short) {
+       if (bsdcat->getopt_state == state_short) {
                /* Peel next option off of a group of short options. */
-               opt = *bsdtar->getopt_word++;
+               opt = *bsdcat->getopt_word++;
                if (opt == '\0') {
                        /* End of this group; recurse to get next option. */
-                       bsdtar->getopt_state = state_next_word;
-                       return bsdtar_getopt(bsdtar);
+                       bsdcat->getopt_state = state_next_word;
+                       return bsdcat_getopt(bsdcat);
                }
 
                /* Does this option take an argument? */
@@ -301,50 +185,50 @@ bsdtar_getopt(struct bsdtar *bsdtar)
 
                /* If it takes an argument, parse that. */
                if (required) {
-                       /* If arg is run-in, bsdtar->getopt_word already points to it. */
-                       if (bsdtar->getopt_word[0] == '\0') {
+                       /* If arg is run-in, bsdcat->getopt_word already points to it. */
+                       if (bsdcat->getopt_word[0] == '\0') {
                                /* Otherwise, pick up the next word. */
-                               bsdtar->getopt_word = *bsdtar->argv;
-                               if (bsdtar->getopt_word == NULL) {
+                               bsdcat->getopt_word = *bsdcat->argv;
+                               if (bsdcat->getopt_word == NULL) {
                                        lafe_warnc(0,
                                            "Option -%c requires an argument",
                                            opt);
                                        return ('?');
                                }
-                               ++bsdtar->argv;
-                               --bsdtar->argc;
+                               ++bsdcat->argv;
+                               --bsdcat->argc;
                        }
                        if (opt == 'W') {
-                               bsdtar->getopt_state = state_long;
+                               bsdcat->getopt_state = state_long;
                                long_prefix = "-W "; /* For clearer errors. */
                        } else {
-                               bsdtar->getopt_state = state_next_word;
-                               bsdtar->argument = bsdtar->getopt_word;
+                               bsdcat->getopt_state = state_next_word;
+                               bsdcat->argument = bsdcat->getopt_word;
                        }
                }
        }
 
        /* We're reading a long option, including -W long=arg convention. */
-       if (bsdtar->getopt_state == state_long) {
+       if (bsdcat->getopt_state == state_long) {
                /* After this long option, we'll be starting a new word. */
-               bsdtar->getopt_state = state_next_word;
+               bsdcat->getopt_state = state_next_word;
 
                /* Option name ends at '=' if there is one. */
-               p = strchr(bsdtar->getopt_word, '=');
+               p = strchr(bsdcat->getopt_word, '=');
                if (p != NULL) {
-                       optlength = (size_t)(p - bsdtar->getopt_word);
-                       bsdtar->argument = (char *)(uintptr_t)(p + 1);
+                       optlength = (size_t)(p - bsdcat->getopt_word);
+                       bsdcat->argument = (char *)(uintptr_t)(p + 1);
                } else {
-                       optlength = strlen(bsdtar->getopt_word);
+                       optlength = strlen(bsdcat->getopt_word);
                }
 
                /* Search the table for an unambiguous match. */
                for (popt = tar_longopts; popt->name != NULL; popt++) {
                        /* Short-circuit if first chars don't match. */
-                       if (popt->name[0] != bsdtar->getopt_word[0])
+                       if (popt->name[0] != bsdcat->getopt_word[0])
                                continue;
                        /* If option is a prefix of name in table, record it.*/
-                       if (strncmp(bsdtar->getopt_word, popt->name, optlength) == 0) {
+                       if (strncmp(bsdcat->getopt_word, popt->name, optlength) == 0) {
                                match2 = match; /* Record up to two matches. */
                                match = popt;
                                /* If it's an exact match, we're done. */
@@ -359,33 +243,33 @@ bsdtar_getopt(struct bsdtar *bsdtar)
                if (match == NULL) {
                        lafe_warnc(0,
                            "Option %s%s is not supported",
-                           long_prefix, bsdtar->getopt_word);
+                           long_prefix, bsdcat->getopt_word);
                        return ('?');
                }
                if (match2 != NULL) {
                        lafe_warnc(0,
                            "Ambiguous option %s%s (matches --%s and --%s)",
-                           long_prefix, bsdtar->getopt_word, match->name, match2->name);
+                           long_prefix, bsdcat->getopt_word, match->name, match2->name);
                        return ('?');
                }
 
                /* We've found a unique match; does it need an argument? */
                if (match->required) {
                        /* Argument required: get next word if necessary. */
-                       if (bsdtar->argument == NULL) {
-                               bsdtar->argument = *bsdtar->argv;
-                               if (bsdtar->argument == NULL) {
+                       if (bsdcat->argument == NULL) {
+                               bsdcat->argument = *bsdcat->argv;
+                               if (bsdcat->argument == NULL) {
                                        lafe_warnc(0,
                                            "Option %s%s requires an argument",
                                            long_prefix, match->name);
                                        return ('?');
                                }
-                               ++bsdtar->argv;
-                               --bsdtar->argc;
+                               ++bsdcat->argv;
+                               --bsdcat->argc;
                        }
                } else {
                        /* Argument forbidden: fail if there is one. */
-                       if (bsdtar->argument != NULL) {
+                       if (bsdcat->argument != NULL) {
                                lafe_warnc(0,
                                    "Option %s%s does not allow an argument",
                                    long_prefix, match->name);
index b3d0d40..e52546e 100644 (file)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd October 7, 2012
+.Dd September 16, 2014
 .Dt CPIO 1
 .Os
 .Sh NAME
 .Nd copy files to and from archives
 .Sh SYNOPSIS
 .Nm
-.Brq Fl i
+.Fl i
 .Op Ar options
 .Op Ar pattern ...
 .Op Ar < archive
 .Nm
-.Brq Fl o
+.Fl o
 .Op Ar options
 .Ar < name-list
 .Op Ar > archive
 .Nm
-.Brq Fl p
+.Fl p
 .Op Ar options
 .Ar dest-dir
 .Ar < name-list
@@ -156,7 +156,8 @@ See above for description.
 .It Fl Fl insecure
 (i and p mode only)
 Disable security checks during extraction or copying.
-This allows extraction via symbolic links and path names containing
+This allows extraction via symbolic links, absolute paths,
+and path names containing
 .Sq ..
 in the name.
 .It Fl J , Fl Fl xz
@@ -181,6 +182,11 @@ instead of copying.
 Compress the resulting archive with
 .Xr lrzip 1 .
 In input mode, this option is ignored.
+.It Fl Fl lz4
+(o mode only)
+Compress the archive with lz4-compatible compression before writing it.
+In input mode, this option is ignored; lz4 compression is recognized
+automatically on input.
 .It Fl Fl lzma
 (o mode only)
 Compress the file with lzma-compatible compression before writing it.
@@ -191,6 +197,15 @@ automatically on input.
 Compress the resulting archive with
 .Xr lzop 1 .
 In input mode, this option is ignored.
+.It Fl Fl passphrase Ar passphrase
+The
+.Pa passphrase
+is used to extract or create an encrypted archive.
+Currently, zip is only a format that
+.Nm
+can handle encrypted archives.
+You shouldn't use this option unless you realize how insecure
+use of this option is.
 .It Fl m , Fl Fl preserve-modification-time
 (i and p modes)
 Set file modification time on created files to match
index 0121fd1..7e59536 100644 (file)
@@ -73,6 +73,7 @@ static const struct option {
        { "link",                       0, 'l' },
        { "list",                       0, 't' },
        { "lrzip",                      0, OPTION_LRZIP },
+       { "lz4",                        0, OPTION_LZ4 },
        { "lzma",                       0, OPTION_LZMA },
        { "lzop",                       0, OPTION_LZOP },
        { "make-directories",           0, 'd' },
@@ -80,6 +81,7 @@ static const struct option {
        { "null",                       0, '0' },
        { "numeric-uid-gid",            0, 'n' },
        { "owner",                      1, 'R' },
+       { "passphrase",                 1, OPTION_PASSPHRASE },
        { "pass-through",               0, 'p' },
        { "preserve-modification-time", 0, 'm' },
        { "preserve-owner",             0, OPTION_PRESERVE_OWNER },
index 6f57d95..b267e9b 100644 (file)
@@ -82,6 +82,7 @@ __FBSDID("$FreeBSD: src/usr.bin/cpio/cpio.c,v 1.15 2008/12/06 07:30:40 kientzle
 #include "cpio.h"
 #include "err.h"
 #include "line_reader.h"
+#include "passphrase.h"
 
 /* Fixed size of uname/gname caches. */
 #define        name_cache_size 101
@@ -123,6 +124,8 @@ static int  restore_time(struct cpio *, struct archive_entry *,
                    const char *, int fd);
 static void    usage(void);
 static void    version(void);
+static const char * passphrase_callback(struct archive *, void *);
+static void    passphrase_free(char *);
 
 int
 main(int argc, char *argv[])
@@ -149,20 +152,9 @@ main(int argc, char *argv[])
        }
 #endif
 
-       /* Need lafe_progname before calling lafe_warnc. */
-       if (*argv == NULL)
-               lafe_progname = "bsdcpio";
-       else {
-#if defined(_WIN32) && !defined(__CYGWIN__)
-               lafe_progname = strrchr(*argv, '\\');
-               if (strrchr(*argv, '/') > lafe_progname)
-#endif
-               lafe_progname = strrchr(*argv, '/');
-               if (lafe_progname != NULL)
-                       lafe_progname++;
-               else
-                       lafe_progname = *argv;
-       }
+       /* Set lafe_progname before calling lafe_warnc. */
+       lafe_setprogname(*argv, "bsdcpio");
+
 #if HAVE_SETLOCALE
        if (setlocale(LC_ALL, "") == NULL)
                lafe_warnc(0, "Failed to set default locale");
@@ -179,6 +171,7 @@ main(int argc, char *argv[])
        cpio->extract_flags |= ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER;
        cpio->extract_flags |= ARCHIVE_EXTRACT_SECURE_SYMLINKS;
        cpio->extract_flags |= ARCHIVE_EXTRACT_SECURE_NODOTDOT;
+       cpio->extract_flags |= ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS;
        cpio->extract_flags |= ARCHIVE_EXTRACT_PERM;
        cpio->extract_flags |= ARCHIVE_EXTRACT_FFLAGS;
        cpio->extract_flags |= ARCHIVE_EXTRACT_ACL;
@@ -264,6 +257,7 @@ main(int argc, char *argv[])
                case OPTION_INSECURE:
                        cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_SYMLINKS;
                        cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_NODOTDOT;
+                       cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS;
                        break;
                case 'L': /* GNU cpio */
                        cpio->option_follow_links = 1;
@@ -272,6 +266,7 @@ main(int argc, char *argv[])
                        cpio->option_link = 1;
                        break;
                case OPTION_LRZIP:
+               case OPTION_LZ4:
                case OPTION_LZMA: /* GNU tar, others */
                case OPTION_LZOP: /* GNU tar, others */
                        cpio->compress = opt;
@@ -301,6 +296,9 @@ main(int argc, char *argv[])
                        cpio->mode = opt;
                        cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_NODOTDOT;
                        break;
+               case OPTION_PASSPHRASE:
+                       cpio->passphrase = cpio->argument;
+                       break;
                case OPTION_PRESERVE_OWNER:
                        cpio->extract_flags |= ARCHIVE_EXTRACT_OWNER;
                        break;
@@ -429,6 +427,7 @@ main(int argc, char *argv[])
        free_cache(cpio->gname_cache);
        free_cache(cpio->uname_cache);
        free(cpio->destdir);
+       passphrase_free(cpio->ppbuff);
        return (cpio->return_value);
 }
 
@@ -437,7 +436,7 @@ usage(void)
 {
        const char      *p;
 
-       p = lafe_progname;
+       p = lafe_getprogname();
 
        fprintf(stderr, "Brief Usage:\n");
        fprintf(stderr, "  List:    %s -it < archive\n", p);
@@ -475,7 +474,7 @@ long_help(void)
        const char      *prog;
        const char      *p;
 
-       prog = lafe_progname;
+       prog = lafe_getprogname();
 
        fflush(stderr);
 
@@ -500,7 +499,7 @@ version(void)
 {
        fprintf(stdout,"bsdcpio %s -- %s\n",
            BSDCPIO_VERSION_STRING,
-           archive_version_string());
+           archive_version_details());
        exit(0);
 }
 
@@ -537,6 +536,9 @@ mode_out(struct cpio *cpio)
        case OPTION_LRZIP:
                r = archive_write_add_filter_lrzip(cpio->archive);
                break;
+       case OPTION_LZ4:
+               r = archive_write_add_filter_lz4(cpio->archive);
+               break;
        case OPTION_LZMA:
                r = archive_write_add_filter_lzma(cpio->archive);
                break;
@@ -578,6 +580,14 @@ mode_out(struct cpio *cpio)
        cpio->linkresolver = archive_entry_linkresolver_new();
        archive_entry_linkresolver_set_strategy(cpio->linkresolver,
            archive_format(cpio->archive));
+       if (cpio->passphrase != NULL)
+               r = archive_write_set_passphrase(cpio->archive,
+                       cpio->passphrase);
+       else
+               r = archive_write_set_passphrase_callback(cpio->archive, cpio,
+                       &passphrase_callback);
+       if (r != ARCHIVE_OK)
+               lafe_errc(1, 0, "%s", archive_error_string(cpio->archive));
 
        /*
         * The main loop:  Copy each file into the output archive.
@@ -944,6 +954,13 @@ mode_in(struct cpio *cpio)
                lafe_errc(1, 0, "Couldn't allocate archive object");
        archive_read_support_filter_all(a);
        archive_read_support_format_all(a);
+       if (cpio->passphrase != NULL)
+               r = archive_read_add_passphrase(a, cpio->passphrase);
+       else
+               r = archive_read_set_passphrase_callback(a, cpio,
+                       &passphrase_callback);
+       if (r != ARCHIVE_OK)
+               lafe_errc(1, 0, "%s", archive_error_string(a));
 
        if (archive_read_open_filename(a, cpio->filename,
                                        cpio->bytes_per_block))
@@ -1047,6 +1064,13 @@ mode_list(struct cpio *cpio)
                lafe_errc(1, 0, "Couldn't allocate archive object");
        archive_read_support_filter_all(a);
        archive_read_support_format_all(a);
+       if (cpio->passphrase != NULL)
+               r = archive_read_add_passphrase(a, cpio->passphrase);
+       else
+               r = archive_read_set_passphrase_callback(a, cpio,
+                       &passphrase_callback);
+       if (r != ARCHIVE_OK)
+               lafe_errc(1, 0, "%s", archive_error_string(a));
 
        if (archive_read_open_filename(a, cpio->filename,
                                        cpio->bytes_per_block))
@@ -1140,7 +1164,8 @@ list_item_verbose(struct cpio *cpio, struct archive_entry *entry)
        else
                fmt = cpio->day_first ? "%d %b %H:%M" : "%b %d %H:%M";
 #else
-       if (abs(mtime - now) > (365/2)*86400)
+       if (mtime - now > 365*86400/2
+               || mtime - now < -365*86400/2)
                fmt = cpio->day_first ? "%e %b  %Y" : "%b %e  %Y";
        else
                fmt = cpio->day_first ? "%e %b %H:%M" : "%b %e %H:%M";
@@ -1235,8 +1260,10 @@ cpio_rename(const char *name)
        if (t == NULL)
                return (name);
        to = fopen("CONOUT$", "w");
-       if (to == NULL)
+       if (to == NULL) {
+               fclose(t);
                return (name);
+       }
        fprintf(to, "%s (Enter/./(new name))? ", name);
        fclose(to);
 #else
@@ -1416,3 +1443,28 @@ cpio_i64toa(int64_t n0)
                *--p = '-';
        return p;
 }
+
+#define PPBUFF_SIZE 1024
+static const char *
+passphrase_callback(struct archive *a, void *_client_data)
+{
+       struct cpio *cpio = (struct cpio *)_client_data;
+       (void)a; /* UNUSED */
+
+       if (cpio->ppbuff == NULL) {
+               cpio->ppbuff = malloc(PPBUFF_SIZE);
+               if (cpio->ppbuff == NULL)
+                       lafe_errc(1, errno, "Out of memory");
+       }
+       return lafe_readpassphrase("Enter passphrase:",
+               cpio->ppbuff, PPBUFF_SIZE);
+}
+
+static void
+passphrase_free(char *ppbuff)
+{
+       if (ppbuff != NULL) {
+               memset(ppbuff, 0, PPBUFF_SIZE);
+               free(ppbuff);
+       }
+}
index 3e951ce..1036dec 100644 (file)
@@ -71,6 +71,7 @@ struct cpio {
        int               gid_override;
        char             *gname_override;
        int               day_first; /* true if locale prefers day/mon */
+       const char       *passphrase;
 
        /* If >= 0, then close this when done. */
        int               fd;
@@ -90,6 +91,7 @@ struct cpio {
        struct archive   *matching;
        char             *buff;
        size_t            buff_size;
+       char             *ppbuff;
 };
 
 const char *owner_parse(const char *, int *, int *);
@@ -101,8 +103,10 @@ enum {
        OPTION_GRZIP,
        OPTION_INSECURE,
        OPTION_LRZIP,
+       OPTION_LZ4,
        OPTION_LZMA,
        OPTION_LZOP,
+       OPTION_PASSPHRASE,
        OPTION_NO_PRESERVE_OWNER,
        OPTION_PRESERVE_OWNER,
        OPTION_QUIET,
index 31d9a73..58d2edb 100644 (file)
 #include "config.h"
 #endif
 
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#include "cpio_windows.h"
+#endif
+
 /* Get a real definition for __FBSDID if we can */
 #if HAVE_SYS_CDEFS_H
 #include <sys/cdefs.h>
@@ -70,8 +74,4 @@
 #define __LA_DEAD
 #endif
 
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#include "cpio_windows.h"
-#endif
-
 #endif /* !CPIO_PLATFORM_H_INCLUDED */
index f56bc38..59e9ef1 100644 (file)
 #ifndef ARCHIVE_H_INCLUDED
 #define        ARCHIVE_H_INCLUDED
 
+/*
+ * The version number is expressed as a single integer that makes it
+ * easy to compare versions at build time: for version a.b.c, the
+ * version number is printf("%d%03d%03d",a,b,c).  For example, if you
+ * know your application requires version 2.12.108 or later, you can
+ * assert that ARCHIVE_VERSION_NUMBER >= 2012108.
+ */
+/* Note: Compiler will complain if this does not match archive_entry.h! */
+#define        ARCHIVE_VERSION_NUMBER 3002000
+
 #include <sys/stat.h>
 #include <stddef.h>  /* for wchar_t */
 #include <stdio.h> /* For FILE * */
+#include <time.h> /* For time_t */
 
 /*
  * Note: archive.h is for use outside of libarchive; the configuration
  */
 #if defined(__BORLANDC__) && __BORLANDC__ >= 0x560
 # include <stdint.h>
-#elif !defined(__WATCOMC__) && !defined(_MSC_VER) && !defined(__INTERIX) && !defined(__BORLANDC__) && !defined(_SCO_DS)
+#elif !defined(__WATCOMC__) && !defined(_MSC_VER) && !defined(__INTERIX) && !defined(__BORLANDC__) && !defined(_SCO_DS) && !defined(__osf__)
 # include <inttypes.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
-# if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_)
-#  define      __LA_SSIZE_T    ssize_t
-# elif defined(_WIN64)
-#  define      __LA_SSIZE_T    __int64
-# else
-#  define      __LA_SSIZE_T    long
+/* Get appropriate definitions of 64-bit integer */
+#if !defined(__LA_INT64_T_DEFINED)
+/* Older code relied on the __LA_INT64_T macro; after 4.0 we'll switch to the typedef exclusively. */
+# if ARCHIVE_VERSION_NUMBER < 4000000
+#define __LA_INT64_T la_int64_t
 # endif
-#else
+#define __LA_INT64_T_DEFINED
+# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
+typedef __int64 la_int64_t;
+# else
 # include <unistd.h>  /* ssize_t */
-# if defined(_SCO_DS)
-#  define      __LA_INT64_T    long long
+#  if defined(_SCO_DS) || defined(__osf__)
+typedef long long la_int64_t;
+#  else
+typedef int64_t la_int64_t;
+#  endif
+# endif
+#endif
+
+/* The la_ssize_t should match the type used in 'struct stat' */
+#if !defined(__LA_SSIZE_T_DEFINED)
+/* Older code relied on the __LA_SSIZE_T macro; after 4.0 we'll switch to the typedef exclusively. */
+# if ARCHIVE_VERSION_NUMBER < 4000000
+#define __LA_SSIZE_T la_ssize_t
+# endif
+#define __LA_SSIZE_T_DEFINED
+# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
+#  if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_)
+typedef ssize_t la_ssize_t;
+#  elif defined(_WIN64)
+typedef __int64 la_ssize_t;
+#  else
+typedef long la_ssize_t;
+#  endif
 # else
-#  define      __LA_INT64_T    int64_t
+# include <unistd.h>  /* ssize_t */
+typedef ssize_t la_ssize_t;
 # endif
-# define       __LA_SSIZE_T    ssize_t
+#endif
+
+/* Large file support for Android */
+#ifdef __ANDROID__
+#include "android_lf.h"
 #endif
 
 /*
@@ -115,24 +150,34 @@ extern "C" {
  * header and library are very different, you should expect some
  * strangeness.  Don't do that.
  */
-
-/*
- * The version number is expressed as a single integer that makes it
- * easy to compare versions at build time: for version a.b.c, the
- * version number is printf("%d%03d%03d",a,b,c).  For example, if you
- * know your application requires version 2.12.108 or later, you can
- * assert that ARCHIVE_VERSION_NUMBER >= 2012108.
- */
-/* Note: Compiler will complain if this does not match archive_entry.h! */
-#define        ARCHIVE_VERSION_NUMBER 3001002
 __LA_DECL int          archive_version_number(void);
 
 /*
  * Textual name/version of the library, useful for version displays.
  */
-#define        ARCHIVE_VERSION_STRING "libarchive 3.1.2"
+#define        ARCHIVE_VERSION_ONLY_STRING "3.2.0"
+#define        ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
 __LA_DECL const char * archive_version_string(void);
 
+/*
+ * Detailed textual name/version of the library and its dependencies.
+ * This has the form:
+ *    "libarchive x.y.z zlib/a.b.c liblzma/d.e.f ... etc ..."
+ * the list of libraries described here will vary depending on how
+ * libarchive was compiled.
+ */
+__LA_DECL const char * archive_version_details(void);
+
+/*
+ * Returns NULL if libarchive was compiled without the associated library.
+ * Otherwise, returns the version number that libarchive was compiled
+ * against.
+ */
+__LA_DECL const char *  archive_zlib_version(void);
+__LA_DECL const char *  archive_liblzma_version(void);
+__LA_DECL const char *  archive_bzlib_version(void);
+__LA_DECL const char *  archive_liblz4_version(void);
+
 /* Declare our basic types. */
 struct archive;
 struct archive_entry;
@@ -173,7 +218,7 @@ struct archive_entry;
  */
 
 /* Returns pointer and size of next block of data from archive. */
-typedef __LA_SSIZE_T   archive_read_callback(struct archive *,
+typedef la_ssize_t     archive_read_callback(struct archive *,
                            void *_client_data, const void **_buffer);
 
 /* Skips at most request bytes from archive and returns the skipped amount.
@@ -181,18 +226,18 @@ typedef __LA_SSIZE_T      archive_read_callback(struct archive *,
  * If you do skip fewer bytes than requested, libarchive will invoke your
  * read callback and discard data as necessary to make up the full skip.
  */
-typedef __LA_INT64_T   archive_skip_callback(struct archive *,
-                           void *_client_data, __LA_INT64_T request);
+typedef la_int64_t     archive_skip_callback(struct archive *,
+                           void *_client_data, la_int64_t request);
 
 /* Seeks to specified location in the file and returns the position.
  * Whence values are SEEK_SET, SEEK_CUR, SEEK_END from stdio.h.
  * Return ARCHIVE_FATAL if the seek fails for any reason.
  */
-typedef __LA_INT64_T   archive_seek_callback(struct archive *,
-    void *_client_data, __LA_INT64_T offset, int whence);
+typedef la_int64_t     archive_seek_callback(struct archive *,
+    void *_client_data, la_int64_t offset, int whence);
 
 /* Returns size actually written, zero on EOF, -1 on error. */
-typedef __LA_SSIZE_T   archive_write_callback(struct archive *,
+typedef la_ssize_t     archive_write_callback(struct archive *,
                            void *_client_data,
                            const void *_buffer, size_t _length);
 
@@ -207,6 +252,13 @@ typedef int        archive_close_callback(struct archive *, void *_client_data);
 typedef int archive_switch_callback(struct archive *, void *_client_data1,
                            void *_client_data2);
 
+/*
+ * Returns a passphrase used for encryption or decryption, NULL on nothing
+ * to do and give it up.
+ */
+typedef const char *archive_passphrase_callback(struct archive *,
+                           void *_client_data);
+
 /*
  * Codes to identify various stream filters.
  */
@@ -223,6 +275,7 @@ typedef int archive_switch_callback(struct archive *, void *_client_data1,
 #define        ARCHIVE_FILTER_LRZIP    10
 #define        ARCHIVE_FILTER_LZOP     11
 #define        ARCHIVE_FILTER_GRZIP    12
+#define        ARCHIVE_FILTER_LZ4      13
 
 #if ARCHIVE_VERSION_NUMBER < 4000000
 #define        ARCHIVE_COMPRESSION_NONE        ARCHIVE_FILTER_NONE
@@ -284,6 +337,31 @@ typedef int archive_switch_callback(struct archive *, void *_client_data1,
 #define        ARCHIVE_FORMAT_CAB                      0xC0000
 #define        ARCHIVE_FORMAT_RAR                      0xD0000
 #define        ARCHIVE_FORMAT_7ZIP                     0xE0000
+#define        ARCHIVE_FORMAT_WARC                     0xF0000
+
+/*
+ * Codes returned by archive_read_format_capabilities().
+ *
+ * This list can be extended with values between 0 and 0xffff.
+ * The original purpose of this list was to let different archive
+ * format readers expose their general capabilities in terms of
+ * encryption.
+ */
+#define ARCHIVE_READ_FORMAT_CAPS_NONE (0) /* no special capabilities */
+#define ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA (1<<0)  /* reader can detect encrypted data */
+#define ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA (1<<1)  /* reader can detect encryptable metadata (pathname, mtime, etc.) */
+
+/*
+ * Codes returned by archive_read_has_encrypted_entries().
+ *
+ * In case the archive does not support encryption detection at all
+ * ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned. If the reader
+ * for some other reason (e.g. not enough bytes read) cannot say if
+ * there are encrypted entries, ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW
+ * is returned.
+ */
+#define ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED -2
+#define ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW -1
 
 /*-
  * Basic outline for reading an archive:
@@ -342,6 +420,7 @@ __LA_DECL int archive_read_support_filter_compress(struct archive *);
 __LA_DECL int archive_read_support_filter_gzip(struct archive *);
 __LA_DECL int archive_read_support_filter_grzip(struct archive *);
 __LA_DECL int archive_read_support_filter_lrzip(struct archive *);
+__LA_DECL int archive_read_support_filter_lz4(struct archive *);
 __LA_DECL int archive_read_support_filter_lzip(struct archive *);
 __LA_DECL int archive_read_support_filter_lzma(struct archive *);
 __LA_DECL int archive_read_support_filter_lzop(struct archive *);
@@ -369,8 +448,17 @@ __LA_DECL int archive_read_support_format_mtree(struct archive *);
 __LA_DECL int archive_read_support_format_rar(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_warc(struct archive *);
 __LA_DECL int archive_read_support_format_xar(struct archive *);
+/* archive_read_support_format_zip() enables both streamable and seekable
+ * zip readers. */
 __LA_DECL int archive_read_support_format_zip(struct archive *);
+/* Reads Zip archives as stream from beginning to end.  Doesn't
+ * correctly handle SFX ZIP files or ZIP archives that have been modified
+ * in-place. */
+__LA_DECL int archive_read_support_format_zip_streamable(struct archive *);
+/* Reads starting from central directory; requires seekable input. */
+__LA_DECL int archive_read_support_format_zip_seekable(struct archive *);
 
 /* Functions to manually set the format and filters to be used. This is
  * useful to bypass the bidding process when the format and filters to use
@@ -441,9 +529,9 @@ __LA_DECL int archive_read_open_file(struct archive *,
                     const char *_filename, size_t _block_size) __LA_DEPRECATED;
 /* Read an archive that's stored in memory. */
 __LA_DECL int archive_read_open_memory(struct archive *,
-                    void * buff, size_t size);
+                    const void * buff, size_t size);
 /* A more involved version that is only used for internal testing. */
-__LA_DECL int archive_read_open_memory2(struct archive *a, void *buff,
+__LA_DECL int archive_read_open_memory2(struct archive *a, const void *buff,
                     size_t size, size_t read_size);
 /* Read an archive that's already open, using the file descriptor. */
 __LA_DECL int archive_read_open_fd(struct archive *, int _fd,
@@ -464,14 +552,40 @@ __LA_DECL int archive_read_next_header2(struct archive *,
  * Retrieve the byte offset in UNCOMPRESSED data where last-read
  * header started.
  */
-__LA_DECL __LA_INT64_T          archive_read_header_position(struct archive *);
+__LA_DECL la_int64_t            archive_read_header_position(struct archive *);
+
+/*
+ * Returns 1 if the archive contains at least one encrypted entry.
+ * If the archive format not support encryption at all
+ * ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned.
+ * If for any other reason (e.g. not enough data read so far)
+ * we cannot say whether there are encrypted entries, then
+ * ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned.
+ * In general, this function will return values below zero when the
+ * reader is uncertain or totally uncapable of encryption support.
+ * When this function returns 0 you can be sure that the reader
+ * supports encryption detection but no encrypted entries have
+ * been found yet.
+ *
+ * NOTE: If the metadata/header of an archive is also encrypted, you
+ * cannot rely on the number of encrypted entries. That is why this
+ * function does not return the number of encrypted entries but#
+ * just shows that there are some.
+ */
+__LA_DECL int  archive_read_has_encrypted_entries(struct archive *);
+
+/*
+ * Returns a bitmask of capabilities that are supported by the archive format reader.
+ * If the reader has no special capabilities, ARCHIVE_READ_FORMAT_CAPS_NONE is returned.
+ */
+__LA_DECL int           archive_read_format_capabilities(struct archive *);
 
 /* Read data from the body of an entry.  Similar to read(2). */
-__LA_DECL __LA_SSIZE_T          archive_read_data(struct archive *,
+__LA_DECL la_ssize_t            archive_read_data(struct archive *,
                                    void *, size_t);
 
 /* Seek within the body of an entry.  Similar to lseek(2). */
-__LA_DECL __LA_INT64_T archive_seek_data(struct archive *, __LA_INT64_T, int);
+__LA_DECL la_int64_t archive_seek_data(struct archive *, la_int64_t, int);
 
 /*
  * A zero-copy version of archive_read_data that also exposes the file offset
@@ -480,7 +594,7 @@ __LA_DECL __LA_INT64_T archive_seek_data(struct archive *, __LA_INT64_T, int);
  * be strictly increasing and that returned blocks will not overlap.
  */
 __LA_DECL int archive_read_data_block(struct archive *a,
-                   const void **buff, size_t *size, __LA_INT64_T *offset);
+                   const void **buff, size_t *size, la_int64_t *offset);
 
 /*-
  * Some convenience functions that are built on archive_read_data:
@@ -510,6 +624,14 @@ __LA_DECL int archive_read_set_option(struct archive *_a,
 __LA_DECL int archive_read_set_options(struct archive *_a,
                            const char *opts);
 
+/*
+ * Add a decryption passphrase.
+ */
+__LA_DECL int archive_read_add_passphrase(struct archive *, const char *);
+__LA_DECL int archive_read_set_passphrase_callback(struct archive *,
+                           void *client_data, archive_passphrase_callback *);
+
+
 /*-
  * Convenience function to recreate the current entry (whose header
  * has just been read) on disk.
@@ -562,6 +684,10 @@ __LA_DECL int archive_read_set_options(struct archive *_a,
 /* Default: Do not use HFS+ compression if it was not compressed. */
 /* This has no effect except on Mac OS v10.6 or later. */
 #define        ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED  (0x8000)
+/* Default: Do not reject entries with absolute paths */
+#define ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS (0x10000)
+/* Default: Do not clear no-change flags when unlinking object */
+#define        ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS   (0x20000)
 
 __LA_DECL int archive_read_extract(struct archive *, struct archive_entry *,
                     int flags);
@@ -573,7 +699,7 @@ __LA_DECL void       archive_read_extract_set_progress_callback(struct archive *,
 /* Record the dev/ino of a file that will not be written.  This is
  * generally set to the dev/ino of the archive being read. */
 __LA_DECL void         archive_read_extract_set_skip_file(struct archive *,
-                    __LA_INT64_T, __LA_INT64_T);
+                    la_int64_t, la_int64_t);
 
 /* Close the file and release most resources. */
 __LA_DECL int           archive_read_close(struct archive *);
@@ -612,7 +738,7 @@ __LA_DECL int archive_write_get_bytes_in_last_block(struct archive *);
 /* The dev/ino of a file that won't be archived.  This is used
  * to avoid recursively adding an archive to itself. */
 __LA_DECL int archive_write_set_skip_file(struct archive *,
-    __LA_INT64_T, __LA_INT64_T);
+    la_int64_t, la_int64_t);
 
 #if ARCHIVE_VERSION_NUMBER < 4000000
 __LA_DECL int archive_write_set_compression_bzip2(struct archive *)
@@ -643,6 +769,7 @@ __LA_DECL int archive_write_add_filter_compress(struct archive *);
 __LA_DECL int archive_write_add_filter_grzip(struct archive *);
 __LA_DECL int archive_write_add_filter_gzip(struct archive *);
 __LA_DECL int archive_write_add_filter_lrzip(struct archive *);
+__LA_DECL int archive_write_add_filter_lz4(struct archive *);
 __LA_DECL int archive_write_add_filter_lzip(struct archive *);
 __LA_DECL int archive_write_add_filter_lzma(struct archive *);
 __LA_DECL int archive_write_add_filter_lzop(struct archive *);
@@ -670,12 +797,16 @@ __LA_DECL int archive_write_set_format_mtree_classic(struct archive *);
 /* TODO: int archive_write_set_format_old_tar(struct archive *); */
 __LA_DECL int archive_write_set_format_pax(struct archive *);
 __LA_DECL int archive_write_set_format_pax_restricted(struct archive *);
+__LA_DECL int archive_write_set_format_raw(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_v7tar(struct archive *);
+__LA_DECL int archive_write_set_format_warc(struct archive *);
 __LA_DECL int archive_write_set_format_xar(struct archive *);
 __LA_DECL int archive_write_set_format_zip(struct archive *);
+__LA_DECL int archive_write_set_format_filter_by_ext(struct archive *a, const char *filename);
+__LA_DECL int archive_write_set_format_filter_by_ext_def(struct archive *a, const char *filename, const char * def_ext);
 __LA_DECL int archive_write_zip_set_compression_deflate(struct archive *);
 __LA_DECL int archive_write_zip_set_compression_store(struct archive *);
 __LA_DECL int archive_write_open(struct archive *, void *,
@@ -700,12 +831,12 @@ __LA_DECL int archive_write_open_memory(struct archive *,
  */
 __LA_DECL int archive_write_header(struct archive *,
                     struct archive_entry *);
-__LA_DECL __LA_SSIZE_T archive_write_data(struct archive *,
+__LA_DECL la_ssize_t   archive_write_data(struct archive *,
                            const void *, size_t);
 
 /* This interface is currently only available for archive_write_disk handles.  */
-__LA_DECL __LA_SSIZE_T  archive_write_data_block(struct archive *,
-                                   const void *, size_t, __LA_INT64_T);
+__LA_DECL la_ssize_t    archive_write_data_block(struct archive *,
+                                   const void *, size_t, la_int64_t);
 
 __LA_DECL int           archive_write_finish_entry(struct archive *);
 __LA_DECL int           archive_write_close(struct archive *);
@@ -740,6 +871,13 @@ __LA_DECL int archive_write_set_option(struct archive *_a,
 __LA_DECL int archive_write_set_options(struct archive *_a,
                            const char *opts);
 
+/*
+ * Set a encryption passphrase.
+ */
+__LA_DECL int archive_write_set_passphrase(struct archive *_a, const char *p);
+__LA_DECL int archive_write_set_passphrase_callback(struct archive *,
+                           void *client_data, archive_passphrase_callback *);
+
 /*-
  * ARCHIVE_WRITE_DISK API
  *
@@ -759,7 +897,7 @@ __LA_DECL int archive_write_set_options(struct archive *_a,
 __LA_DECL struct archive       *archive_write_disk_new(void);
 /* This file will not be overwritten. */
 __LA_DECL int archive_write_disk_set_skip_file(struct archive *,
-    __LA_INT64_T, __LA_INT64_T);
+    la_int64_t, la_int64_t);
 /* Set flags to control how the next item gets created.
  * This accepts a bitmask of ARCHIVE_EXTRACT_XXX flags defined above. */
 __LA_DECL int           archive_write_disk_set_options(struct archive *,
@@ -789,14 +927,14 @@ __LA_DECL int      archive_write_disk_set_standard_lookup(struct archive *);
  */
 __LA_DECL int archive_write_disk_set_group_lookup(struct archive *,
     void * /* private_data */,
-    __LA_INT64_T (*)(void *, const char *, __LA_INT64_T),
+    la_int64_t (*)(void *, const char *, la_int64_t),
     void (* /* cleanup */)(void *));
 __LA_DECL int archive_write_disk_set_user_lookup(struct archive *,
     void * /* private_data */,
-    __LA_INT64_T (*)(void *, const char *, __LA_INT64_T),
+    la_int64_t (*)(void *, const char *, la_int64_t),
     void (* /* cleanup */)(void *));
-__LA_DECL __LA_INT64_T archive_write_disk_gid(struct archive *, const char *, __LA_INT64_T);
-__LA_DECL __LA_INT64_T archive_write_disk_uid(struct archive *, const char *, __LA_INT64_T);
+__LA_DECL la_int64_t archive_write_disk_gid(struct archive *, const char *, la_int64_t);
+__LA_DECL la_int64_t archive_write_disk_uid(struct archive *, const char *, la_int64_t);
 
 /*
  * ARCHIVE_READ_DISK API
@@ -817,19 +955,19 @@ __LA_DECL int archive_read_disk_entry_from_file(struct archive *,
     struct archive_entry *, int /* fd */, const struct stat *);
 /* Look up gname for gid or uname for uid. */
 /* Default implementations are very, very stupid. */
-__LA_DECL const char *archive_read_disk_gname(struct archive *, __LA_INT64_T);
-__LA_DECL const char *archive_read_disk_uname(struct archive *, __LA_INT64_T);
+__LA_DECL const char *archive_read_disk_gname(struct archive *, la_int64_t);
+__LA_DECL const char *archive_read_disk_uname(struct archive *, la_int64_t);
 /* "Standard" implementation uses getpwuid_r, getgrgid_r and caches the
  * results for performance. */
 __LA_DECL int  archive_read_disk_set_standard_lookup(struct archive *);
 /* You can install your own lookups if you like. */
 __LA_DECL int  archive_read_disk_set_gname_lookup(struct archive *,
     void * /* private_data */,
-    const char *(* /* lookup_fn */)(void *, __LA_INT64_T),
+    const char *(* /* lookup_fn */)(void *, la_int64_t),
     void (* /* cleanup_fn */)(void *));
 __LA_DECL int  archive_read_disk_set_uname_lookup(struct archive *,
     void * /* private_data */,
-    const char *(* /* lookup_fn */)(void *, __LA_INT64_T),
+    const char *(* /* lookup_fn */)(void *, la_int64_t),
     void (* /* cleanup_fn */)(void *));
 /* Start traversal. */
 __LA_DECL int  archive_read_disk_open(struct archive *, const char *);
@@ -859,8 +997,10 @@ __LA_DECL int  archive_read_disk_set_atime_restored(struct archive *);
 /* Default: Skip a mac resource fork file whose prefix is "._" because of
  * using copyfile. */
 #define        ARCHIVE_READDISK_MAC_COPYFILE           (0x0004)
-/* Default: Do not traverse mount points. */
+/* Default: Traverse mount points. */
 #define        ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS     (0x0008)
+/* Default: Xattrs are read from disk. */
+#define        ARCHIVE_READDISK_NO_XATTR               (0x0010)
 
 __LA_DECL int  archive_read_disk_set_behavior(struct archive *,
                    int flags);
@@ -879,6 +1019,10 @@ __LA_DECL int     archive_read_disk_set_metadata_filter_callback(struct archive *,
                    int (*_metadata_filter_func)(struct archive *, void *,
                        struct archive_entry *), void *_client_data);
 
+/* Simplified cleanup interface;
+ * This calls archive_read_free() or archive_write_free() as needed. */
+__LA_DECL int  archive_free(struct archive *);
+
 /*
  * Accessor functions to read/set various information in
  * the struct archive object:
@@ -889,7 +1033,7 @@ __LA_DECL int      archive_read_disk_set_metadata_filter_callback(struct archive *,
  * last filter, which is always the pseudo-filter that wraps the
  * client callbacks. */
 __LA_DECL int           archive_filter_count(struct archive *);
-__LA_DECL __LA_INT64_T  archive_filter_bytes(struct archive *, int);
+__LA_DECL la_int64_t    archive_filter_bytes(struct archive *, int);
 __LA_DECL int           archive_filter_code(struct archive *, int);
 __LA_DECL const char *  archive_filter_name(struct archive *, int);
 
@@ -897,10 +1041,10 @@ __LA_DECL const char *    archive_filter_name(struct archive *, int);
 /* These don't properly handle multiple filters, so are deprecated and
  * will eventually be removed. */
 /* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, -1); */
-__LA_DECL __LA_INT64_T  archive_position_compressed(struct archive *)
+__LA_DECL la_int64_t    archive_position_compressed(struct archive *)
                                __LA_DEPRECATED;
 /* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, 0); */
-__LA_DECL __LA_INT64_T  archive_position_uncompressed(struct archive *)
+__LA_DECL la_int64_t    archive_position_uncompressed(struct archive *)
                                __LA_DEPRECATED;
 /* As of libarchive 3.0, this is an alias for archive_filter_name(a, 0); */
 __LA_DECL const char   *archive_compression_name(struct archive *)
@@ -1016,8 +1160,8 @@ __LA_DECL int     archive_match_exclude_entry(struct archive *,
 __LA_DECL int  archive_match_owner_excluded(struct archive *,
                    struct archive_entry *);
 /* Add inclusion uid, gid, uname and gname. */
-__LA_DECL int  archive_match_include_uid(struct archive *, __LA_INT64_T);
-__LA_DECL int  archive_match_include_gid(struct archive *, __LA_INT64_T);
+__LA_DECL int  archive_match_include_uid(struct archive *, la_int64_t);
+__LA_DECL int  archive_match_include_gid(struct archive *, la_int64_t);
 __LA_DECL int  archive_match_include_uname(struct archive *, const char *);
 __LA_DECL int  archive_match_include_uname_w(struct archive *,
                    const wchar_t *);
@@ -1025,6 +1169,10 @@ __LA_DECL int    archive_match_include_gname(struct archive *, const char *);
 __LA_DECL int  archive_match_include_gname_w(struct archive *,
                    const wchar_t *);
 
+/* Utility functions */
+/* Convenience function to sort a NULL terminated list of strings */
+__LA_DECL int archive_utility_string_sort(char **);
+
 #ifdef __cplusplus
 }
 #endif
@@ -1032,9 +1180,4 @@ __LA_DECL int     archive_match_include_gname_w(struct archive *,
 /* These are meaningless outside of this header. */
 #undef __LA_DECL
 
-/* These need to remain defined because they're used in the
- * callback type definitions.  XXX Fix this.  This is ugly. XXX */
-/* #undef __LA_INT64_T */
-/* #undef __LA_SSIZE_T */
-
 #endif /* !ARCHIVE_H_INCLUDED */
diff --git a/contrib/libarchive/libarchive/archive_cryptor.c b/contrib/libarchive/libarchive/archive_cryptor.c
new file mode 100644 (file)
index 0000000..0be30c6
--- /dev/null
@@ -0,0 +1,448 @@
+/*-
+* Copyright (c) 2014 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_STRING_H
+#include <string.h>
+#endif
+#include "archive.h"
+#include "archive_cryptor_private.h"
+
+/*
+ * On systems that do not support any recognized crypto libraries,
+ * this file will normally define no usable symbols.
+ *
+ * But some compilers and linkers choke on empty object files, so
+ * define a public symbol that will always exist.  This could
+ * be removed someday if this file gains another always-present
+ * symbol definition.
+ */
+int __libarchive_cryptor_build_hack(void) {
+       return 0;
+}
+
+#ifdef ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto
+
+static int
+pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
+    size_t salt_len, unsigned rounds, uint8_t *derived_key,
+    size_t derived_key_len)
+{
+       CCKeyDerivationPBKDF(kCCPBKDF2, (const char *)pw,
+           pw_len, salt, salt_len, kCCPRFHmacAlgSHA1, rounds,
+           derived_key, derived_key_len);
+       return 0;
+}
+
+#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
+#ifdef _MSC_VER
+#pragma comment(lib, "Bcrypt.lib")
+#endif
+
+static int
+pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
+       size_t salt_len, unsigned rounds, uint8_t *derived_key,
+       size_t derived_key_len)
+{
+       NTSTATUS status;
+       BCRYPT_ALG_HANDLE hAlg;
+
+       status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA1_ALGORITHM,
+               MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG);
+       if (!BCRYPT_SUCCESS(status))
+               return -1;
+
+       status = BCryptDeriveKeyPBKDF2(hAlg,
+               (PUCHAR)(uintptr_t)pw, (ULONG)pw_len,
+               (PUCHAR)(uintptr_t)salt, (ULONG)salt_len, rounds,
+               (PUCHAR)derived_key, (ULONG)derived_key_len, 0);
+
+       BCryptCloseAlgorithmProvider(hAlg, 0);
+
+       return (BCRYPT_SUCCESS(status)) ? 0: -1;
+}
+
+#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_PBKDF2_H)
+
+static int
+pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
+    size_t salt_len, unsigned rounds, uint8_t *derived_key,
+    size_t derived_key_len) {
+       pbkdf2_hmac_sha1((unsigned)pw_len, (const uint8_t *)pw, rounds,
+           salt_len, salt, derived_key_len, derived_key);
+       return 0;
+}
+
+#elif defined(HAVE_LIBCRYPTO) && defined(HAVE_PKCS5_PBKDF2_HMAC_SHA1)
+
+static int
+pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
+    size_t salt_len, unsigned rounds, uint8_t *derived_key,
+    size_t derived_key_len) {
+
+       PKCS5_PBKDF2_HMAC_SHA1(pw, pw_len, salt, salt_len, rounds,
+           derived_key_len, derived_key);
+       return 0;
+}
+
+#else
+
+/* Stub */
+static int
+pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
+    size_t salt_len, unsigned rounds, uint8_t *derived_key,
+    size_t derived_key_len) {
+       (void)pw; /* UNUSED */
+       (void)pw_len; /* UNUSED */
+       (void)salt; /* UNUSED */
+       (void)salt_len; /* UNUSED */
+       (void)rounds; /* UNUSED */
+       (void)derived_key; /* UNUSED */
+       (void)derived_key_len; /* UNUSED */
+       return -1; /* UNSUPPORTED */
+}
+
+#endif
+
+#ifdef ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto
+# if MAC_OS_X_VERSION_MAX_ALLOWED < 1090
+#  define kCCAlgorithmAES kCCAlgorithmAES128
+# endif
+
+static int
+aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
+{
+       CCCryptorStatus r;
+
+       ctx->key_len = key_len;
+       memcpy(ctx->key, key, key_len);
+       memset(ctx->nonce, 0, sizeof(ctx->nonce));
+       ctx->encr_pos = AES_BLOCK_SIZE;
+       r = CCCryptorCreateWithMode(kCCEncrypt, kCCModeECB, kCCAlgorithmAES,
+           ccNoPadding, NULL, key, key_len, NULL, 0, 0, 0, &ctx->ctx);
+       return (r == kCCSuccess)? 0: -1;
+}
+
+static int
+aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
+{
+       CCCryptorRef ref = ctx->ctx;
+       CCCryptorStatus r;
+
+       r = CCCryptorReset(ref, NULL);
+       if (r != kCCSuccess)
+               return -1;
+       r = CCCryptorUpdate(ref, ctx->nonce, AES_BLOCK_SIZE, ctx->encr_buf,
+           AES_BLOCK_SIZE, NULL);
+       return (r == kCCSuccess)? 0: -1;
+}
+
+static int
+aes_ctr_release(archive_crypto_ctx *ctx)
+{
+       memset(ctx->key, 0, ctx->key_len);
+       memset(ctx->nonce, 0, sizeof(ctx->nonce));
+       return 0;
+}
+
+#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
+
+static int
+aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
+{
+       BCRYPT_ALG_HANDLE hAlg;
+       BCRYPT_KEY_HANDLE hKey;
+       DWORD keyObj_len, aes_key_len;
+       PBYTE keyObj;
+       ULONG result;
+       NTSTATUS status;
+       BCRYPT_KEY_LENGTHS_STRUCT key_lengths;
+
+       ctx->hAlg = NULL;
+       ctx->hKey = NULL;
+       ctx->keyObj = NULL;
+       switch (key_len) {
+       case 16: aes_key_len = 128; break;
+       case 24: aes_key_len = 192; break;
+       case 32: aes_key_len = 256; break;
+       default: return -1;
+       }
+       status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_AES_ALGORITHM,
+               MS_PRIMITIVE_PROVIDER, 0);
+       if (!BCRYPT_SUCCESS(status))
+               return -1;
+       status = BCryptGetProperty(hAlg, BCRYPT_KEY_LENGTHS, (PUCHAR)&key_lengths,
+               sizeof(key_lengths), &result, 0);
+       if (!BCRYPT_SUCCESS(status)) {
+               BCryptCloseAlgorithmProvider(hAlg, 0);
+               return -1;
+       }
+       if (key_lengths.dwMinLength > aes_key_len
+               || key_lengths.dwMaxLength < aes_key_len) {
+               BCryptCloseAlgorithmProvider(hAlg, 0);
+               return -1;
+       }
+       status = BCryptGetProperty(hAlg, BCRYPT_OBJECT_LENGTH, (PUCHAR)&keyObj_len,
+               sizeof(keyObj_len), &result, 0);
+       if (!BCRYPT_SUCCESS(status)) {
+               BCryptCloseAlgorithmProvider(hAlg, 0);
+               return -1;
+       }
+       keyObj = (PBYTE)HeapAlloc(GetProcessHeap(), 0, keyObj_len);
+       if (keyObj == NULL) {
+               BCryptCloseAlgorithmProvider(hAlg, 0);
+               return -1;
+       }
+       status = BCryptSetProperty(hAlg, BCRYPT_CHAINING_MODE,
+               (PUCHAR)BCRYPT_CHAIN_MODE_ECB, sizeof(BCRYPT_CHAIN_MODE_ECB), 0);
+       if (!BCRYPT_SUCCESS(status)) {
+               BCryptCloseAlgorithmProvider(hAlg, 0);
+               HeapFree(GetProcessHeap(), 0, keyObj);
+               return -1;
+       }
+       status = BCryptGenerateSymmetricKey(hAlg, &hKey,
+               keyObj, keyObj_len,
+               (PUCHAR)(uintptr_t)key, (ULONG)key_len, 0);
+       if (!BCRYPT_SUCCESS(status)) {
+               BCryptCloseAlgorithmProvider(hAlg, 0);
+               HeapFree(GetProcessHeap(), 0, keyObj);
+               return -1;
+       }
+
+       ctx->hAlg = hAlg;
+       ctx->hKey = hKey;
+       ctx->keyObj = keyObj;
+       ctx->keyObj_len = keyObj_len;
+       ctx->encr_pos = AES_BLOCK_SIZE;
+
+       return 0;
+}
+
+static int
+aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
+{
+       NTSTATUS status;
+       ULONG result;
+
+       status = BCryptEncrypt(ctx->hKey, (PUCHAR)ctx->nonce, AES_BLOCK_SIZE,
+               NULL, NULL, 0, (PUCHAR)ctx->encr_buf, AES_BLOCK_SIZE,
+               &result, 0);
+       return BCRYPT_SUCCESS(status) ? 0 : -1;
+}
+
+static int
+aes_ctr_release(archive_crypto_ctx *ctx)
+{
+
+       if (ctx->hAlg != NULL) {
+               BCryptCloseAlgorithmProvider(ctx->hAlg, 0);
+               ctx->hAlg = NULL;
+               BCryptDestroyKey(ctx->hKey);
+               ctx->hKey = NULL;
+               HeapFree(GetProcessHeap(), 0, ctx->keyObj);
+               ctx->keyObj = NULL;
+       }
+       memset(ctx, 0, sizeof(*ctx));
+       return 0;
+}
+
+#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_AES_H)
+
+static int
+aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
+{
+       ctx->key_len = key_len;
+       memcpy(ctx->key, key, key_len);
+       memset(ctx->nonce, 0, sizeof(ctx->nonce));
+       ctx->encr_pos = AES_BLOCK_SIZE;
+       memset(&ctx->ctx, 0, sizeof(ctx->ctx));
+       return 0;
+}
+
+static int
+aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
+{
+       aes_set_encrypt_key(&ctx->ctx, ctx->key_len, ctx->key);
+       aes_encrypt(&ctx->ctx, AES_BLOCK_SIZE, ctx->encr_buf, ctx->nonce);
+       return 0;
+}
+
+static int
+aes_ctr_release(archive_crypto_ctx *ctx)
+{
+       memset(ctx, 0, sizeof(*ctx));
+       return 0;
+}
+
+#elif defined(HAVE_LIBCRYPTO)
+
+static int
+aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
+{
+
+       switch (key_len) {
+       case 16: ctx->type = EVP_aes_128_ecb(); break;
+       case 24: ctx->type = EVP_aes_192_ecb(); break;
+       case 32: ctx->type = EVP_aes_256_ecb(); break;
+       default: ctx->type = NULL; return -1;
+       }
+
+       ctx->key_len = key_len;
+       memcpy(ctx->key, key, key_len);
+       memset(ctx->nonce, 0, sizeof(ctx->nonce));
+       ctx->encr_pos = AES_BLOCK_SIZE;
+       EVP_CIPHER_CTX_init(&ctx->ctx);
+       return 0;
+}
+
+static int
+aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
+{
+       int outl = 0;
+       int r;
+
+       r = EVP_EncryptInit_ex(&ctx->ctx, ctx->type, NULL, ctx->key, NULL);
+       if (r == 0)
+               return -1;
+       r = EVP_EncryptUpdate(&ctx->ctx, ctx->encr_buf, &outl, ctx->nonce,
+           AES_BLOCK_SIZE);
+       if (r == 0 || outl != AES_BLOCK_SIZE)
+               return -1;
+       return 0;
+}
+
+static int
+aes_ctr_release(archive_crypto_ctx *ctx)
+{
+       EVP_CIPHER_CTX_cleanup(&ctx->ctx);
+       memset(ctx->key, 0, ctx->key_len);
+       memset(ctx->nonce, 0, sizeof(ctx->nonce));
+       return 0;
+}
+
+#else
+
+#define ARCHIVE_CRYPTOR_STUB
+/* Stub */
+static int
+aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
+{
+       (void)ctx; /* UNUSED */
+       (void)key; /* UNUSED */
+       (void)key_len; /* UNUSED */
+       return -1;
+}
+
+static int
+aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
+{
+       (void)ctx; /* UNUSED */
+       return -1;
+}
+
+static int
+aes_ctr_release(archive_crypto_ctx *ctx)
+{
+       (void)ctx; /* UNUSED */
+       return 0;
+}
+
+#endif
+
+#ifdef ARCHIVE_CRYPTOR_STUB
+static int
+aes_ctr_update(archive_crypto_ctx *ctx, const uint8_t * const in,
+    size_t in_len, uint8_t * const out, size_t *out_len)
+{
+       (void)ctx; /* UNUSED */
+       (void)in; /* UNUSED */
+       (void)in_len; /* UNUSED */
+       (void)out; /* UNUSED */
+       (void)out_len; /* UNUSED */
+       aes_ctr_encrypt_counter(ctx); /* UNUSED */ /* Fix unused function warning */
+       return -1;
+}
+
+#else
+static void
+aes_ctr_increase_counter(archive_crypto_ctx *ctx)
+{
+       uint8_t *const nonce = ctx->nonce;
+       int j;
+
+       for (j = 0; j < 8; j++) {
+               if (++nonce[j])
+                       break;
+       }
+}
+
+static int
+aes_ctr_update(archive_crypto_ctx *ctx, const uint8_t * const in,
+    size_t in_len, uint8_t * const out, size_t *out_len)
+{
+       uint8_t *const ebuf = ctx->encr_buf;
+       unsigned pos = ctx->encr_pos;
+       unsigned max = (unsigned)((in_len < *out_len)? in_len: *out_len);
+       unsigned i;
+
+       for (i = 0; i < max; ) {
+               if (pos == AES_BLOCK_SIZE) {
+                       aes_ctr_increase_counter(ctx);
+                       if (aes_ctr_encrypt_counter(ctx) != 0)
+                               return -1;
+                       while (max -i >= AES_BLOCK_SIZE) {
+                               for (pos = 0; pos < AES_BLOCK_SIZE; pos++)
+                                       out[i+pos] = in[i+pos] ^ ebuf[pos];
+                               i += AES_BLOCK_SIZE;
+                               aes_ctr_increase_counter(ctx);
+                               if (aes_ctr_encrypt_counter(ctx) != 0)
+                                       return -1;
+                       }
+                       pos = 0;
+                       if (i >= max)
+                               break;
+               }
+               out[i] = in[i] ^ ebuf[pos++];
+               i++;
+       }
+       ctx->encr_pos = pos;
+       *out_len = i;
+
+       return 0;
+}
+#endif /* ARCHIVE_CRYPTOR_STUB */
+
+
+const struct archive_cryptor __archive_cryptor =
+{
+  &pbkdf2_sha1,
+  &aes_ctr_init,
+  &aes_ctr_update,
+  &aes_ctr_release,
+  &aes_ctr_init,
+  &aes_ctr_update,
+  &aes_ctr_release,
+};
diff --git a/contrib/libarchive/libarchive/archive_cryptor_private.h b/contrib/libarchive/libarchive/archive_cryptor_private.h
new file mode 100644 (file)
index 0000000..37eaad3
--- /dev/null
@@ -0,0 +1,163 @@
+/*-
+* Copyright (c) 2014 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.
+*/
+
+#ifndef __LIBARCHIVE_BUILD
+#error This header is only to be used internally to libarchive.
+#endif
+
+#ifndef ARCHIVE_CRYPTOR_PRIVATE_H_INCLUDED
+#define ARCHIVE_CRYPTOR_PRIVATE_H_INCLUDED
+
+/*
+ * On systems that do not support any recognized crypto libraries,
+ * the archive_cryptor.c file will normally define no usable symbols.
+ *
+ * But some compilers and linkers choke on empty object files, so
+ * define a public symbol that will always exist.  This could
+ * be removed someday if this file gains another always-present
+ * symbol definition.
+ */
+int __libarchive_cryptor_build_hack(void);
+
+#ifdef __APPLE__
+# include <AvailabilityMacros.h>
+# if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
+#  define ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto
+# endif
+#endif
+
+#ifdef ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto
+#include <CommonCrypto/CommonCryptor.h>
+#include <CommonCrypto/CommonKeyDerivation.h>
+#define AES_BLOCK_SIZE 16
+#define AES_MAX_KEY_SIZE kCCKeySizeAES256
+
+typedef struct {
+       CCCryptorRef    ctx;
+       uint8_t         key[AES_MAX_KEY_SIZE];
+       unsigned        key_len;
+       uint8_t         nonce[AES_BLOCK_SIZE];
+       uint8_t         encr_buf[AES_BLOCK_SIZE];
+       unsigned        encr_pos;
+} archive_crypto_ctx;
+
+#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
+#include <Bcrypt.h>
+
+/* Common in other bcrypt implementations, but missing from VS2008. */
+#ifndef BCRYPT_SUCCESS
+#define BCRYPT_SUCCESS(r) ((NTSTATUS)(r) == STATUS_SUCCESS)
+#endif
+
+#define AES_MAX_KEY_SIZE 32
+#define AES_BLOCK_SIZE 16
+typedef struct {
+       BCRYPT_ALG_HANDLE hAlg;
+       BCRYPT_KEY_HANDLE hKey;
+       PBYTE           keyObj;
+       DWORD           keyObj_len;
+       uint8_t         nonce[AES_BLOCK_SIZE];
+       uint8_t         encr_buf[AES_BLOCK_SIZE];
+       unsigned        encr_pos;
+} archive_crypto_ctx;
+
+#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_AES_H)
+#if defined(HAVE_NETTLE_PBKDF2_H)
+#include <nettle/pbkdf2.h>
+#endif
+#include <nettle/aes.h>
+
+typedef struct {
+       struct aes_ctx  ctx;
+       uint8_t         key[AES_MAX_KEY_SIZE];
+       unsigned        key_len;
+       uint8_t         nonce[AES_BLOCK_SIZE];
+       uint8_t         encr_buf[AES_BLOCK_SIZE];
+       unsigned        encr_pos;
+} archive_crypto_ctx;
+
+#elif defined(HAVE_LIBCRYPTO)
+#include <openssl/evp.h>
+#define AES_BLOCK_SIZE 16
+#define AES_MAX_KEY_SIZE 32
+
+typedef struct {
+       EVP_CIPHER_CTX  ctx;
+       const EVP_CIPHER *type;
+       uint8_t         key[AES_MAX_KEY_SIZE];
+       unsigned        key_len;
+       uint8_t         nonce[AES_BLOCK_SIZE];
+       uint8_t         encr_buf[AES_BLOCK_SIZE];
+       unsigned        encr_pos;
+} archive_crypto_ctx;
+
+#else
+
+#define AES_BLOCK_SIZE 16
+#define AES_MAX_KEY_SIZE 32
+typedef int archive_crypto_ctx;
+
+#endif
+
+/* defines */
+#define archive_pbkdf2_sha1(pw, pw_len, salt, salt_len, rounds, dk, dk_len)\
+  __archive_cryptor.pbkdf2sha1(pw, pw_len, salt, salt_len, rounds, dk, dk_len)
+
+#define archive_decrypto_aes_ctr_init(ctx, key, key_len) \
+  __archive_cryptor.decrypto_aes_ctr_init(ctx, key, key_len)
+#define archive_decrypto_aes_ctr_update(ctx, in, in_len, out, out_len) \
+  __archive_cryptor.decrypto_aes_ctr_update(ctx, in, in_len, out, out_len)
+#define archive_decrypto_aes_ctr_release(ctx) \
+  __archive_cryptor.decrypto_aes_ctr_release(ctx)
+
+#define archive_encrypto_aes_ctr_init(ctx, key, key_len) \
+  __archive_cryptor.encrypto_aes_ctr_init(ctx, key, key_len)
+#define archive_encrypto_aes_ctr_update(ctx, in, in_len, out, out_len) \
+  __archive_cryptor.encrypto_aes_ctr_update(ctx, in, in_len, out, out_len)
+#define archive_encrypto_aes_ctr_release(ctx) \
+  __archive_cryptor.encrypto_aes_ctr_release(ctx)
+
+/* Minimal interface to cryptographic functionality for internal use in
+ * libarchive */
+struct archive_cryptor
+{
+  /* PKCS5 PBKDF2 HMAC-SHA1 */
+  int (*pbkdf2sha1)(const char *pw, size_t pw_len, const uint8_t *salt,
+    size_t salt_len, unsigned rounds, uint8_t *derived_key,
+    size_t derived_key_len);
+  /* AES CTR mode(little endian version) */
+  int (*decrypto_aes_ctr_init)(archive_crypto_ctx *, const uint8_t *, size_t);
+  int (*decrypto_aes_ctr_update)(archive_crypto_ctx *, const uint8_t *,
+    size_t, uint8_t *, size_t *);
+  int (*decrypto_aes_ctr_release)(archive_crypto_ctx *);
+  int (*encrypto_aes_ctr_init)(archive_crypto_ctx *, const uint8_t *, size_t);
+  int (*encrypto_aes_ctr_update)(archive_crypto_ctx *, const uint8_t *,
+    size_t, uint8_t *, size_t *);
+  int (*encrypto_aes_ctr_release)(archive_crypto_ctx *);
+};
+
+extern const struct archive_cryptor __archive_cryptor;
+
+#endif
@@ -28,7 +28,7 @@
 #include "archive_platform.h"
 
 #include "archive.h"
-#include "archive_crypto_private.h"
+#include "archive_digest_private.h"
 
 /* In particular, force the configure probe to break if it tries
  * to test a combination of OpenSSL and libmd. */
@@ -1216,8 +1216,8 @@ __archive_stub_sha512final(archive_sha512_ctx *ctx, void *md)
 
 #endif
 
-/* NOTE: Crypto functions are set based on availability and by the following
- * order of preference.
+/* NOTE: Message Digest functions are set based on availability and by the
+ * following order of preference.
  * 1. libc
  * 2. libc2
  * 3. libc3
@@ -1227,7 +1227,7 @@ __archive_stub_sha512final(archive_sha512_ctx *ctx, void *md)
  * 7. libmd
  * 8. Windows API
  */
-const struct archive_crypto __archive_crypto =
+const struct archive_digest __archive_digest =
 {
 /* MD5 */
 #if defined(ARCHIVE_CRYPTO_MD5_LIBC)
@@ -1412,7 +1412,7 @@ const struct archive_crypto __archive_crypto =
 #elif defined(ARCHIVE_CRYPTO_SHA512_NETTLE)
   &__archive_nettle_sha512init,
   &__archive_nettle_sha512update,
-  &__archive_nettle_sha512final,
+  &__archive_nettle_sha512final
 #elif defined(ARCHIVE_CRYPTO_SHA512_OPENSSL)
   &__archive_openssl_sha512init,
   &__archive_openssl_sha512update,
@@ -264,11 +264,11 @@ typedef unsigned char archive_sha512_ctx;
 #define ARCHIVE_HAS_MD5
 #endif
 #define archive_md5_init(ctx)\
-  __archive_crypto.md5init(ctx)
+  __archive_digest.md5init(ctx)
 #define archive_md5_final(ctx, md)\
-  __archive_crypto.md5final(ctx, md)
+  __archive_digest.md5final(ctx, md)
 #define archive_md5_update(ctx, buf, n)\
-  __archive_crypto.md5update(ctx, buf, n)
+  __archive_digest.md5update(ctx, buf, n)
 
 #if defined(ARCHIVE_CRYPTO_RMD160_LIBC) ||\
   defined(ARCHIVE_CRYPTO_RMD160_NETTLE) ||\
@@ -276,11 +276,11 @@ typedef unsigned char archive_sha512_ctx;
 #define ARCHIVE_HAS_RMD160
 #endif
 #define archive_rmd160_init(ctx)\
-  __archive_crypto.rmd160init(ctx)
+  __archive_digest.rmd160init(ctx)
 #define archive_rmd160_final(ctx, md)\
-  __archive_crypto.rmd160final(ctx, md)
+  __archive_digest.rmd160final(ctx, md)
 #define archive_rmd160_update(ctx, buf, n)\
-  __archive_crypto.rmd160update(ctx, buf, n)
+  __archive_digest.rmd160update(ctx, buf, n)
 
 #if defined(ARCHIVE_CRYPTO_SHA1_LIBC) ||\
   defined(ARCHIVE_CRYPTO_SHA1_LIBMD) ||        \
@@ -291,11 +291,11 @@ typedef unsigned char archive_sha512_ctx;
 #define ARCHIVE_HAS_SHA1
 #endif
 #define archive_sha1_init(ctx)\
-  __archive_crypto.sha1init(ctx)
+  __archive_digest.sha1init(ctx)
 #define archive_sha1_final(ctx, md)\
-  __archive_crypto.sha1final(ctx, md)
+  __archive_digest.sha1final(ctx, md)
 #define archive_sha1_update(ctx, buf, n)\
-  __archive_crypto.sha1update(ctx, buf, n)
+  __archive_digest.sha1update(ctx, buf, n)
 
 #if defined(ARCHIVE_CRYPTO_SHA256_LIBC) ||\
   defined(ARCHIVE_CRYPTO_SHA256_LIBC2) ||\
@@ -308,11 +308,11 @@ typedef unsigned char archive_sha512_ctx;
 #define ARCHIVE_HAS_SHA256
 #endif
 #define archive_sha256_init(ctx)\
-  __archive_crypto.sha256init(ctx)
+  __archive_digest.sha256init(ctx)
 #define archive_sha256_final(ctx, md)\
-  __archive_crypto.sha256final(ctx, md)
+  __archive_digest.sha256final(ctx, md)
 #define archive_sha256_update(ctx, buf, n)\
-  __archive_crypto.sha256update(ctx, buf, n)
+  __archive_digest.sha256update(ctx, buf, n)
 
 #if defined(ARCHIVE_CRYPTO_SHA384_LIBC) ||\
   defined(ARCHIVE_CRYPTO_SHA384_LIBC2) ||\
@@ -324,11 +324,11 @@ typedef unsigned char archive_sha512_ctx;
 #define ARCHIVE_HAS_SHA384
 #endif
 #define archive_sha384_init(ctx)\
-  __archive_crypto.sha384init(ctx)
+  __archive_digest.sha384init(ctx)
 #define archive_sha384_final(ctx, md)\
-  __archive_crypto.sha384final(ctx, md)
+  __archive_digest.sha384final(ctx, md)
 #define archive_sha384_update(ctx, buf, n)\
-  __archive_crypto.sha384update(ctx, buf, n)
+  __archive_digest.sha384update(ctx, buf, n)
 
 #if defined(ARCHIVE_CRYPTO_SHA512_LIBC) ||\
   defined(ARCHIVE_CRYPTO_SHA512_LIBC2) ||\
@@ -341,14 +341,14 @@ typedef unsigned char archive_sha512_ctx;
 #define ARCHIVE_HAS_SHA512
 #endif
 #define archive_sha512_init(ctx)\
-  __archive_crypto.sha512init(ctx)
+  __archive_digest.sha512init(ctx)
 #define archive_sha512_final(ctx, md)\
-  __archive_crypto.sha512final(ctx, md)
+  __archive_digest.sha512final(ctx, md)
 #define archive_sha512_update(ctx, buf, n)\
-  __archive_crypto.sha512update(ctx, buf, n)
+  __archive_digest.sha512update(ctx, buf, n)
 
-/* Minimal interface to crypto functionality for internal use in libarchive */
-struct archive_crypto
+/* Minimal interface to digest functionality for internal use in libarchive */
+struct archive_digest
 {
   /* Message Digest */
   int (*md5init)(archive_md5_ctx *ctx);
@@ -371,6 +371,6 @@ struct archive_crypto
   int (*sha512final)(archive_sha512_ctx *, void *);
 };
 
-extern const struct archive_crypto __archive_crypto;
+extern const struct archive_digest __archive_digest;
 
 #endif
index 68123b0..1c48563 100644 (file)
  * - Watcom C++ in C code.  (For any version?)
  * - SGI MIPSpro
  * - Microsoft Visual C++ 6.0 (supposedly newer versions too)
+ * - IBM VisualAge 6 (XL v6)
+ * - Sun WorkShop C (SunPro) before 5.9
  */
 #if defined(__WATCOMC__) || defined(__sgi) || defined(__hpux) || defined(__BORLANDC__)
 #define        inline
-#elif defined(_MSC_VER)
+#elif defined(__IBMC__) && __IBMC__ < 700
+#define        inline
+#elif defined(__SUNPRO_C) && __SUNPRO_C < 0x590
+#define inline
+#elif defined(_MSC_VER) || defined(__osf__)
 #define inline __inline
 #endif
 
@@ -58,7 +64,13 @@ archive_be16dec(const void *pp)
 {
        unsigned char const *p = (unsigned char const *)pp;
 
-       return ((p[0] << 8) | p[1]);
+       /* Store into unsigned temporaries before left shifting, to avoid
+       promotion to signed int and then left shifting into the sign bit,
+       which is undefined behaviour. */
+       unsigned int p1 = p[1];
+       unsigned int p0 = p[0];
+
+       return ((p0 << 8) | p1);
 }
 
 static inline uint32_t
@@ -66,7 +78,15 @@ archive_be32dec(const void *pp)
 {
        unsigned char const *p = (unsigned char const *)pp;
 
-       return ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
+       /* Store into unsigned temporaries before left shifting, to avoid
+       promotion to signed int and then left shifting into the sign bit,
+       which is undefined behaviour. */
+       unsigned int p3 = p[3];
+       unsigned int p2 = p[2];
+       unsigned int p1 = p[1];
+       unsigned int p0 = p[0];
+
+       return ((p0 << 24) | (p1 << 16) | (p2 << 8) | p3);
 }
 
 static inline uint64_t
@@ -82,7 +102,13 @@ archive_le16dec(const void *pp)
 {
        unsigned char const *p = (unsigned char const *)pp;
 
-       return ((p[1] << 8) | p[0]);
+       /* Store into unsigned temporaries before left shifting, to avoid
+       promotion to signed int and then left shifting into the sign bit,
+       which is undefined behaviour. */
+       unsigned int p1 = p[1];
+       unsigned int p0 = p[0];
+
+       return ((p1 << 8) | p0);
 }
 
 static inline uint32_t
@@ -90,7 +116,15 @@ archive_le32dec(const void *pp)
 {
        unsigned char const *p = (unsigned char const *)pp;
 
-       return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]);
+       /* Store into unsigned temporaries before left shifting, to avoid
+       promotion to signed int and then left shifting into the sign bit,
+       which is undefined behaviour. */
+       unsigned int p3 = p[3];
+       unsigned int p2 = p[2];
+       unsigned int p1 = p[1];
+       unsigned int p0 = p[0];
+
+       return ((p3 << 24) | (p2 << 16) | (p1 << 8) | p0);
 }
 
 static inline uint64_t
index f77f385..f5e22af 100644 (file)
@@ -131,11 +131,11 @@ be discarded in favor of the new data.
 .\" .Sh RETURN VALUES
 .\" .Sh ERRORS
 .Sh SEE ALSO
-.Xr archive 3 ,
 .Xr archive_entry_acl 3 ,
 .Xr archive_entry_paths 3 ,
 .Xr archive_entry_perms 3 ,
 .Xr archive_entry_time 3
+.Xr libarchive 3 ,
 .Sh HISTORY
 The
 .Nm libarchive
index 386e51d..4ac1966 100644 (file)
@@ -201,6 +201,9 @@ archive_entry_clone(struct archive_entry *entry)
        entry2->ae_set = entry->ae_set;
        archive_mstring_copy(&entry2->ae_uname, &entry->ae_uname);
 
+       /* Copy encryption status */
+       entry2->encryption = entry->encryption;
+       
        /* Copy ACL data over. */
        archive_acl_copy(&entry2->acl, &entry->acl);
 
@@ -415,6 +418,18 @@ archive_entry_gname(struct archive_entry *entry)
        return (NULL);
 }
 
+const char *
+archive_entry_gname_utf8(struct archive_entry *entry)
+{
+       const char *p;
+       if (archive_mstring_get_utf8(entry->archive, &entry->ae_gname, &p) == 0)
+               return (p);
+       if (errno == ENOMEM)
+               __archive_errx(1, "No memory");
+       return (NULL);
+}
+
+
 const wchar_t *
 archive_entry_gname_w(struct archive_entry *entry)
 {
@@ -447,6 +462,20 @@ archive_entry_hardlink(struct archive_entry *entry)
        return (NULL);
 }
 
+const char *
+archive_entry_hardlink_utf8(struct archive_entry *entry)
+{
+       const char *p;
+       if ((entry->ae_set & AE_SET_HARDLINK) == 0)
+               return (NULL);
+       if (archive_mstring_get_utf8(
+           entry->archive, &entry->ae_hardlink, &p) == 0)
+               return (p);
+       if (errno == ENOMEM)
+               __archive_errx(1, "No memory");
+       return (NULL);
+}
+
 const wchar_t *
 archive_entry_hardlink_w(struct archive_entry *entry)
 {
@@ -533,6 +562,18 @@ archive_entry_pathname(struct archive_entry *entry)
        return (NULL);
 }
 
+const char *
+archive_entry_pathname_utf8(struct archive_entry *entry)
+{
+       const char *p;
+       if (archive_mstring_get_utf8(
+           entry->archive, &entry->ae_pathname, &p) == 0)
+               return (p);
+       if (errno == ENOMEM)
+               __archive_errx(1, "No memory");
+       return (NULL);
+}
+
 const wchar_t *
 archive_entry_pathname_w(struct archive_entry *entry)
 {
@@ -634,6 +675,20 @@ archive_entry_symlink(struct archive_entry *entry)
        return (NULL);
 }
 
+const char *
+archive_entry_symlink_utf8(struct archive_entry *entry)
+{
+       const char *p;
+       if ((entry->ae_set & AE_SET_SYMLINK) == 0)
+               return (NULL);
+       if (archive_mstring_get_utf8(
+           entry->archive, &entry->ae_symlink, &p) == 0)
+               return (p);
+       if (errno == ENOMEM)
+               __archive_errx(1, "No memory");
+       return (NULL);
+}
+
 const wchar_t *
 archive_entry_symlink_w(struct archive_entry *entry)
 {
@@ -677,6 +732,17 @@ archive_entry_uname(struct archive_entry *entry)
        return (NULL);
 }
 
+const char *
+archive_entry_uname_utf8(struct archive_entry *entry)
+{
+       const char *p;
+       if (archive_mstring_get_utf8(entry->archive, &entry->ae_uname, &p) == 0)
+               return (p);
+       if (errno == ENOMEM)
+               __archive_errx(1, "No memory");
+       return (NULL);
+}
+
 const wchar_t *
 archive_entry_uname_w(struct archive_entry *entry)
 {
@@ -695,6 +761,24 @@ _archive_entry_uname_l(struct archive_entry *entry,
        return (archive_mstring_get_mbs_l(&entry->ae_uname, p, len, sc));
 }
 
+int
+archive_entry_is_data_encrypted(struct archive_entry *entry)
+{
+       return ((entry->encryption & AE_ENCRYPTION_DATA) == AE_ENCRYPTION_DATA);
+}
+
+int
+archive_entry_is_metadata_encrypted(struct archive_entry *entry)
+{
+       return ((entry->encryption & AE_ENCRYPTION_METADATA) == AE_ENCRYPTION_METADATA);
+}
+
+int
+archive_entry_is_encrypted(struct archive_entry *entry)
+{
+       return (entry->encryption & (AE_ENCRYPTION_DATA|AE_ENCRYPTION_METADATA));
+}
+
 /*
  * Functions to set archive_entry properties.
  */
@@ -747,6 +831,12 @@ archive_entry_set_gname(struct archive_entry *entry, const char *name)
        archive_mstring_copy_mbs(&entry->ae_gname, name);
 }
 
+void
+archive_entry_set_gname_utf8(struct archive_entry *entry, const char *name)
+{
+       archive_mstring_copy_utf8(&entry->ae_gname, name);
+}
+
 void
 archive_entry_copy_gname(struct archive_entry *entry, const char *name)
 {
@@ -803,6 +893,16 @@ archive_entry_set_hardlink(struct archive_entry *entry, const char *target)
                entry->ae_set &= ~AE_SET_HARDLINK;
 }
 
+void
+archive_entry_set_hardlink_utf8(struct archive_entry *entry, const char *target)
+{
+       archive_mstring_copy_utf8(&entry->ae_hardlink, target);
+       if (target != NULL)
+               entry->ae_set |= AE_SET_HARDLINK;
+       else
+               entry->ae_set &= ~AE_SET_HARDLINK;
+}
+
 void
 archive_entry_copy_hardlink(struct archive_entry *entry, const char *target)
 {
@@ -941,6 +1041,15 @@ archive_entry_set_link(struct archive_entry *entry, const char *target)
                archive_mstring_copy_mbs(&entry->ae_hardlink, target);
 }
 
+void
+archive_entry_set_link_utf8(struct archive_entry *entry, const char *target)
+{
+       if (entry->ae_set & AE_SET_SYMLINK)
+               archive_mstring_copy_utf8(&entry->ae_symlink, target);
+       else
+               archive_mstring_copy_utf8(&entry->ae_hardlink, target);
+}
+
 /* Set symlink if symlink is already set, else set hardlink. */
 void
 archive_entry_copy_link(struct archive_entry *entry, const char *target)
@@ -1030,6 +1139,12 @@ archive_entry_set_pathname(struct archive_entry *entry, const char *name)
        archive_mstring_copy_mbs(&entry->ae_pathname, name);
 }
 
+void
+archive_entry_set_pathname_utf8(struct archive_entry *entry, const char *name)
+{
+       archive_mstring_copy_utf8(&entry->ae_pathname, name);
+}
+
 void
 archive_entry_copy_pathname(struct archive_entry *entry, const char *name)
 {
@@ -1130,6 +1245,16 @@ archive_entry_set_symlink(struct archive_entry *entry, const char *linkname)
                entry->ae_set &= ~AE_SET_SYMLINK;
 }
 
+void
+archive_entry_set_symlink_utf8(struct archive_entry *entry, const char *linkname)
+{
+       archive_mstring_copy_utf8(&entry->ae_symlink, linkname);
+       if (linkname != NULL)
+               entry->ae_set |= AE_SET_SYMLINK;
+       else
+               entry->ae_set &= ~AE_SET_SYMLINK;
+}
+
 void
 archive_entry_copy_symlink(struct archive_entry *entry, const char *linkname)
 {
@@ -1193,6 +1318,12 @@ archive_entry_set_uname(struct archive_entry *entry, const char *name)
        archive_mstring_copy_mbs(&entry->ae_uname, name);
 }
 
+void
+archive_entry_set_uname_utf8(struct archive_entry *entry, const char *name)
+{
+       archive_mstring_copy_utf8(&entry->ae_uname, name);
+}
+
 void
 archive_entry_copy_uname(struct archive_entry *entry, const char *name)
 {
@@ -1216,6 +1347,26 @@ archive_entry_update_uname_utf8(struct archive_entry *entry, const char *name)
        return (0);
 }
 
+void
+archive_entry_set_is_data_encrypted(struct archive_entry *entry, char is_encrypted)
+{
+       if (is_encrypted) {
+               entry->encryption |= AE_ENCRYPTION_DATA;
+       } else {
+               entry->encryption &= ~AE_ENCRYPTION_DATA;
+       }
+}
+
+void
+archive_entry_set_is_metadata_encrypted(struct archive_entry *entry, char is_encrypted)
+{
+       if (is_encrypted) {
+               entry->encryption |= AE_ENCRYPTION_METADATA;
+       } else {
+               entry->encryption &= ~AE_ENCRYPTION_METADATA;
+       }
+}
+
 int
 _archive_entry_copy_uname_l(struct archive_entry *entry,
     const char *name, size_t len, struct archive_string_conv *sc)
@@ -1588,19 +1739,23 @@ ae_strtofflags(const char *s, unsigned long *setp, unsigned long *clrp)
        while (*start == '\t'  ||  *start == ' '  ||  *start == ',')
                start++;
        while (*start != '\0') {
+               size_t length;
                /* Locate end of token. */
                end = start;
                while (*end != '\0'  &&  *end != '\t'  &&
                    *end != ' '  &&  *end != ',')
                        end++;
+               length = end - start;
                for (flag = flags; flag->name != NULL; flag++) {
-                       if (memcmp(start, flag->name, end - start) == 0) {
+                       size_t flag_length = strlen(flag->name);
+                       if (length == flag_length
+                           && memcmp(start, flag->name, length) == 0) {
                                /* Matched "noXXXX", so reverse the sense. */
                                clear |= flag->set;
                                set |= flag->clear;
                                break;
-                       } else if (memcmp(start, flag->name + 2, end - start)
-                           == 0) {
+                       } else if (length == flag_length - 2
+                           && memcmp(start, flag->name + 2, length) == 0) {
                                /* Matched "XXXX", so don't reverse. */
                                set |= flag->set;
                                clear |= flag->clear;
@@ -1652,19 +1807,23 @@ ae_wcstofflags(const wchar_t *s, unsigned long *setp, unsigned long *clrp)
        while (*start == L'\t'  ||  *start == L' '  ||  *start == L',')
                start++;
        while (*start != L'\0') {
+               size_t length;
                /* Locate end of token. */
                end = start;
                while (*end != L'\0'  &&  *end != L'\t'  &&
                    *end != L' '  &&  *end != L',')
                        end++;
+               length = end - start;
                for (flag = flags; flag->wname != NULL; flag++) {
-                       if (wmemcmp(start, flag->wname, end - start) == 0) {
+                       size_t flag_length = wcslen(flag->wname);
+                       if (length == flag_length
+                           && wmemcmp(start, flag->wname, length) == 0) {
                                /* Matched "noXXXX", so reverse the sense. */
                                clear |= flag->set;
                                set |= flag->clear;
                                break;
-                       } else if (wmemcmp(start, flag->wname + 2, end - start)
-                           == 0) {
+                       } else if (length == flag_length - 2
+                           && wmemcmp(start, flag->wname + 2, length) == 0) {
                                /* Matched "XXXX", so don't reverse. */
                                set |= flag->set;
                                clear |= flag->clear;
index a905065..423c8d3 100644 (file)
@@ -29,7 +29,7 @@
 #define        ARCHIVE_ENTRY_H_INCLUDED
 
 /* Note: Compiler will complain if this does not match archive.h! */
-#define        ARCHIVE_VERSION_NUMBER 3001002
+#define        ARCHIVE_VERSION_NUMBER 3002000
 
 /*
  * Note: archive_entry.h is for use outside of libarchive; the
 #endif
 
 /* Get a suitable 64-bit integer type. */
-#if defined(_WIN32) && !defined(__CYGWIN__)
-# define       __LA_INT64_T    __int64
-#else
-#include <unistd.h>
-# if defined(_SCO_DS)
-#  define      __LA_INT64_T    long long
+#if !defined(__LA_INT64_T_DEFINED)
+# if ARCHIVE_VERSION_NUMBER < 4000000
+#define __LA_INT64_T la_int64_t
+# endif
+#define __LA_INT64_T_DEFINED
+# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
+typedef __int64 la_int64_t;
 # else
-#  define      __LA_INT64_T    int64_t
+#include <unistd.h>
+#  if defined(_SCO_DS) || defined(__osf__)
+typedef long long la_int64_t;
+#  else
+typedef int64_t la_int64_t;
+#  endif
 # endif
 #endif
 
 #if ARCHIVE_VERSION_NUMBER >= 3999000
 /* Switch to plain 'int' for libarchive 4.0.  It's less broken than 'mode_t' */
 # define       __LA_MODE_T     int
-#elif defined(_WIN32) && !defined(__CYGWIN__) && !defined(__BORLANDC__)
+#elif defined(_WIN32) && !defined(__CYGWIN__) && !defined(__BORLANDC__) && !defined(__WATCOMC__)
 # define       __LA_MODE_T     unsigned short
 #else
 # define       __LA_MODE_T     mode_t
 #endif
 
+/* Large file support for Android */
+#ifdef __ANDROID__
+#include "android_lf.h"
+#endif
+
 /*
  * On Windows, define LIBARCHIVE_STATIC if you're building or using a
  * .lib.  The default here assumes you're building a DLL.  Only
@@ -206,13 +217,15 @@ __LA_DECL void             archive_entry_fflags(struct archive_entry *,
                            unsigned long * /* set */,
                            unsigned long * /* clear */);
 __LA_DECL const char   *archive_entry_fflags_text(struct archive_entry *);
-__LA_DECL __LA_INT64_T  archive_entry_gid(struct archive_entry *);
+__LA_DECL la_int64_t    archive_entry_gid(struct archive_entry *);
 __LA_DECL const char   *archive_entry_gname(struct archive_entry *);
+__LA_DECL const char   *archive_entry_gname_utf8(struct archive_entry *);
 __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 char   *archive_entry_hardlink_utf8(struct archive_entry *);
 __LA_DECL const wchar_t        *archive_entry_hardlink_w(struct archive_entry *);
-__LA_DECL __LA_INT64_T  archive_entry_ino(struct archive_entry *);
-__LA_DECL __LA_INT64_T  archive_entry_ino64(struct archive_entry *);
+__LA_DECL la_int64_t    archive_entry_ino(struct archive_entry *);
+__LA_DECL la_int64_t    archive_entry_ino64(struct archive_entry *);
 __LA_DECL int           archive_entry_ino_is_set(struct archive_entry *);
 __LA_DECL __LA_MODE_T   archive_entry_mode(struct archive_entry *);
 __LA_DECL time_t        archive_entry_mtime(struct archive_entry *);
@@ -220,6 +233,7 @@ __LA_DECL long               archive_entry_mtime_nsec(struct archive_entry *);
 __LA_DECL int           archive_entry_mtime_is_set(struct archive_entry *);
 __LA_DECL unsigned int  archive_entry_nlink(struct archive_entry *);
 __LA_DECL const char   *archive_entry_pathname(struct archive_entry *);
+__LA_DECL const char   *archive_entry_pathname_utf8(struct archive_entry *);
 __LA_DECL const wchar_t        *archive_entry_pathname_w(struct archive_entry *);
 __LA_DECL __LA_MODE_T   archive_entry_perm(struct archive_entry *);
 __LA_DECL dev_t                 archive_entry_rdev(struct archive_entry *);
@@ -227,14 +241,19 @@ __LA_DECL dev_t            archive_entry_rdevmajor(struct archive_entry *);
 __LA_DECL dev_t                 archive_entry_rdevminor(struct archive_entry *);
 __LA_DECL const char   *archive_entry_sourcepath(struct archive_entry *);
 __LA_DECL const wchar_t        *archive_entry_sourcepath_w(struct archive_entry *);
-__LA_DECL __LA_INT64_T  archive_entry_size(struct archive_entry *);
+__LA_DECL la_int64_t    archive_entry_size(struct archive_entry *);
 __LA_DECL int           archive_entry_size_is_set(struct archive_entry *);
 __LA_DECL const char   *archive_entry_strmode(struct archive_entry *);
 __LA_DECL const char   *archive_entry_symlink(struct archive_entry *);
+__LA_DECL const char   *archive_entry_symlink_utf8(struct archive_entry *);
 __LA_DECL const wchar_t        *archive_entry_symlink_w(struct archive_entry *);
-__LA_DECL __LA_INT64_T  archive_entry_uid(struct archive_entry *);
+__LA_DECL la_int64_t    archive_entry_uid(struct archive_entry *);
 __LA_DECL const char   *archive_entry_uname(struct archive_entry *);
+__LA_DECL const char   *archive_entry_uname_utf8(struct archive_entry *);
 __LA_DECL const wchar_t        *archive_entry_uname_w(struct archive_entry *);
+__LA_DECL int archive_entry_is_data_encrypted(struct archive_entry *);
+__LA_DECL int archive_entry_is_metadata_encrypted(struct archive_entry *);
+__LA_DECL int archive_entry_is_encrypted(struct archive_entry *);
 
 /*
  * Set fields in an archive_entry.
@@ -266,18 +285,21 @@ __LA_DECL const char *archive_entry_copy_fflags_text(struct archive_entry *,
            const char *);
 __LA_DECL const wchar_t *archive_entry_copy_fflags_text_w(struct archive_entry *,
            const wchar_t *);
-__LA_DECL void archive_entry_set_gid(struct archive_entry *, __LA_INT64_T);
+__LA_DECL void archive_entry_set_gid(struct archive_entry *, la_int64_t);
 __LA_DECL void archive_entry_set_gname(struct archive_entry *, const char *);
+__LA_DECL void archive_entry_set_gname_utf8(struct archive_entry *, const char *);
 __LA_DECL void archive_entry_copy_gname(struct archive_entry *, const char *);
 __LA_DECL void archive_entry_copy_gname_w(struct archive_entry *, const wchar_t *);
 __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_set_hardlink_utf8(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 *);
-__LA_DECL void archive_entry_set_ino(struct archive_entry *, __LA_INT64_T);
-__LA_DECL void archive_entry_set_ino64(struct archive_entry *, __LA_INT64_T);
+__LA_DECL void archive_entry_set_ino(struct archive_entry *, la_int64_t);
+__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_set_link_utf8(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 *);
 __LA_DECL int  archive_entry_update_link_utf8(struct archive_entry *, const char *);
@@ -286,6 +308,7 @@ __LA_DECL void      archive_entry_set_mtime(struct archive_entry *, time_t, long);
 __LA_DECL void  archive_entry_unset_mtime(struct archive_entry *);
 __LA_DECL void archive_entry_set_nlink(struct archive_entry *, unsigned int);
 __LA_DECL void archive_entry_set_pathname(struct archive_entry *, const char *);
+__LA_DECL void archive_entry_set_pathname_utf8(struct archive_entry *, const char *);
 __LA_DECL void archive_entry_copy_pathname(struct archive_entry *, const char *);
 __LA_DECL void archive_entry_copy_pathname_w(struct archive_entry *, const wchar_t *);
 __LA_DECL int  archive_entry_update_pathname_utf8(struct archive_entry *, const char *);
@@ -293,19 +316,23 @@ __LA_DECL void    archive_entry_set_perm(struct archive_entry *, __LA_MODE_T);
 __LA_DECL void archive_entry_set_rdev(struct archive_entry *, dev_t);
 __LA_DECL void archive_entry_set_rdevmajor(struct archive_entry *, dev_t);
 __LA_DECL void archive_entry_set_rdevminor(struct archive_entry *, dev_t);
-__LA_DECL void archive_entry_set_size(struct archive_entry *, __LA_INT64_T);
+__LA_DECL void archive_entry_set_size(struct archive_entry *, la_int64_t);
 __LA_DECL void archive_entry_unset_size(struct archive_entry *);
 __LA_DECL void archive_entry_copy_sourcepath(struct archive_entry *, const char *);
 __LA_DECL void archive_entry_copy_sourcepath_w(struct archive_entry *, const wchar_t *);
 __LA_DECL void archive_entry_set_symlink(struct archive_entry *, const char *);
+__LA_DECL void archive_entry_set_symlink_utf8(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_INT64_T);
+__LA_DECL void archive_entry_set_uid(struct archive_entry *, la_int64_t);
 __LA_DECL void archive_entry_set_uname(struct archive_entry *, const char *);
+__LA_DECL void archive_entry_set_uname_utf8(struct archive_entry *, const char *);
 __LA_DECL void archive_entry_copy_uname(struct archive_entry *, const char *);
 __LA_DECL void archive_entry_copy_uname_w(struct archive_entry *, const wchar_t *);
 __LA_DECL int  archive_entry_update_uname_utf8(struct archive_entry *, const char *);
+__LA_DECL void archive_entry_set_is_data_encrypted(struct archive_entry *, char is_encrypted);
+__LA_DECL void archive_entry_set_is_metadata_encrypted(struct archive_entry *, char is_encrypted);
 /*
  * Routines to bulk copy fields to/from a platform-native "struct
  * stat."  Libarchive used to just store a struct stat inside of each
@@ -514,7 +541,7 @@ __LA_DECL int       archive_entry_xattr_next(struct archive_entry *,
 
 __LA_DECL void  archive_entry_sparse_clear(struct archive_entry *);
 __LA_DECL void  archive_entry_sparse_add_entry(struct archive_entry *,
-           __LA_INT64_T /* offset */, __LA_INT64_T /* length */);
+           la_int64_t /* offset */, la_int64_t /* length */);
 
 /*
  * To retrieve the xattr list, first "reset", then repeatedly ask for the
@@ -524,7 +551,7 @@ __LA_DECL void       archive_entry_sparse_add_entry(struct archive_entry *,
 __LA_DECL int  archive_entry_sparse_count(struct archive_entry *);
 __LA_DECL int  archive_entry_sparse_reset(struct archive_entry *);
 __LA_DECL int  archive_entry_sparse_next(struct archive_entry *,
-           __LA_INT64_T * /* offset */, __LA_INT64_T * /* length */);
+           la_int64_t * /* offset */, la_int64_t * /* length */);
 
 /*
  * Utility to match up hardlinks.
index f5c3377..5aff996 100644 (file)
@@ -226,8 +226,8 @@ The returned long string is valid until the next call to
 or
 .Fn archive_entry_acl_text_w .
 .Sh SEE ALSO
-.Xr archive 3 ,
 .Xr archive_entry 3
+.Xr libarchive 3 ,
 .Sh BUGS
 .Dv ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID
 and
index 37d4d6e..ac83868 100644 (file)
@@ -44,6 +44,10 @@ archive_entry_copy_stat(struct archive_entry *entry, const struct stat *st)
        archive_entry_set_atime(entry, st->st_atime, st->st_atim.tv_nsec);
        archive_entry_set_ctime(entry, st->st_ctime, st->st_ctim.tv_nsec);
        archive_entry_set_mtime(entry, st->st_mtime, st->st_mtim.tv_nsec);
+#elif HAVE_STRUCT_STAT_ST_MTIME_NSEC
+       archive_entry_set_atime(entry, st->st_atime, st->st_atime_nsec);
+       archive_entry_set_ctime(entry, st->st_ctime, st->st_ctime_nsec);
+       archive_entry_set_mtime(entry, st->st_mtime, st->st_mtime_nsec);
 #elif HAVE_STRUCT_STAT_ST_MTIME_N
        archive_entry_set_atime(entry, st->st_atime, st->st_atime_n);
        archive_entry_set_ctime(entry, st->st_ctime, st->st_ctime_n);
index 51c8b8c..fd22cf7 100644 (file)
@@ -149,5 +149,5 @@ It doesn't have a corresponding get accessor function.
 is an alias for 
 .Fn archive_entry_copy_XXX .
 .Sh SEE ALSO
-.Xr archive 3 ,
 .Xr archive_entry 3
+.Xr libarchive 3 ,
index 5b7b5d9..340c5ea 100644 (file)
@@ -194,11 +194,11 @@ every name that is recognized.
 .Xr strtofflags 3 ,
 which stops parsing at the first unrecognized name.)
 .Sh SEE ALSO
-.Xr archive 3 ,
 .Xr archive_entry 3 ,
 .Xr archive_entry_acl 3 ,
 .Xr archive_read_disk 3 ,
 .Xr archive_write_disk 3
+.Xr libarchive 3 ,
 .Sh BUGS
 The platform types
 .Vt uid_t
index e3547c3..c69233e 100644 (file)
@@ -154,6 +154,11 @@ struct archive_entry {
        /* Not used within libarchive; useful for some clients. */
        struct archive_mstring ae_sourcepath;   /* Path this entry is sourced from. */
 
+#define AE_ENCRYPTION_NONE 0
+#define AE_ENCRYPTION_DATA 1
+#define AE_ENCRYPTION_METADATA 2
+       char encryption;
+       
        void *mac_metadata;
        size_t mac_metadata_size;
 
index 10c5447..fed74f5 100644 (file)
@@ -58,7 +58,7 @@ archive_entry_sparse_add_entry(struct archive_entry *entry,
        if (offset < 0 || length < 0)
                /* Invalid value */
                return;
-       if (offset + length < 0 ||
+       if (offset > INT64_MAX - length ||
            offset + length > archive_entry_size(entry))
                /* A value of "length" parameter is too large. */
                return;
index 84a4ea1..26611e4 100644 (file)
@@ -226,7 +226,7 @@ and
 are used by
 .Xr archive_entry_linkify 3
 to find hardlinks.
-The pair of device and inode is suppossed to identify hardlinked files.
+The pair of device and inode is supposed to identify hardlinked files.
 .Pp
 The device major and minor number can be obtained independently using
 .Fn archive_entry_devmajor
@@ -267,8 +267,8 @@ platforms.
 Some archive formats use the combined form, while other formats use
 the split form.
 .Sh SEE ALSO
-.Xr archive 3 ,
 .Xr archive_entry_acl 3 ,
 .Xr archive_entry_perms 3 ,
 .Xr archive_entry_time 3 ,
+.Xr libarchive 3 ,
 .Xr stat 2
index 17c658a..1864521 100644 (file)
@@ -113,8 +113,8 @@ The current state can be queried using
 .Fn XXX_is_set .
 Unset time fields have a second and nanosecond field of 0.
 .Sh SEE ALSO
-.Xr archive 3 ,
 .Xr archive_entry 3
+.Xr libarchive 3 ,
 .Sh HISTORY
 The
 .Nm libarchive
index a3efe7c..05eb90f 100644 (file)
@@ -98,7 +98,10 @@ archive_entry_xattr_add_entry(struct archive_entry *entry,
                /* XXX Error XXX */
                return;
 
-       xp->name = strdup(name);
+       if ((xp->name = strdup(name)) == NULL)
+               /* XXX Error XXX */
+               return;
+
        if ((xp->value = malloc(size)) != NULL) {
                memcpy(xp->value, value, size);
                xp->size = size;
index f8b5a28..beb0cba 100644 (file)
@@ -38,8 +38,8 @@ __FBSDID("$FreeBSD$");
 #include <string.h>
 #include <time.h>
 
-/* This file defines a single public function. */
-time_t __archive_get_date(time_t now, char *);
+#define __LIBARCHIVE_BUILD 1
+#include "archive_getdate.h"
 
 /* Basic time units. */
 #define        EPOCH           1970
@@ -369,8 +369,8 @@ relunitphrase(struct gdstate *gds)
            && gds->tokenp[1].token == tSEC_UNIT) {
                /* "1 day" */
                gds->HaveRel++;
-               gds->RelSeconds += gds->tokenp[1].value * gds->tokenp[2].value;
-               gds->tokenp += 3;
+               gds->RelSeconds += gds->tokenp[0].value * gds->tokenp[1].value;
+               gds->tokenp += 2;
                return 1;
        }
        if (gds->tokenp[0].token == '-'
@@ -403,7 +403,7 @@ relunitphrase(struct gdstate *gds)
                /* "now", "tomorrow" */
                gds->HaveRel++;
                gds->RelSeconds += gds->tokenp[0].value;
-               ++gds->tokenp;
+               gds->tokenp += 1;
                return 1;
        }
        if (gds->tokenp[0].token == tMONTH_UNIT) {
@@ -782,7 +782,7 @@ RelativeMonth(time_t Start, time_t Timezone, time_t RelMonth)
  * Tokenizer.
  */
 static int
-nexttoken(char **in, time_t *value)
+nexttoken(const char **in, time_t *value)
 {
        char    c;
        char    buff[64];
@@ -809,7 +809,7 @@ nexttoken(char **in, time_t *value)
                /* Try the next token in the word table first. */
                /* This allows us to match "2nd", for example. */
                {
-                       char *src = *in;
+                       const char *src = *in;
                        const struct LEXICON *tp;
                        unsigned i = 0;
 
@@ -894,7 +894,7 @@ difftm (struct tm *a, struct tm *b)
  * TODO: tokens[] array should be dynamically sized.
  */
 time_t
-__archive_get_date(time_t now, char *p)
+__archive_get_date(time_t now, const char *p)
 {
        struct token    tokens[256];
        struct gdstate  _gds;
@@ -1022,10 +1022,11 @@ int
 main(int argc, char **argv)
 {
     time_t     d;
+    time_t     now = time(NULL);
 
     while (*++argv != NULL) {
            (void)printf("Input: %s\n", *argv);
-           d = get_date(*argv);
+           d = get_date(now, *argv);
            if (d == -1)
                    (void)printf("Bad format - couldn't convert.\n");
            else
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2009 Joerg Sonnenberger
+ * Copyright (c) 2003-2015 Tim Kientzle
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * 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$
  */
 
-#ifndef LAFE_ERR_H
-#define LAFE_ERR_H
-
-#if defined(__GNUC__) && (__GNUC__ > 2 || \
-                          (__GNUC__ == 2 && __GNUC_MINOR__ >= 5))
-#define __LA_DEAD       __attribute__((__noreturn__))
-#else
-#define __LA_DEAD
+#ifndef __LIBARCHIVE_BUILD
+#error This header is only to be used internally to libarchive.
 #endif
 
-#if defined(__GNUC__) && (__GNUC__ > 2 || \
-                         (__GNUC__ == 2 && __GNUC_MINOR__ >= 7))
-#define        __LA_PRINTFLIKE(f,a)    __attribute__((__format__(__printf__, f, a)))
-#else
-#define        __LA_PRINTFLIKE(f,a)
-#endif
+#ifndef ARCHIVE_GETDATE_H_INCLUDED
+#define        ARCHIVE_GETDATE_H_INCLUDED
 
-extern const char *lafe_progname;
+#include <time.h>
 
-void   lafe_warnc(int code, const char *fmt, ...) __LA_PRINTFLIKE(2, 3);
-void   lafe_errc(int eval, int code, const char *fmt, ...) __LA_DEAD
-                 __LA_PRINTFLIKE(3, 4);
+time_t __archive_get_date(time_t now, const char *);
 
 #endif
diff --git a/contrib/libarchive/libarchive/archive_hmac.c b/contrib/libarchive/libarchive/archive_hmac.c
new file mode 100644 (file)
index 0000000..7857c0f
--- /dev/null
@@ -0,0 +1,248 @@
+/*-
+* Copyright (c) 2014 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_STRING_H
+#include <string.h>
+#endif
+#include "archive.h"
+#include "archive_hmac_private.h"
+
+/*
+ * On systems that do not support any recognized crypto libraries,
+ * the archive_hmac.c file is expected to define no usable symbols.
+ *
+ * But some compilers and linkers choke on empty object files, so
+ * define a public symbol that will always exist.  This could
+ * be removed someday if this file gains another always-present
+ * symbol definition.
+ */
+int __libarchive_hmac_build_hack(void) {
+       return 0;
+}
+
+
+#ifdef ARCHIVE_HMAC_USE_Apple_CommonCrypto
+
+static int
+__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
+{
+       CCHmacInit(ctx, kCCHmacAlgSHA1, key, key_len);
+       return 0;
+}
+
+static void
+__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data,
+    size_t data_len)
+{
+       CCHmacUpdate(ctx, data, data_len);
+}
+
+static void
+__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len)
+{
+       CCHmacFinal(ctx, out);
+       *out_len = 20;
+}
+
+static void
+__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
+{
+       memset(ctx, 0, sizeof(*ctx));
+}
+
+#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
+
+static int
+__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
+{
+       BCRYPT_ALG_HANDLE hAlg;
+       BCRYPT_HASH_HANDLE hHash;
+       DWORD hash_len;
+       PBYTE hash;
+       ULONG result;
+       NTSTATUS status;
+
+       ctx->hAlg = NULL;
+       status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA1_ALGORITHM,
+               MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG);
+       if (!BCRYPT_SUCCESS(status))
+               return -1;
+       status = BCryptGetProperty(hAlg, BCRYPT_HASH_LENGTH, (PUCHAR)&hash_len,
+               sizeof(hash_len), &result, 0);
+       if (!BCRYPT_SUCCESS(status)) {
+               BCryptCloseAlgorithmProvider(hAlg, 0);
+               return -1;
+       }
+       hash = (PBYTE)HeapAlloc(GetProcessHeap(), 0, hash_len);
+       if (hash == NULL) {
+               BCryptCloseAlgorithmProvider(hAlg, 0);
+               return -1;
+       }
+       status = BCryptCreateHash(hAlg, &hHash, NULL, 0,
+               (PUCHAR)key, (ULONG)key_len, BCRYPT_HASH_REUSABLE_FLAG);
+       if (!BCRYPT_SUCCESS(status)) {
+               BCryptCloseAlgorithmProvider(hAlg, 0);
+               HeapFree(GetProcessHeap(), 0, hash);
+               return -1;
+       }
+
+       ctx->hAlg = hAlg;
+       ctx->hHash = hHash;
+       ctx->hash_len = hash_len;
+       ctx->hash = hash;
+
+       return 0;
+}
+
+static void
+__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data,
+       size_t data_len)
+{
+       BCryptHashData(ctx->hHash, (PUCHAR)(uintptr_t)data, (ULONG)data_len, 0);
+}
+
+static void
+__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len)
+{
+       BCryptFinishHash(ctx->hHash, ctx->hash, ctx->hash_len, 0);
+       if (ctx->hash_len == *out_len)
+               memcpy(out, ctx->hash, *out_len);
+}
+
+static void
+__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
+{
+       if (ctx->hAlg != NULL) {
+               BCryptCloseAlgorithmProvider(ctx->hAlg, 0);
+               HeapFree(GetProcessHeap(), 0, ctx->hash);
+               ctx->hAlg = NULL;
+       }
+}
+
+#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_HMAC_H)
+
+static int
+__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
+{
+       hmac_sha1_set_key(ctx, key_len, key);
+       return 0;
+}
+
+static void
+__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data,
+    size_t data_len)
+{
+       hmac_sha1_update(ctx, data_len, data);
+}
+
+static void
+__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len)
+{
+       hmac_sha1_digest(ctx, (unsigned)*out_len, out);
+}
+
+static void
+__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
+{
+       memset(ctx, 0, sizeof(*ctx));
+}
+
+#elif defined(HAVE_LIBCRYPTO)
+
+static int
+__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
+{
+       HMAC_CTX_init(ctx);
+       HMAC_Init(ctx, key, key_len, EVP_sha1());
+       return 0;
+}
+
+static void
+__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data,
+    size_t data_len)
+{
+       HMAC_Update(ctx, data, data_len);
+}
+
+static void
+__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len)
+{
+       unsigned int len = (unsigned int)*out_len;
+       HMAC_Final(ctx, out, &len);
+       *out_len = len;
+}
+
+static void
+__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
+{
+       HMAC_CTX_cleanup(ctx);
+       memset(ctx, 0, sizeof(*ctx));
+}
+
+#else
+
+/* Stub */
+static int
+__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
+{
+       (void)ctx;/* UNUSED */
+       (void)key;/* UNUSED */
+       (void)key_len;/* UNUSED */
+       return -1;
+}
+
+static void
+__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data,
+    size_t data_len)
+{
+       (void)ctx;/* UNUSED */
+       (void)data;/* UNUSED */
+       (void)data_len;/* UNUSED */
+}
+
+static void
+__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len)
+{
+       (void)ctx;/* UNUSED */
+       (void)out;/* UNUSED */
+       (void)out_len;/* UNUSED */
+}
+
+static void
+__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
+{
+       (void)ctx;/* UNUSED */
+}
+
+#endif
+
+const struct archive_hmac __archive_hmac = {
+       &__hmac_sha1_init,
+       &__hmac_sha1_update,
+       &__hmac_sha1_final,
+       &__hmac_sha1_cleanup,
+};
diff --git a/contrib/libarchive/libarchive/archive_hmac_private.h b/contrib/libarchive/libarchive/archive_hmac_private.h
new file mode 100644 (file)
index 0000000..64de743
--- /dev/null
@@ -0,0 +1,106 @@
+/*-
+* Copyright (c) 2014 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.
+*/
+
+#ifndef __LIBARCHIVE_BUILD
+#error This header is only to be used internally to libarchive.
+#endif
+
+#ifndef ARCHIVE_HMAC_PRIVATE_H_INCLUDED
+#define ARCHIVE_HMAC_PRIVATE_H_INCLUDED
+
+/*
+ * On systems that do not support any recognized crypto libraries,
+ * the archive_hmac.c file is expected to define no usable symbols.
+ *
+ * But some compilers and linkers choke on empty object files, so
+ * define a public symbol that will always exist.  This could
+ * be removed someday if this file gains another always-present
+ * symbol definition.
+ */
+int __libarchive_hmac_build_hack(void);
+
+#ifdef __APPLE__
+# include <AvailabilityMacros.h>
+# if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
+#  define ARCHIVE_HMAC_USE_Apple_CommonCrypto
+# endif
+#endif
+
+#ifdef ARCHIVE_HMAC_USE_Apple_CommonCrypto
+#include <CommonCrypto/CommonHMAC.h>
+
+typedef        CCHmacContext archive_hmac_sha1_ctx;
+
+#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
+#include <bcrypt.h>
+
+typedef struct {
+       BCRYPT_ALG_HANDLE       hAlg;
+       BCRYPT_HASH_HANDLE      hHash;
+       DWORD                           hash_len;
+       PBYTE                           hash;
+
+} archive_hmac_sha1_ctx;
+
+#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_HMAC_H)
+#include <nettle/hmac.h>
+
+typedef        struct hmac_sha1_ctx archive_hmac_sha1_ctx;
+
+#elif defined(HAVE_LIBCRYPTO)
+#include <openssl/hmac.h>
+
+typedef        HMAC_CTX archive_hmac_sha1_ctx;
+
+#else
+
+typedef int archive_hmac_sha1_ctx;
+
+#endif
+
+
+/* HMAC */
+#define archive_hmac_sha1_init(ctx, key, key_len)\
+       __archive_hmac.__hmac_sha1_init(ctx, key, key_len)
+#define archive_hmac_sha1_update(ctx, data, data_len)\
+       __archive_hmac.__hmac_sha1_update(ctx, data, data_len)
+#define archive_hmac_sha1_final(ctx, out, out_len)\
+       __archive_hmac.__hmac_sha1_final(ctx, out, out_len)
+#define archive_hmac_sha1_cleanup(ctx)\
+       __archive_hmac.__hmac_sha1_cleanup(ctx)
+
+
+struct archive_hmac {
+       /* HMAC */
+       int (*__hmac_sha1_init)(archive_hmac_sha1_ctx *, const uint8_t *,
+               size_t);
+       void (*__hmac_sha1_update)(archive_hmac_sha1_ctx *, const uint8_t *,
+               size_t);
+       void (*__hmac_sha1_final)(archive_hmac_sha1_ctx *, uint8_t *, size_t *);
+       void (*__hmac_sha1_cleanup)(archive_hmac_sha1_ctx *);
+};
+
+extern const struct archive_hmac __archive_hmac;
+#endif /* ARCHIVE_HMAC_PRIVATE_H_INCLUDED */
index 6b6be9c..4c41bad 100644 (file)
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
 #include "archive.h"
 #include "archive_private.h"
 #include "archive_entry.h"
+#include "archive_getdate.h"
 #include "archive_pathmatch.h"
 #include "archive_rb.h"
 #include "archive_string.h"
@@ -184,7 +185,6 @@ static int  time_excluded(struct archive_match *,
                    struct archive_entry *);
 static int     validate_time_flag(struct archive *, int, const char *);
 
-time_t __archive_get_date(time_t now, const char *);
 #define get_date __archive_get_date
 
 static const struct archive_rb_tree_ops rb_ops_mbs = {
@@ -580,6 +580,7 @@ add_pattern_from_file(struct archive_match *a, struct match_list *mlist,
                return (ARCHIVE_FATAL);
        }
        r = archive_read_support_format_raw(ar);
+       r = archive_read_support_format_empty(ar);
        if (r != ARCHIVE_OK) {
                archive_copy_error(&(a->archive), ar);
                archive_read_free(ar);
@@ -596,9 +597,13 @@ add_pattern_from_file(struct archive_match *a, struct match_list *mlist,
        }
        r = archive_read_next_header(ar, &ae);
        if (r != ARCHIVE_OK) {
-               archive_copy_error(&(a->archive), ar);
                archive_read_free(ar);
-               return (r);
+               if (r == ARCHIVE_EOF) {
+                       return (ARCHIVE_OK);
+               } else {
+                       archive_copy_error(&(a->archive), ar);
+                       return (r);
+               }
        }
 
        archive_string_init(&as);
@@ -1152,7 +1157,7 @@ set_timefilter_pathname_mbs(struct archive_match *a, int timetype,
 {
        /* NOTE: stat() on Windows cannot handle nano seconds. */
        HANDLE h;
-       WIN32_FIND_DATA d;
+       WIN32_FIND_DATAA d;
 
        if (path == NULL || *path == '\0') {
                archive_set_error(&(a->archive), EINVAL, "pathname is empty");
index 8af6239..dbf3e80 100644 (file)
@@ -42,9 +42,9 @@ _archive_set_option(struct archive *a,
 
        archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn);
 
-       mp = m != NULL && m[0] == '\0' ? NULL : m;
-       op = o != NULL && o[0] == '\0' ? NULL : o;
-       vp = v != NULL && v[0] == '\0' ? NULL : v;
+       mp = (m != NULL && m[0] != '\0') ? m : NULL;
+       op = (o != NULL && o[0] != '\0') ? o : NULL;
+       vp = (v != NULL && v[0] != '\0') ? v : NULL;
 
        if (op == NULL && vp == NULL)
                return (ARCHIVE_OK);
diff --git a/contrib/libarchive/libarchive/archive_pack_dev.c b/contrib/libarchive/libarchive/archive_pack_dev.c
new file mode 100644 (file)
index 0000000..6b7b472
--- /dev/null
@@ -0,0 +1,329 @@
+/*     $NetBSD: pack_dev.c,v 1.12 2013/06/14 16:28:20 tsutsui Exp $    */
+
+/*-
+ * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * 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.
+ */
+
+/* Originally from NetBSD's mknod(8) source. */
+
+#include "archive_platform.h"
+
+#if HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#if !defined(lint)
+__RCSID("$NetBSD$");
+#endif /* not lint */
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "archive_pack_dev.h"
+
+static pack_t  pack_netbsd;
+static pack_t  pack_freebsd;
+static pack_t  pack_8_8;
+static pack_t  pack_12_20;
+static pack_t  pack_14_18;
+static pack_t  pack_8_24;
+static pack_t  pack_bsdos;
+static int     compare_format(const void *, const void *);
+
+static const char iMajorError[] = "invalid major number";
+static const char iMinorError[] = "invalid minor number";
+static const char tooManyFields[] = "too many fields for format";
+
+/* This is blatantly stolen from libarchive/archive_entry.c,
+ * in an attempt to get this to play nice on MinGW... */
+#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> */
+#include <sys/netmgr.h>
+#define apd_makedev(maj, min) makedev(ND_LOCAL_NODE, (maj), (min))
+#elif defined makedev
+/* There's a "makedev" macro. */
+#define apd_makedev(maj, min) makedev((maj), (min))
+#elif defined mkdev || ((defined _WIN32 || defined __WIN32__) && !defined(__CYGWIN__))
+/* Windows. <sigh> */
+#define apd_makedev(maj, min) mkdev((maj), (min))
+#else
+/* There's a "makedev" function. */
+#define apd_makedev(maj, min) makedev((maj), (min))
+#endif
+
+/* exported */
+dev_t
+pack_native(int n, unsigned long numbers[], const char **error)
+{
+       dev_t dev = 0;
+
+       if (n == 2) {
+               dev = apd_makedev(numbers[0], numbers[1]);
+               if ((unsigned long)major(dev) != numbers[0])
+                       *error = iMajorError;
+               else if ((unsigned long)minor(dev) != numbers[1])
+                       *error = iMinorError;
+       } else
+               *error = tooManyFields;
+       return (dev);
+}
+
+
+static dev_t
+pack_netbsd(int n, unsigned long numbers[], const char **error)
+{
+       dev_t dev = 0;
+
+       if (n == 2) {
+               dev = makedev_netbsd(numbers[0], numbers[1]);
+               if ((unsigned long)major_netbsd(dev) != numbers[0])
+                       *error = iMajorError;
+               else if ((unsigned long)minor_netbsd(dev) != numbers[1])
+                       *error = iMinorError;
+       } else
+               *error = tooManyFields;
+       return (dev);
+}
+
+
+#define        major_freebsd(x)        ((int32_t)(((x) & 0x0000ff00) >> 8))
+#define        minor_freebsd(x)        ((int32_t)(((x) & 0xffff00ff) >> 0))
+#define        makedev_freebsd(x,y)    ((dev_t)((((x) << 8) & 0x0000ff00) | \
+                                        (((y) << 0) & 0xffff00ff)))
+
+static dev_t
+pack_freebsd(int n, unsigned long numbers[], const char **error)
+{
+       dev_t dev = 0;
+
+       if (n == 2) {
+               dev = makedev_freebsd(numbers[0], numbers[1]);
+               if ((unsigned long)major_freebsd(dev) != numbers[0])
+                       *error = iMajorError;
+               if ((unsigned long)minor_freebsd(dev) != numbers[1])
+                       *error = iMinorError;
+       } else
+               *error = tooManyFields;
+       return (dev);
+}
+
+
+#define        major_8_8(x)            ((int32_t)(((x) & 0x0000ff00) >> 8))
+#define        minor_8_8(x)            ((int32_t)(((x) & 0x000000ff) >> 0))
+#define        makedev_8_8(x,y)        ((dev_t)((((x) << 8) & 0x0000ff00) | \
+                                        (((y) << 0) & 0x000000ff)))
+
+static dev_t
+pack_8_8(int n, unsigned long numbers[], const char **error)
+{
+       dev_t dev = 0;
+
+       if (n == 2) {
+               dev = makedev_8_8(numbers[0], numbers[1]);
+               if ((unsigned long)major_8_8(dev) != numbers[0])
+                       *error = iMajorError;
+               if ((unsigned long)minor_8_8(dev) != numbers[1])
+                       *error = iMinorError;
+       } else
+               *error = tooManyFields;
+       return (dev);
+}
+
+
+#define        major_12_20(x)          ((int32_t)(((x) & 0xfff00000) >> 20))
+#define        minor_12_20(x)          ((int32_t)(((x) & 0x000fffff) >>  0))
+#define        makedev_12_20(x,y)      ((dev_t)((((x) << 20) & 0xfff00000) | \
+                                        (((y) <<  0) & 0x000fffff)))
+
+static dev_t
+pack_12_20(int n, unsigned long numbers[], const char **error)
+{
+       dev_t dev = 0;
+
+       if (n == 2) {
+               dev = makedev_12_20(numbers[0], numbers[1]);
+               if ((unsigned long)major_12_20(dev) != numbers[0])
+                       *error = iMajorError;
+               if ((unsigned long)minor_12_20(dev) != numbers[1])
+                       *error = iMinorError;
+       } else
+               *error = tooManyFields;
+       return (dev);
+}
+
+
+#define        major_14_18(x)          ((int32_t)(((x) & 0xfffc0000) >> 18))
+#define        minor_14_18(x)          ((int32_t)(((x) & 0x0003ffff) >>  0))
+#define        makedev_14_18(x,y)      ((dev_t)((((x) << 18) & 0xfffc0000) | \
+                                        (((y) <<  0) & 0x0003ffff)))
+
+static dev_t
+pack_14_18(int n, unsigned long numbers[], const char **error)
+{
+       dev_t dev = 0;
+
+       if (n == 2) {
+               dev = makedev_14_18(numbers[0], numbers[1]);
+               if ((unsigned long)major_14_18(dev) != numbers[0])
+                       *error = iMajorError;
+               if ((unsigned long)minor_14_18(dev) != numbers[1])
+                       *error = iMinorError;
+       } else
+               *error = tooManyFields;
+       return (dev);
+}
+
+
+#define        major_8_24(x)           ((int32_t)(((x) & 0xff000000) >> 24))
+#define        minor_8_24(x)           ((int32_t)(((x) & 0x00ffffff) >>  0))
+#define        makedev_8_24(x,y)       ((dev_t)((((x) << 24) & 0xff000000) | \
+                                        (((y) <<  0) & 0x00ffffff)))
+
+static dev_t
+pack_8_24(int n, unsigned long numbers[], const char **error)
+{
+       dev_t dev = 0;
+
+       if (n == 2) {
+               dev = makedev_8_24(numbers[0], numbers[1]);
+               if ((unsigned long)major_8_24(dev) != numbers[0])
+                       *error = iMajorError;
+               if ((unsigned long)minor_8_24(dev) != numbers[1])
+                       *error = iMinorError;
+       } else
+               *error = tooManyFields;
+       return (dev);
+}
+
+
+#define        major_12_12_8(x)        ((int32_t)(((x) & 0xfff00000) >> 20))
+#define        unit_12_12_8(x)         ((int32_t)(((x) & 0x000fff00) >>  8))
+#define        subunit_12_12_8(x)      ((int32_t)(((x) & 0x000000ff) >>  0))
+#define        makedev_12_12_8(x,y,z)  ((dev_t)((((x) << 20) & 0xfff00000) | \
+                                        (((y) <<  8) & 0x000fff00) | \
+                                        (((z) <<  0) & 0x000000ff)))
+
+static dev_t
+pack_bsdos(int n, unsigned long numbers[], const char **error)
+{
+       dev_t dev = 0;
+
+       if (n == 2) {
+               dev = makedev_12_20(numbers[0], numbers[1]);
+               if ((unsigned long)major_12_20(dev) != numbers[0])
+                       *error = iMajorError;
+               if ((unsigned long)minor_12_20(dev) != numbers[1])
+                       *error = iMinorError;
+       } else if (n == 3) {
+               dev = makedev_12_12_8(numbers[0], numbers[1], numbers[2]);
+               if ((unsigned long)major_12_12_8(dev) != numbers[0])
+                       *error = iMajorError;
+               if ((unsigned long)unit_12_12_8(dev) != numbers[1])
+                       *error = "invalid unit number";
+               if ((unsigned long)subunit_12_12_8(dev) != numbers[2])
+                       *error = "invalid subunit number";
+       } else
+               *error = tooManyFields;
+       return (dev);
+}
+
+
+               /* list of formats and pack functions */
+               /* this list must be sorted lexically */
+static struct format {
+       const char      *name;
+       pack_t          *pack;
+} formats[] = {
+       {"386bsd",  pack_8_8},
+       {"4bsd",    pack_8_8},
+       {"bsdos",   pack_bsdos},
+       {"freebsd", pack_freebsd},
+       {"hpux",    pack_8_24},
+       {"isc",     pack_8_8},
+       {"linux",   pack_8_8},
+       {"native",  pack_native},
+       {"netbsd",  pack_netbsd},
+       {"osf1",    pack_12_20},
+       {"sco",     pack_8_8},
+       {"solaris", pack_14_18},
+       {"sunos",   pack_8_8},
+       {"svr3",    pack_8_8},
+       {"svr4",    pack_14_18},
+       {"ultrix",  pack_8_8},
+};
+
+static int
+compare_format(const void *key, const void *element)
+{
+       const char              *name;
+       const struct format     *format;
+
+       name = key;
+       format = element;
+
+       return (strcmp(name, format->name));
+}
+
+
+pack_t *
+pack_find(const char *name)
+{
+       struct format   *format;
+
+       format = bsearch(name, formats,
+           sizeof(formats)/sizeof(formats[0]),
+           sizeof(formats[0]), compare_format);
+       if (format == 0)
+               return (NULL);
+       return (format->pack);
+}
diff --git a/contrib/libarchive/libarchive/archive_pack_dev.h b/contrib/libarchive/libarchive/archive_pack_dev.h
new file mode 100644 (file)
index 0000000..749fd3d
--- /dev/null
@@ -0,0 +1,49 @@
+/*     $NetBSD: pack_dev.h,v 1.8 2013/06/14 16:28:20 tsutsui Exp $     */
+
+/*-
+ * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * 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.
+ */
+
+/* Originally from NetBSD's mknod(8) source. */
+
+#ifndef        _PACK_DEV_H
+#define        _PACK_DEV_H
+
+typedef        dev_t pack_t(int, unsigned long [], const char **);
+
+pack_t *pack_find(const char *);
+pack_t  pack_native;
+
+#define        major_netbsd(x)         ((int32_t)((((x) & 0x000fff00) >>  8)))
+#define        minor_netbsd(x)         ((int32_t)((((x) & 0xfff00000) >> 12) | \
+                                          (((x) & 0x000000ff) >>  0)))
+#define        makedev_netbsd(x,y)     ((dev_t)((((x) <<  8) & 0x000fff00) | \
+                                        (((y) << 12) & 0xfff00000) | \
+                                        (((y) <<  0) & 0x000000ff)))
+
+#endif /* _PACK_DEV_H */
index 505252a..619e2b6 100644 (file)
@@ -394,8 +394,8 @@ __archive_pathmatch(const char *p, const char *s, int flags)
        if (*p == '/' && *s != '/')
                return (0);
 
-       /* Certain patterns and file names anchor implicitly. */
-       if (*p == '*' || *p == '/' || *p == '/') {
+       /* Certain patterns anchor implicitly. */
+       if (*p == '*' || *p == '/') {
                while (*p == '/')
                        ++p;
                while (*s == '/')
@@ -434,8 +434,8 @@ __archive_pathmatch_w(const wchar_t *p, const wchar_t *s, int flags)
        if (*p == L'/' && *s != L'/')
                return (0);
 
-       /* Certain patterns and file names anchor implicitly. */
-       if (*p == L'*' || *p == L'/' || *p == L'/') {
+       /* Certain patterns anchor implicitly. */
+       if (*p == L'*' || *p == L'/') {
                while (*p == L'/')
                        ++p;
                while (*s == L'/')
index ce2f482..b06c3cd 100644 (file)
  * headers as required.
  */
 
-/* Get a real definition for __FBSDID if we can */
+/* Get a real definition for __FBSDID or __RCSID if we can */
 #if HAVE_SYS_CDEFS_H
 #include <sys/cdefs.h>
 #endif
 
-/* If not, define it so as to avoid dangling semicolons. */
+/* If not, define them so as to avoid dangling semicolons. */
 #ifndef __FBSDID
 #define        __FBSDID(a)     struct _undefined_hack
 #endif
+#ifndef __RCSID
+#define        __RCSID(a)     struct _undefined_hack
+#endif
 
 /* Try to get standard C99-style integer type definitions. */
 #if HAVE_INTTYPES_H
 #if !HAVE_DECL_UINT32_MAX
 #define        UINT32_MAX (~(uint32_t)0)
 #endif
+#if !HAVE_DECL_INT32_MAX
+#define        INT32_MAX ((int32_t)(UINT32_MAX >> 1))
+#endif
+#if !HAVE_DECL_INT32_MIN
+#define        INT32_MIN ((int32_t)(~INT32_MAX))
+#endif
 #if !HAVE_DECL_UINT64_MAX
 #define        UINT64_MAX (~(uint64_t)0)
 #endif
 #if !HAVE_DECL_INT64_MIN
 #define        INT64_MIN ((int64_t)(~INT64_MAX))
 #endif
+#if !HAVE_DECL_UINTMAX_MAX
+#define        UINTMAX_MAX (~(uintmax_t)0)
+#endif
+#if !HAVE_DECL_INTMAX_MAX
+#define        INTMAX_MAX ((intmax_t)(UINTMAX_MAX >> 1))
+#endif
+#if !HAVE_DECL_INTMAX_MIN
+#define        INTMAX_MIN ((intmax_t)(~INTMAX_MAX))
+#endif
 
 /*
  * If this platform has <sys/acl.h>, acl_create(), acl_init(),
index 30d472f..4b4be97 100644 (file)
@@ -119,6 +119,23 @@ struct archive {
        unsigned current_codepage; /* Current ACP(ANSI CodePage). */
        unsigned current_oemcp; /* Current OEMCP(OEM CodePage). */
        struct archive_string_conv *sconv;
+
+       /*
+        * Used by archive_read_data() to track blocks and copy
+        * data to client buffers, filling gaps with zero bytes.
+        */
+       const char       *read_data_block;
+       int64_t           read_data_offset;
+       int64_t           read_data_output_offset;
+       size_t            read_data_remaining;
+
+       /*
+        * Used by formats/filters to determine the amount of data
+        * requested from a call to archive_read_data(). This is only
+        * useful when the format/filter has seek support.
+        */
+       char              read_data_is_posix_read;
+       size_t            read_data_requested;
 };
 
 /* Check magic value and state; return(ARCHIVE_FATAL) if it isn't valid. */
@@ -139,6 +156,8 @@ int __archive_mktemp(const char *tmpdir);
 
 int    __archive_clean(struct archive *);
 
+void __archive_reset_read_data(struct archive *);
+
 #define        err_combine(a,b)        ((a) < (b) ? (a) : (b))
 
 #if defined(__BORLANDC__) || (defined(_MSC_VER) &&  _MSC_VER <= 1300)
diff --git a/contrib/libarchive/libarchive/archive_random.c b/contrib/libarchive/libarchive/archive_random.c
new file mode 100644 (file)
index 0000000..a20b9b1
--- /dev/null
@@ -0,0 +1,269 @@
+/*-
+ * Copyright (c) 2014 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#if !defined(HAVE_ARC4RANDOM_BUF) && (!defined(_WIN32) || defined(__CYGWIN__))
+
+#ifdef HAVE_FCNTL
+#include <fcntl.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+
+static void arc4random_buf(void *, size_t);
+
+#endif /* HAVE_ARC4RANDOM_BUF */
+
+#include "archive.h"
+#include "archive_random_private.h"
+
+#if defined(HAVE_WINCRYPT_H) && !defined(__CYGWIN__)
+#include <wincrypt.h>
+#endif
+
+#ifndef O_CLOEXEC
+#define O_CLOEXEC      0
+#endif
+
+/*
+ * Random number generator function.
+ * This simply calls arc4random_buf function if the platform provides it.
+ */
+
+int
+archive_random(void *buf, size_t nbytes)
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+       HCRYPTPROV hProv;
+       BOOL success;
+
+       success = CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
+           CRYPT_VERIFYCONTEXT);
+       if (!success && GetLastError() == NTE_BAD_KEYSET) {
+               success = CryptAcquireContext(&hProv, NULL, NULL,
+                   PROV_RSA_FULL, CRYPT_NEWKEYSET);
+       }
+       if (success) {
+               success = CryptGenRandom(hProv, (DWORD)nbytes, (BYTE*)buf);
+               CryptReleaseContext(hProv, 0);
+               if (success)
+                       return ARCHIVE_OK;
+       }
+       /* TODO: Does this case really happen? */
+       return ARCHIVE_FAILED;
+#else
+       arc4random_buf(buf, nbytes);
+       return ARCHIVE_OK;
+#endif
+}
+
+#if !defined(HAVE_ARC4RANDOM_BUF) && (!defined(_WIN32) || defined(__CYGWIN__))
+
+/*     $OpenBSD: arc4random.c,v 1.24 2013/06/11 16:59:50 deraadt Exp $ */
+/*
+ * Copyright (c) 1996, David Mazieres <dm@uun.org>
+ * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Arc4 random number generator for OpenBSD.
+ *
+ * This code is derived from section 17.1 of Applied Cryptography,
+ * second edition, which describes a stream cipher allegedly
+ * compatible with RSA Labs "RC4" cipher (the actual description of
+ * which is a trade secret).  The same algorithm is used as a stream
+ * cipher called "arcfour" in Tatu Ylonen's ssh package.
+ *
+ * RC4 is a registered trademark of RSA Laboratories.
+ */
+
+#ifdef __GNUC__
+#define inline __inline
+#else                          /* !__GNUC__ */
+#define inline
+#endif                         /* !__GNUC__ */
+
+struct arc4_stream {
+       uint8_t i;
+       uint8_t j;
+       uint8_t s[256];
+};
+
+#define        RANDOMDEV       "/dev/urandom"
+#define        KEYSIZE         128
+#ifdef HAVE_PTHREAD_H
+static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
+#define        _ARC4_LOCK()    pthread_mutex_lock(&arc4random_mtx);
+#define        _ARC4_UNLOCK()  pthread_mutex_unlock(&arc4random_mtx);
+#else
+#define        _ARC4_LOCK()
+#define        _ARC4_UNLOCK()
+#endif
+
+static int rs_initialized;
+static struct arc4_stream rs;
+static pid_t arc4_stir_pid;
+static int arc4_count;
+
+static inline uint8_t arc4_getbyte(void);
+static void arc4_stir(void);
+
+static inline void
+arc4_init(void)
+{
+       int     n;
+
+       for (n = 0; n < 256; n++)
+               rs.s[n] = n;
+       rs.i = 0;
+       rs.j = 0;
+}
+
+static inline void
+arc4_addrandom(u_char *dat, int datlen)
+{
+       int     n;
+       uint8_t si;
+
+       rs.i--;
+       for (n = 0; n < 256; n++) {
+               rs.i = (rs.i + 1);
+               si = rs.s[rs.i];
+               rs.j = (rs.j + si + dat[n % datlen]);
+               rs.s[rs.i] = rs.s[rs.j];
+               rs.s[rs.j] = si;
+       }
+       rs.j = rs.i;
+}
+
+static void
+arc4_stir(void)
+{
+       int done, fd, i;
+       struct {
+               struct timeval  tv;
+               pid_t           pid;
+               u_char          rnd[KEYSIZE];
+       } rdat;
+
+       if (!rs_initialized) {
+               arc4_init();
+               rs_initialized = 1;
+       }
+       done = 0;
+       fd = open(RANDOMDEV, O_RDONLY | O_CLOEXEC, 0);
+       if (fd >= 0) {
+               if (read(fd, &rdat, KEYSIZE) == KEYSIZE)
+                       done = 1;
+               (void)close(fd);
+       }
+       if (!done) {
+               (void)gettimeofday(&rdat.tv, NULL);
+               rdat.pid = getpid();
+               /* We'll just take whatever was on the stack too... */
+       }
+
+       arc4_addrandom((u_char *)&rdat, KEYSIZE);
+
+       /*
+        * Discard early keystream, as per recommendations in:
+        * "(Not So) Random Shuffles of RC4" by Ilya Mironov.
+        */
+       for (i = 0; i < 1024; i++)
+               (void)arc4_getbyte();
+       arc4_count = 1600000;
+}
+
+static void
+arc4_stir_if_needed(void)
+{
+       pid_t pid = getpid();
+
+       if (arc4_count <= 0 || !rs_initialized || arc4_stir_pid != pid) {
+               arc4_stir_pid = pid;
+               arc4_stir();
+       }
+}
+
+static inline uint8_t
+arc4_getbyte(void)
+{
+       uint8_t si, sj;
+
+       rs.i = (rs.i + 1);
+       si = rs.s[rs.i];
+       rs.j = (rs.j + si);
+       sj = rs.s[rs.j];
+       rs.s[rs.i] = sj;
+       rs.s[rs.j] = si;
+       return (rs.s[(si + sj) & 0xff]);
+}
+
+static void
+arc4random_buf(void *_buf, size_t n)
+{
+       u_char *buf = (u_char *)_buf;
+       _ARC4_LOCK();
+       arc4_stir_if_needed();
+       while (n--) {
+               if (--arc4_count <= 0)
+                       arc4_stir();
+               buf[n] = arc4_getbyte();
+       }
+       _ARC4_UNLOCK();
+}
+
+#endif /* !HAVE_ARC4RANDOM_BUF */
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2009 Joerg Sonnenberger
+ * Copyright (c) 2014 Michihiro NAKAJIMA
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef LAFE_ERR_H
-#define LAFE_ERR_H
-
-#if defined(__GNUC__) && (__GNUC__ > 2 || \
-                          (__GNUC__ == 2 && __GNUC_MINOR__ >= 5))
-#define __LA_DEAD       __attribute__((__noreturn__))
-#else
-#define __LA_DEAD
-#endif
-
-#if defined(__GNUC__) && (__GNUC__ > 2 || \
-                         (__GNUC__ == 2 && __GNUC_MINOR__ >= 7))
-#define        __LA_PRINTFLIKE(f,a)    __attribute__((__format__(__printf__, f, a)))
-#else
-#define        __LA_PRINTFLIKE(f,a)
+#ifndef __LIBARCHIVE_BUILD
+#error This header is only to be used internally to libarchive.
 #endif
 
-extern const char *lafe_progname;
+#ifndef ARCHIVE_RANDOM_PRIVATE_H_INCLUDED
+#define ARCHIVE_RANDOM_PRIVATE_H_INCLUDED
 
-void   lafe_warnc(int code, const char *fmt, ...) __LA_PRINTFLIKE(2, 3);
-void   lafe_errc(int eval, int code, const char *fmt, ...) __LA_DEAD
-                 __LA_PRINTFLIKE(3, 4);
+/* Random number generator. */
+int archive_random(void *buf, size_t nbytes);
 
-#endif
+#endif /* ARCHIVE_RANDOM_PRIVATE_H_INCLUDED */
index a29cc1e..d37e732 100644 (file)
@@ -130,7 +130,7 @@ which provides a slightly more efficient interface.
 You may prefer to use the higher-level
 .Fn archive_read_data_skip ,
 which reads and discards the data for this entry,
-.Fn archive_read_data_to_file ,
+.Fn archive_read_data_into_fd ,
 which copies the data to the provided file descriptor, or
 .Fn archive_read_extract ,
 which recreates the specified entry on disk and copies data
@@ -186,7 +186,7 @@ list_archive(const char *name)
   free(mydata);
 }
 
-ssize_t
+la_ssize_t
 myread(struct archive *a, void *client_data, const void **buff)
 {
   struct mydata *mydata = client_data;
index 048c316..0bbacc8 100644 (file)
@@ -101,16 +101,17 @@ archive_read_new(void)
 {
        struct archive_read *a;
 
-       a = (struct archive_read *)malloc(sizeof(*a));
+       a = (struct archive_read *)calloc(1, sizeof(*a));
        if (a == NULL)
                return (NULL);
-       memset(a, 0, sizeof(*a));
        a->archive.magic = ARCHIVE_READ_MAGIC;
 
        a->archive.state = ARCHIVE_STATE_NEW;
        a->entry = archive_entry_new2(&a->archive);
        a->archive.vtable = archive_read_vtable();
 
+       a->passphrases.last = &a->passphrases.first;
+
        return (&a->archive);
 }
 
@@ -194,10 +195,12 @@ client_skip_proxy(struct archive_read_filter *self, int64_t request)
                                ask = skip_limit;
                        get = (self->archive->client.skipper)
                                (&self->archive->archive, self->data, ask);
-                       if (get == 0)
+                       total += get;
+                       if (get == 0 || get == request)
                                return (total);
+                       if (get > request)
+                               return ARCHIVE_FATAL;
                        request -= get;
-                       total += get;
                }
        } else if (self->archive->client.seeker != NULL
                && request > 64 * 1024) {
@@ -230,8 +233,11 @@ client_seek_proxy(struct archive_read_filter *self, int64_t offset, int whence)
         * other libarchive code that assumes a successful forward
         * seek means it can also seek backwards.
         */
-       if (self->archive->client.seeker == NULL)
+       if (self->archive->client.seeker == NULL) {
+               archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
+                   "Current client reader does not support seeking a device");
                return (ARCHIVE_FAILED);
+       }
        return (self->archive->client.seeker)(&self->archive->archive,
            self->data, offset, whence);
 }
@@ -454,7 +460,7 @@ archive_read_open1(struct archive *_a)
 {
        struct archive_read *a = (struct archive_read *)_a;
        struct archive_read_filter *filter, *tmp;
-       int slot, e;
+       int slot, e = ARCHIVE_OK;
        unsigned int i;
 
        archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
@@ -541,16 +547,20 @@ archive_read_open1(struct archive *_a)
  * it wants to handle this stream.  Repeat until we've finished
  * building the pipeline.
  */
+
+/* We won't build a filter pipeline with more stages than this. */
+#define MAX_NUMBER_FILTERS 25
+
 static int
 choose_filters(struct archive_read *a)
 {
-       int number_bidders, i, bid, best_bid;
+       int number_bidders, i, bid, best_bid, number_filters;
        struct archive_read_filter_bidder *bidder, *best_bidder;
        struct archive_read_filter *filter;
        ssize_t avail;
        int r;
 
-       for (;;) {
+       for (number_filters = 0; number_filters < MAX_NUMBER_FILTERS; ++number_filters) {
                number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]);
 
                best_bid = 0;
@@ -596,6 +606,9 @@ choose_filters(struct archive_read *a)
                        return (ARCHIVE_FATAL);
                }
        }
+       archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+           "Input requires too many filters for decoding");
+       return (ARCHIVE_FATAL);
 }
 
 /*
@@ -658,16 +671,14 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
                break;
        }
 
-       a->read_data_output_offset = 0;
-       a->read_data_remaining = 0;
-       a->read_data_is_posix_read = 0;
-       a->read_data_requested = 0;
+       __archive_reset_read_data(&a->archive);
+
        a->data_start_node = a->client.cursor;
        /* EOF always wins; otherwise return the worst error. */
        return (r2 < r1 || r2 == ARCHIVE_EOF) ? r2 : r1;
 }
 
-int
+static int
 _archive_read_next_header(struct archive *_a, struct archive_entry **entryp)
 {
        int ret;
@@ -746,6 +757,59 @@ archive_read_header_position(struct archive *_a)
        return (a->header_position);
 }
 
+/*
+ * Returns 1 if the archive contains at least one encrypted entry.
+ * If the archive format not support encryption at all
+ * ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned.
+ * If for any other reason (e.g. not enough data read so far)
+ * we cannot say whether there are encrypted entries, then
+ * ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned.
+ * In general, this function will return values below zero when the
+ * reader is uncertain or totally uncapable of encryption support.
+ * When this function returns 0 you can be sure that the reader
+ * supports encryption detection but no encrypted entries have
+ * been found yet.
+ *
+ * NOTE: If the metadata/header of an archive is also encrypted, you
+ * cannot rely on the number of encrypted entries. That is why this
+ * function does not return the number of encrypted entries but#
+ * just shows that there are some.
+ */
+int
+archive_read_has_encrypted_entries(struct archive *_a)
+{
+       struct archive_read *a = (struct archive_read *)_a;
+       int format_supports_encryption = archive_read_format_capabilities(_a)
+                       & (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA | ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA);
+
+       if (!_a || !format_supports_encryption) {
+               /* Format in general doesn't support encryption */
+               return ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED;
+       }
+
+       /* A reader potentially has read enough data now. */
+       if (a->format && a->format->has_encrypted_entries) {
+               return (a->format->has_encrypted_entries)(a);
+       }
+
+       /* For any other reason we cannot say how many entries are there. */
+       return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
+}
+
+/*
+ * Returns a bitmask of capabilities that are supported by the archive format reader.
+ * If the reader has no special capabilities, ARCHIVE_READ_FORMAT_CAPS_NONE is returned.
+ */
+int
+archive_read_format_capabilities(struct archive *_a)
+{
+       struct archive_read *a = (struct archive_read *)_a;
+       if (a && a->format && a->format->format_capabilties) {
+               return (a->format->format_capabilties)(a);
+       }
+       return ARCHIVE_READ_FORMAT_CAPS_NONE;
+}
+
 /*
  * Read data from an archive entry, using a read(2)-style interface.
  * This is a convenience routine that just calls
@@ -760,7 +824,7 @@ archive_read_header_position(struct archive *_a)
 ssize_t
 archive_read_data(struct archive *_a, void *buff, size_t s)
 {
-       struct archive_read *a = (struct archive_read *)_a;
+       struct archive *a = (struct archive *)_a;
        char    *dest;
        const void *read_buf;
        size_t   bytes_read;
@@ -775,7 +839,7 @@ archive_read_data(struct archive *_a, void *buff, size_t s)
                        read_buf = a->read_data_block;
                        a->read_data_is_posix_read = 1;
                        a->read_data_requested = s;
-                       r = _archive_read_data_block(&a->archive, &read_buf,
+                       r = archive_read_data_block(a, &read_buf,
                            &a->read_data_remaining, &a->read_data_offset);
                        a->read_data_block = read_buf;
                        if (r == ARCHIVE_EOF)
@@ -790,7 +854,7 @@ archive_read_data(struct archive *_a, void *buff, size_t s)
                }
 
                if (a->read_data_offset < a->read_data_output_offset) {
-                       archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+                       archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
                            "Encountered out-of-order sparse blocks");
                        return (ARCHIVE_RETRY);
                }
@@ -833,6 +897,21 @@ archive_read_data(struct archive *_a, void *buff, size_t s)
        return (bytes_read);
 }
 
+/*
+ * Reset the read_data_* variables, used for starting a new entry.
+ */
+void __archive_reset_read_data(struct archive * a)
+{
+       a->read_data_output_offset = 0;
+       a->read_data_remaining = 0;
+       a->read_data_is_posix_read = 0;
+       a->read_data_requested = 0;
+
+   /* extra resets, from rar.c */
+   a->read_data_block = NULL;
+   a->read_data_offset = 0;
+}
+
 /*
  * Skip over all remaining data in this entry.
  */
@@ -900,7 +979,7 @@ _archive_read_data_block(struct archive *_a,
        if (a->format->read_data == NULL) {
                archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
                    "Internal error: "
-                   "No format_read_data_block function registered");
+                   "No format->read_data function registered");
                return (ARCHIVE_FATAL);
        }
 
@@ -987,6 +1066,7 @@ static int
 _archive_read_free(struct archive *_a)
 {
        struct archive_read *a = (struct archive_read *)_a;
+       struct archive_read_passphrase *p;
        int i, n;
        int slots;
        int r = ARCHIVE_OK;
@@ -1024,9 +1104,20 @@ _archive_read_free(struct archive *_a)
                }
        }
 
+       /* Release passphrase list. */
+       p = a->passphrases.first;
+       while (p != NULL) {
+               struct archive_read_passphrase *np = p->next;
+
+               /* A passphrase should be cleaned. */
+               memset(p->passphrase, 0, strlen(p->passphrase));
+               free(p->passphrase);
+               free(p);
+               p = np;
+       }
+
        archive_string_free(&a->archive.error_string);
-       if (a->entry)
-               archive_entry_free(a->entry);
+       archive_entry_free(a->entry);
        a->archive.magic = 0;
        __archive_clean(&a->archive);
        free(a->client.dataset);
@@ -1070,7 +1161,7 @@ static const char *
 _archive_filter_name(struct archive *_a, int n)
 {
        struct archive_read_filter *f = get_filter(_a, n);
-       return f == NULL ? NULL : f->name;
+       return f != NULL ? f->name : NULL;
 }
 
 static int64_t
@@ -1094,7 +1185,9 @@ __archive_read_register_format(struct archive_read *a,
     int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *),
     int (*read_data_skip)(struct archive_read *),
     int64_t (*seek_data)(struct archive_read *, int64_t, int),
-    int (*cleanup)(struct archive_read *))
+    int (*cleanup)(struct archive_read *),
+    int (*format_capabilities)(struct archive_read *),
+    int (*has_encrypted_entries)(struct archive_read *))
 {
        int i, number_slots;
 
@@ -1117,6 +1210,8 @@ __archive_read_register_format(struct archive_read *a,
                        a->formats[i].cleanup = cleanup;
                        a->formats[i].data = format_data;
                        a->formats[i].name = name;
+                       a->formats[i].format_capabilties = format_capabilities;
+                       a->formats[i].has_encrypted_entries = has_encrypted_entries;
                        return (ARCHIVE_OK);
                }
        }
@@ -1394,6 +1489,8 @@ __archive_read_filter_consume(struct archive_read_filter * filter,
 {
        int64_t skipped;
 
+       if (request < 0)
+               return ARCHIVE_FATAL;
        if (request == 0)
                return 0;
 
@@ -1557,10 +1654,9 @@ __archive_read_filter_seek(struct archive_read_filter *filter, int64_t offset,
                        client->dataset[++cursor].begin_position = r;
                }
                offset -= client->dataset[cursor].begin_position;
-               if (offset < 0)
-                       offset = 0;
-               else if (offset > client->dataset[cursor].total_size - 1)
-                       offset = client->dataset[cursor].total_size - 1;
+               if (offset < 0
+                   || offset > client->dataset[cursor].total_size)
+                       return ARCHIVE_FATAL;
                if ((r = client_seek_proxy(filter, offset, SEEK_SET)) < 0)
                        return r;
                break;
@@ -1,4 +1,4 @@
-.\" Copyright (c) 2003-2011 Tim Kientzle
+.\" Copyright (c) 2014 Michihiro NAKAJIMA
 .\" All rights reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without
 .\"
 .\" $FreeBSD$
 .\"
-.Dd February 2, 2012
-.Dt ARCHIVE_WRITE_DATA 3
+.Dd September 14, 2014
+.Dt ARCHIVE_READ_ADD_PASSPHRASE 3
 .Os
 .Sh NAME
-.Nm archive_write_data
-.Nd functions for creating archives
+.Nm archive_read_add_passphrase ,
+.Nm archive_read_set_passphrase_callback
+.Nd functions for reading encrypted archives
 .Sh LIBRARY
 Streaming Archive Library (libarchive, -larchive)
 .Sh SYNOPSIS
 .In archive.h
-.Ft ssize_t
-.Fn archive_write_data "struct archive *" "const void *" "size_t"
+.Ft int
+.Fo archive_read_add_passphrase
+.Fa "struct archive *"
+.Fa "const char *passphrase"
+.Fc
+.Ft int
+.Fo archive_read_set_passphrase_callback
+.Fa "struct archive *"
+.Fa "void *client_data"
+.Fa "archive_passphrase_callback *"
+.Fc
 .Sh DESCRIPTION
-Write data corresponding to the header just written.
-.\" .Sh EXAMPLE
-.\"
-.Sh RETURN VALUES
-This function returns the number of bytes actually written, or
-.Li -1
-on error.
-.\"
-.Sh ERRORS
-Detailed error codes and textual descriptions are available from the
-.Fn archive_errno
-and
-.Fn archive_error_string
-functions.
-.\"
+.Bl -tag -width indent
+.It Fn archive_read_add_passphrase
+Register passphrases for reading an encryption archive.
+If
+.Ar passphrase
+is
+.Dv NULL
+or empty, this function will do nothing and
+.Cm ARCHIVE_FAILED
+will be returned.
+Otherwise,
+.Cm ARCHIVE_OK
+will be returned. 
+.It Fn archive_read_set_passphrase_callback
+Register callback function that will be invoked to get a passphrase 
+for decrption after trying all passphrases registered by the
+.Fn archive_read_add_passphrase
+function failed.
+.El
+.\" .Sh ERRORS
 .Sh SEE ALSO
 .Xr tar 1 ,
 .Xr libarchive 3 ,
-.Xr archive_write_finish_entry 3 ,
-.Xr archive_write_set_options 3 ,
-.Xr cpio 5 ,
-.Xr mtree 5 ,
-.Xr tar 5
+.Xr archive_read 3 ,
+.Xr archive_read_set_options 3
diff --git a/contrib/libarchive/libarchive/archive_read_add_passphrase.c b/contrib/libarchive/libarchive/archive_read_add_passphrase.c
new file mode 100644 (file)
index 0000000..f67f1eb
--- /dev/null
@@ -0,0 +1,186 @@
+/*-
+ * Copyright (c) 2014 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include "archive_read_private.h"
+
+static void
+add_passphrase_to_tail(struct archive_read *a,
+    struct archive_read_passphrase *p)
+{
+       *a->passphrases.last = p;
+       a->passphrases.last = &p->next;
+       p->next = NULL;
+}
+
+static struct archive_read_passphrase *
+remove_passphrases_from_head(struct archive_read *a)
+{
+       struct archive_read_passphrase *p;
+
+       p = a->passphrases.first;
+       if (p != NULL)
+               a->passphrases.first = p->next;
+       return (p);
+}
+
+static void
+insert_passphrase_to_head(struct archive_read *a,
+    struct archive_read_passphrase *p)
+{
+       p->next = a->passphrases.first;
+       a->passphrases.first = p;
+}
+
+static struct archive_read_passphrase *
+new_read_passphrase(struct archive_read *a, const char *passphrase)
+{
+       struct archive_read_passphrase *p;
+
+       p = malloc(sizeof(*p));
+       if (p == NULL) {
+               archive_set_error(&a->archive, ENOMEM,
+                   "Can't allocate memory");
+               return (NULL);
+       }
+       p->passphrase = strdup(passphrase);
+       if (p->passphrase == NULL) {
+               free(p);
+               archive_set_error(&a->archive, ENOMEM,
+                   "Can't allocate memory");
+               return (NULL);
+       }
+       return (p);
+}
+
+int
+archive_read_add_passphrase(struct archive *_a, const char *passphrase)
+{
+       struct archive_read *a = (struct archive_read *)_a;
+       struct archive_read_passphrase *p;
+
+       archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
+               "archive_read_add_passphrase");
+
+       if (passphrase == NULL || passphrase[0] == '\0') {
+               archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+                   "Empty passphrase is unacceptable");
+               return (ARCHIVE_FAILED);
+       }
+
+       p = new_read_passphrase(a, passphrase);
+       if (p == NULL)
+               return (ARCHIVE_FATAL);
+       add_passphrase_to_tail(a, p);
+
+       return (ARCHIVE_OK);
+}
+
+int
+archive_read_set_passphrase_callback(struct archive *_a, void *client_data,
+    archive_passphrase_callback *cb)
+{
+       struct archive_read *a = (struct archive_read *)_a;
+
+       archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
+               "archive_read_set_passphrase_callback");
+
+       a->passphrases.callback = cb;
+       a->passphrases.client_data = client_data;
+       return (ARCHIVE_OK);
+}
+
+/*
+ * Call this in advance when you start to get a passphrase for decryption
+ * for a entry.
+ */
+void
+__archive_read_reset_passphrase(struct archive_read *a)
+{
+
+       a->passphrases.candiate = -1;
+}
+
+/*
+ * Get a passphrase for decryption.
+ */
+const char *
+__archive_read_next_passphrase(struct archive_read *a)
+{
+       struct archive_read_passphrase *p;
+       const char *passphrase;
+
+       if (a->passphrases.candiate < 0) {
+               /* Count out how many passphrases we have. */
+               int cnt = 0;
+
+               for (p = a->passphrases.first; p != NULL; p = p->next)
+                       cnt++;
+               a->passphrases.candiate = cnt;
+               p = a->passphrases.first;
+       } else if (a->passphrases.candiate > 1) {
+               /* Rotate a passphrase list. */
+               a->passphrases.candiate--;
+               p = remove_passphrases_from_head(a);
+               add_passphrase_to_tail(a, p);
+               /* Pick a new passphrase candiate up. */
+               p = a->passphrases.first;
+       } else if (a->passphrases.candiate == 1) {
+               /* This case is that all cadiates failed to decryption. */
+               a->passphrases.candiate = 0;
+               if (a->passphrases.first->next != NULL) {
+                       /* Rotate a passphrase list. */
+                       p = remove_passphrases_from_head(a);
+                       add_passphrase_to_tail(a, p);
+               }
+               p = NULL;
+       } else  /* There is no passphrase candaite. */
+               p = NULL;
+
+       if (p != NULL)
+               passphrase = p->passphrase;
+       else if (a->passphrases.callback != NULL) {
+               /* Get a passphrase through a call-back function
+                * since we tried all passphrases out or we don't
+                * have it. */
+               passphrase = a->passphrases.callback(&a->archive,
+                   a->passphrases.client_data);
+               if (passphrase != NULL) {
+                       p = new_read_passphrase(a, passphrase);
+                       if (p == NULL)
+                               return (NULL);
+                       insert_passphrase_to_head(a, p);
+                       a->passphrases.candiate = 1;
+               }
+       } else
+               passphrase = NULL;
+
+       return (passphrase);
+}
index 017d7c6..3a0d4d6 100644 (file)
@@ -43,7 +43,7 @@ archive_read_append_filter(struct archive *_a, int code)
   struct archive_read_filter *filter;
   struct archive_read *a = (struct archive_read *)_a;
 
-  r1 = r2 = (ARCHIVE_OK);
+  r2 = (ARCHIVE_OK);
   switch (code)
   {
     case ARCHIVE_FILTER_NONE:
@@ -85,6 +85,10 @@ archive_read_append_filter(struct archive *_a, int code)
       strcpy(str, "rpm");
       r1 = archive_read_support_filter_rpm(_a);
       break;
+    case ARCHIVE_FILTER_LZ4:
+      strcpy(str, "lz4");
+      r1 = archive_read_support_filter_lz4(_a);
+      break;
     case ARCHIVE_FILTER_LZIP:
       strcpy(str, "lzip");
       r1 = archive_read_support_filter_lzip(_a);
index bf0578c..c1bc15d 100644 (file)
@@ -37,7 +37,7 @@
 Streaming Archive Library (libarchive, -larchive)
 .Sh SYNOPSIS
 .In archive.h
-.Ft ssize_t
+.Ft la_ssize_t
 .Fn archive_read_data "struct archive *" "void *buff" "size_t len"
 .Ft int
 .Fo archive_read_data_block
index e984aaa..74fe353 100644 (file)
@@ -251,9 +251,11 @@ archive_read_disk_entry_from_file(struct archive *_a,
 #endif /* HAVE_READLINK || HAVE_READLINKAT */
 
        r = setup_acls(a, entry, &fd);
-       r1 = setup_xattrs(a, entry, &fd);
-       if (r1 < r)
-               r = r1;
+       if (!a->suppress_xattr) {
+               r1 = setup_xattrs(a, entry, &fd);
+               if (r1 < r)
+                       r = r1;
+       }
        if (a->enable_copyfile) {
                r1 = setup_mac_metadata(a, entry, &fd);
                if (r1 < r)
@@ -399,7 +401,7 @@ setup_mac_metadata(struct archive_read_disk *a,
 #endif
 
 
-#if defined(HAVE_POSIX_ACL) && defined(ACL_TYPE_NFS4)
+#ifdef HAVE_POSIX_ACL
 static int translate_acl(struct archive_read_disk *a,
     struct archive_entry *entry, acl_t acl, int archive_entry_acl_type);
 
@@ -419,6 +421,7 @@ setup_acls(struct archive_read_disk *a,
 
        archive_entry_acl_clear(entry);
 
+#ifdef ACL_TYPE_NFS4
        /* Try NFS4 ACL first. */
        if (*fd >= 0)
                acl = acl_get_fd(*fd);
@@ -447,6 +450,7 @@ setup_acls(struct archive_read_disk *a,
                acl_free(acl);
                return (ARCHIVE_OK);
        }
+#endif
 
        /* Retrieve access ACL from file. */
        if (*fd >= 0)
@@ -492,6 +496,7 @@ static struct {
         {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
         {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
         {ARCHIVE_ENTRY_ACL_READ, ACL_READ},
+#ifdef ACL_TYPE_NFS4
         {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
         {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
         {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
@@ -508,8 +513,10 @@ static struct {
         {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
         {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
         {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
+#endif
 };
 
+#ifdef ACL_TYPE_NFS4
 static struct {
         int archive_inherit;
         int platform_inherit;
@@ -519,21 +526,25 @@ static struct {
        {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
        {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}
 };
-
+#endif
 static int
 translate_acl(struct archive_read_disk *a,
     struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
 {
        acl_tag_t        acl_tag;
+#ifdef ACL_TYPE_NFS4
        acl_entry_type_t acl_type;
        acl_flagset_t    acl_flagset;
+       int brand, r;
+#endif
        acl_entry_t      acl_entry;
        acl_permset_t    acl_permset;
-       int              brand, i, r, entry_acl_type;
+       int              i, entry_acl_type;
        int              s, ae_id, ae_tag, ae_perm;
        const char      *ae_name;
 
 
+#ifdef ACL_TYPE_NFS4
        // FreeBSD "brands" ACLs as POSIX.1e or NFSv4
        // Make sure the "brand" on this ACL is consistent
        // with the default_entry_acl_type bits provided.
@@ -560,6 +571,7 @@ translate_acl(struct archive_read_disk *a,
                return ARCHIVE_FAILED;
                break;
        }
+#endif
 
 
        s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
@@ -592,9 +604,11 @@ translate_acl(struct archive_read_disk *a,
                case ACL_OTHER:
                        ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
                        break;
+#ifdef ACL_TYPE_NFS4
                case ACL_EVERYONE:
                        ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
                        break;
+#endif
                default:
                        /* Skip types that libarchive can't support. */
                        s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
@@ -605,6 +619,7 @@ translate_acl(struct archive_read_disk *a,
                // XXX acl_get_entry_type_np on FreeBSD returns EINVAL for
                // non-NFSv4 ACLs
                entry_acl_type = default_entry_acl_type;
+#ifdef ACL_TYPE_NFS4
                r = acl_get_entry_type_np(acl_entry, &acl_type);
                if (r == 0) {
                        switch (acl_type) {
@@ -634,9 +649,10 @@ translate_acl(struct archive_read_disk *a,
                                ae_perm |= acl_inherit_map[i].archive_inherit;
 
                 }
+#endif
 
                acl_get_permset(acl_entry, &acl_permset);
-                for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
+               for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
                        /*
                         * acl_get_perm() is spelled differently on different
                         * platforms; see above.
@@ -1030,7 +1046,7 @@ setup_sparse(struct archive_read_disk *a,
        struct fiemap *fm;
        struct fiemap_extent *fe;
        int64_t size;
-       int count, do_fiemap;
+       int count, do_fiemap, iters;
        int exit_sts = ARCHIVE_OK;
 
        if (archive_entry_filetype(entry) != AE_IFREG
@@ -1067,7 +1083,7 @@ setup_sparse(struct archive_read_disk *a,
        fm->fm_extent_count = count;
        do_fiemap = 1;
        size = archive_entry_size(entry);
-       for (;;) {
+       for (iters = 0; ; ++iters) {
                int i, r;
 
                r = ioctl(*fd, FS_IOC_FIEMAP, fm); 
@@ -1077,8 +1093,13 @@ setup_sparse(struct archive_read_disk *a,
                         * version(<2.6.28) cannot perfom FS_IOC_FIEMAP. */
                        goto exit_setup_sparse;
                }
-               if (fm->fm_mapped_extents == 0)
+               if (fm->fm_mapped_extents == 0) {
+                       if (iters == 0) {
+                               /* Fully sparse file; insert a zero-length "data" entry */
+                               archive_entry_sparse_add_entry(entry, 0, 0);
+                       }
                        break;
+               }
                fe = fm->fm_extents;
                for (i = 0; i < (int)fm->fm_mapped_extents; i++, fe++) {
                        if (!(fe->fe_flags & FIEMAP_EXTENT_UNWRITTEN)) {
@@ -1123,6 +1144,7 @@ setup_sparse(struct archive_read_disk *a,
        off_t initial_off; /* FreeBSD/Solaris only, so off_t okay here */
        off_t off_s, off_e; /* FreeBSD/Solaris only, so off_t okay here */
        int exit_sts = ARCHIVE_OK;
+       int check_fully_sparse = 0;
 
        if (archive_entry_filetype(entry) != AE_IFREG
            || archive_entry_size(entry) <= 0
@@ -1175,8 +1197,14 @@ setup_sparse(struct archive_read_disk *a,
        while (off_s < size) {
                off_s = lseek(*fd, off_s, SEEK_DATA);
                if (off_s == (off_t)-1) {
-                       if (errno == ENXIO)
-                               break;/* no more hole */
+                       if (errno == ENXIO) {
+                               /* no more hole */
+                               if (archive_entry_sparse_count(entry) == 0) {
+                                       /* Potentially a fully-sparse file. */
+                                       check_fully_sparse = 1;
+                               }
+                               break;
+                       }
                        archive_set_error(&a->archive, errno,
                            "lseek(SEEK_HOLE) failed");
                        exit_sts = ARCHIVE_FAILED;
@@ -1200,6 +1228,14 @@ setup_sparse(struct archive_read_disk *a,
                        off_e - off_s);
                off_s = off_e;
        }
+
+       if (check_fully_sparse) {
+               if (lseek(*fd, 0, SEEK_HOLE) == 0 &&
+                       lseek(*fd, 0, SEEK_END) == size) {
+                       /* Fully sparse file; insert a zero-length "data" entry */
+                       archive_entry_sparse_add_entry(entry, 0, 0);
+               }
+       }
 exit_setup_sparse:
        lseek(*fd, initial_off, SEEK_SET);
        return (exit_sts);
index a13dbbf..22a1f14 100644 (file)
@@ -356,6 +356,8 @@ static int  _archive_read_free(struct archive *);
 static int     _archive_read_close(struct archive *);
 static int     _archive_read_data_block(struct archive *,
                    const void **, size_t *, int64_t *);
+static int     _archive_read_next_header(struct archive *,
+                   struct archive_entry **);
 static int     _archive_read_next_header2(struct archive *,
                    struct archive_entry *);
 static const char *trivial_lookup_gname(void *, int64_t gid);
@@ -377,6 +379,7 @@ archive_read_disk_vtable(void)
                av.archive_free = _archive_read_free;
                av.archive_close = _archive_read_close;
                av.archive_read_data_block = _archive_read_data_block;
+               av.archive_read_next_header = _archive_read_next_header;
                av.archive_read_next_header2 = _archive_read_next_header2;
                inited = 1;
        }
@@ -459,6 +462,7 @@ archive_read_disk_new(void)
        a->archive.magic = ARCHIVE_READ_DISK_MAGIC;
        a->archive.state = ARCHIVE_STATE_NEW;
        a->archive.vtable = archive_read_disk_vtable();
+       a->entry = archive_entry_new2(&a->archive);
        a->lookup_uname = trivial_lookup_uname;
        a->lookup_gname = trivial_lookup_gname;
        a->enable_copyfile = 1;
@@ -491,6 +495,7 @@ _archive_read_free(struct archive *_a)
        if (a->cleanup_uname != NULL && a->lookup_uname_data != NULL)
                (a->cleanup_uname)(a->lookup_uname_data);
        archive_string_free(&a->archive.error_string);
+       archive_entry_free(a->entry);
        a->archive.magic = 0;
        __archive_clean(&a->archive);
        free(a);
@@ -609,6 +614,10 @@ archive_read_disk_set_behavior(struct archive *_a, int flags)
                a->traverse_mount_points = 0;
        else
                a->traverse_mount_points = 1;
+       if (flags & ARCHIVE_READDISK_NO_XATTR)
+               a->suppress_xattr = 1;
+       else
+               a->suppress_xattr = 0;
        return (r);
 }
 
@@ -708,6 +717,7 @@ _archive_read_data_block(struct archive *_a, const void **buff,
        int r;
        ssize_t bytes;
        size_t buffbytes;
+       int empty_sparse_region = 0;
 
        archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA,
            "archive_read_data_block");
@@ -789,6 +799,9 @@ _archive_read_data_block(struct archive *_a, const void **buff,
        if ((int64_t)buffbytes > t->current_sparse->length)
                buffbytes = t->current_sparse->length;
 
+       if (t->current_sparse->length == 0)
+               empty_sparse_region = 1;
+
        /*
         * Skip hole.
         * TODO: Should we consider t->current_filesystem->xfer_align?
@@ -819,7 +832,11 @@ _archive_read_data_block(struct archive *_a, const void **buff,
                }
        } else
                bytes = 0;
-       if (bytes == 0) {
+       /*
+        * Return an EOF unless we've read a leading empty sparse region, which
+        * is used to represent fully-sparse files.
+       */
+       if (bytes == 0 && !empty_sparse_region) {
                /* Get EOF */
                t->entry_eof = 1;
                r = ARCHIVE_EOF;
@@ -974,7 +991,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
                t->initial_filesystem_id = t->current_filesystem_id;
        if (!a->traverse_mount_points) {
                if (t->initial_filesystem_id != t->current_filesystem_id)
-                       return (ARCHIVE_RETRY);
+                       descend = 0;
        }
        t->descend = descend;
 
@@ -1080,6 +1097,17 @@ next_entry(struct archive_read_disk *a, struct tree *t,
        return (r);
 }
 
+static int
+_archive_read_next_header(struct archive *_a, struct archive_entry **entryp)
+{
+       int ret;
+       struct archive_read_disk *a = (struct archive_read_disk *)_a;
+       *entryp = NULL;
+       ret = _archive_read_next_header2(_a, a->entry);
+       *entryp = a->entry;
+       return ret;
+}
+
 static int
 _archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
 {
@@ -1148,6 +1176,7 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
                break;
        }
 
+       __archive_reset_read_data(&a->archive);
        return (r);
 }
 
@@ -1555,6 +1584,7 @@ setup_current_filesystem(struct archive_read_disk *a)
 #if defined(HAVE_STRUCT_STATFS_F_NAMEMAX)
        t->current_filesystem->name_max = sfs.f_namemax;
 #else
+# if defined(_PC_NAME_MAX)
        /* Mac OS X does not have f_namemax in struct statfs. */
        if (tree_current_is_symblic_link_target(t)) {
                if (tree_enter_working_dir(t) != 0) {
@@ -1564,6 +1594,9 @@ setup_current_filesystem(struct archive_read_disk *a)
                nm = pathconf(tree_current_access_path(t), _PC_NAME_MAX);
        } else
                nm = fpathconf(tree_current_dir_fd(t), _PC_NAME_MAX);
+# else
+       nm = -1;
+# endif
        if (nm == -1)
                t->current_filesystem->name_max = NAME_MAX;
        else
@@ -1660,7 +1693,9 @@ setup_current_filesystem(struct archive_read_disk *a)
 {
        struct tree *t = a->tree;
        struct statfs sfs;
+#if defined(HAVE_STATVFS)
        struct statvfs svfs;
+#endif
        int r, vr = 0, xr = 0;
 
        if (tree_current_is_symblic_link_target(t)) {
@@ -1677,7 +1712,9 @@ setup_current_filesystem(struct archive_read_disk *a)
                            "openat failed");
                        return (ARCHIVE_FAILED);
                }
+#if defined(HAVE_FSTATVFS)
                vr = fstatvfs(fd, &svfs);/* for f_flag, mount flags */
+#endif
                r = fstatfs(fd, &sfs);
                if (r == 0)
                        xr = get_xfer_size(t, fd, NULL);
@@ -1687,14 +1724,18 @@ setup_current_filesystem(struct archive_read_disk *a)
                        archive_set_error(&a->archive, errno, "fchdir failed");
                        return (ARCHIVE_FAILED);
                }
+#if defined(HAVE_STATVFS)
                vr = statvfs(tree_current_access_path(t), &svfs);
+#endif
                r = statfs(tree_current_access_path(t), &sfs);
                if (r == 0)
                        xr = get_xfer_size(t, -1, tree_current_access_path(t));
 #endif
        } else {
 #ifdef HAVE_FSTATFS
+#if defined(HAVE_FSTATVFS)
                vr = fstatvfs(tree_current_dir_fd(t), &svfs);
+#endif
                r = fstatfs(tree_current_dir_fd(t), &sfs);
                if (r == 0)
                        xr = get_xfer_size(t, tree_current_dir_fd(t), NULL);
@@ -1703,7 +1744,9 @@ setup_current_filesystem(struct archive_read_disk *a)
                        archive_set_error(&a->archive, errno, "fchdir failed");
                        return (ARCHIVE_FAILED);
                }
+#if defined(HAVE_STATVFS)
                vr = statvfs(".", &svfs);
+#endif
                r = statfs(".", &sfs);
                if (r == 0)
                        xr = get_xfer_size(t, -1, ".");
@@ -1716,10 +1759,17 @@ setup_current_filesystem(struct archive_read_disk *a)
                return (ARCHIVE_FAILED);
        } else if (xr == 1) {
                /* pathconf(_PC_REX_*) operations are not supported. */
+#if defined(HAVE_STATVFS)
                t->current_filesystem->xfer_align = svfs.f_frsize;
                t->current_filesystem->max_xfer_size = -1;
                t->current_filesystem->min_xfer_size = svfs.f_bsize;
                t->current_filesystem->incr_xfer_size = svfs.f_bsize;
+#else
+               t->current_filesystem->xfer_align = sfs.f_frsize;
+               t->current_filesystem->max_xfer_size = -1;
+               t->current_filesystem->min_xfer_size = sfs.f_bsize;
+               t->current_filesystem->incr_xfer_size = sfs.f_bsize;
+#endif
        }
        switch (sfs.f_type) {
        case AFS_SUPER_MAGIC:
@@ -1744,7 +1794,11 @@ setup_current_filesystem(struct archive_read_disk *a)
        }
 
 #if defined(ST_NOATIME)
+#if defined(HAVE_STATVFS)
        if (svfs.f_flag & ST_NOATIME)
+#else
+       if (sfs.f_flag & ST_NOATIME)
+#endif
                t->current_filesystem->noatime = 1;
        else
 #endif
@@ -1973,7 +2027,7 @@ tree_dup(int fd)
        static volatile int can_dupfd_cloexec = 1;
 
        if (can_dupfd_cloexec) {
-               new_fd = fcntl(fd, F_DUPFD_CLOEXEC);
+               new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
                if (new_fd != -1)
                        return (new_fd);
                /* Linux 2.6.18 - 2.6.23 declare F_DUPFD_CLOEXEC,
index e5af16b..2569321 100644 (file)
@@ -39,6 +39,9 @@ struct archive_entry;
 struct archive_read_disk {
        struct archive  archive;
 
+       /* Reused by archive_read_next_header() */
+       struct archive_entry *entry;
+
        /*
         * Symlink mode is one of 'L'ogical, 'P'hysical, or 'H'ybrid,
         * following an old BSD convention.  'L' follows all symlinks,
@@ -68,6 +71,8 @@ struct archive_read_disk {
        int              enable_copyfile;
        /* Set 1 if users request to traverse mount points. */
        int              traverse_mount_points;
+       /* Set 1 if users want to suppress xattr information. */
+       int              suppress_xattr;
 
        const char * (*lookup_gname)(void *private, int64_t gid);
        void    (*cleanup_gname)(void *private);
index 3bc52c7..d6b2d55 100644 (file)
@@ -83,7 +83,7 @@ static const char *   lookup_uname_helper(struct name_cache *, id_t uid);
  * a simple cache to accelerate such lookups---into the archive_read_disk
  * object.  This is in a separate file because getpwuid()/getgrgid()
  * can pull in a LOT of library code (including NIS/LDAP functions, which
- * pull in DNS resolveers, etc).  This can easily top 500kB, which makes
+ * pull in DNS resolvers, etc).  This can easily top 500kB, which makes
  * it inappropriate for some space-constrained applications.
  *
  * Applications that are size-sensitive may want to just use the
index 795f2ab..b7973fa 100644 (file)
 #include "archive_platform.h"
 __FBSDID("$FreeBSD: src/lib/libarchive/archive_read_extract.c,v 1.61 2008/05/26 17:00:22 kientzle Exp $");
 
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
 #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_entry.h"
 #include "archive_private.h"
 #include "archive_read_private.h"
-#include "archive_write_disk_private.h"
-
-struct extract {
-       struct archive *ad; /* archive_write_disk object */
-
-       /* Progress function invoked during extract. */
-       void                    (*extract_progress)(void *);
-       void                     *extract_progress_user_data;
-};
-
-static int     archive_read_extract_cleanup(struct archive_read *);
-static int     copy_data(struct archive *ar, struct archive *aw);
-static struct extract *get_extract(struct archive_read *);
-
-static struct extract *
-get_extract(struct archive_read *a)
-{
-       /* If we haven't initialized, do it now. */
-       /* This also sets up a lot of global state. */
-       if (a->extract == NULL) {
-               a->extract = (struct extract *)malloc(sizeof(*a->extract));
-               if (a->extract == NULL) {
-                       archive_set_error(&a->archive, ENOMEM, "Can't extract");
-                       return (NULL);
-               }
-               memset(a->extract, 0, sizeof(*a->extract));
-               a->extract->ad = archive_write_disk_new();
-               if (a->extract->ad == NULL) {
-                       archive_set_error(&a->archive, ENOMEM, "Can't extract");
-                       return (NULL);
-               }
-               archive_write_disk_set_standard_lookup(a->extract->ad);
-               a->cleanup_archive_extract = archive_read_extract_cleanup;
-       }
-       return (a->extract);
-}
 
 int
 archive_read_extract(struct archive *_a, struct archive_entry *entry, int flags)
 {
-       struct extract *extract;
+       struct archive_read_extract *extract;
+       struct archive_read * a = (struct archive_read *)_a;
 
-       extract = get_extract((struct archive_read *)_a);
+       extract = __archive_read_get_extract(a);
        if (extract == NULL)
                return (ARCHIVE_FATAL);
-       archive_write_disk_set_options(extract->ad, flags);
-       return (archive_read_extract2(_a, entry, extract->ad));
-}
 
-int
-archive_read_extract2(struct archive *_a, struct archive_entry *entry,
-    struct archive *ad)
-{
-       struct archive_read *a = (struct archive_read *)_a;
-       int r, r2;
-
-       /* Set up for this particular entry. */
-       if (a->skip_file_set)
-               archive_write_disk_set_skip_file(ad,
-                   a->skip_file_dev, a->skip_file_ino);
-       r = archive_write_header(ad, entry);
-       if (r < ARCHIVE_WARN)
-               r = ARCHIVE_WARN;
-       if (r != ARCHIVE_OK)
-               /* If _write_header failed, copy the error. */
-               archive_copy_error(&a->archive, ad);
-       else if (!archive_entry_size_is_set(entry) || archive_entry_size(entry) > 0)
-               /* Otherwise, pour data into the entry. */
-               r = copy_data(_a, ad);
-       r2 = archive_write_finish_entry(ad);
-       if (r2 < ARCHIVE_WARN)
-               r2 = ARCHIVE_WARN;
-       /* Use the first message. */
-       if (r2 != ARCHIVE_OK && r == ARCHIVE_OK)
-               archive_copy_error(&a->archive, ad);
-       /* Use the worst error return. */
-       if (r2 < r)
-               r = r2;
-       return (r);
-}
-
-void
-archive_read_extract_set_progress_callback(struct archive *_a,
-    void (*progress_func)(void *), void *user_data)
-{
-       struct archive_read *a = (struct archive_read *)_a;
-       struct extract *extract = get_extract(a);
-       if (extract != NULL) {
-               extract->extract_progress = progress_func;
-               extract->extract_progress_user_data = user_data;
-       }
-}
-
-static int
-copy_data(struct archive *ar, struct archive *aw)
-{
-       int64_t offset;
-       const void *buff;
-       struct extract *extract;
-       size_t size;
-       int r;
-
-       extract = get_extract((struct archive_read *)ar);
-       if (extract == NULL)
-               return (ARCHIVE_FATAL);
-       for (;;) {
-               r = archive_read_data_block(ar, &buff, &size, &offset);
-               if (r == ARCHIVE_EOF)
-                       return (ARCHIVE_OK);
-               if (r != ARCHIVE_OK)
-                       return (r);
-               r = (int)archive_write_data_block(aw, buff, size, offset);
-               if (r < ARCHIVE_WARN)
-                       r = ARCHIVE_WARN;
-               if (r != ARCHIVE_OK) {
-                       archive_set_error(ar, archive_errno(aw),
-                           "%s", archive_error_string(aw));
-                       return (r);
+       /* If we haven't initialized the archive_write_disk object, do it now. */
+       if (extract->ad == NULL) {
+               extract->ad = archive_write_disk_new();
+               if (extract->ad == NULL) {
+                       archive_set_error(&a->archive, ENOMEM, "Can't extract");
+                       return (ARCHIVE_FATAL);
                }
-               if (extract->extract_progress)
-                       (extract->extract_progress)
-                           (extract->extract_progress_user_data);
+               archive_write_disk_set_standard_lookup(extract->ad);
        }
-}
 
-/*
- * Cleanup function for archive_extract.
- */
-static int
-archive_read_extract_cleanup(struct archive_read *a)
-{
-       int ret = ARCHIVE_OK;
-
-       ret = archive_write_free(a->extract->ad);
-       free(a->extract);
-       a->extract = NULL;
-       return (ret);
+       archive_write_disk_set_options(extract->ad, flags);
+       return (archive_read_extract2(&a->archive, entry, extract->ad));
 }
@@ -32,9 +32,6 @@ __FBSDID("$FreeBSD: src/lib/libarchive/archive_read_extract.c,v 1.61 2008/05/26
 #ifdef HAVE_ERRNO_H
 #include <errno.h>
 #endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
 #ifdef HAVE_STRING_H
 #include <string.h>
 #endif
@@ -43,53 +40,43 @@ __FBSDID("$FreeBSD: src/lib/libarchive/archive_read_extract.c,v 1.61 2008/05/26
 #include "archive_entry.h"
 #include "archive_private.h"
 #include "archive_read_private.h"
-#include "archive_write_disk_private.h"
-
-struct extract {
-       struct archive *ad; /* archive_write_disk object */
-
-       /* Progress function invoked during extract. */
-       void                    (*extract_progress)(void *);
-       void                     *extract_progress_user_data;
-};
 
-static int     archive_read_extract_cleanup(struct archive_read *);
 static int     copy_data(struct archive *ar, struct archive *aw);
-static struct extract *get_extract(struct archive_read *);
+static int     archive_read_extract_cleanup(struct archive_read *);
 
-static struct extract *
-get_extract(struct archive_read *a)
+
+/* Retrieve an extract object without initialising the associated
+ * archive_write_disk object.
+ */
+struct archive_read_extract *
+__archive_read_get_extract(struct archive_read *a)
 {
-       /* If we haven't initialized, do it now. */
-       /* This also sets up a lot of global state. */
        if (a->extract == NULL) {
-               a->extract = (struct extract *)malloc(sizeof(*a->extract));
+               a->extract = (struct archive_read_extract *)malloc(sizeof(*a->extract));
                if (a->extract == NULL) {
                        archive_set_error(&a->archive, ENOMEM, "Can't extract");
                        return (NULL);
                }
                memset(a->extract, 0, sizeof(*a->extract));
-               a->extract->ad = archive_write_disk_new();
-               if (a->extract->ad == NULL) {
-                       archive_set_error(&a->archive, ENOMEM, "Can't extract");
-                       return (NULL);
-               }
-               archive_write_disk_set_standard_lookup(a->extract->ad);
                a->cleanup_archive_extract = archive_read_extract_cleanup;
        }
        return (a->extract);
 }
 
-int
-archive_read_extract(struct archive *_a, struct archive_entry *entry, int flags)
+/*
+ * Cleanup function for archive_extract.
+ */
+static int
+archive_read_extract_cleanup(struct archive_read *a)
 {
-       struct extract *extract;
+       int ret = ARCHIVE_OK;
 
-       extract = get_extract((struct archive_read *)_a);
-       if (extract == NULL)
-               return (ARCHIVE_FATAL);
-       archive_write_disk_set_options(extract->ad, flags);
-       return (archive_read_extract2(_a, entry, extract->ad));
+       if (a->extract->ad != NULL) {
+               ret = archive_write_free(a->extract->ad);
+       }
+       free(a->extract);
+       a->extract = NULL;
+       return (ret);
 }
 
 int
@@ -129,7 +116,7 @@ archive_read_extract_set_progress_callback(struct archive *_a,
     void (*progress_func)(void *), void *user_data)
 {
        struct archive_read *a = (struct archive_read *)_a;
-       struct extract *extract = get_extract(a);
+       struct archive_read_extract *extract = __archive_read_get_extract(a);
        if (extract != NULL) {
                extract->extract_progress = progress_func;
                extract->extract_progress_user_data = user_data;
@@ -141,11 +128,11 @@ copy_data(struct archive *ar, struct archive *aw)
 {
        int64_t offset;
        const void *buff;
-       struct extract *extract;
+       struct archive_read_extract *extract;
        size_t size;
        int r;
 
-       extract = get_extract((struct archive_read *)ar);
+       extract = __archive_read_get_extract((struct archive_read *)ar);
        if (extract == NULL)
                return (ARCHIVE_FATAL);
        for (;;) {
@@ -157,7 +144,7 @@ copy_data(struct archive *ar, struct archive *aw)
                r = (int)archive_write_data_block(aw, buff, size, offset);
                if (r < ARCHIVE_WARN)
                        r = ARCHIVE_WARN;
-               if (r != ARCHIVE_OK) {
+               if (r < ARCHIVE_OK) {
                        archive_set_error(ar, archive_errno(aw),
                            "%s", archive_error_string(aw));
                        return (r);
@@ -167,17 +154,3 @@ copy_data(struct archive *ar, struct archive *aw)
                            (extract->extract_progress_user_data);
        }
 }
-
-/*
- * Cleanup function for archive_extract.
- */
-static int
-archive_read_extract_cleanup(struct archive_read *a)
-{
-       int ret = ARCHIVE_OK;
-
-       ret = archive_write_free(a->extract->ad);
-       free(a->extract);
-       a->extract = NULL;
-       return (ret);
-}
index 8761127..7f020e3 100644 (file)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd February 2, 2012
+.Dd August 14, 2014
 .Dt ARCHIVE_READ_FILTER 3
 .Os
 .Sh NAME
 .Nm archive_read_support_filter_bzip2 ,
 .Nm archive_read_support_filter_compress ,
 .Nm archive_read_support_filter_gzip ,
+.Nm archive_read_support_filter_lz4 ,
 .Nm archive_read_support_filter_lzma ,
 .Nm archive_read_support_filter_none ,
+.Nm archive_read_support_filter_rpm ,
+.Nm archive_read_support_filter_uu ,
 .Nm archive_read_support_filter_xz ,
 .Nm archive_read_support_filter_program ,
 .Nm archive_read_support_filter_program_signature
@@ -50,12 +53,24 @@ Streaming Archive Library (libarchive, -larchive)
 .Ft int
 .Fn archive_read_support_filter_compress "struct archive *"
 .Ft int
+.Fn archive_read_support_filter_grzip "struct archive *"
+.Ft int
 .Fn archive_read_support_filter_gzip "struct archive *"
 .Ft int
+.Fn archive_read_support_filter_lrzip "struct archive *"
+.Ft int
+.Fn archive_read_support_filter_lz4 "struct archive *"
+.Ft int
 .Fn archive_read_support_filter_lzma "struct archive *"
 .Ft int
+.Fn archive_read_support_filter_lzop "struct archive *"
+.Ft int
 .Fn archive_read_support_filter_none "struct archive *"
 .Ft int
+.Fn archive_read_support_filter_rpm "struct archive *"
+.Ft int
+.Fn archive_read_support_filter_uu "struct archive *"
+.Ft int
 .Fn archive_read_support_filter_xz "struct archive *"
 .Ft int
 .Fo archive_read_support_filter_program
@@ -75,9 +90,15 @@ Streaming Archive Library (libarchive, -larchive)
 .It Xo
 .Fn archive_read_support_filter_bzip2 ,
 .Fn archive_read_support_filter_compress ,
+.Fn archive_read_support_filter_grzip ,
 .Fn archive_read_support_filter_gzip ,
+.Fn archive_read_support_filter_lrzip ,
+.Fn archive_read_support_filter_lz4 ,
 .Fn archive_read_support_filter_lzma ,
+.Fn archive_read_support_filter_lzop ,
 .Fn archive_read_support_filter_none ,
+.Fn archive_read_support_filter_rpm ,
+.Fn archive_read_support_filter_uu ,
 .Fn archive_read_support_filter_xz
 .Xc
 Enables auto-detection code and decompression support for the
index 30a740b..4d8272c 100644 (file)
@@ -130,14 +130,14 @@ objects can be found in the overview manual page for
 The callback functions must match the following prototypes:
 .Bl -item -offset indent
 .It
-.Ft typedef ssize_t
+.Ft typedef la_ssize_t
 .Fo archive_read_callback
 .Fa "struct archive *"
 .Fa "void *client_data"
 .Fa "const void **buffer"
 .Fc
 .It
-.Ft typedef off_t
+.Ft typedef la_int64_t
 .Fo archive_skip_callback
 .Fa "struct archive *"
 .Fa "void *client_data"
index e0f95bf..f59cd07 100644 (file)
@@ -59,6 +59,7 @@ struct read_fd_data {
 
 static int     file_close(struct archive *, void *);
 static ssize_t file_read(struct archive *, void *, const void **buff);
+static int64_t file_seek(struct archive *, void *, int64_t request, int);
 static int64_t file_skip(struct archive *, void *, int64_t request);
 
 int
@@ -102,6 +103,7 @@ archive_read_open_fd(struct archive *a, int fd, size_t block_size)
 
        archive_read_set_read_callback(a, file_read);
        archive_read_set_skip_callback(a, file_skip);
+       archive_read_set_seek_callback(a, file_seek);
        archive_read_set_close_callback(a, file_close);
        archive_read_set_callback_data(a, mine);
        return (archive_read_open1(a));
@@ -170,6 +172,33 @@ file_skip(struct archive *a, void *client_data, int64_t request)
        return (-1);
 }
 
+/*
+ * TODO: Store the offset and use it in the read callback.
+ */
+static int64_t
+file_seek(struct archive *a, void *client_data, int64_t request, int whence)
+{
+       struct read_fd_data *mine = (struct read_fd_data *)client_data;
+       int64_t r;
+
+       /* We use off_t here because lseek() is declared that way. */
+       /* See above for notes about when off_t is less than 64 bits. */
+       r = lseek(mine->fd, request, whence);
+       if (r >= 0)
+               return r;
+
+       if (errno == ESPIPE) {
+               archive_set_error(a, errno,
+                   "A file descriptor(%d) is not seekable(PIPE)", mine->fd);
+               return (ARCHIVE_FAILED);
+       } else {
+               /* If the input is corrupted or truncated, fail. */
+               archive_set_error(a, errno,
+                   "Error seeking in a file descriptor(%d)", mine->fd);
+               return (ARCHIVE_FATAL);
+       }
+}
+
 static int
 file_close(struct archive *a, void *client_data)
 {
index 3a33c25..bfe933b 100644 (file)
@@ -83,8 +83,9 @@ archive_read_open_FILE(struct archive *a, FILE *f)
        mine->f = f;
        /*
         * If we can't fstat() the file, it may just be that it's not
-        * a file.  (FILE * objects can wrap many kinds of I/O
-        * streams, some of which don't support fileno()).)
+        * a file.  (On some platforms, FILE * objects can wrap I/O
+        * streams that don't support fileno()).  As a result, fileno()
+        * should be used cautiously.)
         */
        if (fstat(fileno(mine->f), &st) == 0 && S_ISREG(st.st_mode)) {
                archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
@@ -150,7 +151,10 @@ file_skip(struct archive *a, void *client_data, int64_t request)
                        skip = max_skip;
        }
 
-#if HAVE_FSEEKO
+#ifdef __ANDROID__
+        /* fileno() isn't safe on all platforms ... see above. */
+       if (lseek(fileno(mine->f), skip, SEEK_CUR) < 0)
+#elif HAVE_FSEEKO
        if (fseeko(mine->f, skip, SEEK_CUR) != 0)
 #elif HAVE__FSEEKI64
        if (_fseeki64(mine->f, skip, SEEK_CUR) != 0)
index fefcd90..5611aa8 100644 (file)
@@ -103,7 +103,9 @@ int
 archive_read_open_filename(struct archive *a, const char *filename,
     size_t block_size)
 {
-       const char *filenames[2] = { filename, NULL };
+       const char *filenames[2];
+       filenames[0] = filename;
+       filenames[1] = NULL;
        return archive_read_open_filenames(a, filenames, block_size);
 }
 
@@ -176,7 +178,7 @@ archive_read_open_filename_w(struct archive *a, const wchar_t *wfilename,
 #else
                /*
                 * POSIX system does not support a wchar_t interface for
-                * open() system call, so we have to translate a whcar_t
+                * open() system call, so we have to translate a wchar_t
                 * filename to multi-byte one and use it.
                 */
                struct archive_string fn;
index bcc7d6f..ff935a7 100644 (file)
@@ -41,9 +41,9 @@ __FBSDID("$FreeBSD: src/lib/libarchive/archive_read_open_memory.c,v 1.6 2007/07/
  */
 
 struct read_memory_data {
-       unsigned char   *start;
-       unsigned char   *p;
-       unsigned char   *end;
+       const unsigned char     *start;
+       const unsigned char     *p;
+       const unsigned char     *end;
        ssize_t  read_size;
 };
 
@@ -54,7 +54,7 @@ static int64_t        memory_read_skip(struct archive *, void *, int64_t request);
 static ssize_t memory_read(struct archive *, void *, const void **buff);
 
 int
-archive_read_open_memory(struct archive *a, void *buff, size_t size)
+archive_read_open_memory(struct archive *a, const void *buff, size_t size)
 {
        return archive_read_open_memory2(a, buff, size, size);
 }
@@ -65,7 +65,7 @@ archive_read_open_memory(struct archive *a, void *buff, size_t size)
  * test harnesses can exercise block operations inside the library.
  */
 int
-archive_read_open_memory2(struct archive *a, void *buff,
+archive_read_open_memory2(struct archive *a, const void *buff,
     size_t size, size_t read_size)
 {
        struct read_memory_data *mine;
@@ -76,7 +76,7 @@ archive_read_open_memory2(struct archive *a, void *buff,
                return (ARCHIVE_FATAL);
        }
        memset(mine, 0, sizeof(*mine));
-       mine->start = mine->p = (unsigned char *)buff;
+       mine->start = mine->p = (const unsigned char *)buff;
        mine->end = mine->start + size;
        mine->read_size = read_size;
        archive_read_set_open_callback(a, memory_read_open);
index 8a6c859..9b61a53 100644 (file)
  */
 
 #ifndef __LIBARCHIVE_BUILD
+#ifndef __LIBARCHIVE_TEST
 #error This header is only to be used internally to libarchive.
 #endif
+#endif
 
 #ifndef ARCHIVE_READ_PRIVATE_H_INCLUDED
 #define        ARCHIVE_READ_PRIVATE_H_INCLUDED
@@ -141,6 +143,18 @@ struct archive_read_client {
        int64_t position;
        struct archive_read_data_node *dataset;
 };
+struct archive_read_passphrase {
+       char    *passphrase;
+       struct archive_read_passphrase *next;
+};
+
+struct archive_read_extract {
+       struct archive *ad; /* archive_write_disk object */
+
+       /* Progress function invoked during extract. */
+       void                    (*extract_progress)(void *);
+       void                     *extract_progress_user_data;
+};
 
 struct archive_read {
        struct archive  archive;
@@ -152,28 +166,11 @@ struct archive_read {
        int64_t           skip_file_dev;
        int64_t           skip_file_ino;
 
-       /*
-        * Used by archive_read_data() to track blocks and copy
-        * data to client buffers, filling gaps with zero bytes.
-        */
-       const char       *read_data_block;
-       int64_t           read_data_offset;
-       int64_t           read_data_output_offset;
-       size_t            read_data_remaining;
-
-       /*
-        * Used by formats/filters to determine the amount of data
-        * requested from a call to archive_read_data(). This is only
-        * useful when the format/filter has seek support.
-        */
-       char              read_data_is_posix_read;
-       size_t            read_data_requested;
-
        /* Callbacks to open/read/write/close client archive streams. */
        struct archive_read_client client;
 
        /* Registered filter bidders. */
-       struct archive_read_filter_bidder bidders[14];
+       struct archive_read_filter_bidder bidders[16];
 
        /* Last filter in chain */
        struct archive_read_filter *filter;
@@ -207,26 +204,41 @@ struct archive_read {
                int     (*read_data_skip)(struct archive_read *);
                int64_t (*seek_data)(struct archive_read *, int64_t, int);
                int     (*cleanup)(struct archive_read *);
+               int     (*format_capabilties)(struct archive_read *);
+               int     (*has_encrypted_entries)(struct archive_read *);
        }       formats[16];
        struct archive_format_descriptor        *format; /* Active format. */
 
        /*
         * Various information needed by archive_extract.
         */
-       struct extract           *extract;
+       struct archive_read_extract             *extract;
        int                     (*cleanup_archive_extract)(struct archive_read *);
+
+       /*
+        * Decryption passphrase.
+        */
+       struct {
+               struct archive_read_passphrase *first;
+               struct archive_read_passphrase **last;
+               int candiate;
+               archive_passphrase_callback *callback;
+               void *client_data;
+       }               passphrases;
 };
 
 int    __archive_read_register_format(struct archive_read *a,
-           void *format_data,
-           const char *name,
-           int (*bid)(struct archive_read *, int),
-           int (*options)(struct archive_read *, const char *, const char *),
-           int (*read_header)(struct archive_read *, struct archive_entry *),
-           int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *),
-           int (*read_data_skip)(struct archive_read *),
-           int64_t (*seek_data)(struct archive_read *, int64_t, int),
-           int (*cleanup)(struct archive_read *));
+               void *format_data,
+               const char *name,
+               int (*bid)(struct archive_read *, int),
+               int (*options)(struct archive_read *, const char *, const char *),
+               int (*read_header)(struct archive_read *, struct archive_entry *),
+               int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *),
+               int (*read_data_skip)(struct archive_read *),
+               int64_t (*seek_data)(struct archive_read *, int64_t, int),
+               int (*cleanup)(struct archive_read *),
+               int (*format_capabilities)(struct archive_read *),
+               int (*has_encrypted_entries)(struct archive_read *));
 
 int __archive_read_get_bidder(struct archive_read *a,
     struct archive_read_filter_bidder **bidder);
@@ -241,4 +253,12 @@ int64_t    __archive_read_filter_consume(struct archive_read_filter *, int64_t);
 int __archive_read_program(struct archive_read_filter *, const char *);
 void __archive_read_free_filters(struct archive_read *);
 int  __archive_read_close_filters(struct archive_read *);
+struct archive_read_extract *__archive_read_get_extract(struct archive_read *);
+
+
+/*
+ * Get a decryption passphrase.
+ */
+void __archive_read_reset_passphrase(struct archive_read *a);
+const char * __archive_read_next_passphrase(struct archive_read *a);
 #endif
index 6fe9f90..1a251ce 100644 (file)
@@ -193,6 +193,28 @@ Defaults to enabled, use
 .Cm !rockridge
 to disable.
 .El
+.It Format tar
+.Bl -tag -compact -width indent
+.It Cm compat-2x
+Libarchive 2.x incorrectly encoded Unicode filenames on
+some platforms.
+This option mimics the libarchive 2.x filename handling
+so that such archives can be read correctly.
+.It Cm hdrcharset
+The value is used as a character set name that will be
+used when translating filenames.
+.It Cm mac-ext
+Support Mac OS metadata extension that records data in special
+files beginning with a period and underscore.
+Defaults to enabled on Mac OS, disabled on other platforms.
+Use
+.Cm !mac-ext
+to disable.
+.It Cm read_concatenated_archives
+Ignore zeroed blocks in the archive, which occurs when multiple tar archives
+have been concatenated together.  Without this option, only the contents of
+the first concatenated archive would be read.
+.El
 .El
 .\"
 .Sh ERRORS
index 793f8f7..2e2eea6 100644 (file)
@@ -76,18 +76,20 @@ archive_set_format_option(struct archive *_a, const char *m, const char *o,
     const char *v)
 {
        struct archive_read *a = (struct archive_read *)_a;
-       struct archive_format_descriptor *format;
        size_t i;
-       int r, rv = ARCHIVE_WARN;
+       int r, rv = ARCHIVE_WARN, matched_modules = 0;
 
        for (i = 0; i < sizeof(a->formats)/sizeof(a->formats[0]); i++) {
-               format = &a->formats[i];
-               if (format == NULL || format->options == NULL ||
-                   format->name == NULL)
+               struct archive_format_descriptor *format = &a->formats[i];
+
+               if (format->options == NULL || format->name == NULL)
                        /* This format does not support option. */
                        continue;
-               if (m != NULL && strcmp(format->name, m) != 0)
-                       continue;
+               if (m != NULL) {
+                       if (strcmp(format->name, m) != 0)
+                               continue;
+                       ++matched_modules;
+               }
 
                a->format = format;
                r = format->options(a, o, v);
@@ -96,16 +98,13 @@ archive_set_format_option(struct archive *_a, const char *m, const char *o,
                if (r == ARCHIVE_FATAL)
                        return (ARCHIVE_FATAL);
 
-               if (m != NULL)
-                       return (r);
-
                if (r == ARCHIVE_OK)
                        rv = ARCHIVE_OK;
        }
        /* If the format name didn't match, return a special code for
         * _archive_set_option[s]. */
-       if (rv == ARCHIVE_WARN && m != NULL)
-               rv = ARCHIVE_WARN - 1;
+       if (m != NULL && matched_modules == 0)
+               return ARCHIVE_WARN - 1;
        return (rv);
 }
 
@@ -116,7 +115,7 @@ archive_set_filter_option(struct archive *_a, const char *m, const char *o,
        struct archive_read *a = (struct archive_read *)_a;
        struct archive_read_filter *filter;
        struct archive_read_filter_bidder *bidder;
-       int r, rv = ARCHIVE_WARN;
+       int r, rv = ARCHIVE_WARN, matched_modules = 0;
 
        for (filter = a->filter; filter != NULL; filter = filter->upstream) {
                bidder = filter->bidder;
@@ -125,24 +124,24 @@ archive_set_filter_option(struct archive *_a, const char *m, const char *o,
                if (bidder->options == NULL)
                        /* This bidder does not support option */
                        continue;
-               if (m != NULL && strcmp(filter->name, m) != 0)
-                       continue;
+               if (m != NULL) {
+                       if (strcmp(filter->name, m) != 0)
+                               continue;
+                       ++matched_modules;
+               }
 
                r = bidder->options(bidder, o, v);
 
                if (r == ARCHIVE_FATAL)
                        return (ARCHIVE_FATAL);
 
-               if (m != NULL)
-                       return (r);
-
                if (r == ARCHIVE_OK)
                        rv = ARCHIVE_OK;
        }
        /* If the filter name didn't match, return a special code for
         * _archive_set_option[s]. */
-       if (rv == ARCHIVE_WARN && m != NULL)
-               rv = ARCHIVE_WARN - 1;
+       if (m != NULL && matched_modules == 0)
+               return ARCHIVE_WARN - 1;
        return (rv);
 }
 
index b778cfb..68c53de 100644 (file)
@@ -69,6 +69,8 @@ archive_read_support_filter_all(struct archive *a)
        archive_read_support_filter_lzop(a);
        /* The decode code always uses "grzip -d" command-line. */
        archive_read_support_filter_grzip(a);
+       /* Lz4 falls back to "lz4 -d" command-line program. */
+       archive_read_support_filter_lz4(a);
 
        /* Note: We always return ARCHIVE_OK here, even if some of the
         * above return ARCHIVE_WARN.  The intent here is to enable
index 3f5d1f3..e05132d 100644 (file)
@@ -185,19 +185,22 @@ compress_bidder_bid(struct archive_read_filter_bidder *self,
 
        (void)self; /* UNUSED */
 
-       buffer = __archive_read_filter_ahead(filter, 2, &avail);
+       /* Shortest valid compress file is 3 bytes. */
+       buffer = __archive_read_filter_ahead(filter, 3, &avail);
 
        if (buffer == NULL)
                return (0);
 
        bits_checked = 0;
+       /* First two bytes are the magic value */
        if (buffer[0] != 0x1F || buffer[1] != 0x9D)
                return (0);
-       bits_checked += 16;
-
-       /*
-        * TODO: Verify more.
-        */
+       /* Third byte holds compression parameters. */
+       if (buffer[2] & 0x20) /* Reserved bit, must be zero. */
+               return (0);
+       if (buffer[2] & 0x40) /* Reserved bit, must be zero. */
+               return (0);
+       bits_checked += 18;
 
        return (bits_checked);
 }
@@ -239,7 +242,13 @@ compress_bidder_init(struct archive_read_filter *self)
        (void)getbits(self, 8); /* Skip first signature byte. */
        (void)getbits(self, 8); /* Skip second signature byte. */
 
+       /* Get compression parameters. */
        code = getbits(self, 8);
+       if ((code & 0x1f) > 16) {
+               archive_set_error(&self->archive->archive, -1,
+                   "Invalid compressed data");
+               return (ARCHIVE_FATAL);
+       }
        state->maxcode_bits = code & 0x1f;
        state->maxcode = (1 << state->maxcode_bits);
        state->use_reset_code = code & 0x80;
@@ -368,7 +377,8 @@ next_code(struct archive_read_filter *self)
                return (next_code(self));
        }
 
-       if (code > state->free_ent) {
+       if (code > state->free_ent
+           || (code == state->free_ent && state->oldcode < 0)) {
                /* An invalid code is a fatal error. */
                archive_set_error(&(self->archive->archive), -1,
                    "Invalid compressed data");
diff --git a/contrib/libarchive/libarchive/archive_read_support_filter_lz4.c b/contrib/libarchive/libarchive/archive_read_support_filter_lz4.c
new file mode 100644 (file)
index 0000000..e877917
--- /dev/null
@@ -0,0 +1,737 @@
+/*-
+ * Copyright (c) 2014 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_LZ4_H
+#include <lz4.h>
+#endif
+
+#include "archive.h"
+#include "archive_endian.h"
+#include "archive_private.h"
+#include "archive_read_private.h"
+#include "archive_xxhash.h"
+
+#define LZ4_MAGICNUMBER                0x184d2204
+#define LZ4_SKIPPABLED         0x184d2a50
+#define LZ4_LEGACY             0x184c2102
+
+#if defined(HAVE_LIBLZ4)
+struct private_data {
+       enum {  SELECT_STREAM,
+               READ_DEFAULT_STREAM,
+               READ_DEFAULT_BLOCK,
+               READ_LEGACY_STREAM,
+               READ_LEGACY_BLOCK,
+       }               stage;
+       struct {
+               unsigned block_independence:1;
+               unsigned block_checksum:3;
+               unsigned stream_size:1;
+               unsigned stream_checksum:1;
+               unsigned preset_dictionary:1;
+               int      block_maximum_size;
+       } flags;
+       int64_t          stream_size;
+       uint32_t         dict_id;
+       char            *out_block;
+       size_t           out_block_size;
+
+       /* Bytes read but not yet consumed via __archive_read_consume() */
+       size_t           unconsumed;
+       size_t           decoded_size;
+       void            *xxh32_state;
+
+       char             valid; /* True = decompressor is initialized */
+       char             eof; /* True = found end of compressed data. */
+};
+
+#define LEGACY_BLOCK_SIZE      (8 * 1024 * 1024)
+
+/* Lz4 filter */
+static ssize_t lz4_filter_read(struct archive_read_filter *, const void **);
+static int     lz4_filter_close(struct archive_read_filter *);
+#endif
+
+/*
+ * Note that we can detect lz4 archives even if we can't decompress
+ * them.  (In fact, we like detecting them because we can give better
+ * error messages.)  So the bid framework here gets compiled even
+ * if liblz4 is unavailable.
+ */
+static int     lz4_reader_bid(struct archive_read_filter_bidder *, struct archive_read_filter *);
+static int     lz4_reader_init(struct archive_read_filter *);
+static int     lz4_reader_free(struct archive_read_filter_bidder *);
+#if defined(HAVE_LIBLZ4)
+static ssize_t  lz4_filter_read_default_stream(struct archive_read_filter *,
+                   const void **);
+static ssize_t  lz4_filter_read_legacy_stream(struct archive_read_filter *,
+                   const void **);
+#endif
+
+int
+archive_read_support_filter_lz4(struct archive *_a)
+{
+       struct archive_read *a = (struct archive_read *)_a;
+       struct archive_read_filter_bidder *reader;
+
+       archive_check_magic(_a, ARCHIVE_READ_MAGIC,
+           ARCHIVE_STATE_NEW, "archive_read_support_filter_lz4");
+
+       if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK)
+               return (ARCHIVE_FATAL);
+
+       reader->data = NULL;
+       reader->name = "lz4";
+       reader->bid = lz4_reader_bid;
+       reader->init = lz4_reader_init;
+       reader->options = NULL;
+       reader->free = lz4_reader_free;
+#if defined(HAVE_LIBLZ4)
+       return (ARCHIVE_OK);
+#else
+       archive_set_error(_a, ARCHIVE_ERRNO_MISC,
+           "Using external lz4 program");
+       return (ARCHIVE_WARN);
+#endif
+}
+
+static int
+lz4_reader_free(struct archive_read_filter_bidder *self){
+       (void)self; /* UNUSED */
+       return (ARCHIVE_OK);
+}
+
+/*
+ * Test whether we can handle this data.
+ *
+ * This logic returns zero if any part of the signature fails.  It
+ * also tries to Do The Right Thing if a very short buffer prevents us
+ * from verifying as much as we would like.
+ */
+static int
+lz4_reader_bid(struct archive_read_filter_bidder *self,
+    struct archive_read_filter *filter)
+{
+       const unsigned char *buffer;
+       ssize_t avail;
+       int bits_checked;
+       uint32_t number;
+
+       (void)self; /* UNUSED */
+
+       /* Minimal lz4 archive is 11 bytes. */
+       buffer = __archive_read_filter_ahead(filter, 11, &avail);
+       if (buffer == NULL)
+               return (0);
+
+       /* First four bytes must be LZ4 magic numbers. */
+       bits_checked = 0;
+       if ((number = archive_le32dec(buffer)) == LZ4_MAGICNUMBER) {
+               unsigned char flag, BD;
+
+               bits_checked += 32;
+               /* Next follows a stream descriptor. */
+               /* Descriptor Flags. */
+               flag = buffer[4];
+               /* A version number must be "01". */
+               if (((flag & 0xc0) >> 6) != 1)
+                       return (0);
+               /* A reserved bit must be "0". */
+               if (flag & 2)
+                       return (0);
+               bits_checked += 8;
+               BD = buffer[5];
+               /* A block maximum size shuld be more than 3. */
+               if (((BD & 0x70) >> 4) < 4)
+                       return (0);
+               /* Reserved bits must be "0". */
+               if (BD & ~0x70)
+                       return (0);
+               bits_checked += 8;
+       } else if (number == LZ4_LEGACY) {
+               bits_checked += 32;
+       }
+       
+       return (bits_checked);
+}
+
+#if !defined(HAVE_LIBLZ4)
+
+/*
+ * If we don't have the library on this system, we can't actually do the
+ * decompression.  We can, however, still detect compressed archives
+ * and emit a useful message.
+ */
+static int
+lz4_reader_init(struct archive_read_filter *self)
+{
+       int r;
+
+       r = __archive_read_program(self, "lz4 -d -q");
+       /* Note: We set the format here even if __archive_read_program()
+        * above&