Author: mm
Date: Thu Feb  2 00:50:46 2017
New Revision: 313074
URL: https://svnweb.freebsd.org/changeset/base/313074

Log:
  MFV r313071:
  Sync libarchive with vendor
  
  Vendor changes (relevant to FreeBSD):
  - support extracting NFSv4 ACLs from Solaris tar archives
  - bugfixes and optimizations in the ACL code
  - multiple fixes in the test suite
  - typo and other small bugfixes
  
  Security fixes:
  - cab reader: endless loop when parsing MSZIP signature (OSS-Fuzz 335)
  - LHA reader: heap-buffer-overflow in lha_read_file_header_1()
    (CVE-2017-5601)
  - LZ4 reader: null-pointer dereference in lz4_filter_read_legacy_stream()
    (OSS-Fuzz 453)
  - mtree reader: heap-buffer-overflow in detect_form() (OSS-Fuzz 421, 443)
  - WARC reader: heap-buffer-overflow in xstrpisotime() (OSS-Fuzz 382, 458)
  
  Memory leak fixes:
  - ACL support: free memory allocated by acl_get_qualifier()
  - disk writer: missing free in create_filesystem_object()
  - file reader: fd leak (Coverity 1016755)
  - gnutar writer: fix free in archive_write_gnutar_header()
    (Coverity 101675)
  - iso 9660 reader: missing free in parse_file_info()
    (partial Coverity 1016754)
  - program reader: missing free in __archive_read_program()
  - program writer: missing free in __archive_write_program_free()
  - xar reader: missing free in xar_cleanup()
  - xar reader: missing frees in expat_xmlattr_setup()
    (Coverity 1229979-1229981)
  - xar writer: missing free in file_free()
  - zip reader: missing free in zip_read_local_file_header()
  
  MFC after:    1 week
  X-MFC with:   310866, 310868, 310870, 311899

Added:
  head/contrib/libarchive/libarchive/test/test_acl_platform_nfs4.c
     - copied unchanged from r313071, 
vendor/libarchive/dist/libarchive/test/test_acl_platform_nfs4.c
  head/contrib/libarchive/libarchive/test/test_acl_platform_posix1e.c
     - copied unchanged from r313071, 
vendor/libarchive/dist/libarchive/test/test_acl_platform_posix1e.c
Deleted:
  head/contrib/libarchive/libarchive/test/test_acl_freebsd_nfs4.c
  head/contrib/libarchive/libarchive/test/test_acl_freebsd_posix1e.c
Modified:
  head/contrib/libarchive/NEWS
  head/contrib/libarchive/libarchive/archive_acl.c
  head/contrib/libarchive/libarchive/archive_acl_private.h
  head/contrib/libarchive/libarchive/archive_entry.c
  head/contrib/libarchive/libarchive/archive_entry_strmode.c
  head/contrib/libarchive/libarchive/archive_platform.h
  head/contrib/libarchive/libarchive/archive_random.c
  head/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c
  head/contrib/libarchive/libarchive/archive_read_open_filename.c
  head/contrib/libarchive/libarchive/archive_read_support_filter_lz4.c
  head/contrib/libarchive/libarchive/archive_read_support_filter_program.c
  head/contrib/libarchive/libarchive/archive_read_support_format_cab.c
  head/contrib/libarchive/libarchive/archive_read_support_format_cpio.c
  head/contrib/libarchive/libarchive/archive_read_support_format_iso9660.c
  head/contrib/libarchive/libarchive/archive_read_support_format_lha.c
  head/contrib/libarchive/libarchive/archive_read_support_format_mtree.c
  head/contrib/libarchive/libarchive/archive_read_support_format_tar.c
  head/contrib/libarchive/libarchive/archive_read_support_format_warc.c
  head/contrib/libarchive/libarchive/archive_read_support_format_xar.c
  head/contrib/libarchive/libarchive/archive_read_support_format_zip.c
  head/contrib/libarchive/libarchive/archive_write_add_filter_program.c
  head/contrib/libarchive/libarchive/archive_write_disk_acl.c
  head/contrib/libarchive/libarchive/archive_write_disk_posix.c
  head/contrib/libarchive/libarchive/archive_write_open.3
  head/contrib/libarchive/libarchive/archive_write_set_format_gnutar.c
  head/contrib/libarchive/libarchive/archive_write_set_format_iso9660.c
  head/contrib/libarchive/libarchive/archive_write_set_format_xar.c
  head/contrib/libarchive/libarchive/test/main.c
  head/contrib/libarchive/libarchive/test/test.h
  head/contrib/libarchive/libarchive/test/test_acl_text.c
  head/contrib/libarchive/libarchive/test/test_archive_string.c
  head/contrib/libarchive/libarchive/test/test_compat_gtar.c
  head/contrib/libarchive/libarchive/test/test_compat_solaris_tar_acl.c
  head/contrib/libarchive/libarchive/test/test_compat_solaris_tar_acl.tar.uu
  head/contrib/libarchive/libarchive/test/test_fuzz.c
  head/contrib/libarchive/libarchive/test/test_read_disk_directory_traversals.c
  head/contrib/libarchive/libarchive/test/test_read_filter_lzop.c
  head/contrib/libarchive/libarchive/test/test_read_filter_lzop_multiple_parts.c
  head/contrib/libarchive/libarchive/test/test_read_format_zip.c
  head/contrib/libarchive/libarchive/test/test_read_format_zip_comment_stored.c
  head/contrib/libarchive/libarchive/test/test_read_format_zip_mac_metadata.c
  head/contrib/libarchive/libarchive/test/test_read_format_zip_malformed.c
  head/contrib/libarchive/libarchive/test/test_read_format_zip_nested.c
  head/contrib/libarchive/libarchive/test/test_read_format_zip_padded.c
  head/contrib/libarchive/libarchive/test/test_read_format_zip_sfx.c
  head/contrib/libarchive/libarchive/test/test_write_disk_secure746.c
  head/contrib/libarchive/libarchive/test/test_write_filter_lz4.c
  head/contrib/libarchive/libarchive/test/test_write_filter_lzop.c
  head/contrib/libarchive/libarchive/test/test_write_format_zip_large.c
  head/contrib/libarchive/libarchive/test/test_write_format_zip_zip64.c
  head/contrib/libarchive/tar/test/test_option_uid_uname.c
  head/contrib/libarchive/tar/util.c
  head/lib/libarchive/config_freebsd.h
  head/lib/libarchive/tests/Makefile
