Author: mm
Date: Tue Nov 29 22:14:42 2016
New Revision: 309300
URL: https://svnweb.freebsd.org/changeset/base/309300

Log:
  MFV r309299:
  Sync libarchive with vendor.
  
  Important vendor bugfixes (relevant to FreeBSD):
  #821: tar -P cannot extract hardlinks through symlinks
  #825: Add sanity check of tar "uid, "gid" and "mtime" fields
  
  PR:           213255
  Reported by:  Tijl Coosemans <t...@freebsd.org>
  MFC after:    1 week

Added:
  head/contrib/libarchive/libarchive/test/test_compat_gtar_2.tar.uu
     - copied unchanged from r309299, 
vendor/libarchive/dist/libarchive/test/test_compat_gtar_2.tar.uu
  head/contrib/libarchive/libarchive/test/test_compat_star_acl_posix1e.c
     - copied unchanged from r309299, 
vendor/libarchive/dist/libarchive/test/test_compat_star_acl_posix1e.c
  head/contrib/libarchive/libarchive/test/test_compat_star_acl_posix1e.tar.uu
     - copied unchanged from r309299, 
vendor/libarchive/dist/libarchive/test/test_compat_star_acl_posix1e.tar.uu
  head/contrib/libarchive/libarchive/test/test_read_format_raw.bufr.uu
     - copied unchanged from r309299, 
vendor/libarchive/dist/libarchive/test/test_read_format_raw.bufr.uu
Modified:
  head/contrib/libarchive/NEWS
  head/contrib/libarchive/libarchive/archive_acl.c
  head/contrib/libarchive/libarchive/archive_entry.c
  head/contrib/libarchive/libarchive/archive_entry.h
  head/contrib/libarchive/libarchive/archive_entry_acl.3
  head/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c
  head/contrib/libarchive/libarchive/archive_read_support_filter_xz.c
  head/contrib/libarchive/libarchive/archive_read_support_format_tar.c
  head/contrib/libarchive/libarchive/archive_read_support_format_xar.c
  head/contrib/libarchive/libarchive/archive_write_disk_posix.c
  head/contrib/libarchive/libarchive/test/test_compat_gtar.c
  head/contrib/libarchive/libarchive/test/test_read_format_raw.c
  head/contrib/libarchive/libarchive/test/test_sparse_basic.c
  head/contrib/libarchive/tar/test/test_symlink_dir.c
  head/lib/libarchive/tests/Makefile
Directory Properties:
  head/contrib/libarchive/   (props changed)

Modified: head/contrib/libarchive/NEWS
==============================================================================
--- head/contrib/libarchive/NEWS        Tue Nov 29 21:53:16 2016        
(r309299)
+++ head/contrib/libarchive/NEWS        Tue Nov 29 22:14:42 2016        
(r309300)
@@ -1,3 +1,5 @@
+Oct 26, 2016: Remove liblzmadec support
+
 Oct 23, 2016: libarchive 3.2.2 released
     Security release
 

Modified: head/contrib/libarchive/libarchive/archive_acl.c
==============================================================================
--- head/contrib/libarchive/libarchive/archive_acl.c    Tue Nov 29 21:53:16 
2016        (r309299)
+++ head/contrib/libarchive/libarchive/archive_acl.c    Tue Nov 29 22:14:42 
2016        (r309300)
@@ -94,6 +94,7 @@ archive_acl_clear(struct archive_acl *ac
                acl->acl_text = NULL;
        }
        acl->acl_p = NULL;
+       acl->acl_types = 0;
        acl->acl_state = 0; /* Not counting. */
 }
 