Directory Properties:
  head/contrib/libarchive/   (props changed)

Modified: head/contrib/libarchive/NEWS
==============================================================================
--- head/contrib/libarchive/NEWS        Thu Feb  2 00:37:21 2017        
(r313073)
+++ head/contrib/libarchive/NEWS        Thu Feb  2 00:50:46 2017        
(r313074)
@@ -1,3 +1,7 @@
+Jan 29, 2017: Limited NFSv4 ACL support for Mac OS (Darwin)
+
+Jan 10, 2017: POSIX.1e and NFSv4 ACL support for Solaris and derivates
+
 Dec 27, 2016: NFSv4 ACL read and write support for pax
     Deprecated functions: archive_entry_acl_text(), archive_entry_acl_text_w()
 

Modified: head/contrib/libarchive/libarchive/archive_acl.c
==============================================================================
--- head/contrib/libarchive/libarchive/archive_acl.c    Thu Feb  2 00:37:21 
2017        (r313073)
+++ head/contrib/libarchive/libarchive/archive_acl.c    Thu Feb  2 00:50:46 
2017        (r313074)
@@ -349,6 +349,15 @@ archive_acl_count(struct archive_acl *ac
 }
 
 /*
+ * Return a bitmask of stored ACL types in an ACL list
+ */
+int
+archive_acl_types(struct archive_acl *acl)
+{
+       return (acl->acl_types);
+}
+
+/*
  * Prepare for reading entries from the ACL data.  Returns a count
  * of entries matching "want_type", or zero if there are no
  * non-extended ACL entries of that type.
@@ -1144,7 +1153,7 @@ archive_acl_from_text_w(struct archive_a
 
        const wchar_t *s, *st;
 
-       int numfields, fields, n, r, ret;
+       int numfields, fields, n, r, sol, ret;
        int type, types, tag, permset, id;
        size_t len;
        wchar_t sep;
@@ -1192,6 +1201,7 @@ archive_acl_from_text_w(struct archive_a
                }
 
                n = 0;
+               sol = 0;
                id = -1;
                permset = 0;
                name.start = name.end = NULL;
@@ -1263,6 +1273,7 @@ archive_acl_from_text_w(struct archive_a
                                    && ismode_w(field[n + 1].start,
                                    field[n + 1].end, &permset)) {
                                        /* This is Solaris-style "other:rwx" */
+                                       sol = 1;
                                } else if (fields == (n + 3) &&
                                    field[n + 1].start < field[n + 1].end) {
                                        /* Invalid mask or other field */
@@ -1287,9 +1298,12 @@ archive_acl_from_text_w(struct archive_a
                                continue;
                        }
 
-                       /* Without "default:" we expect mode in field 2 */
-                       if (permset == 0 && !ismode_w(field[n + 2].start,
-                           field[n + 2].end, &permset)) {
+                       /*
+                        * Without "default:" we expect mode in field 2
+                        * Exception: Solaris other and mask fields
+                        */
+                       if (permset == 0 && !ismode_w(field[n + 2 - sol].start,
+                           field[n + 2 - sol].end, &permset)) {
                                /* Invalid mode, skip entry */
                                ret = ARCHIVE_WARN;
                                continue;
@@ -1615,7 +1629,7 @@ archive_acl_from_text_l(struct archive_a
        } field[6], name;
 
        const char *s, *st;
-       int numfields, fields, n, r, ret;
+       int numfields, fields, n, r, sol, ret;
        int type, types, tag, permset, id;
        size_t len;
        char sep;
@@ -1663,6 +1677,7 @@ archive_acl_from_text_l(struct archive_a
                }
 
                n = 0;
+               sol = 0;
                id = -1;
                permset = 0;
                name.start = name.end = NULL;
@@ -1734,6 +1749,7 @@ archive_acl_from_text_l(struct archive_a
                                    && ismode(field[n + 1].start,
                                    field[n + 1].end, &permset)) {
                                        /* This is Solaris-style "other:rwx" */
+                                       sol = 1;
                                } else if (fields == (n + 3) &&
                                    field[n + 1].start < field[n + 1].end) {
                                        /* Invalid mask or other field */
@@ -1758,9 +1774,12 @@ archive_acl_from_text_l(struct archive_a
                                continue;
                        }
 
-                       /* Without "default:" we expect mode in field 2 */
-                       if (permset == 0 && !ismode(field[n + 2].start,
-                           field[n + 2].end, &permset)) {
+                       /*
+                        * Without "default:" we expect mode in field 3
+                        * Exception: Solaris other and mask fields
+                        */
+                       if (permset == 0 && !ismode(field[n + 2 - sol].start,
+                           field[n + 2 - sol].end, &permset)) {
                                /* Invalid mode, skip entry */
                                ret = ARCHIVE_WARN;
                                continue;

Modified: head/contrib/libarchive/libarchive/archive_acl_private.h
==============================================================================
--- head/contrib/libarchive/libarchive/archive_acl_private.h    Thu Feb  2 
00:37:21 2017        (r313073)
+++ head/contrib/libarchive/libarchive/archive_acl_private.h    Thu Feb  2 
00:50:46 2017        (r313074)
@@ -56,6 +56,7 @@ struct archive_acl {
 void archive_acl_clear(struct archive_acl *);
 void archive_acl_copy(struct archive_acl *, struct archive_acl *);
 int archive_acl_count(struct archive_acl *, int);
+int archive_acl_types(struct archive_acl *);
 int archive_acl_reset(struct archive_acl *, int);
 int archive_acl_next(struct archive *, struct archive_acl *, int,
     int *, int *, int *, int *, const char **);

Modified: head/contrib/libarchive/libarchive/archive_entry.c
==============================================================================
--- head/contrib/libarchive/libarchive/archive_entry.c  Thu Feb  2 00:37:21 
2017        (r313073)
+++ head/contrib/libarchive/libarchive/archive_entry.c  Thu Feb  2 00:50:46 
2017        (r313074)
@@ -1447,7 +1447,7 @@ archive_entry_acl_add_entry_w(struct arc
 int
 archive_entry_acl_types(struct archive_entry *entry)
 {
-       return ((&entry->acl)->acl_types);
+       return (archive_acl_types(&entry->acl));
 }
 
 /*

Modified: head/contrib/libarchive/libarchive/archive_entry_strmode.c
==============================================================================
--- head/contrib/libarchive/libarchive/archive_entry_strmode.c  Thu Feb  2 
00:37:21 2017        (r313073)
+++ head/contrib/libarchive/libarchive/archive_entry_strmode.c  Thu Feb  2 
00:50:46 2017        (r313074)
@@ -80,7 +80,7 @@ archive_entry_strmode(struct archive_ent
                if (mode & 0001) bp[9] = 't';
                else bp[9] = 'T';
        }
-       if (archive_entry_acl_count(entry, ARCHIVE_ENTRY_ACL_TYPE_ACCESS))
+       if (archive_entry_acl_types(entry) != 0)
                bp[10] = '+';
 
        return (bp);

Modified: head/contrib/libarchive/libarchive/archive_platform.h
==============================================================================
--- head/contrib/libarchive/libarchive/archive_platform.h       Thu Feb  2 
00:37:21 2017        (r313073)
+++ head/contrib/libarchive/libarchive/archive_platform.h       Thu Feb  2 
00:50:46 2017        (r313074)
@@ -147,8 +147,25 @@
  * acl_set_file(), and ACL_USER, we assume it has the rest of the
  * POSIX.1e draft functions used in archive_read_extract.c.
  */
-#if HAVE_SYS_ACL_H && HAVE_ACL_CREATE_ENTRY && HAVE_ACL_INIT && 
HAVE_ACL_SET_FILE && HAVE_ACL_USER
+#if HAVE_SYS_ACL_H && HAVE_ACL_CREATE_ENTRY && HAVE_ACL_INIT && 
HAVE_ACL_SET_FILE
+#if HAVE_ACL_USER
 #define        HAVE_POSIX_ACL  1
+#elif HAVE_ACL_TYPE_EXTENDED
+#define HAVE_DARWIN_ACL 1
+#endif
+#endif
+
+/*
+ * If this platform has <sys/acl.h>, acl_get(), facl_get(), acl_set(),
+ * facl_set() and types aclent_t and ace_t it uses Solaris-style ACL functions
+ */
+#if HAVE_SYS_ACL_H && HAVE_ACL_GET && HAVE_FACL_GET && HAVE_ACL_SET && 
HAVE_FACL_SET && HAVE_ACLENT_T && HAVE_ACE_T
+#define        HAVE_SUN_ACL    1
+#endif
+
+/* Define if platform supports NFSv4 ACLs */
+#if (HAVE_POSIX_ACL && HAVE_ACL_TYPE_NFS4) || HAVE_SUN_ACL || HAVE_DARWIN_ACL
+#define HAVE_NFS4_ACL  1
 #endif
 
 /*

Modified: head/contrib/libarchive/libarchive/archive_random.c
==============================================================================
--- head/contrib/libarchive/libarchive/archive_random.c Thu Feb  2 00:37:21 
2017        (r313073)
+++ head/contrib/libarchive/libarchive/archive_random.c Thu Feb  2 00:50:46 
2017        (r313074)
@@ -80,7 +80,7 @@ archive_random(void *buf, size_t nbytes)
 
        success = CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
            CRYPT_VERIFYCONTEXT);
-       if (!success && GetLastError() == NTE_BAD_KEYSET) {
+       if (!success && GetLastError() == (DWORD)NTE_BAD_KEYSET) {
                success = CryptAcquireContext(&hProv, NULL, NULL,
                    PROV_RSA_FULL, CRYPT_NEWKEYSET);
        }

Modified: head/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c
==============================================================================
--- head/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c      
Thu Feb  2 00:37:21 2017        (r313073)
+++ head/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c      
Thu Feb  2 00:50:46 2017        (r313074)
@@ -38,6 +38,11 @@ __FBSDID("$FreeBSD$");
 #ifdef HAVE_SYS_ACL_H
 #include <sys/acl.h>
 #endif
+#ifdef HAVE_DARWIN_ACL
+#include <membership.h>
+#include <grp.h>
+#include <pwd.h>
+#endif
 #ifdef HAVE_SYS_EXTATTR_H
 #include <sys/extattr.h>
 #endif
@@ -118,6 +123,15 @@ __FBSDID("$FreeBSD$");
 #define        ACL_GET_PERM acl_get_perm_np
 #endif
 
+/* NFSv4 platform ACL type */
+#if HAVE_SUN_ACL
+#define        ARCHIVE_PLATFORM_ACL_TYPE_NFS4  ACE_T
+#elif HAVE_DARWIN_ACL
+#define        ARCHIVE_PLATFORM_ACL_TYPE_NFS4  ACL_TYPE_EXTENDED
+#elif HAVE_ACL_TYPE_NFS4
+#define        ARCHIVE_PLATFORM_ACL_TYPE_NFS4  ACL_TYPE_NFS4
+#endif
+
 static int setup_acls(struct archive_read_disk *,
     struct archive_entry *, int *fd);
 static int setup_mac_metadata(struct archive_read_disk *,
@@ -405,17 +419,38 @@ setup_mac_metadata(struct archive_read_d
 }
 #endif
 
+#if HAVE_DARWIN_ACL
+static int translate_guid(struct archive *, acl_entry_t,
+    int *, int *, const char **);
+
+static void add_trivial_nfs4_acl(struct archive_entry *);
+#endif
+
+#if HAVE_SUN_ACL
+static int
+sun_acl_is_trivial(acl_t *, mode_t, int *trivialp);
+#endif
 
-#ifdef HAVE_POSIX_ACL
+#if HAVE_POSIX_ACL || HAVE_NFS4_ACL
 static int translate_acl(struct archive_read_disk *a,
-    struct archive_entry *entry, acl_t acl, int archive_entry_acl_type);
+    struct archive_entry *entry,
+#if HAVE_SUN_ACL
+    acl_t *acl,
+#else
+    acl_t acl,
+#endif
+    int archive_entry_acl_type);
 
 static int
 setup_acls(struct archive_read_disk *a,
     struct archive_entry *entry, int *fd)
 {
        const char      *accpath;
-       acl_t            acl;
+#if HAVE_SUN_ACL
+       acl_t           *acl;
+#else
+       acl_t           acl;
+#endif
        int             r;
 
        accpath = archive_entry_sourcepath(entry);
@@ -440,17 +475,20 @@ setup_acls(struct archive_read_disk *a,
 
        acl = NULL;
 
-#ifdef ACL_TYPE_NFS4
+#if HAVE_NFS4_ACL
        /* Try NFSv4 ACL first. */
        if (*fd >= 0)
-#if HAVE_ACL_GET_FD_NP
-               acl = acl_get_fd_np(*fd, ACL_TYPE_NFS4);
+#if HAVE_SUN_ACL
+               /* Solaris reads both POSIX.1e and NFSv4 ACL here */
+               facl_get(*fd, 0, &acl);
+#elif HAVE_ACL_GET_FD_NP
+               acl = acl_get_fd_np(*fd, ARCHIVE_PLATFORM_ACL_TYPE_NFS4);
 #else
                acl = acl_get_fd(*fd);
 #endif
 #if HAVE_ACL_GET_LINK_NP
        else if (!a->follow_symlinks)
-               acl = acl_get_link_np(accpath, ACL_TYPE_NFS4);
+               acl = acl_get_link_np(accpath, ARCHIVE_PLATFORM_ACL_TYPE_NFS4);
 #else
        else if ((!a->follow_symlinks)
            && (archive_entry_filetype(entry) == AE_IFLNK))
@@ -459,12 +497,24 @@ setup_acls(struct archive_read_disk *a,
                acl = NULL;
 #endif
        else
-               acl = acl_get_file(accpath, ACL_TYPE_NFS4);
+#if HAVE_SUN_ACL
+               /* Solaris reads both POSIX.1e and NFSv4 ACLs here */
+               acl_get(accpath, 0, &acl);
+#else
+               acl = acl_get_file(accpath, ARCHIVE_PLATFORM_ACL_TYPE_NFS4);
+#endif
 
-#if HAVE_ACL_IS_TRIVIAL_NP
-       if (acl != NULL && acl_is_trivial_np(acl, &r) == 0) {
-               /* Ignore "trivial" ACLs that just mirror the file mode. */
-               if (r) {
+
+#if HAVE_ACL_IS_TRIVIAL_NP || HAVE_SUN_ACL
+       /* Ignore "trivial" ACLs that just mirror the file mode. */
+       if (acl != NULL) {
+#if HAVE_SUN_ACL
+               if (sun_acl_is_trivial(acl, archive_entry_mode(entry),
+                   &r) == 0 && r == 1)
+#elif HAVE_ACL_IS_TRIVIAL_NP
+               if (acl_is_trivial_np(acl, &r) == 0 && r == 1)
+#endif
+               {
                        acl_free(acl);
                        acl = NULL;
                        /*
@@ -474,17 +524,35 @@ setup_acls(struct archive_read_disk *a,
                        return (ARCHIVE_OK);
                }
        }
-#endif
+#endif /* HAVE_ACL_IS_TRIVIAL_NP || HAVE_SUN_ACL */
        if (acl != NULL) {
                r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
                acl_free(acl);
                if (r != ARCHIVE_OK) {
                        archive_set_error(&a->archive, errno,
+#if HAVE_SUN_ACL
+                           "Couldn't translate ACLs: %s", accpath);
+#else
                            "Couldn't translate NFSv4 ACLs: %s", accpath);
+#endif
                }
+#if HAVE_DARWIN_ACL
+               /*
+                * Because Mac OS doesn't support owner@, group@ and everyone@
+                * ACLs we need to add NFSv4 ACLs mirroring the file mode to
+                * the archive entry. Otherwise extraction on non-Mac platforms
+                * would lead to an invalid file mode.
+                */
+               if (archive_entry_acl_count(entry,
+                   ARCHIVE_ENTRY_ACL_TYPE_NFS4) > 0)
+                       add_trivial_nfs4_acl(entry);
+#endif
                return (r);
        }
-#endif /* ACL_TYPE_NFS4 */
+#endif /* HAVE_NFS4_ACL */
+
+#if HAVE_POSIX_ACL
+       /* This code path is skipped on MacOS and Solaris */
 
        /* Retrieve access ACL from file. */
        if (*fd >= 0)
@@ -513,8 +581,7 @@ setup_acls(struct archive_read_disk *a,
 #endif
 
        if (acl != NULL) {
-               r = translate_acl(a, entry, acl,
-                   ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
+               r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
                acl_free(acl);
                acl = NULL;
                if (r != ARCHIVE_OK) {
@@ -544,71 +611,560 @@ setup_acls(struct archive_read_disk *a,
                        }
                }
        }
+#endif /* HAVE_POSIX_ACL */
        return (ARCHIVE_OK);
 }
 
 /*
- * Translate system ACL into libarchive internal structure.
+ * Translate system ACL permissions into libarchive internal structure
  */
-
 static struct {
-        int archive_perm;
-        int platform_perm;
+       int archive_perm;
+       int platform_perm;
 } acl_perm_map[] = {
-        {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},
-        {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
-        {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
-        {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
-        {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
-        {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
-        {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
-        {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
-        {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
-        {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
-        {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
-        {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
-        {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
-        {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
+#if HAVE_SUN_ACL       /* Solaris NFSv4 ACL permissions */
+       {ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE},
+       {ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA},
+       {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY},
+       {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA},
+       {ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE},
+       {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA},
+       {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY},
+       {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS},
+       {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS},
+       {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD},
+       {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES},
+       {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES},
+       {ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE},
+       {ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL},
+       {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL},
+       {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER},
+       {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE}
+#elif HAVE_DARWIN_ACL  /* MacOS ACL permissions */
+       {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
+       {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
+       {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
+       {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
+       {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
+       {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
+       {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
+       {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
+       {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
+       {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
+       {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
+       {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES},
+       {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES},
+       {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY},
+       {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY},
+       {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER},
+       {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
+#else  /* POSIX.1e ACL permissions */
+       {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
+       {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
+       {ARCHIVE_ENTRY_ACL_READ, ACL_READ},
+#if HAVE_ACL_TYPE_NFS4 /* FreeBSD NFSv4 ACL permissions */
+       {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
+       {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
+       {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
+       {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
+       {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
+       {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
+       {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
+       {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
+       {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
+       {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
+       {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
+       {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
+       {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
+       {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
+       {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
+       {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
 #endif
+#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
 };
 
-#ifdef ACL_TYPE_NFS4
+#if HAVE_NFS4_ACL
+/*
+ * Translate system NFSv4 inheritance flags into libarchive internal structure
+ */
 static struct {
-        int archive_inherit;
-        int platform_inherit;
+       int archive_inherit;
+       int platform_inherit;
 } acl_inherit_map[] = {
-        {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
+#if HAVE_SUN_ACL       /* Solaris ACL inheritance flags */
+       {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE},
+       {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE},
+       {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, 
ACE_NO_PROPAGATE_INHERIT_ACE},
+       {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE},
+       {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, 
ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
+       {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG},
+       {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}
+#elif HAVE_DARWIN_ACL  /* MacOS NFSv4 inheritance flags */
+       {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED},
+       {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
+       {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, 
ACL_ENTRY_DIRECTORY_INHERIT},
+       {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_LIMIT_INHERIT},
+       {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT}
+#else  /* FreeBSD NFSv4 ACL inheritance flags */
+       {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
        {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, 
ACL_ENTRY_DIRECTORY_INHERIT},
        {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, 
ACL_ENTRY_NO_PROPAGATE_INHERIT},
        {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY},
        {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, 
ACL_ENTRY_SUCCESSFUL_ACCESS},
        {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
        {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}
+#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
 };
-#endif
+#endif /* HAVE_NFS4_ACL */
+
+#if HAVE_DARWIN_ACL
+static int translate_guid(struct archive *a, acl_entry_t acl_entry,
+    int *ae_id, int *ae_tag, const char **ae_name)
+{
+       void *q;
+       uid_t ugid;
+       int r, idtype;
+       struct passwd *pwd;
+       struct group *grp;
+
+       q = acl_get_qualifier(acl_entry);
+       if (q == NULL)
+               return (1);
+       r = mbr_uuid_to_id((const unsigned char *)q, &ugid, &idtype);
+       if (r != 0) {
+               acl_free(q);
+               return (1);
+       }
+       if (idtype == ID_TYPE_UID) {
+               *ae_tag = ARCHIVE_ENTRY_ACL_USER;
+               pwd = getpwuuid(q);
+               if (pwd == NULL) {
+                       *ae_id = ugid;
+                       *ae_name = NULL;
+               } else {
+                       *ae_id = pwd->pw_uid;
+                       *ae_name = archive_read_disk_uname(a, *ae_id);
+               }
+       } else if (idtype == ID_TYPE_GID) {
+               *ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
+               grp = getgruuid(q);
+               if (grp == NULL) {
+                       *ae_id = ugid;
+                       *ae_name = NULL;
+               } else {
+                       *ae_id = grp->gr_gid;
+                       *ae_name = archive_read_disk_gname(a, *ae_id);
+               }
+       } else
+               r = 1;
+
+       acl_free(q);
+       return (r);
+}
+
+/*
+ * Add trivial NFSv4 ACL entries from mode
+ */
+static void
+add_trivial_nfs4_acl(struct archive_entry *entry)
+{
+       mode_t mode;
+       int i;
+       const int rperm = ARCHIVE_ENTRY_ACL_READ_DATA;
+       const int wperm = ARCHIVE_ENTRY_ACL_WRITE_DATA |
+           ARCHIVE_ENTRY_ACL_APPEND_DATA;
+       const int eperm = ARCHIVE_ENTRY_ACL_EXECUTE;
+       const int pubset = ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
+           ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
+           ARCHIVE_ENTRY_ACL_READ_ACL |
+           ARCHIVE_ENTRY_ACL_SYNCHRONIZE;
+       const int ownset = pubset | ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
+           ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
+           ARCHIVE_ENTRY_ACL_WRITE_ACL |
+           ARCHIVE_ENTRY_ACL_WRITE_OWNER;
+
+       struct {
+           const int type;
+           const int tag;
+           int permset;
+       } tacl_entry[] = {
+           {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, 0},
+           {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_USER_OBJ, 0},
+           {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0},
+           {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, ownset},
+           {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_GROUP_OBJ, pubset},
+           {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EVERYONE, pubset}
+       };
+
+       mode = archive_entry_mode(entry);
+
+       /* Permissions for everyone@ */
+       if (mode & 0004)
+               tacl_entry[5].permset |= rperm;
+       if (mode & 0002)
+               tacl_entry[5].permset |= wperm;
+       if (mode & 0001)
+               tacl_entry[5].permset |= eperm;
+
+       /* Permissions for group@ */
+       if (mode & 0040)
+               tacl_entry[4].permset |= rperm;
+       else if (mode & 0004)
+               tacl_entry[2].permset |= rperm;
+       if (mode & 0020)
+               tacl_entry[4].permset |= wperm;
+       else if (mode & 0002)
+               tacl_entry[2].permset |= wperm;
+       if (mode & 0010)
+               tacl_entry[4].permset |= eperm;
+       else if (mode & 0001)
+               tacl_entry[2].permset |= eperm;
+
+       /* Permissions for owner@ */
+       if (mode & 0400) {
+               tacl_entry[3].permset |= rperm;
+               if (!(mode & 0040) && (mode & 0004))
+                       tacl_entry[0].permset |= rperm;
+       } else if ((mode & 0040) || (mode & 0004))
+               tacl_entry[1].permset |= rperm;
+       if (mode & 0200) {
+               tacl_entry[3].permset |= wperm;
+               if (!(mode & 0020) && (mode & 0002))
+                       tacl_entry[0].permset |= wperm;
+       } else if ((mode & 0020) || (mode & 0002))
+               tacl_entry[1].permset |= wperm;
+       if (mode & 0100) {
+               tacl_entry[3].permset |= eperm;
+               if (!(mode & 0010) && (mode & 0001))
+                       tacl_entry[0].permset |= eperm;
+       } else if ((mode & 0010) || (mode & 0001))
+               tacl_entry[1].permset |= eperm;
+
+       for (i = 0; i < 6; i++) {
+               if (tacl_entry[i].permset != 0) {
+                       archive_entry_acl_add_entry(entry,
+                           tacl_entry[i].type, tacl_entry[i].permset,
+                           tacl_entry[i].tag, -1, NULL);
+               }
+       }
+
+       return;
+}
+#elif HAVE_SUN_ACL
+/*
+ * Check if acl is trivial
+ * This is a FreeBSD acl_is_trivial_np() implementation for Solaris
+ */
+static int
+sun_acl_is_trivial(acl_t *acl, mode_t mode, int *trivialp)
+{
+       int i, p;
+       const uint32_t rperm = ACE_READ_DATA;
+       const uint32_t wperm = ACE_WRITE_DATA | ACE_APPEND_DATA;
+       const uint32_t eperm = ACE_EXECUTE;
+       const uint32_t pubset = ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS |
+           ACE_READ_ACL | ACE_SYNCHRONIZE;
+       const uint32_t ownset = pubset | ACE_WRITE_ATTRIBUTES |
+           ACE_WRITE_NAMED_ATTRS | ACE_WRITE_ACL | ACE_WRITE_OWNER;
+
+       ace_t *ace;
+       ace_t tace[6];
+
+       if (acl == NULL || trivialp == NULL)
+               return (-1);
+
+       *trivialp = 0;
+
+       /* ACL_IS_TRIVIAL flag must be set for both POSIX.1e and NFSv4 ACLs */
+       if ((acl->acl_flags & ACL_IS_TRIVIAL) == 0)
+               return (0);
+
+       /*
+        * POSIX.1e ACLs marked with ACL_IS_TRIVIAL are compatible with
+        * FreeBSD acl_is_trivial_np(). On Solaris they have 4 entries,
+        * incuding mask.
+        */
+       if (acl->acl_type == ACLENT_T) {
+               if (acl->acl_cnt == 4)
+                       *trivialp = 1;
+               return (0);
+       }
+
+       if (acl->acl_type != ACE_T || acl->acl_entry_size != sizeof(ace_t))
+               return (-1);
+
+       /*
+        * Continue with checking NFSv4 ACLs
+        *
+        * Create list of trivial ace's to be compared
+        */
+
+       /* owner@ allow pre */
+       tace[0].a_flags = ACE_OWNER;
+       tace[0].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
+       tace[0].a_access_mask = 0;
+
+       /* owner@ deny */
+       tace[1].a_flags = ACE_OWNER;
+       tace[1].a_type = ACE_ACCESS_DENIED_ACE_TYPE;
+       tace[1].a_access_mask = 0;
+
+       /* group@ deny */
+       tace[2].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP;
+       tace[2].a_type = ACE_ACCESS_DENIED_ACE_TYPE;
+       tace[2].a_access_mask = 0;
+
+       /* owner@ allow */
+       tace[3].a_flags = ACE_OWNER;
+       tace[3].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
+       tace[3].a_access_mask = ownset;
+
+       /* group@ allow */
+       tace[4].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP;
+       tace[4].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
+       tace[4].a_access_mask = pubset;
+
+       /* everyone@ allow */
+       tace[5].a_flags = ACE_EVERYONE;
+       tace[5].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
+       tace[5].a_access_mask = pubset;
+
+       /* Permissions for everyone@ */
+       if (mode & 0004)
+               tace[5].a_access_mask |= rperm;
+       if (mode & 0002)
+               tace[5].a_access_mask |= wperm;
+       if (mode & 0001)
+               tace[5].a_access_mask |= eperm;
+
+       /* Permissions for group@ */
+       if (mode & 0040)
+               tace[4].a_access_mask |= rperm;
+       else if (mode & 0004)
+               tace[2].a_access_mask |= rperm;
+       if (mode & 0020)
+               tace[4].a_access_mask |= wperm;
+       else if (mode & 0002)
+               tace[2].a_access_mask |= wperm;
+       if (mode & 0010)
+               tace[4].a_access_mask |= eperm;
+       else if (mode & 0001)
+               tace[2].a_access_mask |= eperm;
+
+       /* Permissions for owner@ */
+       if (mode & 0400) {
+               tace[3].a_access_mask |= rperm;
+               if (!(mode & 0040) && (mode & 0004))
+                       tace[0].a_access_mask |= rperm;
+       } else if ((mode & 0040) || (mode & 0004))
+               tace[1].a_access_mask |= rperm;
+       if (mode & 0200) {
+               tace[3].a_access_mask |= wperm;
+               if (!(mode & 0020) && (mode & 0002))
+                       tace[0].a_access_mask |= wperm;
+       } else if ((mode & 0020) || (mode & 0002))
+               tace[1].a_access_mask |= wperm;
+       if (mode & 0100) {
+               tace[3].a_access_mask |= eperm;
+               if (!(mode & 0010) && (mode & 0001))
+                       tace[0].a_access_mask |= eperm;
+       } else if ((mode & 0010) || (mode & 0001))
+               tace[1].a_access_mask |= eperm;
+
+       /* Check if the acl count matches */
+       p = 3;
+       for (i = 0; i < 3; i++) {
+               if (tace[i].a_access_mask != 0)
+                       p++;
+       }
+       if (acl->acl_cnt != p)
+               return (0);
+
+       p = 0;
+       for (i = 0; i < 6; i++) {
+               if (tace[i].a_access_mask != 0) {
+                       ace = &((ace_t *)acl->acl_aclp)[p];
+                       /*
+                        * Illumos added ACE_DELETE_CHILD to write perms for
+                        * directories. We have to check against that, too.
+                        */
+                       if (ace->a_flags != tace[i].a_flags ||
+                           ace->a_type != tace[i].a_type ||
+                           (ace->a_access_mask != tace[i].a_access_mask &&
+                           ((acl->acl_flags & ACL_IS_DIR) == 0 ||
+                           (tace[i].a_access_mask & wperm) == 0 ||
+                           ace->a_access_mask !=
+                           (tace[i].a_access_mask | ACE_DELETE_CHILD))))
+                               return (0);
+                       p++;
+               }
+       }
+
+       *trivialp = 1;
+       return (0);
+}
+#endif /* HAVE_SUN_ACL */
+
+#if HAVE_SUN_ACL
+/*
+ * Translate Solaris POSIX.1e and NFSv4 ACLs into libarchive internal ACL
+ */
+static int
+translate_acl(struct archive_read_disk *a,
+    struct archive_entry *entry, acl_t *acl, int default_entry_acl_type)
+{
+       int e, i;
+       int ae_id, ae_tag, ae_perm;
+       int entry_acl_type;
+       const char *ae_name;
+       aclent_t *aclent;
+       ace_t *ace;
+
+       (void)default_entry_acl_type;
+
+       if (acl->acl_cnt <= 0)
+               return (ARCHIVE_OK);
+
+       for (e = 0; e < acl->acl_cnt; e++) {
+               ae_name = NULL;
+               ae_tag = 0;
+               ae_perm = 0;
+
+               if (acl->acl_type == ACE_T) {
+                       ace = &((ace_t *)acl->acl_aclp)[e];
+                       ae_id = ace->a_who;
+
+                       switch(ace->a_type) {
+                       case ACE_ACCESS_ALLOWED_ACE_TYPE:
+                               entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
+                               break;
+                       case ACE_ACCESS_DENIED_ACE_TYPE:
+                               entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
+                               break;
+                       case ACE_SYSTEM_AUDIT_ACE_TYPE:
+                               entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+                               break;
+                       case ACE_SYSTEM_ALARM_ACE_TYPE:
+                               entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
+                               break;
+                       default:
+                               /* Unknown entry type, skip */
+                               continue;
+                       }
+
+                       if ((ace->a_flags & ACE_OWNER) != 0)
+                               ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+                       else if ((ace->a_flags & ACE_GROUP) != 0)
+                               ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+                       else if ((ace->a_flags & ACE_EVERYONE) != 0)
+                               ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
+                       else if ((ace->a_flags & ACE_IDENTIFIER_GROUP) != 0) {
+                               ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
+                               ae_name = archive_read_disk_gname(&a->archive,
+                                   ae_id);
+                       } else {
+                               ae_tag = ARCHIVE_ENTRY_ACL_USER;
+                               ae_name = archive_read_disk_uname(&a->archive,
+                                   ae_id);
+                       }
+
+                       for (i = 0; i < (int)(sizeof(acl_inherit_map) /
+                           sizeof(acl_inherit_map[0])); ++i) {
+                               if ((ace->a_flags &
+                                   acl_inherit_map[i].platform_inherit) != 0)
+                                       ae_perm |=
+                                           acl_inherit_map[i].archive_inherit;
+                       }
+
+                       for (i = 0; i < (int)(sizeof(acl_perm_map) /
+                           sizeof(acl_perm_map[0])); ++i) {
+                               if ((ace->a_access_mask &
+                                   acl_perm_map[i].platform_perm) != 0)
+                                       ae_perm |=
+                                           acl_perm_map[i].archive_perm;
+                       }
+               } else {
+                       aclent = &((aclent_t *)acl->acl_aclp)[e];
+                       if ((aclent->a_type & ACL_DEFAULT) != 0)
+                               entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
+                       else
+                               entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+                       ae_id = aclent->a_id;
+
+                       switch(aclent->a_type) {
+                       case DEF_USER:
+                       case USER:
+                               ae_name = archive_read_disk_uname(&a->archive,
+                                   ae_id);
+                               ae_tag = ARCHIVE_ENTRY_ACL_USER;
+                               break;
+                       case DEF_GROUP:
+                       case GROUP:
+                               ae_name = archive_read_disk_gname(&a->archive,
+                                   ae_id);
+                               ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
+                               break;
+                       case DEF_CLASS_OBJ:
+                       case CLASS_OBJ:
+                               ae_tag = ARCHIVE_ENTRY_ACL_MASK;
+                               break;
+                       case DEF_USER_OBJ:
+                       case USER_OBJ:
+                               ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+                               break;
+                       case DEF_GROUP_OBJ:
+                       case GROUP_OBJ:
+                               ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+                               break;
+                       case DEF_OTHER_OBJ:
+                       case OTHER_OBJ:
+                               ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
+                               break;
+                       default:
+                               /* Unknown tag type, skip */
+                               continue;
+                       }
+
+                       if ((aclent->a_perm & 1) != 0)
+                               ae_perm |= ARCHIVE_ENTRY_ACL_EXECUTE;
+                       if ((aclent->a_perm & 2) != 0)
+                               ae_perm |= ARCHIVE_ENTRY_ACL_WRITE;
+                       if ((aclent->a_perm & 4) != 0)
+                               ae_perm |= ARCHIVE_ENTRY_ACL_READ;
+               } /* default_entry_acl_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4 */
+
+               archive_entry_acl_add_entry(entry, entry_acl_type,
+                   ae_perm, ae_tag, ae_id, ae_name);
+       }
+       return (ARCHIVE_OK);
+}
+#else  /* !HAVE_SUN_ACL */
+/*
+ * Translate POSIX.1e (Linux), FreeBSD (both POSIX.1e and NFSv4) and
+ * MacOS (NFSv4 only) ACLs into libarchive internal structure
+ */
 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
+#if HAVE_ACL_TYPE_NFS4
        acl_entry_type_t acl_type;
-       acl_flagset_t    acl_flagset;
        int brand;
 #endif
+#if HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL
+       acl_flagset_t    acl_flagset;
+#endif
        acl_entry_t      acl_entry;
        acl_permset_t    acl_permset;
        int              i, entry_acl_type;
        int              r, s, ae_id, ae_tag, ae_perm;
+#if !HAVE_DARWIN_ACL
+       void            *q;
+#endif
        const char      *ae_name;
 
-#ifdef ACL_TYPE_NFS4
+#if HAVE_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.
@@ -643,14 +1199,19 @@ translate_acl(struct archive_read_disk *
        }
 #endif
 
-
        s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
        if (s == -1) {
                archive_set_error(&a->archive, errno,
                    "Failed to get first ACL entry");
                return (ARCHIVE_WARN);
        }
-       while (s == 1) {
+
+#if HAVE_DARWIN_ACL
+       while (s == 0)
+#else  /* FreeBSD, Linux */
+       while (s == 1)
+#endif
+       {
                ae_id = -1;
                ae_name = NULL;
                ae_perm = 0;
@@ -661,14 +1222,25 @@ translate_acl(struct archive_read_disk *
                        return (ARCHIVE_WARN);
                }
                switch (acl_tag) {
+#if !HAVE_DARWIN_ACL   /* FreeBSD, Linux */
                case ACL_USER:
-                       ae_id = (int)*(uid_t *)acl_get_qualifier(acl_entry);
-                       ae_name = archive_read_disk_uname(&a->archive, ae_id);
+                       q = acl_get_qualifier(acl_entry);
+                       if (q != NULL) {
+                               ae_id = (int)*(uid_t *)q;
+                               acl_free(q);
+                               ae_name = archive_read_disk_uname(&a->archive,
+                                   ae_id);
+                       }
                        ae_tag = ARCHIVE_ENTRY_ACL_USER;
                        break;
                case ACL_GROUP:
-                       ae_id = (int)*(gid_t *)acl_get_qualifier(acl_entry);
-                       ae_name = archive_read_disk_gname(&a->archive, ae_id);
+                       q = acl_get_qualifier(acl_entry);
+                       if (q != NULL) {
+                               ae_id = (int)*(gid_t *)q;
+                               acl_free(q);
+                               ae_name = archive_read_disk_gname(&a->archive,
+                                   ae_id);
+                       }
                        ae_tag = ARCHIVE_ENTRY_ACL_GROUP;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to