@@ -284,8 +285,11 @@ acl_new_entry(struct archive_acl *acl,
        aq = NULL;
        while (ap != NULL) {
                if (ap->type == type && ap->tag == tag && ap->id == id) {
-                       ap->permset = permset;
-                       return (ap);
+                       if (id != -1 || (tag != ARCHIVE_ENTRY_ACL_USER &&
+                           tag != ARCHIVE_ENTRY_ACL_GROUP)) {
+                               ap->permset = permset;
+                               return (ap);
+                       }
                }
                aq = ap;
                ap = ap->next;

Modified: head/contrib/libarchive/libarchive/archive_entry.c
==============================================================================
--- head/contrib/libarchive/libarchive/archive_entry.c  Tue Nov 29 21:53:16 
2016        (r309299)
+++ head/contrib/libarchive/libarchive/archive_entry.c  Tue Nov 29 22:14:42 
2016        (r309300)
@@ -1442,6 +1442,15 @@ archive_entry_acl_add_entry_w(struct arc
 }
 
 /*
+ * Return a bitmask of ACL types in an archive entry ACL list
+ */
+int
+archive_entry_acl_types(struct archive_entry *entry)
+{
+       return ((&entry->acl)->acl_types);
+}
+
+/*
  * Return a count of entries matching "want_type".
  */
 int

Modified: head/contrib/libarchive/libarchive/archive_entry.h
==============================================================================
--- head/contrib/libarchive/libarchive/archive_entry.h  Tue Nov 29 21:53:16 
2016        (r309299)
+++ head/contrib/libarchive/libarchive/archive_entry.h  Tue Nov 29 22:14:42 
2016        (r309300)
@@ -508,6 +508,9 @@ __LA_DECL const wchar_t     *archive_entry_a
 __LA_DECL const char *archive_entry_acl_text(struct archive_entry *,
                    int /* flags */);
 
+/* Return bitmask of ACL types in an archive entry */
+__LA_DECL int   archive_entry_acl_types(struct archive_entry *);
+
 /* Return a count of entries matching 'want_type' */
 __LA_DECL int   archive_entry_acl_count(struct archive_entry *, int /* 
want_type */);
 

Modified: head/contrib/libarchive/libarchive/archive_entry_acl.3
==============================================================================
--- head/contrib/libarchive/libarchive/archive_entry_acl.3      Tue Nov 29 
21:53:16 2016        (r309299)
+++ head/contrib/libarchive/libarchive/archive_entry_acl.3      Tue Nov 29 
22:14:42 2016        (r309300)
@@ -33,7 +33,8 @@
 .Nm archive_entry_acl_next ,
 .Nm archive_entry_acl_next_w ,
 .Nm archive_entry_acl_reset ,
-.Nm archive_entry_acl_text_w
+.Nm archive_entry_acl_text_w ,
+.Nm archive_entry_acl_types
 .Nd functions for manipulating Access Control Lists in archive entry 
descriptions
 .Sh LIBRARY
 Streaming Archive Library (libarchive, -larchive)
@@ -85,6 +86,8 @@ Streaming Archive Library (libarchive, -
 .Fn archive_entry_acl_reset "struct archive_entry *a" "int type"
 .Ft const wchar_t *
 .Fn archive_entry_acl_text_w "struct archive_entry *a" "int flags"
+.Ft int
+.Fn archive_entry_acl_types "struct archive_entry *a"
 .\" enum?
 .Sh DESCRIPTION
 An
@@ -192,6 +195,11 @@ The returned long string is valid until 
 .Fn archive_entry_acl_add_entry_w
 or
 .Fn archive_entry_acl_text_w .
+.Pp
+.Fn archive_entry_acl_types
+get ACL entry types contained in an archive entry's ACL. As POSIX.1e and NFSv4
+ACL entries cannot be mixed, this function is a very efficient way to detect if
+an ACL already contains POSIX.1e or NFSv4 ACL entries.
 .Sh RETURN VALUES
 .Fn archive_entry_acl_count
 and
@@ -225,6 +233,9 @@ The returned long string is valid until 
 .Fn archive_entry_acl_add_entry_w
 or
 .Fn archive_entry_acl_text_w .
+.Pp
+.Fn archive_entry_acl_types
+returns a bitmask of ACL entry types or 0 if archive entry has no ACL entries.
 .Sh SEE ALSO
 .Xr archive_entry 3
 .Xr libarchive 3 ,

Modified: head/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c
==============================================================================
--- head/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c      
Tue Nov 29 21:53:16 2016        (r309299)
+++ head/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c      
Tue Nov 29 22:14:42 2016        (r309300)
@@ -125,6 +125,10 @@ static int setup_xattrs(struct archive_r
     struct archive_entry *, int *fd);
 static int setup_sparse(struct archive_read_disk *,
     struct archive_entry *, int *fd);
+#if defined(HAVE_LINUX_FIEMAP_H)
+static int setup_sparse_fiemap(struct archive_read_disk *,
+    struct archive_entry *, int *fd);
+#endif
 
 int
 archive_read_disk_entry_from_file(struct archive *_a,
@@ -1124,7 +1128,7 @@ setup_xattrs(struct archive_read_disk *a
 #if defined(HAVE_LINUX_FIEMAP_H)
 
 /*
- * Linux sparse interface.
+ * Linux FIEMAP sparse interface.
  *
  * The FIEMAP ioctl returns an "extent" for each physical allocation
  * on disk.  We need to process those to generate a more compact list
@@ -1139,7 +1143,7 @@ setup_xattrs(struct archive_read_disk *a
  */
 
 static int
-setup_sparse(struct archive_read_disk *a,
+setup_sparse_fiemap(struct archive_read_disk *a,
     struct archive_entry *entry, int *fd)
 {
        char buff[4096];
@@ -1191,7 +1195,7 @@ setup_sparse(struct archive_read_disk *a
                        /* When something error happens, it is better we
                         * should return ARCHIVE_OK because an earlier
                         * version(<2.6.28) cannot perfom FS_IOC_FIEMAP. */
-                       goto exit_setup_sparse;
+                       goto exit_setup_sparse_fiemap;
                }
                if (fm->fm_mapped_extents == 0) {
                        if (iters == 0) {
@@ -1226,14 +1230,24 @@ setup_sparse(struct archive_read_disk *a
                } else
                        break;
        }
-exit_setup_sparse:
+exit_setup_sparse_fiemap:
        return (exit_sts);
 }
 
-#elif defined(SEEK_HOLE) && defined(SEEK_DATA) && defined(_PC_MIN_HOLE_SIZE)
+#if !defined(SEEK_HOLE) || !defined(SEEK_DATA)
+static int
+setup_sparse(struct archive_read_disk *a,
+    struct archive_entry *entry, int *fd)
+{
+       return setup_sparse_fiemap(a, entry, fd);
+}
+#endif
+#endif /* defined(HAVE_LINUX_FIEMAP_H) */
+
+#if defined(SEEK_HOLE) && defined(SEEK_DATA)
 
 /*
- * FreeBSD and Solaris sparse interface.
+ * SEEK_HOLE sparse interface (FreeBSD, Linux, Solaris)
  */
 
 static int
@@ -1241,8 +1255,8 @@ setup_sparse(struct archive_read_disk *a
     struct archive_entry *entry, int *fd)
 {
        int64_t size;
-       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 */
+       off_t initial_off;
+       off_t off_s, off_e;
        int exit_sts = ARCHIVE_OK;
        int check_fully_sparse = 0;
 
@@ -1268,8 +1282,10 @@ setup_sparse(struct archive_read_disk *a
        }
 
        if (*fd >= 0) {
+#ifdef _PC_MIN_HOLE_SIZE
                if (fpathconf(*fd, _PC_MIN_HOLE_SIZE) <= 0)
                        return (ARCHIVE_OK);
+#endif
                initial_off = lseek(*fd, 0, SEEK_CUR);
                if (initial_off != 0)
                        lseek(*fd, 0, SEEK_SET);
@@ -1280,8 +1296,10 @@ setup_sparse(struct archive_read_disk *a
                if (path == NULL)
                        path = archive_entry_pathname(entry);
                        
+#ifdef _PC_MIN_HOLE_SIZE
                if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0)
                        return (ARCHIVE_OK);
+#endif
                *fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
                if (*fd < 0) {
                        archive_set_error(&a->archive, errno,
@@ -1292,6 +1310,19 @@ setup_sparse(struct archive_read_disk *a
                initial_off = 0;
        }
 
+#ifndef _PC_MIN_HOLE_SIZE
+       /* Check if the underlying filesystem supports seek hole */
+       off_s = lseek(*fd, 0, SEEK_HOLE);
+       if (off_s < 0)
+#if defined(HAVE_LINUX_FIEMAP_H)
+               return setup_sparse_fiemap(a, entry, fd);
+#else
+               goto exit_setup_sparse;
+#endif
+       else if (off_s > 0)
+               lseek(*fd, 0, SEEK_SET);
+#endif
+
        off_s = 0;
        size = archive_entry_size(entry);
        while (off_s < size) {
@@ -1341,7 +1372,7 @@ exit_setup_sparse:
        return (exit_sts);
 }
 
-#else
+#elif !defined(HAVE_LINUX_FIEMAP_H)
 
 /*
  * Generic (stub) sparse support.

Modified: head/contrib/libarchive/libarchive/archive_read_support_filter_xz.c
==============================================================================
--- head/contrib/libarchive/libarchive/archive_read_support_filter_xz.c Tue Nov 
29 21:53:16 2016        (r309299)
+++ head/contrib/libarchive/libarchive/archive_read_support_filter_xz.c Tue Nov 
29 22:14:42 2016        (r309300)
@@ -43,8 +43,6 @@ __FBSDID("$FreeBSD$");
 #endif
 #if HAVE_LZMA_H
 #include <lzma.h>
-#elif HAVE_LZMADEC_H
-#include <lzmadec.h>
 #endif
 
 #include "archive.h"
@@ -82,19 +80,6 @@ static ssize_t       xz_filter_read(struct arc
 static int     xz_filter_close(struct archive_read_filter *);
 static int     xz_lzma_bidder_init(struct archive_read_filter *);
 
-#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC
-
-struct private_data {
-       lzmadec_stream   stream;
-       unsigned char   *out_block;
-       size_t           out_block_size;
-       int64_t          total_out;
-       char             eof; /* True = found end of compressed data. */
-};
-
-/* Lzma-only filter */
-static ssize_t lzma_filter_read(struct archive_read_filter *, const void **);
-static int     lzma_filter_close(struct archive_read_filter *);
 #endif
 
 /*
@@ -178,8 +163,6 @@ archive_read_support_filter_lzma(struct 
        bidder->free = NULL;
 #if HAVE_LZMA_H && HAVE_LIBLZMA
        return (ARCHIVE_OK);
-#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC
-       return (ARCHIVE_OK);
 #else
        archive_set_error(_a, ARCHIVE_ERRNO_MISC,
            "Using external lzma program for lzma decompression");
@@ -763,175 +746,6 @@ xz_filter_close(struct archive_read_filt
 
 #else
 
-#if HAVE_LZMADEC_H && HAVE_LIBLZMADEC
-
-/*
- * If we have the older liblzmadec library, then we can handle
- * LZMA streams but not XZ streams.
- */
-
-/*
- * Setup the callbacks.
- */
-static int
-lzma_bidder_init(struct archive_read_filter *self)
-{
-       static const size_t out_block_size = 64 * 1024;
-       void *out_block;
-       struct private_data *state;
-       ssize_t ret, avail_in;
-
-       self->code = ARCHIVE_FILTER_LZMA;
-       self->name = "lzma";
-
-       state = (struct private_data *)calloc(sizeof(*state), 1);
-       out_block = (unsigned char *)malloc(out_block_size);
-       if (state == NULL || out_block == NULL) {
-               archive_set_error(&self->archive->archive, ENOMEM,
-                   "Can't allocate data for lzma decompression");
-               free(out_block);
-               free(state);
-               return (ARCHIVE_FATAL);
-       }
-
-       self->data = state;
-       state->out_block_size = out_block_size;
-       state->out_block = out_block;
-       self->read = lzma_filter_read;
-       self->skip = NULL; /* not supported */
-       self->close = lzma_filter_close;
-
-       /* Prime the lzma library with 18 bytes of input. */
-       state->stream.next_in = (unsigned char *)(uintptr_t)
-           __archive_read_filter_ahead(self->upstream, 18, &avail_in);
-       if (state->stream.next_in == NULL)
-               return (ARCHIVE_FATAL);
-       state->stream.avail_in = avail_in;
-       state->stream.next_out = state->out_block;
-       state->stream.avail_out = state->out_block_size;
-
-       /* Initialize compression library. */
-       ret = lzmadec_init(&(state->stream));
-       __archive_read_filter_consume(self->upstream,
-           avail_in - state->stream.avail_in);
-       if (ret == LZMADEC_OK)
-               return (ARCHIVE_OK);
-
-       /* Library setup failed: Clean up. */
-       archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
-           "Internal error initializing lzma library");
-
-       /* Override the error message if we know what really went wrong. */
-       switch (ret) {
-       case LZMADEC_HEADER_ERROR:
-               archive_set_error(&self->archive->archive,
-                   ARCHIVE_ERRNO_MISC,
-                   "Internal error initializing compression library: "
-                   "invalid header");
-               break;
-       case LZMADEC_MEM_ERROR:
-               archive_set_error(&self->archive->archive, ENOMEM,
-                   "Internal error initializing compression library: "
-                   "out of memory");
-               break;
-       }
-
-       free(state->out_block);
-       free(state);
-       self->data = NULL;
-       return (ARCHIVE_FATAL);
-}
-
-/*
- * Return the next block of decompressed data.
- */
-static ssize_t
-lzma_filter_read(struct archive_read_filter *self, const void **p)
-{
-       struct private_data *state;
-       size_t decompressed;
-       ssize_t avail_in, ret;
-
-       state = (struct private_data *)self->data;
-
-       /* Empty our output buffer. */
-       state->stream.next_out = state->out_block;
-       state->stream.avail_out = state->out_block_size;
-
-       /* Try to fill the output buffer. */
-       while (state->stream.avail_out > 0 && !state->eof) {
-               state->stream.next_in = (unsigned char *)(uintptr_t)
-                   __archive_read_filter_ahead(self->upstream, 1, &avail_in);
-               if (state->stream.next_in == NULL && avail_in < 0) {
-                       archive_set_error(&self->archive->archive,
-                           ARCHIVE_ERRNO_MISC,
-                           "truncated lzma input");
-                       return (ARCHIVE_FATAL);
-               }
-               state->stream.avail_in = avail_in;
-
-               /* Decompress as much as we can in one pass. */
-               ret = lzmadec_decode(&(state->stream), avail_in == 0);
-               switch (ret) {
-               case LZMADEC_STREAM_END: /* Found end of stream. */
-                       state->eof = 1;
-                       /* FALL THROUGH */
-               case LZMADEC_OK: /* Decompressor made some progress. */
-                       __archive_read_filter_consume(self->upstream,
-                           avail_in - state->stream.avail_in);
-                       break;
-               case LZMADEC_BUF_ERROR: /* Insufficient input data? */
-                       archive_set_error(&self->archive->archive,
-                           ARCHIVE_ERRNO_MISC,
-                           "Insufficient compressed data");
-                       return (ARCHIVE_FATAL);
-               default:
-                       /* Return an error. */
-                       archive_set_error(&self->archive->archive,
-                           ARCHIVE_ERRNO_MISC,
-                           "Lzma decompression failed");
-                       return (ARCHIVE_FATAL);
-               }
-       }
-
-       decompressed = state->stream.next_out - state->out_block;
-       state->total_out += decompressed;
-       if (decompressed == 0)
-               *p = NULL;
-       else
-               *p = state->out_block;
-       return (decompressed);
-}
-
-/*
- * Clean up the decompressor.
- */
-static int
-lzma_filter_close(struct archive_read_filter *self)
-{
-       struct private_data *state;
-       int ret;
-
-       state = (struct private_data *)self->data;
-       ret = ARCHIVE_OK;
-       switch (lzmadec_end(&(state->stream))) {
-       case LZMADEC_OK:
-               break;
-       default:
-               archive_set_error(&(self->archive->archive),
-                   ARCHIVE_ERRNO_MISC,
-                   "Failed to clean up %s compressor",
-                   self->archive->archive.compression_name);
-               ret = ARCHIVE_FATAL;
-       }
-
-       free(state->out_block);
-       free(state);
-       return (ret);
-}
-
-#else
-
 /*
  *
  * If we have no suitable library on this system, we can't actually do
@@ -953,9 +767,6 @@ lzma_bidder_init(struct archive_read_fil
        return (r);
 }
 
-#endif /* HAVE_LZMADEC_H */
-
-
 static int
 xz_bidder_init(struct archive_read_filter *self)
 {
@@ -984,5 +795,4 @@ lzip_bidder_init(struct archive_read_fil
        return (r);
 }
 
-
 #endif /* HAVE_LZMA_H */

Modified: head/contrib/libarchive/libarchive/archive_read_support_format_tar.c
==============================================================================
--- head/contrib/libarchive/libarchive/archive_read_support_format_tar.c        
Tue Nov 29 21:53:16 2016        (r309299)
+++ head/contrib/libarchive/libarchive/archive_read_support_format_tar.c        
Tue Nov 29 22:14:42 2016        (r309300)
@@ -294,6 +294,46 @@ archive_read_format_tar_cleanup(struct a
        return (ARCHIVE_OK);
 }
 
+static int
+validate_number_field(const char* p_field, size_t i_size)
+{
+       unsigned char marker = (unsigned char)p_field[0];
+       /* octal? */
+       if ((marker >= '0' && marker <= '7') || marker == ' ') {
+               size_t i = 0;
+               int octal_found = 0;
+               for (i = 0; i < i_size; ++i) {
+                       switch (p_field[i])
+                       {
+                       case ' ': /* skip any leading spaces and trailing 
space*/
+                               if (octal_found == 0 || i == i_size - 1) {
+                                       continue;
+                               }
+                               break;
+                       case '\0': /* null is allowed only at the end */
+                               if (i != i_size - 1) {
+                                       return 0;
+                               }
+                               break;
+                       /* rest must be octal digits */
+                       case '0': case '1': case '2': case '3':
+                       case '4': case '5': case '6': case '7':
+                               ++octal_found;
+                               break;
+                       }
+               }
+               return octal_found > 0;
+       }
+       /* base 256 (i.e. binary number) */
+       else if (marker == 128 || marker == 255 || marker == 0) {
+               /* nothing to check */
+               return 1;
+       }
+       /* not a number field */
+       else {
+               return 0;
+       }
+}
 
 static int
 archive_read_format_tar_bid(struct archive_read *a, int best_bid)
@@ -346,23 +386,23 @@ archive_read_format_tar_bid(struct archi
                return (0);
        bid += 2;  /* 6 bits of variation in an 8-bit field leaves 2 bits. */
 
-       /* Sanity check: Look at first byte of mode field. */
-       switch (255 & (unsigned)header->mode[0]) {
-       case 0: case 255:
-               /* Base-256 value: No further verification possible! */
-               break;
-       case ' ': /* Not recommended, but not illegal, either. */
-               break;
-       case '0': case '1': case '2': case '3':
-       case '4': case '5': case '6': case '7':
-               /* Octal Value. */
-               /* TODO: Check format of remainder of this field. */
-               break;
-       default:
-               /* Not a valid mode; bail out here. */
-               return (0);
+       /*
+        * Check format of mode/uid/gid/mtime/size/rdevmajor/rdevminor fields.
+        * These are usually octal numbers but GNU tar encodes "big" values as
+        * base256 and leading zeroes are sometimes replaced by spaces.
+        * Even the null terminator is sometimes omitted. Anyway, must be 
checked
+        * to avoid false positives.
+        */
+       if (bid > 0 &&
+               (validate_number_field(header->mode, sizeof(header->mode)) == 0 
||
+                validate_number_field(header->uid, sizeof(header->uid)) == 0 ||
+                validate_number_field(header->gid, sizeof(header->gid)) == 0 ||
+                validate_number_field(header->mtime, sizeof(header->mtime)) == 
0 ||
+                validate_number_field(header->size, sizeof(header->size)) == 0 
||
+                validate_number_field(header->rdevmajor, 
sizeof(header->rdevmajor)) == 0 ||
+                validate_number_field(header->rdevminor, 
sizeof(header->rdevminor)) == 0)) {
+                       bid = 0;
        }
-       /* TODO: Sanity test uid/gid/size/mtime/rdevmajor/rdevminor fields. */
 
        return (bid);
 }

Modified: head/contrib/libarchive/libarchive/archive_read_support_format_xar.c
==============================================================================
--- head/contrib/libarchive/libarchive/archive_read_support_format_xar.c        
Tue Nov 29 21:53:16 2016        (r309299)
+++ head/contrib/libarchive/libarchive/archive_read_support_format_xar.c        
Tue Nov 29 22:14:42 2016        (r309300)
@@ -43,8 +43,6 @@ __FBSDID("$FreeBSD$");
 #endif
 #if HAVE_LZMA_H
 #include <lzma.h>
-#elif HAVE_LZMADEC_H
-#include <lzmadec.h>
 #endif
 #ifdef HAVE_ZLIB_H
 #include <zlib.h>
@@ -334,9 +332,6 @@ struct xar {
 #if HAVE_LZMA_H && HAVE_LIBLZMA
        lzma_stream              lzstream;
        int                      lzstream_valid;
-#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC
-       lzmadec_stream           lzstream;
-       int                      lzstream_valid;
 #endif
        /*
         * For Checksum data.
@@ -1526,34 +1521,6 @@ decompression_init(struct archive_read *
                xar->lzstream.total_in = 0;
                xar->lzstream.total_out = 0;
                break;
-#elif defined(HAVE_LZMADEC_H) && defined(HAVE_LIBLZMADEC)
-       case LZMA:
-               if (xar->lzstream_valid)
-                       lzmadec_end(&(xar->lzstream));
-               r = lzmadec_init(&(xar->lzstream));
-               if (r != LZMADEC_OK) {
-                       switch (r) {
-                       case LZMADEC_HEADER_ERROR:
-                               archive_set_error(&a->archive,
-                                   ARCHIVE_ERRNO_MISC,
-                                   "Internal error initializing "
-                                   "compression library: "
-                                   "invalid header");
-                               break;
-                       case LZMADEC_MEM_ERROR:
-                               archive_set_error(&a->archive,
-                                   ENOMEM,
-                                   "Internal error initializing "
-                                   "compression library: "
-                                   "out of memory");
-                               break;
-                       }
-                       return (ARCHIVE_FATAL);
-               }
-               xar->lzstream_valid = 1;
-               xar->lzstream.total_in = 0;
-               xar->lzstream.total_out = 0;
-               break;
 #endif
        /*
         * Unsupported compression.
@@ -1563,9 +1530,7 @@ decompression_init(struct archive_read *
        case BZIP2:
 #endif
 #if !defined(HAVE_LZMA_H) || !defined(HAVE_LIBLZMA)
-#if !defined(HAVE_LZMADEC_H) || !defined(HAVE_LIBLZMADEC)
        case LZMA:
-#endif
        case XZ:
 #endif
                switch (xar->entry_encoding) {
@@ -1685,46 +1650,12 @@ decompress(struct archive_read *a, const
                *used = avail_in - xar->lzstream.avail_in;
                *outbytes = avail_out - xar->lzstream.avail_out;
                break;
-#elif defined(HAVE_LZMADEC_H) && defined(HAVE_LIBLZMADEC)
-       case LZMA:
-               xar->lzstream.next_in = (unsigned char *)(uintptr_t)b;
-               xar->lzstream.avail_in = avail_in;
-               xar->lzstream.next_out = (unsigned char *)outbuff;
-               xar->lzstream.avail_out = avail_out;
-               r = lzmadec_decode(&(xar->lzstream), 0);
-               switch (r) {
-               case LZMADEC_STREAM_END: /* Found end of stream. */
-                       switch (lzmadec_end(&(xar->lzstream))) {
-                       case LZMADEC_OK:
-                               break;
-                       default:
-                               archive_set_error(&(a->archive),
-                                   ARCHIVE_ERRNO_MISC,
-                                   "Failed to clean up lzmadec decompressor");
-                               return (ARCHIVE_FATAL);
-                       }
-                       xar->lzstream_valid = 0;
-                       /* FALLTHROUGH */
-               case LZMADEC_OK: /* Decompressor made some progress. */
-                       break;
-               default:
-                       archive_set_error(&(a->archive),
-                           ARCHIVE_ERRNO_MISC,
-                           "lzmadec decompression failed(%d)",
-                           r);
-                       return (ARCHIVE_FATAL);
-               }
-               *used = avail_in - xar->lzstream.avail_in;
-               *outbytes = avail_out - xar->lzstream.avail_out;
-               break;
 #endif
 #if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR)
        case BZIP2:
 #endif
 #if !defined(HAVE_LZMA_H) || !defined(HAVE_LIBLZMA)
-#if !defined(HAVE_LZMADEC_H) || !defined(HAVE_LIBLZMADEC)
        case LZMA:
-#endif
        case XZ:
 #endif
        case NONE:

Modified: head/contrib/libarchive/libarchive/archive_write_disk_posix.c
==============================================================================
--- head/contrib/libarchive/libarchive/archive_write_disk_posix.c       Tue Nov 
29 21:53:16 2016        (r309299)
+++ head/contrib/libarchive/libarchive/archive_write_disk_posix.c       Tue Nov 
29 22:14:42 2016        (r309300)
@@ -336,14 +336,19 @@ struct archive_write_disk {
 
 #define HFS_BLOCKS(s)  ((s) >> 12)
 
-static int     check_symlinks_fsobj(char *path, int *error_number, struct 
archive_string *error_string, int flags);
+static void    fsobj_error(int *, struct archive_string *, int, const char *,
+                   const char *);
+static int     check_symlinks_fsobj(char *, int *, struct archive_string *,
+                   int);
 static int     check_symlinks(struct archive_write_disk *);
 static int     create_filesystem_object(struct archive_write_disk *);
-static struct fixup_entry *current_fixup(struct archive_write_disk *, const 
char *pathname);
+static struct fixup_entry *current_fixup(struct archive_write_disk *,
+                   const char *pathname);
 #if defined(HAVE_FCHDIR) && defined(PATH_MAX)
 static void    edit_deep_directories(struct archive_write_disk *ad);
 #endif
-static int     cleanup_pathname_fsobj(char *path, int *error_number, struct 
archive_string *error_string, int flags);
+static int     cleanup_pathname_fsobj(char *, int *, struct archive_string *,
+                   int);
 static int     cleanup_pathname(struct archive_write_disk *);
 static int     create_dir(struct archive_write_disk *, char *);
 static int     create_parent_dir(struct archive_write_disk *, char *);
@@ -374,11 +379,14 @@ static struct archive_vtable *archive_wr
 
 static int     _archive_write_disk_close(struct archive *);
 static int     _archive_write_disk_free(struct archive *);
-static int     _archive_write_disk_header(struct archive *, struct 
archive_entry *);
+static int     _archive_write_disk_header(struct archive *,
+                   struct archive_entry *);
 static int64_t _archive_write_disk_filter_bytes(struct archive *, int);
 static int     _archive_write_disk_finish_entry(struct archive *);
-static ssize_t _archive_write_disk_data(struct archive *, const void *, 
size_t);
-static ssize_t _archive_write_disk_data_block(struct archive *, const void *, 
size_t, int64_t);
+static ssize_t _archive_write_disk_data(struct archive *, const void *,
+                   size_t);
+static ssize_t _archive_write_disk_data_block(struct archive *, const void *,
+                   size_t, int64_t);
 
 static int
 lazy_stat(struct archive_write_disk *a)
@@ -649,7 +657,8 @@ _archive_write_disk_header(struct archiv
        if (a->restore_pwd >= 0) {
                r = fchdir(a->restore_pwd);
                if (r != 0) {
-                       archive_set_error(&a->archive, errno, "chdir() 
failure");
+                       archive_set_error(&a->archive, errno,
+                           "chdir() failure");
                        ret = ARCHIVE_FATAL;
                }
                close(a->restore_pwd);
@@ -697,7 +706,8 @@ _archive_write_disk_header(struct archiv
                }
                if (archive_entry_birthtime_is_set(entry)) {
                        fe->birthtime = archive_entry_birthtime(entry);
-                       fe->birthtime_nanos = 
archive_entry_birthtime_nsec(entry);
+                       fe->birthtime_nanos = archive_entry_birthtime_nsec(
+                           entry);
                } else {
                        /* If birthtime is unset, use mtime. */
                        fe->birthtime = fe->mtime;
@@ -723,7 +733,8 @@ _archive_write_disk_header(struct archiv
                                return (ARCHIVE_FATAL);
                        fe->mac_metadata = malloc(metadata_size);
                        if (fe->mac_metadata != NULL) {
-                               memcpy(fe->mac_metadata, metadata, 
metadata_size);
+                               memcpy(fe->mac_metadata, metadata,
+                                   metadata_size);
                                fe->mac_metadata_size = metadata_size;
                                fe->fixup |= TODO_MAC_METADATA;
                        }
@@ -1480,7 +1491,8 @@ _archive_write_disk_data_block(struct ar
                return (r);
        if ((size_t)r < size) {
                archive_set_error(&a->archive, 0,
-                   "Too much data: Truncating file at %ju bytes", 
(uintmax_t)a->filesize);
+                   "Too much data: Truncating file at %ju bytes",
+                   (uintmax_t)a->filesize);
                return (ARCHIVE_WARN);
        }
 #if ARCHIVE_VERSION_NUMBER < 3999000
@@ -2005,8 +2017,9 @@ restore_entry(struct archive_write_disk 
 
        if (en) {
                /* Everything failed; give up here. */
-               archive_set_error(&a->archive, en, "Can't create '%s'",
-                   a->name);
+               if ((&a->archive)->error == NULL)
+                       archive_set_error(&a->archive, en, "Can't create '%s'",
+                           a->name);
                return (ARCHIVE_FAILED);
        }
 
@@ -2043,19 +2056,32 @@ create_filesystem_object(struct archive_
                if (linkname_copy == NULL) {
                    return (EPERM);
                }
-               /* TODO: consider using the cleaned-up path as the link target? 
*/
-               r = cleanup_pathname_fsobj(linkname_copy, &error_number, 
&error_string, a->flags);
+               /*
+                * TODO: consider using the cleaned-up path as the link
+                * target?
+                */
+               r = cleanup_pathname_fsobj(linkname_copy, &error_number,
+                   &error_string, a->flags);
                if (r != ARCHIVE_OK) {
-                       archive_set_error(&a->archive, error_number, "%s", 
error_string.s);
+                       archive_set_error(&a->archive, error_number, "%s",
+                           error_string.s);
                        free(linkname_copy);
-                       /* EPERM is more appropriate than error_number for our 
callers */
+                       /*
+                        * EPERM is more appropriate than error_number for our
+                        * callers
+                        */
                        return (EPERM);
                }
-               r = check_symlinks_fsobj(linkname_copy, &error_number, 
&error_string, a->flags);
+               r = check_symlinks_fsobj(linkname_copy, &error_number,
+                   &error_string, a->flags);
                if (r != ARCHIVE_OK) {
-                       archive_set_error(&a->archive, error_number, "%s", 
error_string.s);
+                       archive_set_error(&a->archive, error_number, "%s",
+                           error_string.s);
                        free(linkname_copy);
-                       /* EPERM is more appropriate than error_number for our 
callers */
+                       /*
+                        * EPERM is more appropriate than error_number for our
+                        * callers
+                        */
                        return (EPERM);
                }
                free(linkname_copy);
@@ -2076,8 +2102,8 @@ create_filesystem_object(struct archive_
                        a->todo = 0;
                        a->deferred = 0;
                } else if (r == 0 && a->filesize > 0) {
-                       a->fd = open(a->name,
-                                    O_WRONLY | O_TRUNC | O_BINARY | O_CLOEXEC 
| O_NOFOLLOW);
+                       a->fd = open(a->name, O_WRONLY | O_TRUNC | O_BINARY
+                           | O_CLOEXEC | O_NOFOLLOW);
                        __archive_ensure_cloexec_flag(a->fd);
                        if (a->fd < 0)
                                r = errno;
@@ -2388,6 +2414,17 @@ current_fixup(struct archive_write_disk 
        return (a->current_fixup);
 }
 
+/* Error helper for new *_fsobj functions */
+static void
+fsobj_error(int *a_eno, struct archive_string *a_estr,
+    int err, const char *errstr, const char *path)
+{
+       if (a_eno)
+               *a_eno = err;
+       if (a_estr)
+               archive_string_sprintf(a_estr, errstr, path);
+}
+
 /*
  * TODO: Someday, integrate this with the deep dir support; they both
  * scan the path and both can be optimized by comparing against other
@@ -2400,7 +2437,8 @@ current_fixup(struct archive_write_disk 
  * ARCHIVE_OK if there are none, otherwise puts an error in errmsg.
  */
 static int
-check_symlinks_fsobj(char *path, int *error_number, struct archive_string 
*error_string, int flags)
+check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
+    int flags)
 {
 #if !defined(HAVE_LSTAT)
        /* Platform doesn't have lstat, so we can't look for symlinks. */
@@ -2433,7 +2471,8 @@ check_symlinks_fsobj(char *path, int *er
         *  - if it's a directory and it's not the last chunk, cd into it
         * As we go:
         *  head points to the current (relative) path
-        *  tail points to the temporary \0 terminating the segment we're 
currently examining
+        *  tail points to the temporary \0 terminating the segment we're
+        *      currently examining
         *  c holds what used to be in *tail
         *  last is 1 if this is the last tail
         */
@@ -2455,7 +2494,9 @@ check_symlinks_fsobj(char *path, int *er
         * Exiting the loop with break is okay; continue is not.
         */
        while (!last) {
-               /* Skip the separator we just consumed, plus any adjacent ones 
*/
+               /*
+                * Skip the separator we just consumed, plus any adjacent ones
+                */
                while (*tail == '/')
                    ++tail;
                /* Skip the next path element. */
@@ -2474,19 +2515,20 @@ check_symlinks_fsobj(char *path, int *er
                        if (errno == ENOENT) {
                                break;
                        } else {
-                               /* Treat any other error as fatal - best to be 
paranoid here
-                                * Note: This effectively disables deep 
directory
-                                * support when security checks are enabled.
-                                * Otherwise, very long pathnames that trigger
-                                * an error here could evade the sandbox.
-                                * TODO: We could do better, but it would 
probably
-                                * require merging the symlink checks with the
-                                * deep-directory editing. */
-                               if (error_number) *error_number = errno;
-                               if (error_string)
-                                       archive_string_sprintf(error_string,
-                                                       "Could not stat %s",
-                                                       path);
+                               /*
+                                * Treat any other error as fatal - best to be
+                                * paranoid here.
+                                * Note: This effectively disables deep
+                                * directory support when security checks are
+                                * enabled. Otherwise, very long pathnames that
+                                * trigger an error here could evade the
+                                * sandbox.
+                                * TODO: We could do better, but it would
+                                * probably require merging the symlink checks
+                                * with the deep-directory editing.
+                                */
+                               fsobj_error(a_eno, a_estr, errno,
+                                   "Could not stat %s", path);
                                res = ARCHIVE_FAILED;
                                break;
                        }
@@ -2494,11 +2536,8 @@ check_symlinks_fsobj(char *path, int *er
                        if (!last) {
                                if (chdir(head) != 0) {
                                        tail[0] = c;
-                                       if (error_number) *error_number = errno;
-                                       if (error_string)
-                                               
archive_string_sprintf(error_string,
-                                                               "Could not 
chdir %s",
-                                                               path);
+                                       fsobj_error(a_eno, a_estr, errno,
+                                           "Could not chdir %s", path);
                                        res = (ARCHIVE_FATAL);
                                        break;
                                }
@@ -2514,11 +2553,9 @@ check_symlinks_fsobj(char *path, int *er
                                 */
                                if (unlink(head)) {
                                        tail[0] = c;
-                                       if (error_number) *error_number = errno;
-                                       if (error_string)
-                                               
archive_string_sprintf(error_string,
-                                                               "Could not 
remove symlink %s",
-                                                               path);
+                                       fsobj_error(a_eno, a_estr, errno,
+                                           "Could not remove symlink %s",
+                                           path);
                                        res = ARCHIVE_FAILED;
                                        break;
                                }
@@ -2529,13 +2566,14 @@ check_symlinks_fsobj(char *path, int *er
                                 * symlink with another symlink.
                                 */
                                tail[0] = c;
-                               /* FIXME:  not sure how important this is to 
restore
+                               /*
+                                * FIXME:  not sure how important this is to
+                                * restore
+                                */
+                               /*
                                if (!S_ISLNK(path)) {
-                                       if (error_number) *error_number = 0;
-                                       if (error_string)
-                                               
archive_string_sprintf(error_string,
-                                                               "Removing 
symlink %s",
-                                                               path);
+                                       fsobj_error(a_eno, a_estr, 0,
+                                           "Removing symlink %s", path);
                                }
                                */
                                /* Symlink gone.  No more problem! */
@@ -2545,22 +2583,60 @@ check_symlinks_fsobj(char *path, int *er
                                /* User asked us to remove problems. */
                                if (unlink(head) != 0) {
                                        tail[0] = c;
-                                       if (error_number) *error_number = 0;
-                                       if (error_string)
-                                               
archive_string_sprintf(error_string,
-                                                               "Cannot remove 
intervening symlink %s",
-                                                               path);
+                                       fsobj_error(a_eno, a_estr, 0,
+                                           "Cannot remove intervening "
+                                           "symlink %s", path);
                                        res = ARCHIVE_FAILED;
                                        break;
                                }
                                tail[0] = c;
+                       } else if ((flags &
+                           ARCHIVE_EXTRACT_SECURE_SYMLINKS) == 0) {
+                               /*
+                                * We are not the last element and we want to
+                                * follow symlinks if they are a directory.
+                                * 
+                                * This is needed to extract hardlinks over
+                                * symlinks.
+                                */
+                               r = stat(head, &st);
+                               if (r != 0) {
+                                       tail[0] = c;
+                                       if (errno == ENOENT) {
+                                               break;
+                                       } else {
+                                               fsobj_error(a_eno, a_estr,
+                                                   errno,
+                                                   "Could not stat %s", path);
+                                               res = (ARCHIVE_FAILED);
+                                               break;
+                                       }
+                               } else if (S_ISDIR(st.st_mode)) {
+                                       if (chdir(head) != 0) {
+                                               tail[0] = c;
+                                               fsobj_error(a_eno, a_estr,
+                                                   errno,
+                                                   "Could not chdir %s", path);
+                                               res = (ARCHIVE_FATAL);
+                                               break;
+                                       }
+                                       /*
+                                        * Our view is now from inside
+                                        * this dir:
+                                        */
+                                       head = tail + 1;
+                               } else {

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to