Ticket #53712: libarchive_fix_from_3.3.1_try_2.diff

File libarchive_fix_from_3.3.1_try_2.diff, 336.9 KB (added by michaelld (Michael Dickens), 8 years ago)
  • archivers/libarchive/Portfile

    commit d488b0781117d354e624c50f88092beb59bfcd73
    Author: Michael Dickens <michaelld@macports.org>
    Date:   Sun Mar 19 22:07:50 2017 -0400
    
        libarchive: add patch to fix build on older Mac OS X
        
        Addresses ticket https://trac.macports.org/ticket/53712
    
    diff --git a/archivers/libarchive/Portfile b/archivers/libarchive/Portfile
    index 3678221b87..7b29447b6d 100644
    a b depends_lib port:bzip2 port:zlib port:libxml2 port:xz \ 
    2323                 port:lzo2 port:libiconv \
    2424                 port:lz4 port:expat
    2525
    26 patchfiles       patch-libarchive__archive_read_support_format_lha.c.diff
     26# patchfiles       patch-libarchive__archive_read_support_format_lha.c.diff
     27
     28####
     29# the following section is to be removed when 3.3.2 is released. it is
     30# a temporary fix for older Mac OS X versions, and is already upstream.
     31# comment back in the above patchfile, too.
     32
     33revision         1
     34
     35patchfiles-append \
     36    patch-3.3.1_to_master.diff \
     37    patch-Makefile.am.diff \
     38    patch-libarchive__archive_read_support_format_lha.c_p1.diff
     39patch.pre_args   -p1
     40
     41depends_build    port:autoconf port:automake port:libtool
     42
     43post-patch {
     44    system -W ${worksrcpath} "build/autogen.sh"
     45}
     46
     47####
    2748
    2849configure.args   --enable-bsdtar=shared --enable-bsdcpio=shared \
    2950                 --disable-silent-rules --without-nettle \
    30                  --without-openssl --without-lzmadec
     51                 --without-openssl
    3152
    3253livecheck.type  regex
    3354livecheck.regex libarchive-(\[0-9.\]+)\\.tar.gz
  • new file archivers/libarchive/files/patch-3.3.1_to_master.diff

    diff --git a/archivers/libarchive/files/patch-3.3.1_to_master.diff b/archivers/libarchive/files/patch-3.3.1_to_master.diff
    new file mode 100644
    index 0000000000..acdfba17ad
    - +  
     1commit 4476a775c2241a43a471e7b5a5819dd7e51b4f6c
     2Author: Tim Kientzle <kientzle@acm.org>
     3Date:   Sat Feb 25 11:39:55 2017 -0800
     4
     5    After the 3.3.1 release, bump the version to 3.3.2dev and go back to debug building.
     6   
     7    Use types consistent with the prototypes in the header.
     8   
     9    bsdtar manpage: be more precise what -p and --no-same-permissions does
     10   
     11    bsdtar tests: add test_option_fflags
     12   
     13    Mark functions that don't return as dead.
     14   
     15    Use ctype macros with unsigned char arguments.
     16   
     17    Be more friendly to format string checkers.
     18   
     19    Mark functions that don't return as dead.
     20   
     21    Add format function annotation.
     22   
     23    Mark function that doesn't return as dead.
     24   
     25    mdoc should not contain empty lines.
     26   
     27    test_main: compact canNodump() source code a bit
     28   
     29    Fix typos.
     30   
     31    Drop trailing comma.
     32   
     33    Drop documentation for functions with their own man page.
     34   
     35    Move documentation from archive_write_disk(3) into individual man pages.
     36   
     37    Fix markup
     38   
     39    Fix markup
     40   
     41    Missing commas
     42   
     43    Compare full file flags in test_option_fflags
     44   
     45    Fix compilation on Mac OS X versions without ACL_SYNCHRONIZE
     46   
     47    Change Solaris ACL support to use acl() and facl()
     48   
     49    This removes dependency on libsec and enables compilation on Solaris 10.
     50   
     51    Reorganize ACL defines and fix detection of ACL_SYNCHRONIZE on Mac OS
     52    Adjust MacOS part of test_acl_platform_nfs4
     53   
     54    New tar test: test_option_acls
     55    Add sunacl_get() and setTestAcl() to common test code
     56    Test for membership.h on Mac OS X and make it a requirement for ACLs
     57   
     58    Solaris: use aclp instead of acl to not shadow global acl()
     59   
     60    tar: test_option_fflags adjustments
     61      - Clear fflags on created directories
     62      - FreeBSD ZFS workaround - ZFS sets uarch on all touched files
     63   
     64    Fix typos
     65   
     66    The "size" pax header keyword overrides tar header's size field.
     67   
     68    Fixes #880
     69   
     70    Darwin ACL: avoid using mbr_identifier_to_uuid()
     71    Use mbr_uid_to_uuid() and mbr_gid_to_uuid() for backwards compatibility
     72    instead. These functions have been introduced together with membership.h.
     73   
     74    Fixes #882
     75   
     76    Darwin ACL: avoid unnecessary use of getpwuuid() and getgruuid()
     77   
     78    Darwin ACL: fix legacy support in tar/test_option_acls.c
     79    Remove ACL_FLAG_DEFER_INHERIT and ACL_FLAG_NO_INHERIT
     80   
     81    OSS-Fuzz Issue 806: integer overflow in mtree_atol10
     82   
     83    Rework the mtree_atol10 integer parser so it can parse
     84    INT64_MIN without overflowing the intermediate value.
     85   
     86    While here, make this function behave a little more predictably for
     87    too-large input: It now always advances the pointer to the first
     88    non-digit character.
     89   
     90    Break out the library version functions into a separate source file.
     91   
     92    This breaks a static dependency on libbz2.  Before this,
     93    any use of libarchive that ended up linking archive_util.c would
     94    require libbz2.  (And since archive_util.c contains a bunch of
     95    very core functions, this is pretty much everybody.)
     96    Now you only require libbz2 if you request library version information
     97    or actually use some other feature that involves bzip2 support.
     98   
     99    Note that most of the libraries provide version information via
     100    compile-time macros -- libbz2 only provides such information via
     101    a function call, which is why this issue only arises with libbz2.
     102    In particular, the libbz2 version reports the version that we
     103    are currently linked against; the other library versions report
     104    the version we were compiled with (which may not be the same as
     105    what we are currently using).
     106   
     107    bsdcpio: ignore ENOENT for get{grg,pwu}id()
     108   
     109    Starting from glibc 2.25, those calls set errno to ENOENT
     110    when the requested id is not found.  So let's stop throwing
     111    warning in this expected case.
     112   
     113    Also rework the api of lookup_* functions so it is guaranteed that
     114    lookup_name never returns NULL (unless ENOMEM).
     115   
     116    Changes to configure.ac from MSYS2 Pacman project for mingw-w64.  This allows you to use Bcrypt for CNG with autotools.
     117   
     118    Add bcrypt to libaries if BCrypt.h exists to enable Crypto-Next-Generation (CNG).
     119   
     120    seekable zip backend: Accept files with valid ZIP64 EOCD headers
     121   
     122    Previously, a ZIP64 file needed to have a valid classic EOCD header.
     123    This is not the case at least for archives generated by PHPZipStreamer.
     124   
     125    This commit allows for a bit more than necessary: While PHPZipStreamer
     126    sets the classic EOCD header to all -1's, the bidding function now
     127    succeeds also if the EOCD header values have arbitrary values, as long
     128    as the ZIP64 EOCD header seems plausible. This simplifies the logic and
     129    should not do any harm in practice.
     130   
     131    This fixes #869.
     132   
     133    Move platform-specific ACL code to individual source files.
     134   
     135    This makes the code much more readable and eases the addition of new
     136    ACL implementatons in the future.
     137   
     138    Additional changes:
     139    - most of ACL detection is now done at configure stage
     140    - configuration now reports what ACL was detected
     141    - NFSv4 ACL tests now test INHERIT_ONLY and NO_PROPAGATE_INHERIT
     142   
     143    Add NFSv4 ACL support for Linux via librichacl
     144   
     145    Richacls are interpreted as NFSv4 ACLs and stored in archive_acl (Richacl
     146    flags and masks are not stored). Analog to mac_metadata, NFSv4 ACLs do not
     147    get extracted when the extraction of extended attributes is enabled and the
     148    "trusted.richacl" extended attribute is present.
     149   
     150    RichACL masks and are calculated from file mode on extraction.
     151   
     152    mac_metadata acl check has been moved in the code to be together with the
     153    richacl check.
     154   
     155    Do not treat archive_read_disk_entry_setup_acls() as static
     156   
     157    Deduplicate working path code in archive_read_disk_entry_from_file
     158   
     159    As per Cryptographic Requirements published on Wikileaks on March 2017.
     160   
     161    We discard more bytes of the first keystream
     162    to reduce the possibility of non-random bytes.
     163   
     164    Similar to:
     165    freebsd/freebsd@9395fdf
     166
     167diff --git a/CMakeLists.txt b/CMakeLists.txt
     168index 1ca9d8fd..f62153cb 100644
     169--- a/CMakeLists.txt
     170+++ b/CMakeLists.txt
     171@@ -15,7 +15,7 @@ endif()
     172 #   RelWithDebInfo : Release build with Debug Info
     173 #   MinSizeRel     : Release Min Size build
     174 IF(NOT CMAKE_BUILD_TYPE)
     175-  SET(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build Type" FORCE)
     176+  SET(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build Type" FORCE)
     177 ENDIF(NOT CMAKE_BUILD_TYPE)
     178 # Set a value type to properly display CMAKE_BUILD_TYPE on GUI if the
     179 # value type is "UNINITIALIZED".
     180@@ -579,6 +579,7 @@ int main(void) { return FS_IOC_GETFLAGS; }" HAVE_WORKING_FS_IOC_GETFLAGS)
     181 
     182 LA_CHECK_INCLUDE_FILE("linux/magic.h" HAVE_LINUX_MAGIC_H)
     183 LA_CHECK_INCLUDE_FILE("locale.h" HAVE_LOCALE_H)
     184+LA_CHECK_INCLUDE_FILE("membership.h" HAVE_MEMBERSHIP_H)
     185 LA_CHECK_INCLUDE_FILE("memory.h" HAVE_MEMORY_H)
     186 LA_CHECK_INCLUDE_FILE("paths.h" HAVE_PATHS_H)
     187 LA_CHECK_INCLUDE_FILE("poll.h" HAVE_POLL_H)
     188@@ -601,6 +602,7 @@ LA_CHECK_INCLUDE_FILE("sys/mkdev.h" HAVE_SYS_MKDEV_H)
     189 LA_CHECK_INCLUDE_FILE("sys/mount.h" HAVE_SYS_MOUNT_H)
     190 LA_CHECK_INCLUDE_FILE("sys/param.h" HAVE_SYS_PARAM_H)
     191 LA_CHECK_INCLUDE_FILE("sys/poll.h" HAVE_SYS_POLL_H)
     192+LA_CHECK_INCLUDE_FILE("sys/richacl.h" HAVE_SYS_RICHACL_H)
     193 LA_CHECK_INCLUDE_FILE("sys/select.h" HAVE_SYS_SELECT_H)
     194 LA_CHECK_INCLUDE_FILE("sys/stat.h" HAVE_SYS_STAT_H)
     195 LA_CHECK_INCLUDE_FILE("sys/statfs.h" HAVE_SYS_STATFS_H)
     196@@ -618,6 +620,9 @@ LA_CHECK_INCLUDE_FILE("wctype.h" HAVE_WCTYPE_H)
     197 LA_CHECK_INCLUDE_FILE("windows.h" HAVE_WINDOWS_H)
     198 IF(ENABLE_CNG)
     199   LA_CHECK_INCLUDE_FILE("Bcrypt.h" HAVE_BCRYPT_H)
     200+  IF(HAVE_BCRYPT_H)
     201+    LIST(APPEND ADDITIONAL_LIBS "Bcrypt")
     202+  ENDIF(HAVE_BCRYPT_H)
     203 ELSE(ENABLE_CNG)
     204   UNSET(HAVE_BCRYPT_H CACHE)
     205 ENDIF(ENABLE_CNG)
     206@@ -1592,78 +1597,212 @@ ENDIF(ENABLE_XATTR)
     207 # which makes the following checks rather more complex than I would like.
     208 #
     209 IF(ENABLE_ACL)
     210+  # Solaris and derivates ACLs
     211+  CHECK_FUNCTION_EXISTS(acl HAVE_ACL)
     212+  CHECK_FUNCTION_EXISTS(facl HAVE_FACL)
     213+
     214+  # Libacl
     215   CHECK_LIBRARY_EXISTS(acl "acl_get_file" "" HAVE_LIBACL)
     216   IF(HAVE_LIBACL)
     217     SET(CMAKE_REQUIRED_LIBRARIES "acl")
     218     FIND_LIBRARY(ACL_LIBRARY NAMES acl)
     219     LIST(APPEND ADDITIONAL_LIBS ${ACL_LIBRARY})
     220   ENDIF(HAVE_LIBACL)
     221-  #
     222-  CHECK_FUNCTION_EXISTS_GLIBC(acl_create_entry HAVE_ACL_CREATE_ENTRY)
     223-  CHECK_FUNCTION_EXISTS_GLIBC(acl_init HAVE_ACL_INIT)
     224-  CHECK_FUNCTION_EXISTS_GLIBC(acl_set_fd HAVE_ACL_SET_FD)
     225-  CHECK_FUNCTION_EXISTS_GLIBC(acl_set_fd_np HAVE_ACL_SET_FD_NP)
     226-  CHECK_FUNCTION_EXISTS_GLIBC(acl_set_file HAVE_ACL_SET_FILE)
     227-  CHECK_TYPE_EXISTS(acl_permset_t "${INCLUDES}"    HAVE_ACL_PERMSET_T)
     228-
     229-  # The "acl_get_perm()" function was omitted from the POSIX draft.
     230-  # (It's a pretty obvious oversight; otherwise, there's no way to
     231-  # test for specific permissions in a permset.)  Linux uses the obvious
     232-  # name, FreeBSD adds _np to mark it as "non-Posix extension."
     233-  # Test for both as a double-check that we really have POSIX-style ACL support.
     234-  CHECK_FUNCTION_EXISTS(acl_get_fd_np HAVE_ACL_GET_FD_NP)
     235-  CHECK_FUNCTION_EXISTS(acl_get_perm HAVE_ACL_GET_PERM)
     236-  CHECK_FUNCTION_EXISTS(acl_get_perm_np HAVE_ACL_GET_PERM_NP)
     237-  CHECK_FUNCTION_EXISTS(acl_get_link HAVE_ACL_GET_LINK)
     238-  CHECK_FUNCTION_EXISTS(acl_get_link_np HAVE_ACL_GET_LINK_NP)
     239-  CHECK_FUNCTION_EXISTS(acl_is_trivial_np HAVE_ACL_IS_TRIVIAL_NP)
     240-  CHECK_FUNCTION_EXISTS(acl_set_link_np HAVE_ACL_SET_LINK_NP)
     241-  CHECK_SYMBOL_EXISTS(ACL_TYPE_NFS4 "${INCLUDES}" HAVE_ACL_TYPE_NFS4)
     242-
     243-  # MacOS has an acl.h that isn't POSIX.  It can be detected by
     244-  # checking for ACL_USER
     245-  CHECK_SYMBOL_EXISTS(ACL_USER "${INCLUDES}" HAVE_ACL_USER)
     246-  CHECK_C_SOURCE_COMPILES("#include <sys/types.h>
     247+
     248+  CHECK_TYPE_EXISTS(acl_t "sys/types.h;sys/acl.h" HAVE_ACL_T)
     249+  CHECK_TYPE_EXISTS(acl_entry_t "sys/types.h;sys/acl.h" HAVE_ACL_ENTRY_T)
     250+  CHECK_TYPE_EXISTS(acl_permset_t "sys/types.h;sys/acl.h" HAVE_ACL_PERMSET_T)
     251+  CHECK_TYPE_EXISTS(acl_tag_t "sys/types.h;sys/acl.h" HAVE_ACL_TAG_T)
     252+
     253+  IF(HAVE_ACL AND HAVE_FACL)
     254+    CHECK_TYPE_EXISTS(aclent_t "sys/acl.h" HAVE_ACLENT_T)
     255+    IF(HAVE_ACLENT_T)
     256+      CHECK_SYMBOL_EXISTS(GETACL "sys/acl.h" HAVE_DECL_GETACL)
     257+      CHECK_SYMBOL_EXISTS(GETACLCNT "sys/acl.h" HAVE_DECL_GETACLCNT)
     258+      CHECK_SYMBOL_EXISTS(SETACL "sys/acl.h" HAVE_DECL_SETACL)
     259+      IF(HAVE_DECL_GETACL AND
     260+         HAVE_DECL_GETACLCNT AND
     261+         HAVE_DECL_SETACL)
     262+        SET(ARCHIVE_ACL_SUNOS TRUE)
     263+      ENDIF()
     264+      CHECK_TYPE_EXISTS(ace_t "sys/acl.h" HAVE_ACE_T)
     265+      IF(HAVE_ACE_T)
     266+        CHECK_SYMBOL_EXISTS(ACE_GETACL "sys/acl.h" HAVE_DECL_ACE_GETACL)
     267+        CHECK_SYMBOL_EXISTS(ACE_GETACLCNT "sys/acl.h" HAVE_DECL_ACE_GETACLCNT)
     268+        CHECK_SYMBOL_EXISTS(ACE_SETACL "sys/acl.h" HAVE_DECL_ACE_SETACL)
     269+        IF(HAVE_DECL_ACE_GETACL AND
     270+           HAVE_DECL_ACE_GETACLCNT AND
     271+           HAVE_DECL_ACE_SETACL)
     272+          SET(ARCHIVE_ACL_SUNOS_NFS4 TRUE)
     273+        ENDIF()
     274+      ENDIF(HAVE_ACE_T)
     275+    ENDIF(HAVE_ACLENT_T)
     276+  ENDIF(HAVE_ACL AND HAVE_FACL)
     277+
     278+  IF(HAVE_ACL_T AND HAVE_ACL_ENTRY_T AND HAVE_ACL_PERMSET_T AND HAVE_ACL_TAG_T)
     279+    CHECK_FUNCTION_EXISTS_GLIBC(acl_add_perm HAVE_ACL_ADD_PERM)
     280+    CHECK_FUNCTION_EXISTS_GLIBC(acl_clear_perms HAVE_ACL_CLEAR_PERMS)
     281+    CHECK_FUNCTION_EXISTS_GLIBC(acl_create_entry HAVE_ACL_CREATE_ENTRY)
     282+    CHECK_FUNCTION_EXISTS_GLIBC(acl_delete_def_file HAVE_ACL_DELETE_DEF_FILE)
     283+    CHECK_FUNCTION_EXISTS_GLIBC(acl_free HAVE_ACL_FREE)
     284+    CHECK_FUNCTION_EXISTS_GLIBC(acl_get_entry HAVE_ACL_GET_ENTRY)
     285+    CHECK_FUNCTION_EXISTS_GLIBC(acl_get_fd HAVE_ACL_GET_FD)
     286+    CHECK_FUNCTION_EXISTS_GLIBC(acl_get_file HAVE_ACL_GET_FILE)
     287+    CHECK_FUNCTION_EXISTS_GLIBC(acl_get_permset HAVE_ACL_GET_PERMSET)
     288+    CHECK_FUNCTION_EXISTS_GLIBC(acl_get_qualifier HAVE_ACL_GET_QUALIFIER)
     289+    CHECK_FUNCTION_EXISTS_GLIBC(acl_get_tag_type HAVE_ACL_GET_TAG_TYPE)
     290+    CHECK_FUNCTION_EXISTS_GLIBC(acl_init HAVE_ACL_INIT)
     291+    CHECK_FUNCTION_EXISTS_GLIBC(acl_set_fd HAVE_ACL_SET_FD)
     292+    CHECK_FUNCTION_EXISTS_GLIBC(acl_set_file HAVE_ACL_SET_FILE)
     293+    CHECK_FUNCTION_EXISTS_GLIBC(acl_set_qualifier HAVE_ACL_SET_QUALIFIER)
     294+    CHECK_FUNCTION_EXISTS_GLIBC(acl_set_tag_type HAVE_ACL_SET_TAG_TYPE)
     295+    IF(HAVE_ACL_ADD_PERM AND
     296+       HAVE_ACL_CLEAR_PERMS AND
     297+       HAVE_ACL_CREATE_ENTRY AND
     298+       HAVE_ACL_DELETE_DEF_FILE AND
     299+       HAVE_ACL_FREE AND
     300+       HAVE_ACL_GET_ENTRY AND
     301+       HAVE_ACL_GET_FD AND
     302+       HAVE_ACL_GET_FILE AND
     303+       HAVE_ACL_GET_PERMSET AND
     304+       HAVE_ACL_GET_QUALIFIER AND
     305+       HAVE_ACL_GET_TAG_TYPE AND
     306+       HAVE_ACL_INIT AND
     307+       HAVE_ACL_SET_FD AND
     308+       HAVE_ACL_SET_FILE AND
     309+       HAVE_ACL_SET_QUALIFIER AND
     310+       HAVE_ACL_SET_TAG_TYPE)
     311+         SET(HAVE_POSIX_ACL_FUNCS 1)
     312+    ENDIF()
     313+
     314+    CHECK_FUNCTION_EXISTS_GLIBC(acl_get_perm HAVE_ACL_GET_PERM)
     315+
     316+    IF(HAVE_POSIX_ACL_FUNCS AND HAVE_ACL_LIBACL_H AND HAVE_LIBACL AND
     317+       HAVE_ACL_GET_PERM)
     318+      SET(ARCHIVE_ACL_LIBACL TRUE)
     319+    ELSE()
     320+      CHECK_FUNCTION_EXISTS(acl_add_flag_np HAVE_ACL_ADD_FLAG_NP)
     321+      CHECK_FUNCTION_EXISTS(acl_clear_flags_np HAVE_ACL_CLEAR_FLAGS_NP)
     322+      CHECK_FUNCTION_EXISTS(acl_get_brand_np HAVE_ACL_GET_BRAND_NP)
     323+      CHECK_FUNCTION_EXISTS(acl_get_entry_type_np HAVE_ACL_GET_ENTRY_TYPE_NP)
     324+      CHECK_FUNCTION_EXISTS(acl_get_flag_np HAVE_ACL_GET_FLAG_NP)
     325+      CHECK_FUNCTION_EXISTS(acl_get_flagset_np HAVE_ACL_GET_FLAGSET_NP)
     326+      CHECK_FUNCTION_EXISTS(acl_get_fd_np HAVE_ACL_GET_FD_NP)
     327+      CHECK_FUNCTION_EXISTS(acl_get_link_np HAVE_ACL_GET_LINK_NP)
     328+      CHECK_FUNCTION_EXISTS(acl_get_perm_np HAVE_ACL_GET_PERM_NP)
     329+      CHECK_FUNCTION_EXISTS(acl_is_trivial_np HAVE_ACL_IS_TRIVIAL_NP)
     330+      CHECK_FUNCTION_EXISTS(acl_set_entry_type_np HAVE_ACL_SET_ENTRY_TYPE_NP)
     331+      CHECK_FUNCTION_EXISTS(acl_set_fd_np HAVE_ACL_SET_FD_NP)
     332+      CHECK_FUNCTION_EXISTS(acl_set_link_np HAVE_ACL_SET_LINK_NP)
     333+      CHECK_FUNCTION_EXISTS(mbr_gid_to_uuid HAVE_MBR_GID_TO_UUID)
     334+      CHECK_FUNCTION_EXISTS(mbr_uid_to_uuid HAVE_MBR_UID_TO_UUID)
     335+      CHECK_FUNCTION_EXISTS(mbr_uuid_to_id HAVE_MBR_UUID_TO_ID)
     336+
     337+      CHECK_C_SOURCE_COMPILES("#include <sys/types.h>
     338+#include <sys/acl.h>
     339+int main(void) { return ACL_TYPE_EXTENDED; }" HAVE_DECL_ACL_TYPE_EXTENDED)
     340+      CHECK_C_SOURCE_COMPILES("#include <sys/types.h>
     341 #include <sys/acl.h>
     342-int main(void) { return ACL_TYPE_EXTENDED; }" HAVE_ACL_TYPE_EXTENDED)
     343+int main(void) { return ACL_SYNCHRONIZE; }" HAVE_DECL_ACL_SYNCHRONIZE)
     344+      CHECK_SYMBOL_EXISTS(ACL_TYPE_NFS4 "sys/acl.h" HAVE_DECL_ACL_TYPE_NFS4)
     345+      CHECK_SYMBOL_EXISTS(ACL_USER "sys/acl.h" HAVE_DECL_ACL_USER)
     346+
     347+      IF(HAVE_POSIX_ACL_FUNCS AND
     348+         HAVE_ACL_GET_FD_NP AND
     349+         HAVE_ACL_GET_PERM_NP AND
     350+         NOT HAVE_ACL_GET_PERM AND
     351+         HAVE_ACL_SET_FD_NP)
     352+        IF(HAVE_DECL_ACL_USER)
     353+          SET(ARCHIVE_ACL_FREEBSD TRUE)
     354+          IF(HAVE_DECL_ACL_TYPE_NFS4 AND
     355+             HAVE_ACL_ADD_FLAG_NP AND
     356+             HAVE_ACL_CLEAR_FLAGS_NP AND
     357+             HAVE_ACL_GET_BRAND_NP AND
     358+             HAVE_ACL_GET_ENTRY_TYPE_NP AND
     359+             HAVE_ACL_GET_FLAGSET_NP AND
     360+             HAVE_ACL_SET_ENTRY_TYPE_NP)
     361+            SET(ARCHIVE_ACL_FREEBSD_NFS4 TRUE)
     362+          ENDIF()
     363+        ELSEIF(HAVE_DECL_ACL_TYPE_EXTENDED AND
     364+               HAVE_MEMBERSHIP_H AND
     365+               HAVE_ACL_ADD_FLAG_NP AND
     366+               HAVE_ACL_CLEAR_FLAGS_NP AND
     367+               HAVE_ACL_GET_FLAGSET_NP AND
     368+               HAVE_ACL_GET_LINK_NP AND
     369+               HAVE_ACL_SET_LINK_NP AND
     370+               HAVE_MBR_UID_TO_UUID AND
     371+               HAVE_MBR_GID_TO_UUID AND
     372+               HAVE_MBR_UUID_TO_ID)
     373+          SET(ARCHIVE_ACL_DARWIN TRUE)
     374+        ENDIF()
     375+      ENDIF()
     376+    ENDIF()
     377+  ENDIF(HAVE_ACL_T AND HAVE_ACL_ENTRY_T AND HAVE_ACL_PERMSET_T AND
     378+        HAVE_ACL_TAG_T)
     379+
     380+  # Richacl
     381+  CHECK_LIBRARY_EXISTS(richacl "richacl_get_file" "" HAVE_LIBRICHACL)
     382+  IF(HAVE_LIBRICHACL)
     383+    SET(CMAKE_REQUIRED_LIBRARIES "richacl")
     384+    FIND_LIBRARY(RICHACL_LIBRARY NAMES richacl)
     385+    LIST(APPEND ADDITIONAL_LIBS ${RICHACL_LIBRARY})
     386+  ENDIF(HAVE_LIBRICHACL)
     387+
     388+  CHECK_STRUCT_HAS_MEMBER("struct richace" e_type "sys/richacl.h"
     389+    HAVE_STRUCT_RICHACE)
     390+  CHECK_STRUCT_HAS_MEMBER("struct richacl" a_flags "sys/richacl.h"
     391+    HAVE_STRUCT_RICHACL)
     392+
     393+  IF(HAVE_LIBRICHACL AND HAVE_STRUCT_RICHACL AND HAVE_STRUCT_RICHACE)
     394+    CHECK_FUNCTION_EXISTS_GLIBC(richacl_alloc HAVE_RICHACL_ALLOC)
     395+    CHECK_FUNCTION_EXISTS_GLIBC(richacl_equiv_mode HAVE_RICHACL_EQUIV_MODE)
     396+    CHECK_FUNCTION_EXISTS_GLIBC(richacl_free HAVE_RICHACL_FREE)
     397+    CHECK_FUNCTION_EXISTS_GLIBC(richacl_get_fd HAVE_RICHACL_GET_FD)
     398+    CHECK_FUNCTION_EXISTS_GLIBC(richacl_get_file HAVE_RICHACL_GET_FILE)
     399+    CHECK_FUNCTION_EXISTS_GLIBC(richacl_set_fd HAVE_RICHACL_SET_FD)
     400+    CHECK_FUNCTION_EXISTS_GLIBC(richacl_set_file HAVE_RICHACL_SET_FILE)
     401+    IF(HAVE_RICHACL_ALLOC AND
     402+       HAVE_RICHACL_EQUIV_MODE AND
     403+       HAVE_RICHACL_FREE AND
     404+       HAVE_RICHACL_GET_FD AND
     405+       HAVE_RICHACL_GET_FILE AND
     406+       HAVE_RICHACL_SET_FD AND
     407+       HAVE_RICHACL_SET_FILE)
     408+      SET(ARCHIVE_ACL_LIBRICHACL TRUE)
     409+    ENDIF()
     410+  ENDIF(HAVE_LIBRICHACL AND HAVE_STRUCT_RICHACL AND HAVE_STRUCT_RICHACE)
     411+
     412+  IF(ARCHIVE_ACL_DARWIN)
     413+    MESSAGE(STATUS "ACL support: Darwin (limited NFSv4)")
     414+  ELSEIF(ARCHIVE_ACL_FREEBSD_NFS4)
     415+    MESSAGE(STATUS "ACL support: FreeBSD (POSIX.1e and NFSv4)")
     416+  ELSEIF(ARCHIVE_ACL_FREEBSD)
     417+    MESSAGE(STATUS "ACL support: FreeBSD (POSIX.1e)")
     418+  ELSEIF(ARCHIVE_ACL_LIBACL OR ARCHIVE_ACL_LIBRICHACL)
     419+    IF(ARCHIVE_ACL_LIBACL AND ARCHIVE_ACL_LIBRICHACL)
     420+      MESSAGE(STATUS "ACL support: libacl (POSIX.1e) + librichacl (NFSv4)")
     421+    ELSEIF(ARCHIVE_ACL_LIBRICHACL)
     422+      MESSAGE(STATUS "ACL support: librichacl (NFSv4)")
     423+    ELSE()
     424+      MESSAGE(STATUS "ACL support: libacl (POSIX.1e)")
     425+    ENDIF()
     426+  ELSEIF(ARCHIVE_ACL_SUNOS_NFS4)
     427+    MESSAGE(STATUS "ACL support: Solaris (POSIX.1e and NFSv4)")
     428+  ELSEIF(ARCHIVE_ACL_SUNOS)
     429+    MESSAGE(STATUS "ACL support: Solaris (POSIX.1e)")
     430+  ELSE()
     431+    MESSAGE(STATUS "ACL support: none")
     432+  ENDIF()
     433 
     434-  # Solaris and derivates ACLs
     435-  CHECK_LIBRARY_EXISTS(sec "acl_get" "" HAVE_LIBSEC)
     436-  IF(HAVE_LIBSEC)
     437-    SET(CMAKE_REQUIRED_LIBRARIES "sec")
     438-    FIND_LIBRARY(SEC_LIBRARY NAMES sec)
     439-    LIST(APPEND ADDITIONAL_LIBS ${SEC_LIBRARY})
     440-  ENDIF(HAVE_LIBSEC)
     441-  #
     442-  CHECK_TYPE_EXISTS(aclent_t "${INCLUDES}" HAVE_ACLENT_T)
     443-  CHECK_TYPE_EXISTS(ace_t "${INCLUDES}" HAVE_ACE_T)
     444-  CHECK_FUNCTION_EXISTS(acl_get HAVE_FACL_GET)
     445-  CHECK_FUNCTION_EXISTS(facl_get HAVE_FACL_GET)
     446-  CHECK_FUNCTION_EXISTS(acl_set HAVE_FACL_SET)
     447-  CHECK_FUNCTION_EXISTS(facl_set HAVE_FACL_SET)
     448 ELSE(ENABLE_ACL)
     449   # If someone runs cmake, then disables ACL support, we need
     450   # to forcibly override the cached values for these.
     451-  SET(HAVE_ACL_CREATE_ENTRY FALSE)
     452-  SET(HAVE_ACL_GET_LINK FALSE)
     453-  SET(HAVE_ACL_GET_LINK_NP FALSE)
     454-  SET(HAVE_ACL_GET_PERM FALSE)
     455-  SET(HAVE_ACL_GET_PERM_NP FALSE)
     456-  SET(HAVE_ACL_INIT FALSE)
     457-  SET(HAVE_ACL_LIB FALSE)
     458-  SET(HAVE_ACL_PERMSET_T FALSE)
     459-  SET(HAVE_ACL_SET_FD FALSE)
     460-  SET(HAVE_ACL_SET_FD_NP FALSE)
     461-  SET(HAVE_ACL_SET_FILE FALSE)
     462-  SET(HAVE_ACL_TYPE_NFS4 FALSE)
     463-  SET(HAVE_ACL_USER FALSE)
     464-  SET(HAVE_ACL_TYPE_EXTENDED FALSE)
     465-  SET(HAVE_ACL_GET FALSE)
     466-  SET(HAVE_ACLENT_T FALSE)
     467-  SET(HAVE_ACE_T FALSE)
     468-  SET(HAVE_FACL_GET FALSE)
     469-  SET(HAVE_ACL_SET FALSE)
     470-  SET(HAVE_FACL_SET FALSE)
     471+  SET(ARCHIVE_ACL_DARWIN FALSE)
     472+  SET(ARCHIVE_ACL_FREEBSD FALSE)
     473+  SET(ARCHIVE_ACL_FREEBSD_NFS4 FALSE)
     474+  SET(ARCHIVE_ACL_LIBACL FALSE)
     475+  SET(ARCHIVE_ACL_SUNOS FALSE)
     476+  SET(ARCHIVE_ACL_SUNOS_NFS4 FALSE)
     477 ENDIF(ENABLE_ACL)
     478 
     479 #
     480diff --git a/Makefile.am b/Makefile.am
     481index f22a9187..1cbdff56 100644
     482--- a/Makefile.am
     483+++ b/Makefile.am
     484@@ -23,7 +23,7 @@ TESTS_ENVIRONMENT= $(libarchive_TESTS_ENVIRONMENT) $(bsdtar_TESTS_ENVIRONMENT) $
     485 DISTCHECK_CONFIGURE_FLAGS = --enable-bsdtar --enable-bsdcpio
     486 # The next line is commented out by default in shipping libarchive releases.
     487 # It is uncommented by default in trunk.
     488-# DEV_CFLAGS=-Werror -Wextra -Wunused -Wshadow -Wmissing-prototypes -Wcast-qual -g
     489+DEV_CFLAGS=-Werror -Wextra -Wunused -Wshadow -Wmissing-prototypes -Wcast-qual -g
     490 AM_CFLAGS=$(DEV_CFLAGS)
     491 PLATFORMCPPFLAGS = @PLATFORMCPPFLAGS@
     492 AM_CPPFLAGS=$(PLATFORMCPPFLAGS)
     493@@ -127,6 +127,7 @@ libarchive_la_SOURCES= \
     494        libarchive/archive_pathmatch.c \
     495        libarchive/archive_pathmatch.h \
     496        libarchive/archive_platform.h \
     497+       libarchive/archive_platform_acl.h \
     498        libarchive/archive_ppmd_private.h \
     499        libarchive/archive_ppmd7.c \
     500        libarchive/archive_ppmd7_private.h \
     501@@ -186,9 +187,9 @@ libarchive_la_SOURCES= \
     502        libarchive/archive_string_composition.h \
     503        libarchive/archive_string_sprintf.c \
     504        libarchive/archive_util.c \
     505+       libarchive/archive_version_details.c \
     506        libarchive/archive_virtual.c \
     507        libarchive/archive_write.c \
     508-       libarchive/archive_write_disk_acl.c \
     509        libarchive/archive_write_disk_posix.c \
     510        libarchive/archive_write_disk_private.h \
     511        libarchive/archive_write_disk_set_standard_lookup.c \
     512@@ -247,6 +248,38 @@ libarchive_la_SOURCES+= \
     513        libarchive/filter_fork_windows.c
     514 endif
     515 
     516+if INC_LINUX_ACL
     517+libarchive_la_SOURCES+= \
     518+       libarchive/archive_acl_maps.h \
     519+       libarchive/archive_acl_maps_linux.c \
     520+       libarchive/archive_read_disk_acl_linux.c \
     521+       libarchive/archive_write_disk_acl_linux.c
     522+else
     523+if INC_SUNOS_ACL
     524+libarchive_la_SOURCES+= \
     525+       libarchive/archive_acl_maps.h \
     526+       libarchive/archive_acl_maps_sunos.c \
     527+       libarchive/archive_read_disk_acl_sunos.c \
     528+       libarchive/archive_write_disk_acl_sunos.c
     529+else
     530+if INC_DARWIN_ACL
     531+libarchive_la_SOURCES+= \
     532+       libarchive/archive_acl_maps.h \
     533+       libarchive/archive_acl_maps_darwin.c \
     534+       libarchive/archive_read_disk_acl_darwin.c \
     535+       libarchive/archive_write_disk_acl_darwin.c
     536+else
     537+if INC_FREEBSD_ACL
     538+libarchive_la_SOURCES+= \
     539+       libarchive/archive_acl_maps.h \
     540+       libarchive/archive_acl_maps_freebsd.c \
     541+       libarchive/archive_read_disk_acl_freebsd.c \
     542+       libarchive/archive_write_disk_acl_freebsd.c
     543+endif
     544+endif
     545+endif
     546+endif
     547+
     548 # -no-undefined marks that libarchive doesn't rely on symbols
     549 # defined in the application.  This is mandatory for cygwin.
     550 libarchive_la_LDFLAGS= -no-undefined -version-info $(ARCHIVE_LIBTOOL_VERSION)
     551@@ -951,10 +984,12 @@ bsdtar_test_SOURCES= \
     552        tar/test/test_option_T_upper.c \
     553        tar/test/test_option_U_upper.c \
     554        tar/test/test_option_X_upper.c \
     555+       tar/test/test_option_acls.c \
     556        tar/test/test_option_a.c \
     557        tar/test/test_option_b.c \
     558        tar/test/test_option_b64encode.c \
     559        tar/test/test_option_exclude.c \
     560+       tar/test/test_option_fflags.c \
     561        tar/test/test_option_gid_gname.c \
     562        tar/test/test_option_grzip.c \
     563        tar/test/test_option_j.c \
     564diff --git a/NEWS b/NEWS
     565index 281c1768..9e517934 100644
     566--- a/NEWS
     567+++ b/NEWS
     568@@ -1,3 +1,5 @@
     569+Mar 16, 2017: NFSv4 ACL support for Linux (librichacl)
     570+
     571 Feb 26, 2017: libarchive 3.3.1 released
     572     Security & Feature release
     573 
     574@@ -293,7 +295,7 @@ May 04, 2008: libarchive 2.5.3b released
     575        * libarchive: Mark which entry strings are set; be accurate about
     576          distinguishing empty strings ("") from unset ones (NULL)
     577        * tar: Don't crash reading entries with empty filenames
     578-       * libarchive_test, bsdtar_test, bsdcpio_test:  Better detaults:
     579+       * libarchive_test, bsdtar_test, bsdcpio_test:  Better defaults:
     580          run all tests, delete temp dirs, summarize repeated failures
     581        * -no-undefined to libtool for Cygwin
     582        * libarchive_test: Skip large file tests on systems with 32-bit off_t
     583diff --git a/build/cmake/config.h.in b/build/cmake/config.h.in
     584index 923a78e5..cfd2a5c0 100644
     585--- a/build/cmake/config.h.in
     586+++ b/build/cmake/config.h.in
     587@@ -179,6 +179,27 @@ typedef uint64_t uintmax_t;
     588 /* Define ZLIB_WINAPI if zlib was built on Visual Studio. */
     589 #cmakedefine ZLIB_WINAPI 1
     590 
     591+/* Darwin ACL support */
     592+#cmakedefine ARCHIVE_ACL_DARWIN 1
     593+
     594+/* FreeBSD ACL support */
     595+#cmakedefine ARCHIVE_ACL_FREEBSD 1
     596+
     597+/* FreeBSD NFSv4 ACL support */
     598+#cmakedefine ARCHIVE_ACL_FREEBSD_NFS4 1
     599+
     600+/* Linux POSIX.1e ACL support via libacl */
     601+#cmakedefine ARCHIVE_ACL_LIBACL 1
     602+
     603+/* Linux NFSv4 ACL support via librichacl */
     604+#cmakedefine ARCHIVE_ACL_LIBRICHACL 1
     605+
     606+/* Solaris ACL support */
     607+#cmakedefine ARCHIVE_ACL_SUNOS 1
     608+
     609+/* Solaris NFSv4 ACL support */
     610+#cmakedefine ARCHIVE_ACL_SUNOS_NFS4 1
     611+
     612 /* MD5 via ARCHIVE_CRYPTO_MD5_LIBC supported. */
     613 #cmakedefine ARCHIVE_CRYPTO_MD5_LIBC 1
     614 
     615@@ -326,15 +347,6 @@ typedef uint64_t uintmax_t;
     616 /* Define to 1 if you have the `acl_set_file' function. */
     617 #cmakedefine HAVE_ACL_SET_FILE 1
     618 
     619-/* True for FreeBSD with NFSv4 ACL support */
     620-#cmakedefine HAVE_ACL_TYPE_NFS4 1
     621-
     622-/* True for MacOS ACL support */
     623-#cmakedefine HAVE_ACL_TYPE_EXTENDED 1
     624-
     625-/* True for systems with POSIX ACL support */
     626-#cmakedefine HAVE_ACL_USER 1
     627-
     628 /* Define to 1 if you have the `arc4random_buf' function. */
     629 #cmakedefine HAVE_ARC4RANDOM_BUF 1
     630 
     631@@ -371,6 +383,34 @@ typedef uint64_t uintmax_t;
     632 /* Define to 1 if you have the `cygwin_conv_path' function. */
     633 #cmakedefine HAVE_CYGWIN_CONV_PATH 1
     634 
     635+/* Define to 1 if you have the declaration of `ACE_GETACL', and to 0 if you
     636+   don't. */
     637+#cmakedefine HAVE_DECL_ACE_GETACL 1
     638+
     639+/* Define to 1 if you have the declaration of `ACE_GETACLCNT', and to 0 if you
     640+   don't. */
     641+#cmakedefine HAVE_DECL_ACE_GETACLCNT 1
     642+
     643+/* Define to 1 if you have the declaration of `ACE_SETACL', and to 0 if you
     644+   don't. */
     645+#cmakedefine HAVE_DECL_ACE_SETACL 1
     646+
     647+/* Define to 1 if you have the declaration of `ACL_SYNCHRONIZE', and to 0 if
     648+   you don't. */
     649+#cmakedefine HAVE_DECL_ACL_SYNCHRONIZE 1
     650+
     651+/* Define to 1 if you have the declaration of `ACL_TYPE_EXTENDED', and to 0 if
     652+   you don't. */
     653+#cmakedefine HAVE_DECL_ACL_TYPE_EXTENDED 1
     654+
     655+/* Define to 1 if you have the declaration of `ACL_TYPE_NFS4', and to 0 if you
     656+   don't. */
     657+#cmakedefine HAVE_DECL_ACL_TYPE_NFS4 1
     658+
     659+/* Define to 1 if you have the declaration of `ACL_USER', and to 0 if you
     660+   don't. */
     661+#cmakedefine HAVE_DECL_ACL_USER 1
     662+
     663 /* Define to 1 if you have the declaration of `INT32_MAX', and to 0 if you
     664    don't. */
     665 #cmakedefine HAVE_DECL_INT32_MAX 1
     666@@ -395,6 +435,10 @@ typedef uint64_t uintmax_t;
     667    don't. */
     668 #cmakedefine HAVE_DECL_INTMAX_MIN 1
     669 
     670+/* Define to 1 if you have the declaration of `SETACL', and to 0 if you don't.
     671+   */
     672+#cmakedefine HAVE_DECL_SETACL 1
     673+
     674 /* Define to 1 if you have the declaration of `SIZE_MAX', and to 0 if you
     675    don't. */
     676 #cmakedefine HAVE_DECL_SIZE_MAX 1
     677@@ -468,6 +512,14 @@ typedef uint64_t uintmax_t;
     678 /* Define to 1 if EXTATTR_NAMESPACE_USER is defined in sys/extattr.h. */
     679 #cmakedefine HAVE_DECL_EXTATTR_NAMESPACE_USER 1
     680 
     681+/* Define to 1 if you have the declaration of `GETACL', and to 0 if you don't.
     682+   */
     683+#cmakedefine HAVE_DECL_GETACL 1
     684+
     685+/* Define to 1 if you have the declaration of `GETACLCNT', and to 0 if you
     686+   don't. */
     687+#cmakedefine HAVE_DECL_GETACLCNT 1
     688+
     689 /* Define to 1 if you have the `fchdir' function. */
     690 #cmakedefine HAVE_FCHDIR 1
     691 
     692@@ -742,6 +794,9 @@ typedef uint64_t uintmax_t;
     693 /* Define to 1 if you have the `mbrtowc' function. */
     694 #cmakedefine HAVE_MBRTOWC 1
     695 
     696+/* Define to 1 if you have the <membership.h> header file. */
     697+#cmakedefine HAVE_MEMBERSHIP_H 1
     698+
     699 /* Define to 1 if you have the `memmove' function. */
     700 #cmakedefine HAVE_MEMMOVE 1
     701 
     702@@ -979,6 +1034,9 @@ typedef uint64_t uintmax_t;
     703 /* Define to 1 if you have the <sys/poll.h> header file. */
     704 #cmakedefine HAVE_SYS_POLL_H 1
     705 
     706+/* Define to 1 if you have the <sys/richacl.h> header file. */
     707+#cmakedefine HAVE_SYS_RICHACL_H 1
     708+
     709 /* Define to 1 if you have the <sys/select.h> header file. */
     710 #cmakedefine HAVE_SYS_SELECT_H 1
     711 
     712diff --git a/build/version b/build/version
     713index ef834572..6d36e9c1 100644
     714--- a/build/version
     715+++ b/build/version
     716@@ -1 +1 @@
     717-3003001
     718+3003002dev
     719diff --git a/cat/test/CMakeLists.txt b/cat/test/CMakeLists.txt
     720index 7f1ce5e7..0cd3aad8 100644
     721--- a/cat/test/CMakeLists.txt
     722+++ b/cat/test/CMakeLists.txt
     723@@ -29,6 +29,16 @@ IF(ENABLE_CAT AND ENABLE_TEST)
     724   # Register target
     725   #
     726   ADD_EXECUTABLE(bsdcat_test ${bsdcat_test_SOURCES})
     727+  IF(ENABLE_ACL)
     728+    SET(TEST_ACL_LIBS "")
     729+    IF(HAVE_LIBACL)
     730+      LIST(APPEND TEST_ACL_LIBS ${ACL_LIBRARY})
     731+    ENDIF(HAVE_LIBACL)
     732+    IF(HAVE_LIBRICHACL)
     733+      LIST(APPEND TEST_ACL_LIBS ${RICHACL_LIBRARY})
     734+    ENDIF(HAVE_LIBRICHACL)
     735+    TARGET_LINK_LIBRARIES(bsdcat_test ${TEST_ACL_LIBS})
     736+  ENDIF(ENABLE_ACL)
     737   SET_PROPERTY(TARGET bsdcat_test PROPERTY COMPILE_DEFINITIONS LIST_H)
     738 
     739   #
     740diff --git a/configure.ac b/configure.ac
     741index 3a8ac6a8..05b5a099 100644
     742--- a/configure.ac
     743+++ b/configure.ac
     744@@ -4,8 +4,8 @@ dnl First, define all of the version numbers up front.
     745 dnl In particular, this allows the version macro to be used in AC_INIT
     746 
     747 dnl These first two version numbers are updated automatically on each release.
     748-m4_define([LIBARCHIVE_VERSION_S],[3.3.1])
     749-m4_define([LIBARCHIVE_VERSION_N],[3003001])
     750+m4_define([LIBARCHIVE_VERSION_S],[3.3.2dev])
     751+m4_define([LIBARCHIVE_VERSION_N],[3003002])
     752 
     753 dnl bsdtar and bsdcpio versioning tracks libarchive
     754 m4_define([BSDTAR_VERSION_S],LIBARCHIVE_VERSION_S())
     755@@ -253,6 +253,7 @@ esac
     756 # Checks for header files.
     757 AC_HEADER_DIRENT
     758 AC_HEADER_SYS_WAIT
     759+AC_CHECK_HEADERS([acl/libacl.h])
     760 AC_CHECK_HEADERS([copyfile.h ctype.h])
     761 AC_CHECK_HEADERS([errno.h ext2fs/ext2_fs.h fcntl.h grp.h])
     762 
     763@@ -283,16 +284,16 @@ AS_VAR_IF([ac_cv_have_decl_FS_IOC_GETFLAGS], [yes],
     764     [AC_DEFINE_UNQUOTED([HAVE_WORKING_FS_IOC_GETFLAGS], [1],
     765                     [Define to 1 if you have a working FS_IOC_GETFLAGS])])
     766 
     767-AC_CHECK_HEADERS([locale.h paths.h poll.h pthread.h pwd.h])
     768+AC_CHECK_HEADERS([locale.h membership.h paths.h poll.h pthread.h pwd.h])
     769 AC_CHECK_HEADERS([readpassphrase.h signal.h spawn.h])
     770 AC_CHECK_HEADERS([stdarg.h stdint.h stdlib.h string.h])
     771-AC_CHECK_HEADERS([sys/cdefs.h sys/extattr.h])
     772+AC_CHECK_HEADERS([sys/acl.h sys/cdefs.h sys/extattr.h])
     773 AC_CHECK_HEADERS([sys/ioctl.h sys/mkdev.h sys/mount.h])
     774-AC_CHECK_HEADERS([sys/param.h sys/poll.h sys/select.h sys/statfs.h sys/statvfs.h])
     775+AC_CHECK_HEADERS([sys/param.h sys/poll.h sys/richacl.h])
     776+AC_CHECK_HEADERS([sys/select.h sys/statfs.h sys/statvfs.h])
     777 AC_CHECK_HEADERS([sys/time.h sys/utime.h sys/utsname.h sys/vfs.h])
     778 AC_CHECK_HEADERS([time.h unistd.h utime.h wchar.h wctype.h])
     779 AC_CHECK_HEADERS([windows.h])
     780-AC_CHECK_HEADERS([Bcrypt.h])
     781 # check windows.h first; the other headers require it.
     782 AC_CHECK_HEADERS([wincrypt.h winioctl.h],[],[],
     783 [[#ifdef HAVE_WINDOWS_H
     784@@ -399,6 +400,9 @@ if test "x$with_lzo2" = "xyes"; then
     785   AC_CHECK_LIB(lzo2,lzo1x_decompress_safe)
     786 fi
     787 
     788+AC_ARG_WITH([cng],
     789+  AS_HELP_STRING([--without-cng], [Don't build support of CNG(Crypto Next Generation)]))
     790+
     791 AC_ARG_WITH([nettle],
     792   AS_HELP_STRING([--without-nettle], [Don't build with crypto support from Nettle]))
     793 AC_ARG_WITH([openssl],
     794@@ -697,72 +701,211 @@ AC_ARG_ENABLE([acl],
     795                [Disable ACL support (default: check)]))
     796 
     797 if test "x$enable_acl" != "xno"; then
     798-   AC_CHECK_HEADERS([acl/libacl.h])
     799-   AC_CHECK_HEADERS([sys/acl.h])
     800-   AC_CHECK_LIB([acl],[acl_get_file])
     801-   AC_CHECK_FUNCS([acl_create_entry acl_get_fd_np])
     802-   AC_CHECK_FUNCS([acl_init acl_set_fd acl_set_fd_np acl_set_file])
     803+    # Libacl
     804+    AC_CHECK_LIB([acl], [acl_get_file])
     805+
     806+    AC_CHECK_TYPES([acl_t, acl_entry_t, acl_permset_t, acl_tag_t], [], [], [
     807+      #if HAVE_SYS_TYPES_H
     808+      #include <sys/types.h>
     809+      #endif
     810+      #if HAVE_SYS_ACL_H
     811+      #include <sys/acl.h>
     812+      #endif
     813+    ])
     814+
     815+    AC_CHECK_LIB([richacl], [richacl_get_file])
     816+
     817+    AC_CHECK_TYPES([[struct richace], [struct richacl]], [], [], [
     818+      #if HAVE_SYS_RICHACL_H
     819+      #include <sys/richacl.h>
     820+      #endif
     821+    ])
     822 
     823-   AC_CHECK_TYPES(acl_permset_t,,,
     824-       [#if HAVE_SYS_TYPES_H
     825-       #include <sys/types.h>
     826-       #endif
     827-       #if HAVE_SYS_ACL_H
     828-       #include <sys/acl.h>
     829-       #endif
     830-       ])
     831-
     832-    # The "acl_get_perm()" function was omitted from the POSIX draft.
     833-    # (It's a pretty obvious oversight; otherwise, there's no way to
     834-    # test for specific permissions in a permset.)  Linux uses the obvious
     835-    # name, FreeBSD adds _np to mark it as "non-Posix extension."
     836-    # Test for both as a double-check that we really have POSIX-style ACL
     837-    # support.
     838-    AC_CHECK_FUNCS(acl_get_perm_np acl_get_perm acl_get_link acl_get_link_np,,,
     839-       [#if HAVE_SYS_TYPES_H
     840-       #include <sys/types.h>
     841-       #endif
     842-       #if HAVE_SYS_ACL_H
     843-       #include <sys/acl.h>
     844-       #endif
     845-       ])
     846+    # Solaris and derivates ACLs
     847+    AC_CHECK_FUNCS(acl facl)
     848+
     849+    if test "x$ac_cv_lib_richacl_richacl_get_file" = "xyes" \
     850+        -a "x$ac_cv_type_struct_richace" = "xyes" \
     851+        -a "x$ac_cv_type_struct_richacl" = "xyes"; then
     852+       AC_CACHE_VAL([ac_cv_archive_acl_librichacl],
     853+         [AC_CHECK_FUNCS(richacl_alloc \
     854+                         richacl_equiv_mode \
     855+                         richacl_free \
     856+                         richacl_get_fd \
     857+                         richacl_get_file \
     858+                         richacl_set_fd \
     859+                         richacl_set_file,
     860+         [ac_cv_archive_acl_librichacl=yes], [ac_cv_archive_acl_librichacl=no],          [#include <sys/richacl.h>])])
     861+    fi
     862 
     863-    # Check for acl_is_trivial_np on FreeBSD
     864-    AC_CHECK_FUNCS(acl_is_trivial_np,,,
     865-       [#if HAVE_SYS_TYPES_H
     866-       #include <sys/types.h>
     867-       #endif
     868-       #if HAVE_SYS_ACL_H
     869-       #include <sys/acl.h>
     870-       #endif
     871+    if test "x$ac_cv_func_acl" = "xyes" \
     872+        -a "x$ac_cv_func_facl" = "xyes"; then
     873+       AC_CHECK_TYPES([aclent_t], [], [], [[#include <sys/acl.h>]])
     874+       if test "x$ac_cv_type_aclent_t" = "xyes"; then
     875+           AC_CACHE_VAL([ac_cv_archive_acl_sunos],
     876+             [AC_CHECK_DECLS([GETACL, SETACL, GETACLCNT],
     877+             [ac_cv_archive_acl_sunos=yes], [ac_cv_archive_acl_sunos=no],
     878+             [#include <sys/acl.h>])])
     879+           AC_CHECK_TYPES([ace_t], [], [], [[#include <sys/acl.h>]])
     880+           if test "x$ac_cv_type_ace_t" = "xyes"; then
     881+               AC_CACHE_VAL([ac_cv_archive_acl_sunos_nfs4],
     882+                 [AC_CHECK_DECLS([ACE_GETACL, ACE_SETACL, ACE_GETACLCNT],
     883+                 [ac_cv_archive_acl_sunos_nfs4=yes],
     884+                 [ac_cv_archive_acl_sonos_nfs4=no],
     885+                 [#include <sys/acl.h>])])
     886+           fi
     887+       fi
     888+    elif test "x$ac_cv_type_acl_t" = "xyes" \
     889+        -a "x$ac_cv_type_acl_entry_t" = "xyes" \
     890+        -a "x$ac_cv_type_acl_permset_t" = "xyes" \
     891+        -a "x$ac_cv_type_acl_tag_t" = "xyes"; then
     892+       # POSIX.1e ACL functions
     893+       AC_CACHE_VAL([ac_cv_posix_acl_funcs],
     894+         [AC_CHECK_FUNCS(acl_add_perm \
     895+                         acl_clear_perms \
     896+                         acl_create_entry \
     897+                         acl_delete_def_file \
     898+                         acl_free \
     899+                         acl_get_entry \
     900+                         acl_get_fd \
     901+                         acl_get_file \
     902+                         acl_get_permset \
     903+                         acl_get_qualifier \
     904+                         acl_get_tag_type \
     905+                         acl_init \
     906+                         acl_set_fd \
     907+                         acl_set_file \
     908+                         acl_set_qualifier \
     909+                         acl_set_tag_type,
     910+         [ac_cv_posix_acl_funcs=yes], [ac_cv_posix_acl_funcs=no],
     911+         [#if HAVE_SYS_TYPES_H
     912+          #include <sys/types.h>
     913+          #endif
     914+          #if HAVE_SYS_ACL_H
     915+          #include <sys/acl.h>
     916+          #endif
     917+         ])
     918        ])
     919 
     920-    # Check for ACL_TYPE_NFS4
     921-    AC_CHECK_DECL([ACL_TYPE_NFS4],
     922-               [AC_DEFINE(HAVE_ACL_TYPE_NFS4, 1, [True for FreeBSD with NFSv4 ACL support])],
     923-               [],
     924-               [#include <sys/acl.h>])
     925+       AC_CHECK_FUNCS(acl_get_perm)
     926 
     927-    # MacOS has an acl.h that isn't POSIX.  It can be detected by
     928-    # checking for ACL_USER
     929-    AC_CHECK_DECL([ACL_USER],
     930-               [AC_DEFINE(HAVE_ACL_USER, 1, [True for systems with POSIX ACL support])],
     931-               [],
     932-               [#include <sys/acl.h>])
     933+       if test "x$ac_cv_posix_acl_funcs" = "xyes" \
     934+            -a "x$ac_cv_header_acl_libacl_h" = "xyes" \
     935+            -a "x$ac_cv_lib_acl_acl_get_file" = "xyes" \
     936+            -a "x$ac_cv_func_acl_get_perm"; then
     937+           AC_CACHE_VAL([ac_cv_archive_acl_libacl],
     938+             [ac_cv_archive_acl_libacl=yes])
     939+           AC_DEFINE([ARCHIVE_ACL_LIBACL], [1],
     940+             [POSIX.1e ACL support via libacl])
     941+       else
     942+            # FreeBSD/Darwin
     943+            AC_CHECK_FUNCS(acl_add_flag_np \
     944+                           acl_clear_flags_np \
     945+                           acl_get_brand_np \
     946+                           acl_get_entry_type_np \
     947+                           acl_get_flag_np \
     948+                           acl_get_flagset_np \
     949+                           acl_get_fd_np \
     950+                           acl_get_link_np \
     951+                           acl_get_perm_np \
     952+                           acl_is_trivial_np \
     953+                           acl_set_entry_type_np \
     954+                           acl_set_fd_np \
     955+                           acl_set_link_np,,,
     956+             [#include <sys/types.h>
     957+              #include <sys/acl.h>])
     958+
     959+           AC_CHECK_FUNCS(mbr_uid_to_uuid \
     960+                          mbr_uuid_to_id \
     961+                          mbr_gid_to_uuid,,,
     962+             [#include <membership.h>])
     963+
     964+           AC_CHECK_DECLS([ACL_TYPE_EXTENDED, ACL_TYPE_NFS4, ACL_USER,
     965+             ACL_SYNCHRONIZE], [], [],
     966+             [#include <sys/types.h>
     967+              #include <sys/acl.h>])
     968+           if test "x$ac_cv_posix_acl_funcs" = "xyes" \
     969+                -a "x$ac_cv_func_acl_get_fd_np" = "xyes" \
     970+                 -a "x$ac_cv_func_acl_get_perm" != "xyes" \
     971+                -a "x$ac_cv_func_acl_get_perm_np" = "xyes" \
     972+                -a "x$ac_cv_func_acl_set_fd_np" = "xyes"; then
     973+               if test "x$ac_cv_have_decl_ACL_USER" = "xyes"; then
     974+                   AC_CACHE_VAL([ac_cv_archive_acl_freebsd],
     975+                     [ac_cv_archive_acl_freebsd=yes])
     976+                   if test "x$ac_cv_have_decl_ACL_TYPE_NFS4" = "xyes" \
     977+                        -a "x$ac_cv_func_acl_add_flag_np" = "xyes" \
     978+                        -a "x$ac_cv_func_acl_get_brand_np" = "xyes" \
     979+                        -a "x$ac_cv_func_acl_get_entry_type_np" = "xyes" \
     980+                        -a "x$ac_cv_func_acl_get_flagset_np" = "xyes" \
     981+                        -a "x$ac_cv_func_acl_set_entry_type_np" = "xyes"; then
     982+                       AC_CACHE_VAL([ac_cv_archive_acl_freebsd_nfs4],
     983+                         [ac_cv_archive_acl_freebsd_nfs4=yes])
     984+                   fi
     985+               elif test "x$ac_cv_have_decl_ACL_TYPE_EXTENDED" = "xyes" \
     986+                      -a "x$ac_cv_func_acl_add_flag_np" = "xyes" \
     987+                      -a "x$ac_cv_func_acl_get_flagset_np" = "xyes" \
     988+                      -a "x$ac_cv_func_acl_get_link_np" = "xyes" \
     989+                      -a "x$ac_cv_func_acl_set_link_np" = "xyes" \
     990+                      -a "x$ac_cv_func_mbr_uid_to_uuid" = "xyes" \
     991+                      -a "x$ac_cv_func_mbr_uuid_to_id" = "xyes" \
     992+                      -a "x$ac_cv_func_mbr_gid_to_uuid" = "xyes"; then
     993+                   AC_CACHE_VAL([ac_cv_archive_acl_darwin],
     994+                     [ac_cv_archive_acl_darwin=yes])
     995+               fi
     996+           fi
     997+       fi
     998+    fi
     999+    AC_MSG_CHECKING([for ACL support])
     1000+    if test "x$ac_cv_archive_acl_libacl" = "xyes" \
     1001+        -a "x$ac_cv_archive_acl_librichacl" = "xyes"; then
     1002+       AC_MSG_RESULT([libacl (POSIX.1e) + librichacl (NFSv4)])
     1003+       AC_DEFINE([ARCHIVE_ACL_LIBACL], [1],
     1004+         [Linux POSIX.1e ACL support via libacl])
     1005+       AC_DEFINE([ARCHIVE_ACL_LIBRICHACL], [1],
     1006+         [Linux NFSv4 ACL support via librichacl])
     1007+    elif test "x$ac_cv_archive_acl_libacl" = "xyes"; then
     1008+       AC_MSG_RESULT([libacl (POSIX.1e)])
     1009+       AC_DEFINE([ARCHIVE_ACL_LIBACL], [1],
     1010+         [Linux POSIX.1e ACL support via libacl])
     1011+    elif test "x$ac_cv_archive_acl_librichacl" = "xyes"; then
     1012+       AC_MSG_RESULT([librichacl (NFSv4)])
     1013+       AC_DEFINE([ARCHIVE_ACL_LIBRICHACL], [1],
     1014+         [Linux NFSv4 ACL support via librichacl])
     1015+    elif test "x$ac_cv_archive_acl_darwin" = "xyes"; then
     1016+       AC_DEFINE([ARCHIVE_ACL_DARWIN], [1], [Darwin ACL support])
     1017+       AC_MSG_RESULT([Darwin (limited NFSv4)])
     1018+    elif test "x$ac_cv_archive_acl_sunos" = "xyes"; then
     1019+       AC_DEFINE([ARCHIVE_ACL_SUNOS], [1], [Solaris ACL support])
     1020+       if test "x$ac_cv_archive_acl_sunos_nfs4" = "xyes"; then
     1021+           AC_DEFINE([ARCHIVE_ACL_SUNOS_NFS4], [1],
     1022+             [Solaris NFSv4 ACL support])
     1023+           AC_MSG_RESULT([Solaris (POSIX.1e and NFSv4)])
     1024+       else
     1025+           AC_MSG_RESULT([Solaris (POSIX.1e)])
     1026+       fi
     1027+    elif test "x$ac_cv_archive_acl_freebsd" = "xyes"; then
     1028+       AC_DEFINE([ARCHIVE_ACL_FREEBSD], [1], [FreeBSD ACL support])
     1029+       if test "x$ac_cv_archive_acl_freebsd_nfs4" = "xyes"; then
     1030+           AC_DEFINE([ARCHIVE_ACL_FREEBSD_NFS4], [1],
     1031+             [FreeBSD NFSv4 ACL support])
     1032+           AC_MSG_RESULT([FreeBSD (POSIX.1e and NFSv4)])
     1033+       else
     1034+           AC_MSG_RESULT([FreeBSD (POSIX.1e)])
     1035+       fi
     1036+    else
     1037+       AC_MSG_RESULT([none])
     1038+    fi
     1039+fi
     1040 
     1041-    # MacOS has ACL_TYPE_EXTENDED instead
     1042-    AC_CHECK_DECL([ACL_TYPE_EXTENDED],
     1043-               [AC_DEFINE(HAVE_ACL_TYPE_EXTENDED, 1, [True for MacOS ACL support])],
     1044-               [],
     1045-               [#include <sys/types.h>
     1046-               #include <sys/acl.h>])
     1047 
     1048-    # Solaris and derivates ACLs
     1049-    AC_CHECK_LIB([sec], [acl_get])
     1050-    AC_CHECK_TYPES([aclent_t], [], [], [[#include <sys/acl.h>]])
     1051-    AC_CHECK_TYPES([ace_t], [], [], [[#include <sys/acl.h>]])
     1052-    AC_CHECK_FUNCS(acl_get facl_get acl_set facl_set)
     1053-fi
     1054+AM_CONDITIONAL([INC_LINUX_ACL],
     1055+  [test "x$ac_cv_archive_acl_libacl" = "xyes" \
     1056+     -o "x$ac_cv_archive_acl_librichacl" = "xyes"])
     1057+AM_CONDITIONAL([INC_SUNOS_ACL], [test "x$ac_cv_archive_acl_sunos" = "xyes"])
     1058+AM_CONDITIONAL([INC_DARWIN_ACL],
     1059+         [test "x$ac_cv_archive_acl_darwin" = "xyes"])
     1060+AM_CONDITIONAL([INC_FREEBSD_ACL],
     1061+         [test "x$ac_cv_archive_acl_freebsd" = "xyes"])
     1062 
     1063 # Additional requirements
     1064 AC_SYS_LARGEFILE
     1065@@ -852,6 +995,16 @@ case "$host_os" in
     1066        ;;
     1067 esac
     1068 
     1069+if test "x$with_cng" != "xno"; then
     1070+    AC_CHECK_HEADERS([bcrypt.h],[
     1071+        LIBS="$LIBS -lbcrypt"
     1072+    ],[],
     1073+    [[#ifdef HAVE_WINDOWS_H
     1074+    # include <windows.h>
     1075+    #endif
     1076+    ]])
     1077+fi
     1078+
     1079 if test "x$with_nettle" != "xno"; then
     1080     AC_CHECK_HEADERS([nettle/md5.h nettle/ripemd160.h nettle/sha.h])
     1081     AC_CHECK_HEADERS([nettle/pbkdf2.h nettle/aes.h nettle/hmac.h])
     1082diff --git a/cpio/cpio.c b/cpio/cpio.c
     1083index 6c20ee68..1691c756 100644
     1084--- a/cpio/cpio.c
     1085+++ b/cpio/cpio.c
     1086@@ -108,22 +108,22 @@ static int        entry_to_archive(struct cpio *, struct archive_entry *);
     1087 static int     file_to_archive(struct cpio *, const char *);
     1088 static void    free_cache(struct name_cache *cache);
     1089 static void    list_item_verbose(struct cpio *, struct archive_entry *);
     1090-static void    long_help(void);
     1091+static void    long_help(void) __LA_DEAD;
     1092 static const char *lookup_gname(struct cpio *, gid_t gid);
     1093 static int     lookup_gname_helper(struct cpio *,
     1094                    const char **name, id_t gid);
     1095 static const char *lookup_uname(struct cpio *, uid_t uid);
     1096 static int     lookup_uname_helper(struct cpio *,
     1097                    const char **name, id_t uid);
     1098-static void    mode_in(struct cpio *);
     1099-static void    mode_list(struct cpio *);
     1100+static void    mode_in(struct cpio *) __LA_DEAD;
     1101+static void    mode_list(struct cpio *) __LA_DEAD;
     1102 static void    mode_out(struct cpio *);
     1103 static void    mode_pass(struct cpio *, const char *);
     1104 static const char *remove_leading_slash(const char *);
     1105 static int     restore_time(struct cpio *, struct archive_entry *,
     1106                    const char *, int fd);
     1107-static void    usage(void);
     1108-static void    version(void);
     1109+static void    usage(void) __LA_DEAD;
     1110+static void    version(void) __LA_DEAD;
     1111 static const char * passphrase_callback(struct archive *, void *);
     1112 static void    passphrase_free(char *);
     1113 
     1114@@ -1344,23 +1344,23 @@ lookup_name(struct cpio *cpio, struct name_cache **name_cache_variable,
     1115                cache->cache[slot].name = NULL;
     1116        }
     1117 
     1118-       if (lookup_fn(cpio, &name, id) == 0) {
     1119-               if (name == NULL || name[0] == '\0') {
     1120-                       /* If lookup failed, format it as a number. */
     1121-                       snprintf(asnum, sizeof(asnum), "%u", (unsigned)id);
     1122-                       name = asnum;
     1123-               }
     1124-               cache->cache[slot].name = strdup(name);
     1125-               if (cache->cache[slot].name != NULL) {
     1126-                       cache->cache[slot].id = id;
     1127-                       return (cache->cache[slot].name);
     1128-               }
     1129-               /*
     1130-                * Conveniently, NULL marks an empty slot, so
     1131-                * if the strdup() fails, we've just failed to
     1132-                * cache it.  No recovery necessary.
     1133-                */
     1134+       if (lookup_fn(cpio, &name, id)) {
     1135+               /* If lookup failed, format it as a number. */
     1136+               snprintf(asnum, sizeof(asnum), "%u", (unsigned)id);
     1137+               name = asnum;
     1138+       }
     1139+
     1140+       cache->cache[slot].name = strdup(name);
     1141+       if (cache->cache[slot].name != NULL) {
     1142+               cache->cache[slot].id = id;
     1143+               return (cache->cache[slot].name);
     1144        }
     1145+
     1146+       /*
     1147+        * Conveniently, NULL marks an empty slot, so
     1148+        * if the strdup() fails, we've just failed to
     1149+        * cache it.  No recovery necessary.
     1150+        */
     1151        return (NULL);
     1152 }
     1153 
     1154@@ -1381,15 +1381,14 @@ lookup_uname_helper(struct cpio *cpio, const char **name, id_t id)
     1155        errno = 0;
     1156        pwent = getpwuid((uid_t)id);
     1157        if (pwent == NULL) {
     1158-               *name = NULL;
     1159-               if (errno != 0 && errno != ENOENT)
     1160+               if (errno && errno != ENOENT)
     1161                        lafe_warnc(errno, "getpwuid(%s) failed",
     1162                            cpio_i64toa((int64_t)id));
     1163-               return (errno);
     1164+               return 1;
     1165        }
     1166 
     1167        *name = pwent->pw_name;
     1168-       return (0);
     1169+       return 0;
     1170 }
     1171 
     1172 static const char *
     1173@@ -1409,15 +1408,14 @@ lookup_gname_helper(struct cpio *cpio, const char **name, id_t id)
     1174        errno = 0;
     1175        grent = getgrgid((gid_t)id);
     1176        if (grent == NULL) {
     1177-               *name = NULL;
     1178-               if (errno != 0)
     1179+               if (errno && errno != ENOENT)
     1180                        lafe_warnc(errno, "getgrgid(%s) failed",
     1181                            cpio_i64toa((int64_t)id));
     1182-               return (errno);
     1183+               return 1;
     1184        }
     1185 
     1186        *name = grent->gr_name;
     1187-       return (0);
     1188+       return 0;
     1189 }
     1190 
     1191 /*
     1192diff --git a/cpio/test/CMakeLists.txt b/cpio/test/CMakeLists.txt
     1193index ec9509be..4c3fb88a 100644
     1194--- a/cpio/test/CMakeLists.txt
     1195+++ b/cpio/test/CMakeLists.txt
     1196@@ -62,6 +62,16 @@ IF(ENABLE_CPIO AND ENABLE_TEST)
     1197   # Register target
     1198   #
     1199   ADD_EXECUTABLE(bsdcpio_test ${bsdcpio_test_SOURCES})
     1200+  IF(ENABLE_ACL)
     1201+    SET(TEST_ACL_LIBS "")
     1202+    IF(HAVE_LIBACL)
     1203+      LIST(APPEND TEST_ACL_LIBS ${ACL_LIBRARY})
     1204+    ENDIF(HAVE_LIBACL)
     1205+    IF(HAVE_LIBRICHACL)
     1206+      LIST(APPEND TEST_ACL_LIBS ${RICHACL_LIBRARY})
     1207+    ENDIF(HAVE_LIBRICHACL)
     1208+    TARGET_LINK_LIBRARIES(bsdcpio_test ${TEST_ACL_LIBS})
     1209+  ENDIF(ENABLE_ACL)
     1210   SET_PROPERTY(TARGET bsdcpio_test PROPERTY COMPILE_DEFINITIONS LIST_H)
     1211 
     1212   #
     1213diff --git a/libarchive/CMakeLists.txt b/libarchive/CMakeLists.txt
     1214index 1f85c014..0ed3fa48 100644
     1215--- a/libarchive/CMakeLists.txt
     1216+++ b/libarchive/CMakeLists.txt
     1217@@ -14,6 +14,7 @@ SET(include_HEADERS
     1218 # Sources and private headers
     1219 SET(libarchive_SOURCES
     1220   archive_acl.c
     1221+  archive_acl_private.h
     1222   archive_check_magic.c
     1223   archive_cmdline.c
     1224   archive_cmdline_private.h
     1225@@ -47,6 +48,7 @@ SET(libarchive_SOURCES
     1226   archive_pathmatch.c
     1227   archive_pathmatch.h
     1228   archive_platform.h
     1229+  archive_platform_acl.h
     1230   archive_ppmd_private.h
     1231   archive_ppmd7.c
     1232   archive_ppmd7_private.h
     1233@@ -106,9 +108,9 @@ SET(libarchive_SOURCES
     1234   archive_string_composition.h
     1235   archive_string_sprintf.c
     1236   archive_util.c
     1237+  archive_version_details.c
     1238   archive_virtual.c
     1239   archive_write.c
     1240-  archive_write_disk_acl.c
     1241   archive_write_disk_posix.c
     1242   archive_write_disk_private.h
     1243   archive_write_disk_set_standard_lookup.c
     1244@@ -210,6 +212,28 @@ IF(WIN32 AND NOT CYGWIN)
     1245   LIST(APPEND libarchive_SOURCES filter_fork_windows.c)
     1246 ENDIF(WIN32 AND NOT CYGWIN)
     1247 
     1248+IF(ARCHIVE_ACL_DARWIN)
     1249+  LIST(APPEND libarchive_SOURCES archive_acl_maps.h)
     1250+  LIST(APPEND libarchive_SOURCES archive_acl_maps_darwin.c)
     1251+  LIST(APPEND libarchive_SOURCES archive_read_disk_acl_darwin.c)
     1252+  LIST(APPEND libarchive_SOURCES archive_write_disk_acl_darwin.c)
     1253+ELSEIF(ARCHIVE_ACL_FREEBSD)
     1254+  LIST(APPEND libarchive_SOURCES archive_acl_maps.h)
     1255+  LIST(APPEND libarchive_SOURCES archive_acl_maps_freebsd.c)
     1256+  LIST(APPEND libarchive_SOURCES archive_read_disk_acl_freebsd.c)
     1257+  LIST(APPEND libarchive_SOURCES archive_write_disk_acl_freebsd.c)
     1258+ELSEIF(ARCHIVE_ACL_LIBACL)
     1259+  LIST(APPEND libarchive_SOURCES archive_acl_maps.h)
     1260+  LIST(APPEND libarchive_SOURCES archive_acl_maps_linux.c)
     1261+  LIST(APPEND libarchive_SOURCES archive_read_disk_acl_linux.c)
     1262+  LIST(APPEND libarchive_SOURCES archive_write_disk_acl_linux.c)
     1263+ELSEIF(ARCHIVE_ACL_SUNOS)
     1264+  LIST(APPEND libarchive_SOURCES archive_acl_maps.h)
     1265+  LIST(APPEND libarchive_SOURCES archive_acl_maps_sunos.c)
     1266+  LIST(APPEND libarchive_SOURCES archive_read_disk_acl_sunos.c)
     1267+  LIST(APPEND libarchive_SOURCES archive_write_disk_acl_sunos.c)
     1268+ENDIF()
     1269+
     1270 # Libarchive is a shared library
     1271 ADD_LIBRARY(archive SHARED ${libarchive_SOURCES} ${include_HEADERS})
     1272 TARGET_LINK_LIBRARIES(archive ${ADDITIONAL_LIBS})
     1273diff --git a/libarchive/archive.h b/libarchive/archive.h
     1274index d400735a..d6913f35 100644
     1275--- a/libarchive/archive.h
     1276+++ b/libarchive/archive.h
     1277@@ -36,7 +36,7 @@
     1278  * assert that ARCHIVE_VERSION_NUMBER >= 2012108.
     1279  */
     1280 /* Note: Compiler will complain if this does not match archive_entry.h! */
     1281-#define        ARCHIVE_VERSION_NUMBER 3003001
     1282+#define        ARCHIVE_VERSION_NUMBER 3003002
     1283 
     1284 #include <sys/stat.h>
     1285 #include <stddef.h>  /* for wchar_t */
     1286@@ -155,7 +155,7 @@ __LA_DECL int               archive_version_number(void);
     1287 /*
     1288  * Textual name/version of the library, useful for version displays.
     1289  */
     1290-#define        ARCHIVE_VERSION_ONLY_STRING "3.3.1"
     1291+#define        ARCHIVE_VERSION_ONLY_STRING "3.3.2dev"
     1292 #define        ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
     1293 __LA_DECL const char * archive_version_string(void);
     1294 
     1295diff --git a/libarchive/archive_acl_maps.h b/libarchive/archive_acl_maps.h
     1296new file mode 100644
     1297index 00000000..c9dba525
     1298--- /dev/null
     1299+++ b/libarchive/archive_acl_maps.h
     1300@@ -0,0 +1,52 @@
     1301+/*-
     1302+ * Copyright (c) 2017 Martin Matuska
     1303+ * All rights reserved.
     1304+ *
     1305+ * Redistribution and use in source and binary forms, with or without
     1306+ * modification, are permitted provided that the following conditions
     1307+ * are met:
     1308+ * 1. Redistributions of source code must retain the above copyright
     1309+ *    notice, this list of conditions and the following disclaimer.
     1310+ * 2. Redistributions in binary form must reproduce the above copyright
     1311+ *    notice, this list of conditions and the following disclaimer in the
     1312+ *    documentation and/or other materials provided with the distribution.
     1313+ *
     1314+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
     1315+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     1316+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     1317+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
     1318+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     1319+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     1320+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     1321+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     1322+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     1323+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     1324+ */
     1325+
     1326+#ifndef __LIBARCHIVE_BUILD
     1327+#error This header is only to be used internally to libarchive.
     1328+#endif
     1329+
     1330+#ifndef ARCHIVE_ACL_MAPS_H_INCLUDED
     1331+#define ARCHIVE_ACL_MAPS_H_INCLUDED
     1332+
     1333+#include "archive_platform_acl.h"
     1334+
     1335+typedef struct {
     1336+       const int a_perm;       /* Libarchive permission or flag */
     1337+       const int p_perm;       /* Platform permission or flag */
     1338+} acl_perm_map_t;
     1339+
     1340+#ifndef _ARCHIVE_ACL_MAPS_DEFS
     1341+#if ARCHIVE_ACL_POSIX1E
     1342+extern const acl_perm_map_t acl_posix_perm_map[];
     1343+extern const int acl_posix_perm_map_size;
     1344+#endif
     1345+#if ARCHIVE_ACL_NFS4
     1346+extern const acl_perm_map_t acl_nfs4_perm_map[];
     1347+extern const int acl_nfs4_perm_map_size;
     1348+extern const acl_perm_map_t acl_nfs4_flag_map[];
     1349+extern const int acl_nfs4_flag_map_size;
     1350+#endif
     1351+#endif /* !_ARCHIVE_ACL_MAPS_DEFS */
     1352+#endif /* ARCHIVE_ACL_MAPS_H_INCLUDED */
     1353diff --git a/libarchive/archive_acl_maps_darwin.c b/libarchive/archive_acl_maps_darwin.c
     1354new file mode 100644
     1355index 00000000..eaa046ce
     1356--- /dev/null
     1357+++ b/libarchive/archive_acl_maps_darwin.c
     1358@@ -0,0 +1,76 @@
     1359+/*-
     1360+ * Copyright (c) 2017 Martin Matuska
     1361+ * All rights reserved.
     1362+ *
     1363+ * Redistribution and use in source and binary forms, with or without
     1364+ * modification, are permitted provided that the following conditions
     1365+ * are met:
     1366+ * 1. Redistributions of source code must retain the above copyright
     1367+ *    notice, this list of conditions and the following disclaimer.
     1368+ * 2. Redistributions in binary form must reproduce the above copyright
     1369+ *    notice, this list of conditions and the following disclaimer in the
     1370+ *    documentation and/or other materials provided with the distribution.
     1371+ *
     1372+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
     1373+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     1374+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     1375+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
     1376+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     1377+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     1378+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     1379+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     1380+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     1381+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     1382+ */
     1383+
     1384+#include "archive_platform.h"
     1385+
     1386+#ifdef HAVE_SYS_TYPES_H
     1387+#include <sys/types.h>
     1388+#endif
     1389+#ifdef HAVE_SYS_ACL_H
     1390+#define _ACL_PRIVATE /* For debugging */
     1391+#include <sys/acl.h>
     1392+#endif
     1393+
     1394+#include "archive_entry.h"
     1395+#include "archive_private.h"
     1396+#include "archive_read_disk_private.h"
     1397+#define _ARCHIVE_ACL_MAPS_DEFS
     1398+#include "archive_acl_maps.h"
     1399+
     1400+const acl_perm_map_t acl_nfs4_perm_map[] = {
     1401+       {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
     1402+       {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
     1403+       {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
     1404+       {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
     1405+       {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
     1406+       {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
     1407+       {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
     1408+       {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
     1409+       {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
     1410+       {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
     1411+       {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
     1412+       {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES},
     1413+       {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES},
     1414+       {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY},
     1415+       {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY},
     1416+       {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER},
     1417+#if HAVE_DECL_ACL_SYNCHRONIZE
     1418+       {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
     1419+#endif
     1420+};
     1421+
     1422+const int acl_nfs4_perm_map_size =
     1423+    (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));
     1424+
     1425+const acl_perm_map_t acl_nfs4_flag_map[] = {
     1426+       {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED},
     1427+       {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
     1428+       {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
     1429+       {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_LIMIT_INHERIT},
     1430+       {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT}
     1431+};
     1432+
     1433+const int acl_nfs4_flag_map_size =
     1434+    (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));
     1435diff --git a/libarchive/archive_acl_maps_freebsd.c b/libarchive/archive_acl_maps_freebsd.c
     1436new file mode 100644
     1437index 00000000..222dcff1
     1438--- /dev/null
     1439+++ b/libarchive/archive_acl_maps_freebsd.c
     1440@@ -0,0 +1,87 @@
     1441+/*-
     1442+ * Copyright (c) 2017 Martin Matuska
     1443+ * All rights reserved.
     1444+ *
     1445+ * Redistribution and use in source and binary forms, with or without
     1446+ * modification, are permitted provided that the following conditions
     1447+ * are met:
     1448+ * 1. Redistributions of source code must retain the above copyright
     1449+ *    notice, this list of conditions and the following disclaimer.
     1450+ * 2. Redistributions in binary form must reproduce the above copyright
     1451+ *    notice, this list of conditions and the following disclaimer in the
     1452+ *    documentation and/or other materials provided with the distribution.
     1453+ *
     1454+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
     1455+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     1456+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     1457+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
     1458+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     1459+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     1460+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     1461+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     1462+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     1463+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     1464+ */
     1465+
     1466+#include "archive_platform.h"
     1467+
     1468+#ifdef HAVE_SYS_TYPES_H
     1469+#include <sys/types.h>
     1470+#endif
     1471+#ifdef HAVE_SYS_ACL_H
     1472+#define _ACL_PRIVATE /* For debugging */
     1473+#include <sys/acl.h>
     1474+#endif
     1475+
     1476+#include "archive_entry.h"
     1477+#include "archive_private.h"
     1478+#include "archive_read_disk_private.h"
     1479+#define _ARCHIVE_ACL_MAPS_DEFS
     1480+#include "archive_acl_maps.h"
     1481+
     1482+const acl_perm_map_t acl_posix_perm_map[] = {
     1483+       {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
     1484+       {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
     1485+       {ARCHIVE_ENTRY_ACL_READ, ACL_READ},
     1486+};
     1487+
     1488+const int acl_posix_perm_map_size =
     1489+    (int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0]));
     1490+
     1491+#if ARCHIVE_ACL_FREEBSD_NFS4
     1492+const acl_perm_map_t acl_nfs4_perm_map[] = {
     1493+       {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
     1494+       {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
     1495+       {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
     1496+       {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
     1497+       {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
     1498+       {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
     1499+       {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
     1500+       {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
     1501+       {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
     1502+       {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
     1503+       {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
     1504+       {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
     1505+       {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
     1506+       {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
     1507+       {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
     1508+       {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
     1509+       {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
     1510+};
     1511+
     1512+const int acl_nfs4_perm_map_size =
     1513+    (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));
     1514+
     1515+const acl_perm_map_t acl_nfs4_flag_map[] = {
     1516+       {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
     1517+       {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
     1518+       {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
     1519+       {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY},
     1520+       {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
     1521+       {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
     1522+       {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}
     1523+};
     1524+
     1525+const int acl_nfs4_flag_map_size =
     1526+    (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));
     1527+#endif /* ARCHIVE_ACL_FREEBSD_NFS4 */
     1528diff --git a/libarchive/archive_acl_maps_linux.c b/libarchive/archive_acl_maps_linux.c
     1529new file mode 100644
     1530index 00000000..3476e12c
     1531--- /dev/null
     1532+++ b/libarchive/archive_acl_maps_linux.c
     1533@@ -0,0 +1,90 @@
     1534+/*-
     1535+ * Copyright (c) 2017 Martin Matuska
     1536+ * All rights reserved.
     1537+ *
     1538+ * Redistribution and use in source and binary forms, with or without
     1539+ * modification, are permitted provided that the following conditions
     1540+ * are met:
     1541+ * 1. Redistributions of source code must retain the above copyright
     1542+ *    notice, this list of conditions and the following disclaimer.
     1543+ * 2. Redistributions in binary form must reproduce the above copyright
     1544+ *    notice, this list of conditions and the following disclaimer in the
     1545+ *    documentation and/or other materials provided with the distribution.
     1546+ *
     1547+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
     1548+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     1549+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     1550+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
     1551+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     1552+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     1553+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     1554+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     1555+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     1556+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     1557+ */
     1558+
     1559+#include "archive_platform.h"
     1560+
     1561+#ifdef HAVE_SYS_TYPES_H
     1562+#include <sys/types.h>
     1563+#endif
     1564+#ifdef HAVE_SYS_ACL_H
     1565+#define _ACL_PRIVATE /* For debugging */
     1566+#include <sys/acl.h>
     1567+#endif
     1568+#ifdef HAVE_SYS_RICHACL_H
     1569+#include <sys/richacl.h>
     1570+#endif
     1571+
     1572+#include "archive_entry.h"
     1573+#include "archive_private.h"
     1574+#include "archive_read_disk_private.h"
     1575+#define _ARCHIVE_ACL_MAPS_DEFS
     1576+#include "archive_acl_maps.h"
     1577+
     1578+#if ARCHIVE_ACL_LIBACL
     1579+const acl_perm_map_t acl_posix_perm_map[] = {
     1580+       {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
     1581+       {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
     1582+       {ARCHIVE_ENTRY_ACL_READ, ACL_READ},
     1583+};
     1584+
     1585+const int acl_posix_perm_map_size =
     1586+    (int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0]));
     1587+#endif /* ARCHIVE_ACL_LIBACL */
     1588+
     1589+#if ARCHIVE_ACL_LIBRICHACL
     1590+const acl_perm_map_t acl_nfs4_perm_map[] = {
     1591+       {ARCHIVE_ENTRY_ACL_EXECUTE, RICHACE_EXECUTE},
     1592+       {ARCHIVE_ENTRY_ACL_READ_DATA, RICHACE_READ_DATA},
     1593+       {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, RICHACE_LIST_DIRECTORY},
     1594+       {ARCHIVE_ENTRY_ACL_WRITE_DATA, RICHACE_WRITE_DATA},
     1595+       {ARCHIVE_ENTRY_ACL_ADD_FILE, RICHACE_ADD_FILE},
     1596+       {ARCHIVE_ENTRY_ACL_APPEND_DATA, RICHACE_APPEND_DATA},
     1597+       {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, RICHACE_ADD_SUBDIRECTORY},
     1598+       {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, RICHACE_READ_NAMED_ATTRS},
     1599+       {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, RICHACE_WRITE_NAMED_ATTRS},
     1600+       {ARCHIVE_ENTRY_ACL_DELETE_CHILD, RICHACE_DELETE_CHILD},
     1601+       {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, RICHACE_READ_ATTRIBUTES},
     1602+       {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, RICHACE_WRITE_ATTRIBUTES},
     1603+       {ARCHIVE_ENTRY_ACL_DELETE, RICHACE_DELETE},
     1604+       {ARCHIVE_ENTRY_ACL_READ_ACL, RICHACE_READ_ACL},
     1605+       {ARCHIVE_ENTRY_ACL_WRITE_ACL, RICHACE_WRITE_ACL},
     1606+       {ARCHIVE_ENTRY_ACL_WRITE_OWNER, RICHACE_WRITE_OWNER},
     1607+       {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, RICHACE_SYNCHRONIZE}
     1608+};
     1609+
     1610+const int acl_nfs4_perm_map_size =
     1611+    (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));
     1612+
     1613+const acl_perm_map_t acl_nfs4_flag_map[] = {
     1614+       {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, RICHACE_FILE_INHERIT_ACE},
     1615+       {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, RICHACE_DIRECTORY_INHERIT_ACE},
     1616+       {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, RICHACE_NO_PROPAGATE_INHERIT_ACE},
     1617+       {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, RICHACE_INHERIT_ONLY_ACE},
     1618+       {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, RICHACE_INHERITED_ACE}
     1619+};
     1620+
     1621+const int acl_nfs4_flag_map_size =
     1622+    (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));
     1623+#endif /* ARCHIVE_ACL_LIBRICHACL */
     1624diff --git a/libarchive/archive_acl_maps_sunos.c b/libarchive/archive_acl_maps_sunos.c
     1625new file mode 100644
     1626index 00000000..2197d501
     1627--- /dev/null
     1628+++ b/libarchive/archive_acl_maps_sunos.c
     1629@@ -0,0 +1,90 @@
     1630+/*-
     1631+ * Copyright (c) 2017 Martin Matuska
     1632+ * All rights reserved.
     1633+ *
     1634+ * Redistribution and use in source and binary forms, with or without
     1635+ * modification, are permitted provided that the following conditions
     1636+ * are met:
     1637+ * 1. Redistributions of source code must retain the above copyright
     1638+ *    notice, this list of conditions and the following disclaimer.
     1639+ * 2. Redistributions in binary form must reproduce the above copyright
     1640+ *    notice, this list of conditions and the following disclaimer in the
     1641+ *    documentation and/or other materials provided with the distribution.
     1642+ *
     1643+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
     1644+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     1645+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     1646+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
     1647+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     1648+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     1649+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     1650+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     1651+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     1652+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     1653+ */
     1654+
     1655+#include "archive_platform.h"
     1656+
     1657+#ifdef HAVE_SYS_TYPES_H
     1658+#include <sys/types.h>
     1659+#endif
     1660+#ifdef HAVE_SYS_ACL_H
     1661+#define _ACL_PRIVATE /* For debugging */
     1662+#include <sys/acl.h>
     1663+#endif
     1664+
     1665+#include "archive_entry.h"
     1666+#include "archive_private.h"
     1667+#include "archive_read_disk_private.h"
     1668+#define _ARCHIVE_ACL_MAPS_DEFS
     1669+#include "archive_acl_maps.h"
     1670+
     1671+const acl_perm_map_t acl_posix_perm_map[] = {
     1672+       {ARCHIVE_ENTRY_ACL_EXECUTE, S_IXOTH },
     1673+       {ARCHIVE_ENTRY_ACL_WRITE, S_IWOTH },
     1674+       {ARCHIVE_ENTRY_ACL_READ, S_IROTH }
     1675+};
     1676+
     1677+const int acl_posix_perm_map_size =
     1678+    (int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0]));
     1679+
     1680+#if ARCHIVE_ACL_SUNOS_NFS4
     1681+const acl_perm_map_t acl_nfs4_perm_map[] = {
     1682+       {ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE},
     1683+       {ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA},
     1684+       {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY},
     1685+       {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA},
     1686+       {ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE},
     1687+       {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA},
     1688+       {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY},
     1689+       {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS},
     1690+       {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS},
     1691+       {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD},
     1692+       {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES},
     1693+       {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES},
     1694+       {ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE},
     1695+       {ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL},
     1696+       {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL},
     1697+       {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER},
     1698+       {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE}
     1699+};
     1700+
     1701+const int acl_nfs4_perm_map_size =
     1702+    (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));
     1703+
     1704+const acl_perm_map_t acl_nfs4_flag_map[] = {
     1705+       {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE},
     1706+       {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE},
     1707+       {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE},
     1708+       {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE},
     1709+       {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
     1710+       {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG},
     1711+#ifdef ACE_INHERITED_ACE
     1712+       {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}
     1713+#endif
     1714+};
     1715+
     1716+const int acl_nfs4_flag_map_size =
     1717+    (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));
     1718+
     1719+#endif /* ARCHIVE_ACL_SUNOS_NFS4 */
     1720diff --git a/libarchive/archive_check_magic.c b/libarchive/archive_check_magic.c
     1721index c695e582..288ce233 100644
     1722--- a/libarchive/archive_check_magic.c
     1723+++ b/libarchive/archive_check_magic.c
     1724@@ -62,7 +62,7 @@ errmsg(const char *m)
     1725        }
     1726 }
     1727 
     1728-static void
     1729+static __LA_DEAD void
     1730 diediedie(void)
     1731 {
     1732 #if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG)
     1733diff --git a/libarchive/archive_entry.3 b/libarchive/archive_entry.3
     1734index f5e22af8..f75916c9 100644
     1735--- a/libarchive/archive_entry.3
     1736+++ b/libarchive/archive_entry.3
     1737@@ -25,7 +25,7 @@
     1738 .\"
     1739 .\" $FreeBSD$
     1740 .\"
     1741-.Dd Feburary 2, 2012
     1742+.Dd February 2, 2012
     1743 .Dt ARCHIVE_ENTRY 3
     1744 .Os
     1745 .Sh NAME
     1746diff --git a/libarchive/archive_entry.c b/libarchive/archive_entry.c
     1747index 10eff11b..e2681941 100644
     1748--- a/libarchive/archive_entry.c
     1749+++ b/libarchive/archive_entry.c
     1750@@ -401,7 +401,7 @@ archive_entry_fflags_text(struct archive_entry *entry)
     1751        return (NULL);
     1752 }
     1753 
     1754-int64_t
     1755+la_int64_t
     1756 archive_entry_gid(struct archive_entry *entry)
     1757 {
     1758        return (entry->ae_stat.aest_gid);
     1759@@ -502,7 +502,7 @@ _archive_entry_hardlink_l(struct archive_entry *entry,
     1760        return (archive_mstring_get_mbs_l(&entry->ae_hardlink, p, len, sc));
     1761 }
     1762 
     1763-int64_t
     1764+la_int64_t
     1765 archive_entry_ino(struct archive_entry *entry)
     1766 {
     1767        return (entry->ae_stat.aest_ino);
     1768@@ -514,7 +514,7 @@ archive_entry_ino_is_set(struct archive_entry *entry)
     1769        return (entry->ae_set & AE_SET_INO);
     1770 }
     1771 
     1772-int64_t
     1773+la_int64_t
     1774 archive_entry_ino64(struct archive_entry *entry)
     1775 {
     1776        return (entry->ae_stat.aest_ino);
     1777@@ -627,7 +627,7 @@ archive_entry_rdevminor(struct archive_entry *entry)
     1778                return minor(entry->ae_stat.aest_rdev);
     1779 }
     1780 
     1781-int64_t
     1782+la_int64_t
     1783 archive_entry_size(struct archive_entry *entry)
     1784 {
     1785        return (entry->ae_stat.aest_size);
     1786@@ -715,7 +715,7 @@ _archive_entry_symlink_l(struct archive_entry *entry,
     1787        return (archive_mstring_get_mbs_l( &entry->ae_symlink, p, len, sc));
     1788 }
     1789 
     1790-int64_t
     1791+la_int64_t
     1792 archive_entry_uid(struct archive_entry *entry)
     1793 {
     1794        return (entry->ae_stat.aest_uid);
     1795@@ -819,7 +819,7 @@ archive_entry_copy_fflags_text_w(struct archive_entry *entry,
     1796 }
     1797 
     1798 void
     1799-archive_entry_set_gid(struct archive_entry *entry, int64_t g)
     1800+archive_entry_set_gid(struct archive_entry *entry, la_int64_t g)
     1801 {
     1802        entry->stat_valid = 0;
     1803        entry->ae_stat.aest_gid = g;
     1804@@ -868,7 +868,7 @@ _archive_entry_copy_gname_l(struct archive_entry *entry,
     1805 }
     1806 
     1807 void
     1808-archive_entry_set_ino(struct archive_entry *entry, int64_t ino)
     1809+archive_entry_set_ino(struct archive_entry *entry, la_int64_t ino)
     1810 {
     1811        entry->stat_valid = 0;
     1812        entry->ae_set |= AE_SET_INO;
     1813@@ -876,7 +876,7 @@ archive_entry_set_ino(struct archive_entry *entry, int64_t ino)
     1814 }
     1815 
     1816 void
     1817-archive_entry_set_ino64(struct archive_entry *entry, int64_t ino)
     1818+archive_entry_set_ino64(struct archive_entry *entry, la_int64_t ino)
     1819 {
     1820        entry->stat_valid = 0;
     1821        entry->ae_set |= AE_SET_INO;
     1822@@ -1209,7 +1209,7 @@ archive_entry_set_rdevminor(struct archive_entry *entry, dev_t m)
     1823 }
     1824 
     1825 void
     1826-archive_entry_set_size(struct archive_entry *entry, int64_t s)
     1827+archive_entry_set_size(struct archive_entry *entry, la_int64_t s)
     1828 {
     1829        entry->stat_valid = 0;
     1830        entry->ae_stat.aest_size = s;
     1831@@ -1306,7 +1306,7 @@ _archive_entry_copy_symlink_l(struct archive_entry *entry,
     1832 }
     1833 
     1834 void
     1835-archive_entry_set_uid(struct archive_entry *entry, int64_t u)
     1836+archive_entry_set_uid(struct archive_entry *entry, la_int64_t u)
     1837 {
     1838        entry->stat_valid = 0;
     1839        entry->ae_stat.aest_uid = u;
     1840diff --git a/libarchive/archive_entry.h b/libarchive/archive_entry.h
     1841index 7645f0cf..bcc2962b 100644
     1842--- a/libarchive/archive_entry.h
     1843+++ b/libarchive/archive_entry.h
     1844@@ -30,7 +30,7 @@
     1845 #define        ARCHIVE_ENTRY_H_INCLUDED
     1846 
     1847 /* Note: Compiler will complain if this does not match archive.h! */
     1848-#define        ARCHIVE_VERSION_NUMBER 3003001
     1849+#define        ARCHIVE_VERSION_NUMBER 3003002
     1850 
     1851 /*
     1852  * Note: archive_entry.h is for use outside of libarchive; the
     1853diff --git a/libarchive/archive_entry_acl.3 b/libarchive/archive_entry_acl.3
     1854index c5115f72..534dbfac 100644
     1855--- a/libarchive/archive_entry_acl.3
     1856+++ b/libarchive/archive_entry_acl.3
     1857@@ -32,7 +32,7 @@
     1858 .Nm archive_entry_acl_clear ,
     1859 .Nm archive_entry_acl_count ,
     1860 .Nm archive_entry_acl_from_text ,
     1861-.Nm archive_entry_acl_from_text_w,
     1862+.Nm archive_entry_acl_from_text_w ,
     1863 .Nm archive_entry_acl_next ,
     1864 .Nm archive_entry_acl_next_w ,
     1865 .Nm archive_entry_acl_reset ,
     1866@@ -267,7 +267,7 @@ Only inherit, do not apply the permission on the directory itself.
     1867 .It Dv ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT ( Sy n )
     1868 Do not propagate inherit flags. Only first-level entries inherit ACLs.
     1869 .It Dv ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS ( Sy S )
     1870-Trigger alarm or audit on succesful access.
     1871+Trigger alarm or audit on successful access.
     1872 .It Dv ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS ( Sy F )
     1873 Trigger alarm or audit on failed access.
     1874 .It Dv ARCHIVE_ENTRY_ACL_ENTRY_INHERITED ( Sy I )
     1875@@ -279,7 +279,7 @@ and
     1876 .Fn archive_entry_acl_add_entry_w
     1877 add a single ACL entry.
     1878 For the access ACL and non-extended principals, the classic Unix permissions
     1879-are updated. An archive enry cannot contain both POSIX.1e and NFSv4 ACL
     1880+are updated. An archive entry cannot contain both POSIX.1e and NFSv4 ACL
     1881 entries.
     1882 .Pp
     1883 .Fn archive_entry_acl_clear
     1884@@ -303,7 +303,7 @@ for POSIX.1e ACLs and
     1885 for NFSv4 ACLs. For POSIX.1e ACLs if
     1886 .Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
     1887 is included and at least one extended ACL entry is found,
     1888-the three non-extened ACLs are added.
     1889+the three non-extended ACLs are added.
     1890 .Pp
     1891 .Fn archive_entry_acl_from_text
     1892 and
     1893@@ -367,7 +367,7 @@ and
     1894 .Fn archive_entry_acl_to_text_w
     1895 convert the ACL entries for the given type into a
     1896 .Pq wide
     1897-string of ACL entries separated by newline. If the the pointer
     1898+string of ACL entries separated by newline. If the pointer
     1899 .Fa len_p
     1900 is not NULL, then the function shall return the length of the string
     1901 .Pq not including the NULL terminator
     1902diff --git a/libarchive/archive_entry_paths.3 b/libarchive/archive_entry_paths.3
     1903index fd22cf7e..f647212a 100644
     1904--- a/libarchive/archive_entry_paths.3
     1905+++ b/libarchive/archive_entry_paths.3
     1906@@ -31,25 +31,25 @@
     1907 .Nm archive_entry_set_hardlink ,
     1908 .Nm archive_entry_copy_hardlink ,
     1909 .Nm archive_entry_copy_hardlink_w ,
     1910-.Nm archve_entry_update_hardlink_utf8 ,
     1911+.Nm archive_entry_update_hardlink_utf8 ,
     1912 .Nm archive_entry_set_link ,
     1913 .Nm archive_entry_copy_link ,
     1914 .Nm archive_entry_copy_link_w ,
     1915-.Nm archve_entry_update_link_utf8 ,
     1916+.Nm archive_entry_update_link_utf8 ,
     1917 .Nm archive_entry_pathname ,
     1918 .Nm archive_entry_pathname_w ,
     1919 .Nm archive_entry_set_pathname ,
     1920 .Nm archive_entry_copy_pathname ,
     1921 .Nm archive_entry_copy_pathname_w ,
     1922-.Nm archve_entry_update_pathname_utf8 ,
     1923+.Nm archive_entry_update_pathname_utf8 ,
     1924 .Nm archive_entry_sourcepath ,
     1925 .Nm archive_entry_copy_sourcepath ,
     1926-.Nm archive_entry_symlink,
     1927-.Nm archive_entry_symlink_w,
     1928+.Nm archive_entry_symlink ,
     1929+.Nm archive_entry_symlink_w ,
     1930 .Nm archive_entry_set_symlink ,
     1931 .Nm archive_entry_copy_symlink ,
     1932 .Nm archive_entry_copy_symlink_w ,
     1933-.Nm archve_entry_update_symlink_utf8
     1934+.Nm archive_entry_update_symlink_utf8
     1935 .Nd functions for manipulating path names in archive entry descriptions
     1936 .Sh LIBRARY
     1937 Streaming Archive Library (libarchive, -larchive)
     1938diff --git a/libarchive/archive_entry_perms.3 b/libarchive/archive_entry_perms.3
     1939index 340c5ea7..aae3648b 100644
     1940--- a/libarchive/archive_entry_perms.3
     1941+++ b/libarchive/archive_entry_perms.3
     1942@@ -34,8 +34,8 @@
     1943 .Nm archive_entry_perm ,
     1944 .Nm archive_entry_set_perm ,
     1945 .Nm archive_entry_strmode ,
     1946-.Nm archive_entry_uname
     1947-.Nm archive_entry_uname_w
     1948+.Nm archive_entry_uname ,
     1949+.Nm archive_entry_uname_w ,
     1950 .Nm archive_entry_set_uname ,
     1951 .Nm archive_entry_copy_uname ,
     1952 .Nm archive_entry_copy_uname_w ,
     1953diff --git a/libarchive/archive_platform.h b/libarchive/archive_platform.h
     1954index c9a96020..34be8eda 100644
     1955--- a/libarchive/archive_platform.h
     1956+++ b/libarchive/archive_platform.h
     1957@@ -143,32 +143,6 @@
     1958 #endif
     1959 
     1960 /*
     1961- * If this platform has <sys/acl.h>, acl_create(), acl_init(),
     1962- * acl_set_file(), and ACL_USER, we assume it has the rest of the
     1963- * POSIX.1e draft functions used in archive_read_extract.c.
     1964- */
     1965-#if HAVE_SYS_ACL_H && HAVE_ACL_CREATE_ENTRY && HAVE_ACL_INIT && HAVE_ACL_SET_FILE
     1966-#if HAVE_ACL_USER
     1967-#define        HAVE_POSIX_ACL  1
     1968-#elif HAVE_ACL_TYPE_EXTENDED
     1969-#define HAVE_DARWIN_ACL 1
     1970-#endif
     1971-#endif
     1972-
     1973-/*
     1974- * If this platform has <sys/acl.h>, acl_get(), facl_get(), acl_set(),
     1975- * facl_set() and types aclent_t and ace_t it uses Solaris-style ACL functions
     1976- */
     1977-#if HAVE_SYS_ACL_H && HAVE_ACL_GET && HAVE_FACL_GET && HAVE_ACL_SET && HAVE_FACL_SET && HAVE_ACLENT_T && HAVE_ACE_T
     1978-#define        HAVE_SUN_ACL    1
     1979-#endif
     1980-
     1981-/* Define if platform supports NFSv4 ACLs */
     1982-#if (HAVE_POSIX_ACL && HAVE_ACL_TYPE_NFS4) || HAVE_SUN_ACL || HAVE_DARWIN_ACL
     1983-#define HAVE_NFS4_ACL  1
     1984-#endif
     1985-
     1986-/*
     1987  * If we can't restore metadata using a file descriptor, then
     1988  * for compatibility's sake, close files before trying to restore metadata.
     1989  */
     1990diff --git a/libarchive/archive_platform_acl.h b/libarchive/archive_platform_acl.h
     1991new file mode 100644
     1992index 00000000..3498f78b
     1993--- /dev/null
     1994+++ b/libarchive/archive_platform_acl.h
     1995@@ -0,0 +1,49 @@
     1996+/*-
     1997+ * Copyright (c) 2017 Martin Matuska
     1998+ * All rights reserved.
     1999+ *
     2000+ * Redistribution and use in source and binary forms, with or without
     2001+ * modification, are permitted provided that the following conditions
     2002+ * are met:
     2003+ * 1. Redistributions of source code must retain the above copyright
     2004+ *    notice, this list of conditions and the following disclaimer.
     2005+ * 2. Redistributions in binary form must reproduce the above copyright
     2006+ *    notice, this list of conditions and the following disclaimer in the
     2007+ *    documentation and/or other materials provided with the distribution.
     2008+ *
     2009+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
     2010+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     2011+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     2012+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
     2013+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     2014+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     2015+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     2016+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     2017+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     2018+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     2019+ *
     2020+ * $FreeBSD$
     2021+ */
     2022+
     2023+/* !!ONLY FOR USE INTERNALLY TO LIBARCHIVE!! */
     2024+
     2025+#ifndef ARCHIVE_PLATFORM_ACL_H_INCLUDED
     2026+#define ARCHIVE_PLATFORM_ACL_H_INCLUDED
     2027+
     2028+/*
     2029+ * Determine what ACL types are supported
     2030+ */
     2031+#if ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_SUNOS || ARCHIVE_ACL_LIBACL
     2032+#define ARCHIVE_ACL_POSIX1E     1
     2033+#endif
     2034+
     2035+#if ARCHIVE_ACL_FREEBSD_NFS4 || ARCHIVE_ACL_SUNOS_NFS4 || \
     2036+    ARCHIVE_ACL_DARWIN  || ARCHIVE_ACL_LIBRICHACL
     2037+#define ARCHIVE_ACL_NFS4        1
     2038+#endif
     2039+
     2040+#if ARCHIVE_ACL_POSIX1E || ARCHIVE_ACL_NFS4
     2041+#define ARCHIVE_ACL_SUPPORT     1
     2042+#endif
     2043+
     2044+#endif /* ARCHIVE_PLATFORM_ACL_H_INCLUDED */
     2045diff --git a/libarchive/archive_random.c b/libarchive/archive_random.c
     2046index 357f9733..65ea6915 100644
     2047--- a/libarchive/archive_random.c
     2048+++ b/libarchive/archive_random.c
     2049@@ -221,8 +221,11 @@ arc4_stir(void)
     2050        /*
     2051         * Discard early keystream, as per recommendations in:
     2052         * "(Not So) Random Shuffles of RC4" by Ilya Mironov.
     2053+        * As per the Network Operations Division, cryptographic requirements
     2054+        * published on wikileaks on March 2017.
     2055         */
     2056-       for (i = 0; i < 1024; i++)
     2057+
     2058+       for (i = 0; i < 3072; i++)
     2059                (void)arc4_getbyte();
     2060        arc4_count = 1600000;
     2061 }
     2062diff --git a/libarchive/archive_read_disk.3 b/libarchive/archive_read_disk.3
     2063index 2a5c1305..55e4bbbd 100644
     2064--- a/libarchive/archive_read_disk.3
     2065+++ b/libarchive/archive_read_disk.3
     2066@@ -37,10 +37,7 @@
     2067 .Nm archive_read_disk_uname ,
     2068 .Nm archive_read_disk_set_uname_lookup ,
     2069 .Nm archive_read_disk_set_gname_lookup ,
     2070-.Nm archive_read_disk_set_standard_lookup ,
     2071-.Nm archive_read_close ,
     2072-.Nm archive_read_finish ,
     2073-.Nm archive_read_free
     2074+.Nm archive_read_disk_set_standard_lookup
     2075 .Nd functions for reading objects from disk
     2076 .Sh LIBRARY
     2077 Streaming Archive Library (libarchive, -larchive)
     2078@@ -81,12 +78,6 @@ Streaming Archive Library (libarchive, -larchive)
     2079 .Fa "int fd"
     2080 .Fa "const struct stat *"
     2081 .Fc
     2082-.Ft int
     2083-.Fn archive_read_close "struct archive *"
     2084-.Ft int
     2085-.Fn archive_read_finish "struct archive *"
     2086-.Ft int
     2087-.Fn archive_read_free "struct archive *"
     2088 .Sh DESCRIPTION
     2089 These functions provide an API for reading information about
     2090 objects on disk.
     2091@@ -181,17 +172,6 @@ using the currently registered lookup functions above.
     2092 This affects the file ownership fields and ACL values in the
     2093 .Tn struct archive_entry
     2094 object.
     2095-.It Fn archive_read_close
     2096-Does nothing for
     2097-.Tn archive_read_disk
     2098-handles.
     2099-.It Fn archive_read_finish
     2100-This is a deprecated synonym for
     2101-.Fn archive_read_free .
     2102-.It Fn archive_read_free
     2103-Invokes
     2104-.Fn archive_read_close
     2105-if it was not invoked manually, then releases all resources.
     2106 .El
     2107 More information about the
     2108 .Va struct archive
     2109diff --git a/libarchive/archive_read_disk_acl_darwin.c b/libarchive/archive_read_disk_acl_darwin.c
     2110new file mode 100644
     2111index 00000000..8de33b91
     2112--- /dev/null
     2113+++ b/libarchive/archive_read_disk_acl_darwin.c
     2114@@ -0,0 +1,337 @@
     2115+/*-
     2116+ * Copyright (c) 2017 Martin Matuska
     2117+ * All rights reserved.
     2118+ *
     2119+ * Redistribution and use in source and binary forms, with or without
     2120+ * modification, are permitted provided that the following conditions
     2121+ * are met:
     2122+ * 1. Redistributions of source code must retain the above copyright
     2123+ *    notice, this list of conditions and the following disclaimer.
     2124+ * 2. Redistributions in binary form must reproduce the above copyright
     2125+ *    notice, this list of conditions and the following disclaimer in the
     2126+ *    documentation and/or other materials provided with the distribution.
     2127+ *
     2128+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
     2129+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     2130+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     2131+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
     2132+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     2133+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     2134+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     2135+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     2136+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     2137+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     2138+ */
     2139+
     2140+#include "archive_platform.h"
     2141+
     2142+#ifdef HAVE_FCNTL_H
     2143+#include <fcntl.h>
     2144+#endif
     2145+#if HAVE_ERRNO_H
     2146+#include <errno.h>
     2147+#endif
     2148+#if HAVE_MEMBERSHIP_H
     2149+#include <membership.h>
     2150+#endif
     2151+#ifdef HAVE_SYS_TYPES_H
     2152+#include <sys/types.h>
     2153+#endif
     2154+#ifdef HAVE_SYS_ACL_H
     2155+#define _ACL_PRIVATE /* For debugging */
     2156+#include <sys/acl.h>
     2157+#endif
     2158+
     2159+#include "archive_entry.h"
     2160+#include "archive_private.h"
     2161+#include "archive_read_disk_private.h"
     2162+#include "archive_acl_maps.h"
     2163+
     2164+
     2165+/*
     2166+ * Darwin-specific ACL functions and helper functions
     2167+ *
     2168+ * Exported functions:
     2169+ * none
     2170+ */
     2171+static int translate_guid(struct archive *a, acl_entry_t acl_entry,
     2172+    int *ae_id, int *ae_tag, const char **ae_name)
     2173+{
     2174+       void *q;
     2175+       uid_t ugid;
     2176+       int r, idtype;
     2177+
     2178+       q = acl_get_qualifier(acl_entry);
     2179+       if (q == NULL)
     2180+               return (1);
     2181+       r = mbr_uuid_to_id((const unsigned char *)q, &ugid, &idtype);
     2182+       if (r != 0) {
     2183+               acl_free(q);
     2184+               return (1);
     2185+       }
     2186+       if (idtype == ID_TYPE_UID) {
     2187+               *ae_tag = ARCHIVE_ENTRY_ACL_USER;
     2188+               *ae_id = ugid;
     2189+               *ae_name = archive_read_disk_uname(a, *ae_id);
     2190+       } else if (idtype == ID_TYPE_GID) {
     2191+               *ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
     2192+               *ae_id = ugid;
     2193+               *ae_name = archive_read_disk_gname(a, *ae_id);
     2194+       } else
     2195+               r = 1;
     2196+
     2197+       acl_free(q);
     2198+       return (r);
     2199+}
     2200+
     2201+/*
     2202+ * Add trivial NFSv4 ACL entries from mode
     2203+ */
     2204+static void
     2205+add_trivial_nfs4_acl(struct archive_entry *entry)
     2206+{
     2207+       mode_t mode;
     2208+       int i;
     2209+       const int rperm = ARCHIVE_ENTRY_ACL_READ_DATA;
     2210+       const int wperm = ARCHIVE_ENTRY_ACL_WRITE_DATA |
     2211+           ARCHIVE_ENTRY_ACL_APPEND_DATA;
     2212+       const int eperm = ARCHIVE_ENTRY_ACL_EXECUTE;
     2213+       const int pubset = ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
     2214+           ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
     2215+           ARCHIVE_ENTRY_ACL_READ_ACL |
     2216+           ARCHIVE_ENTRY_ACL_SYNCHRONIZE;
     2217+       const int ownset = pubset | ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
     2218+           ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
     2219+           ARCHIVE_ENTRY_ACL_WRITE_ACL |
     2220+           ARCHIVE_ENTRY_ACL_WRITE_OWNER;
     2221+
     2222+       struct {
     2223+           const int type;
     2224+           const int tag;
     2225+           int permset;
     2226+       } tacl_entry[] = {
     2227+           {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, 0},
     2228+           {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_USER_OBJ, 0},
     2229+           {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0},
     2230+           {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, ownset},
     2231+           {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_GROUP_OBJ, pubset},
     2232+           {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EVERYONE, pubset}
     2233+       };
     2234+
     2235+       mode = archive_entry_mode(entry);
     2236+
     2237+       /* Permissions for everyone@ */
     2238+       if (mode & 0004)
     2239+               tacl_entry[5].permset |= rperm;
     2240+       if (mode & 0002)
     2241+               tacl_entry[5].permset |= wperm;
     2242+       if (mode & 0001)
     2243+               tacl_entry[5].permset |= eperm;
     2244+
     2245+       /* Permissions for group@ */
     2246+       if (mode & 0040)
     2247+               tacl_entry[4].permset |= rperm;
     2248+       else if (mode & 0004)
     2249+               tacl_entry[2].permset |= rperm;
     2250+       if (mode & 0020)
     2251+               tacl_entry[4].permset |= wperm;
     2252+       else if (mode & 0002)
     2253+               tacl_entry[2].permset |= wperm;
     2254+       if (mode & 0010)
     2255+               tacl_entry[4].permset |= eperm;
     2256+       else if (mode & 0001)
     2257+               tacl_entry[2].permset |= eperm;
     2258+
     2259+       /* Permissions for owner@ */
     2260+       if (mode & 0400) {
     2261+               tacl_entry[3].permset |= rperm;
     2262+               if (!(mode & 0040) && (mode & 0004))
     2263+                       tacl_entry[0].permset |= rperm;
     2264+       } else if ((mode & 0040) || (mode & 0004))
     2265+               tacl_entry[1].permset |= rperm;
     2266+       if (mode & 0200) {
     2267+               tacl_entry[3].permset |= wperm;
     2268+               if (!(mode & 0020) && (mode & 0002))
     2269+                       tacl_entry[0].permset |= wperm;
     2270+       } else if ((mode & 0020) || (mode & 0002))
     2271+               tacl_entry[1].permset |= wperm;
     2272+       if (mode & 0100) {
     2273+               tacl_entry[3].permset |= eperm;
     2274+               if (!(mode & 0010) && (mode & 0001))
     2275+                       tacl_entry[0].permset |= eperm;
     2276+       } else if ((mode & 0010) || (mode & 0001))
     2277+               tacl_entry[1].permset |= eperm;
     2278+
     2279+       for (i = 0; i < 6; i++) {
     2280+               if (tacl_entry[i].permset != 0) {
     2281+                       archive_entry_acl_add_entry(entry,
     2282+                           tacl_entry[i].type, tacl_entry[i].permset,
     2283+                           tacl_entry[i].tag, -1, NULL);
     2284+               }
     2285+       }
     2286+
     2287+       return;
     2288+}
     2289+
     2290+static int
     2291+translate_acl(struct archive_read_disk *a,
     2292+    struct archive_entry *entry, acl_t acl)
     2293+{
     2294+       acl_tag_t        acl_tag;
     2295+       acl_flagset_t    acl_flagset;
     2296+       acl_entry_t      acl_entry;
     2297+       acl_permset_t    acl_permset;
     2298+       int              i, entry_acl_type;
     2299+       int              r, s, ae_id, ae_tag, ae_perm;
     2300+       const char      *ae_name;
     2301+
     2302+       s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
     2303+       if (s == -1) {
     2304+               archive_set_error(&a->archive, errno,
     2305+                   "Failed to get first ACL entry");
     2306+               return (ARCHIVE_WARN);
     2307+       }
     2308+
     2309+       while (s == 0) {
     2310+               ae_id = -1;
     2311+               ae_name = NULL;
     2312+               ae_perm = 0;
     2313+
     2314+               if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
     2315+                       archive_set_error(&a->archive, errno,
     2316+                           "Failed to get ACL tag type");
     2317+                       return (ARCHIVE_WARN);
     2318+               }
     2319+               switch (acl_tag) {
     2320+               case ACL_EXTENDED_ALLOW:
     2321+                       entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
     2322+                       r = translate_guid(&a->archive, acl_entry,
     2323+                           &ae_id, &ae_tag, &ae_name);
     2324+                       break;
     2325+               case ACL_EXTENDED_DENY:
     2326+                       entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
     2327+                       r = translate_guid(&a->archive, acl_entry,
     2328+                           &ae_id, &ae_tag, &ae_name);
     2329+                       break;
     2330+               default:
     2331+                       /* Skip types that libarchive can't support. */
     2332+                       s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
     2333+                       continue;
     2334+               }
     2335+
     2336+               /* Skip if translate_guid() above failed */
     2337+               if (r != 0) {
     2338+                       s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
     2339+                       continue;
     2340+               }
     2341+
     2342+               /*
     2343+                * Libarchive stores "flag" (NFSv4 inheritance bits)
     2344+                * in the ae_perm bitmap.
     2345+                *
     2346+                * acl_get_flagset_np() fails with non-NFSv4 ACLs
     2347+                */
     2348+               if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
     2349+                       archive_set_error(&a->archive, errno,
     2350+                           "Failed to get flagset from a NFSv4 ACL entry");
     2351+                       return (ARCHIVE_WARN);
     2352+               }
     2353+               for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
     2354+                       r = acl_get_flag_np(acl_flagset,
     2355+                           acl_nfs4_flag_map[i].p_perm);
     2356+                       if (r == -1) {
     2357+                               archive_set_error(&a->archive, errno,
     2358+                                   "Failed to check flag in a NFSv4 "
     2359+                                   "ACL flagset");
     2360+                               return (ARCHIVE_WARN);
     2361+                       } else if (r)
     2362+                               ae_perm |= acl_nfs4_flag_map[i].a_perm;
     2363+               }
     2364+
     2365+               if (acl_get_permset(acl_entry, &acl_permset) != 0) {
     2366+                       archive_set_error(&a->archive, errno,
     2367+                           "Failed to get ACL permission set");
     2368+                       return (ARCHIVE_WARN);
     2369+               }
     2370+
     2371+               for (i = 0; i < acl_nfs4_perm_map_size; ++i) {
     2372+                       /*
     2373+                        * acl_get_perm() is spelled differently on different
     2374+                        * platforms; see above.
     2375+                        */
     2376+                       r = acl_get_perm_np(acl_permset,
     2377+                           acl_nfs4_perm_map[i].p_perm);
     2378+                       if (r == -1) {
     2379+                               archive_set_error(&a->archive, errno,
     2380+                                   "Failed to check permission in an ACL "
     2381+                                   "permission set");
     2382+                               return (ARCHIVE_WARN);
     2383+                       } else if (r)
     2384+                               ae_perm |= acl_nfs4_perm_map[i].a_perm;
     2385+               }
     2386+
     2387+#if !HAVE_DECL_ACL_SYNCHRONIZE
     2388+               /* On Mac OS X without ACL_SYNCHRONIZE assume it is set */
     2389+               ae_perm |= ARCHIVE_ENTRY_ACL_SYNCHRONIZE;
     2390+#endif
     2391+
     2392+               archive_entry_acl_add_entry(entry, entry_acl_type,
     2393+                                           ae_perm, ae_tag,
     2394+                                           ae_id, ae_name);
     2395+
     2396+               s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
     2397+       }
     2398+       return (ARCHIVE_OK);
     2399+}
     2400+
     2401+int
     2402+archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
     2403+    struct archive_entry *entry, int *fd)
     2404+{
     2405+       const char      *accpath;
     2406+       acl_t           acl;
     2407+       int             r;
     2408+
     2409+       accpath = NULL;
     2410+
     2411+       if (*fd < 0) {
     2412+               accpath = archive_read_disk_entry_setup_path(a, entry, fd);
     2413+               if (accpath == NULL)
     2414+                       return (ARCHIVE_WARN);
     2415+       }
     2416+
     2417+       archive_entry_acl_clear(entry);
     2418+
     2419+       acl = NULL;
     2420+
     2421+       if (*fd >= 0)
     2422+               acl = acl_get_fd_np(*fd, ACL_TYPE_EXTENDED);
     2423+       else if (!a->follow_symlinks)
     2424+               acl = acl_get_link_np(accpath, ACL_TYPE_EXTENDED);
     2425+       else
     2426+               acl = acl_get_file(accpath, ACL_TYPE_EXTENDED);
     2427+
     2428+       if (acl != NULL) {
     2429+               r = translate_acl(a, entry, acl);
     2430+               acl_free(acl);
     2431+               acl = NULL;
     2432+
     2433+               if (r != ARCHIVE_OK) {
     2434+                       archive_set_error(&a->archive, errno,
     2435+                           "Couldn't translate NFSv4 ACLs");
     2436+               }
     2437+
     2438+               /*
     2439+                * Because Mac OS doesn't support owner@, group@ and everyone@
     2440+                * ACLs we need to add NFSv4 ACLs mirroring the file mode to
     2441+                * the archive entry. Otherwise extraction on non-Mac platforms
     2442+                * would lead to an invalid file mode.
     2443+                */
     2444+               if ((archive_entry_acl_types(entry) &
     2445+                   ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0)
     2446+                       add_trivial_nfs4_acl(entry);
     2447+
     2448+               return (r);
     2449+       }
     2450+       return (ARCHIVE_OK);
     2451+}
     2452diff --git a/libarchive/archive_read_disk_acl_freebsd.c b/libarchive/archive_read_disk_acl_freebsd.c
     2453new file mode 100644
     2454index 00000000..c09c3e1c
     2455--- /dev/null
     2456+++ b/libarchive/archive_read_disk_acl_freebsd.c
     2457@@ -0,0 +1,371 @@
     2458+/*-
     2459+ * Copyright (c) 2003-2009 Tim Kientzle
     2460+ * Copyright (c) 2010-2012 Michihiro NAKAJIMA
     2461+ * Copyright (c) 2016-2017 Martin Matuska
     2462+ * All rights reserved.
     2463+ *
     2464+ * Redistribution and use in source and binary forms, with or without
     2465+ * modification, are permitted provided that the following conditions
     2466+ * are met:
     2467+ * 1. Redistributions of source code must retain the above copyright
     2468+ *    notice, this list of conditions and the following disclaimer.
     2469+ * 2. Redistributions in binary form must reproduce the above copyright
     2470+ *    notice, this list of conditions and the following disclaimer in the
     2471+ *    documentation and/or other materials provided with the distribution.
     2472+ *
     2473+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
     2474+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     2475+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     2476+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
     2477+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     2478+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     2479+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     2480+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     2481+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     2482+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     2483+ */
     2484+
     2485+#include "archive_platform.h"
     2486+
     2487+#ifdef HAVE_ERRNO_H
     2488+#include <errno.h>
     2489+#endif
     2490+#ifdef HAVE_FCNTL_H
     2491+#include <fcntl.h>
     2492+#endif
     2493+#ifdef HAVE_SYS_TYPES_H
     2494+#include <sys/types.h>
     2495+#endif
     2496+#ifdef HAVE_SYS_ACL_H
     2497+#define _ACL_PRIVATE /* For debugging */
     2498+#include <sys/acl.h>
     2499+#endif
     2500+
     2501+#include "archive_entry.h"
     2502+#include "archive_private.h"
     2503+#include "archive_read_disk_private.h"
     2504+#include "archive_acl_maps.h"
     2505+
     2506+/*
     2507+ * Translate FreeBSD ACLs into libarchive internal structure
     2508+ */
     2509+static int
     2510+translate_acl(struct archive_read_disk *a,
     2511+    struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
     2512+{
     2513+#if ARCHIVE_ACL_FREEBSD_NFS4
     2514+       int brand;
     2515+       acl_flagset_t    acl_flagset;
     2516+#endif
     2517+       acl_tag_t        acl_tag;
     2518+       acl_entry_t      acl_entry;
     2519+       acl_permset_t    acl_permset;
     2520+       acl_entry_type_t acl_type;
     2521+       int              i, entry_acl_type, perm_map_size;
     2522+       const acl_perm_map_t    *perm_map;
     2523+       int              r, s, ae_id, ae_tag, ae_perm;
     2524+       void            *q;
     2525+       const char      *ae_name;
     2526+
     2527+#if ARCHIVE_ACL_FREEBSD_NFS4
     2528+       // FreeBSD "brands" ACLs as POSIX.1e or NFSv4
     2529+       // Make sure the "brand" on this ACL is consistent
     2530+       // with the default_entry_acl_type bits provided.
     2531+       if (acl_get_brand_np(acl, &brand) != 0) {
     2532+               archive_set_error(&a->archive, errno,
     2533+                   "Failed to read ACL brand");
     2534+               return (ARCHIVE_WARN);
     2535+       }
     2536+       switch (brand) {
     2537+       case ACL_BRAND_POSIX:
     2538+               switch (default_entry_acl_type) {
     2539+               case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
     2540+               case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
     2541+                       break;
     2542+               default:
     2543+                       archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
     2544+                           "Invalid ACL entry type for POSIX.1e ACL");
     2545+                       return (ARCHIVE_WARN);
     2546+               }
     2547+               break;
     2548+       case ACL_BRAND_NFS4:
     2549+               if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
     2550+                       archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
     2551+                           "Invalid ACL entry type for NFSv4 ACL");
     2552+                       return (ARCHIVE_WARN);
     2553+               }
     2554+               break;
     2555+       default:
     2556+               archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
     2557+                   "Unknown ACL brand");
     2558+               return (ARCHIVE_WARN);
     2559+       }
     2560+#endif
     2561+
     2562+       s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
     2563+       if (s == -1) {
     2564+               archive_set_error(&a->archive, errno,
     2565+                   "Failed to get first ACL entry");
     2566+               return (ARCHIVE_WARN);
     2567+       }
     2568+
     2569+       while (s == 1) {
     2570+               ae_id = -1;
     2571+               ae_name = NULL;
     2572+               ae_perm = 0;
     2573+
     2574+               if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
     2575+                       archive_set_error(&a->archive, errno,
     2576+                           "Failed to get ACL tag type");
     2577+                       return (ARCHIVE_WARN);
     2578+               }
     2579+               switch (acl_tag) {
     2580+               case ACL_USER:
     2581+                       q = acl_get_qualifier(acl_entry);
     2582+                       if (q != NULL) {
     2583+                               ae_id = (int)*(uid_t *)q;
     2584+                               acl_free(q);
     2585+                               ae_name = archive_read_disk_uname(&a->archive,
     2586+                                   ae_id);
     2587+                       }
     2588+                       ae_tag = ARCHIVE_ENTRY_ACL_USER;
     2589+                       break;
     2590+               case ACL_GROUP:
     2591+                       q = acl_get_qualifier(acl_entry);
     2592+                       if (q != NULL) {
     2593+                               ae_id = (int)*(gid_t *)q;
     2594+                               acl_free(q);
     2595+                               ae_name = archive_read_disk_gname(&a->archive,
     2596+                                   ae_id);
     2597+                       }
     2598+                       ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
     2599+                       break;
     2600+               case ACL_MASK:
     2601+                       ae_tag = ARCHIVE_ENTRY_ACL_MASK;
     2602+                       break;
     2603+               case ACL_USER_OBJ:
     2604+                       ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
     2605+                       break;
     2606+               case ACL_GROUP_OBJ:
     2607+                       ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
     2608+                       break;
     2609+               case ACL_OTHER:
     2610+                       ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
     2611+                       break;
     2612+#if ARCHIVE_ACL_FREEBSD_NFS4
     2613+               case ACL_EVERYONE:
     2614+                       ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
     2615+                       break;
     2616+#endif
     2617+               default:
     2618+                       /* Skip types that libarchive can't support. */
     2619+                       s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
     2620+                       continue;
     2621+               }
     2622+
     2623+               // XXX acl_type maps to allow/deny/audit/YYYY bits
     2624+               entry_acl_type = default_entry_acl_type;
     2625+
     2626+#if ARCHIVE_ACL_FREEBSD_NFS4
     2627+               if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
     2628+                       /*
     2629+                        * acl_get_entry_type_np() fails with non-NFSv4 ACLs
     2630+                        */
     2631+                       if (acl_get_entry_type_np(acl_entry, &acl_type) != 0) {
     2632+                               archive_set_error(&a->archive, errno, "Failed "
     2633+                                   "to get ACL type from a NFSv4 ACL entry");
     2634+                               return (ARCHIVE_WARN);
     2635+                       }
     2636+                       switch (acl_type) {
     2637+                       case ACL_ENTRY_TYPE_ALLOW:
     2638+                               entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
     2639+                               break;
     2640+                       case ACL_ENTRY_TYPE_DENY:
     2641+                               entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
     2642+                               break;
     2643+                       case ACL_ENTRY_TYPE_AUDIT:
     2644+                               entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
     2645+                               break;
     2646+                       case ACL_ENTRY_TYPE_ALARM:
     2647+                               entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
     2648+                               break;
     2649+                       default:
     2650+                               archive_set_error(&a->archive, errno,
     2651+                                   "Invalid NFSv4 ACL entry type");
     2652+                               return (ARCHIVE_WARN);
     2653+                       }
     2654+
     2655+                       /*
     2656+                        * Libarchive stores "flag" (NFSv4 inheritance bits)
     2657+                        * in the ae_perm bitmap.
     2658+                        *
     2659+                        * acl_get_flagset_np() fails with non-NFSv4 ACLs
     2660+                        */
     2661+                       if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
     2662+                               archive_set_error(&a->archive, errno,
     2663+                                   "Failed to get flagset from a NFSv4 "
     2664+                                   "ACL entry");
     2665+                               return (ARCHIVE_WARN);
     2666+                       }
     2667+                       for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
     2668+                               r = acl_get_flag_np(acl_flagset,
     2669+                                   acl_nfs4_flag_map[i].p_perm);
     2670+                               if (r == -1) {
     2671+                                       archive_set_error(&a->archive, errno,
     2672+                                           "Failed to check flag in a NFSv4 "
     2673+                                           "ACL flagset");
     2674+                                       return (ARCHIVE_WARN);
     2675+                               } else if (r)
     2676+                                       ae_perm |= acl_nfs4_flag_map[i].a_perm;
     2677+                       }
     2678+               }
     2679+#endif
     2680+
     2681+               if (acl_get_permset(acl_entry, &acl_permset) != 0) {
     2682+                       archive_set_error(&a->archive, errno,
     2683+                           "Failed to get ACL permission set");
     2684+                       return (ARCHIVE_WARN);
     2685+               }
     2686+
     2687+#if ARCHIVE_ACL_FREEBSD_NFS4
     2688+               if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
     2689+                       perm_map_size = acl_nfs4_perm_map_size;
     2690+                       perm_map = acl_nfs4_perm_map;
     2691+               } else {
     2692+#endif
     2693+                       perm_map_size = acl_posix_perm_map_size;
     2694+                       perm_map = acl_posix_perm_map;
     2695+#if ARCHIVE_ACL_FREEBSD_NFS4
     2696+               }
     2697+#endif
     2698+
     2699+               for (i = 0; i < perm_map_size; ++i) {
     2700+                       r = acl_get_perm_np(acl_permset, perm_map[i].p_perm);
     2701+                       if (r == -1) {
     2702+                               archive_set_error(&a->archive, errno,
     2703+                                   "Failed to check permission in an ACL "
     2704+                                   "permission set");
     2705+                               return (ARCHIVE_WARN);
     2706+                       } else if (r)
     2707+                               ae_perm |= perm_map[i].a_perm;
     2708+               }
     2709+
     2710+               archive_entry_acl_add_entry(entry, entry_acl_type,
     2711+                                           ae_perm, ae_tag,
     2712+                                           ae_id, ae_name);
     2713+
     2714+               s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
     2715+               if (s == -1) {
     2716+                       archive_set_error(&a->archive, errno,
     2717+                           "Failed to get next ACL entry");
     2718+                       return (ARCHIVE_WARN);
     2719+               }
     2720+       }
     2721+       return (ARCHIVE_OK);
     2722+}
     2723+
     2724+int
     2725+archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
     2726+    struct archive_entry *entry, int *fd)
     2727+{
     2728+       const char      *accpath;
     2729+       acl_t           acl;
     2730+       int             r;
     2731+
     2732+       accpath = NULL;
     2733+
     2734+       if (*fd < 0) {
     2735+               accpath = archive_read_disk_entry_setup_path(a, entry, fd);
     2736+               if (accpath == NULL)
     2737+                       return (ARCHIVE_WARN);
     2738+       }
     2739+
     2740+       archive_entry_acl_clear(entry);
     2741+
     2742+       acl = NULL;
     2743+
     2744+#if ARCHIVE_ACL_FREEBSD_NFS4
     2745+       /* Try NFSv4 ACL first. */
     2746+       if (*fd >= 0)
     2747+               acl = acl_get_fd_np(*fd, ACL_TYPE_NFS4);
     2748+       else if (!a->follow_symlinks)
     2749+               acl = acl_get_link_np(accpath, ACL_TYPE_NFS4);
     2750+       else
     2751+               acl = acl_get_file(accpath, ACL_TYPE_NFS4);
     2752+
     2753+       /* Ignore "trivial" ACLs that just mirror the file mode. */
     2754+       if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) {
     2755+               acl_free(acl);
     2756+               acl = NULL;
     2757+               return (ARCHIVE_OK);
     2758+       }
     2759+
     2760+       if (acl != NULL) {
     2761+               r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
     2762+               acl_free(acl);
     2763+               acl = NULL;
     2764+
     2765+               if (r != ARCHIVE_OK) {
     2766+                       archive_set_error(&a->archive, errno,
     2767+                           "Couldn't translate NFSv4 ACLs");
     2768+               }
     2769+
     2770+               return (r);
     2771+       }
     2772+#endif
     2773+
     2774+       /* Retrieve access ACL from file. */
     2775+       if (*fd >= 0)
     2776+               acl = acl_get_fd_np(*fd, ACL_TYPE_ACCESS);
     2777+#if HAVE_ACL_GET_LINK_NP
     2778+       else if (!a->follow_symlinks)
     2779+               acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS);
     2780+#else
     2781+       else if ((!a->follow_symlinks)
     2782+           && (archive_entry_filetype(entry) == AE_IFLNK))
     2783+               /* We can't get the ACL of a symlink, so we assume it can't
     2784+                  have one. */
     2785+               acl = NULL;
     2786+#endif
     2787+       else
     2788+               acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
     2789+
     2790+#if HAVE_ACL_IS_TRIVIAL_NP
     2791+       /* Ignore "trivial" ACLs that just mirror the file mode. */
     2792+       if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) {
     2793+               acl_free(acl);
     2794+               acl = NULL;
     2795+       }
     2796+#endif
     2797+
     2798+       if (acl != NULL) {
     2799+               r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
     2800+               acl_free(acl);
     2801+               acl = NULL;
     2802+
     2803+               if (r != ARCHIVE_OK) {
     2804+                       archive_set_error(&a->archive, errno,
     2805+                           "Couldn't translate access ACLs");
     2806+                       return (r);
     2807+               }
     2808+       }
     2809+
     2810+       /* Only directories can have default ACLs. */
     2811+       if (S_ISDIR(archive_entry_mode(entry))) {
     2812+               if (*fd >= 0)
     2813+                       acl = acl_get_fd_np(*fd, ACL_TYPE_DEFAULT);
     2814+               else
     2815+                       acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
     2816+               if (acl != NULL) {
     2817+                       r = translate_acl(a, entry, acl,
     2818+                           ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
     2819+                       acl_free(acl);
     2820+                       if (r != ARCHIVE_OK) {
     2821+                               archive_set_error(&a->archive, errno,
     2822+                                   "Couldn't translate default ACLs");
     2823+                               return (r);
     2824+                       }
     2825+               }
     2826+       }
     2827+       return (ARCHIVE_OK);
     2828+}
     2829diff --git a/libarchive/archive_read_disk_acl_linux.c b/libarchive/archive_read_disk_acl_linux.c
     2830new file mode 100644
     2831index 00000000..033e68a1
     2832--- /dev/null
     2833+++ b/libarchive/archive_read_disk_acl_linux.c
     2834@@ -0,0 +1,352 @@
     2835+/*-
     2836+ * Copyright (c) 2003-2009 Tim Kientzle
     2837+ * Copyright (c) 2010-2012 Michihiro NAKAJIMA
     2838+ * Copyright (c) 2016-2017 Martin Matuska
     2839+ * All rights reserved.
     2840+ *
     2841+ * Redistribution and use in source and binary forms, with or without
     2842+ * modification, are permitted provided that the following conditions
     2843+ * are met:
     2844+ * 1. Redistributions of source code must retain the above copyright
     2845+ *    notice, this list of conditions and the following disclaimer.
     2846+ * 2. Redistributions in binary form must reproduce the above copyright
     2847+ *    notice, this list of conditions and the following disclaimer in the
     2848+ *    documentation and/or other materials provided with the distribution.
     2849+ *
     2850+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
     2851+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     2852+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     2853+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
     2854+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     2855+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     2856+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     2857+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     2858+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     2859+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     2860+ */
     2861+
     2862+#include "archive_platform.h"
     2863+
     2864+#ifdef HAVE_ERRNO_H
     2865+#include <errno.h>
     2866+#endif
     2867+#ifdef HAVE_FCNTL_H
     2868+#include <fcntl.h>
     2869+#endif
     2870+#if HAVE_ACL_LIBACL_H
     2871+#include <acl/libacl.h>
     2872+#endif
     2873+#ifdef HAVE_SYS_ACL_H
     2874+#include <sys/acl.h>
     2875+#endif
     2876+#if HAVE_SYS_RICHACL_H
     2877+#include <sys/richacl.h>
     2878+#endif
     2879+
     2880+#include "archive_entry.h"
     2881+#include "archive_private.h"
     2882+#include "archive_read_disk_private.h"
     2883+#include "archive_acl_maps.h"
     2884+
     2885+#if HAVE_LIBACL
     2886+#include <acl/libacl.h>
     2887+#endif
     2888+
     2889+#if ARCHIVE_ACL_LIBACL
     2890+/*
     2891+ * Translate POSIX.1e ACLs into libarchive internal structure
     2892+ */
     2893+static int
     2894+translate_acl(struct archive_read_disk *a,
     2895+    struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
     2896+{
     2897+       acl_tag_t        acl_tag;
     2898+       acl_entry_t      acl_entry;
     2899+       acl_permset_t    acl_permset;
     2900+       int              i, entry_acl_type;
     2901+       int              r, s, ae_id, ae_tag, ae_perm;
     2902+       void            *q;
     2903+       const char      *ae_name;
     2904+
     2905+       s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
     2906+       if (s == -1) {
     2907+               archive_set_error(&a->archive, errno,
     2908+                   "Failed to get first ACL entry");
     2909+               return (ARCHIVE_WARN);
     2910+       }
     2911+
     2912+       while (s == 1) {
     2913+               ae_id = -1;
     2914+               ae_name = NULL;
     2915+               ae_perm = 0;
     2916+
     2917+               if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
     2918+                       archive_set_error(&a->archive, errno,
     2919+                           "Failed to get ACL tag type");
     2920+                       return (ARCHIVE_WARN);
     2921+               }
     2922+               switch (acl_tag) {
     2923+               case ACL_USER:
     2924+                       q = acl_get_qualifier(acl_entry);
     2925+                       if (q != NULL) {
     2926+                               ae_id = (int)*(uid_t *)q;
     2927+                               acl_free(q);
     2928+                               ae_name = archive_read_disk_uname(&a->archive,
     2929+                                   ae_id);
     2930+                       }
     2931+                       ae_tag = ARCHIVE_ENTRY_ACL_USER;
     2932+                       break;
     2933+               case ACL_GROUP:
     2934+                       q = acl_get_qualifier(acl_entry);
     2935+                       if (q != NULL) {
     2936+                               ae_id = (int)*(gid_t *)q;
     2937+                               acl_free(q);
     2938+                               ae_name = archive_read_disk_gname(&a->archive,
     2939+                                   ae_id);
     2940+                       }
     2941+                       ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
     2942+                       break;
     2943+               case ACL_MASK:
     2944+                       ae_tag = ARCHIVE_ENTRY_ACL_MASK;
     2945+                       break;
     2946+               case ACL_USER_OBJ:
     2947+                       ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
     2948+                       break;
     2949+               case ACL_GROUP_OBJ:
     2950+                       ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
     2951+                       break;
     2952+               case ACL_OTHER:
     2953+                       ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
     2954+                       break;
     2955+               default:
     2956+                       /* Skip types that libarchive can't support. */
     2957+                       s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
     2958+                       continue;
     2959+               }
     2960+
     2961+               // XXX acl_type maps to allow/deny/audit/YYYY bits
     2962+               entry_acl_type = default_entry_acl_type;
     2963+
     2964+               if (acl_get_permset(acl_entry, &acl_permset) != 0) {
     2965+                       archive_set_error(&a->archive, errno,
     2966+                           "Failed to get ACL permission set");
     2967+                       return (ARCHIVE_WARN);
     2968+               }
     2969+
     2970+               for (i = 0; i < acl_posix_perm_map_size; ++i) {
     2971+                       r = acl_get_perm(acl_permset,
     2972+                           acl_posix_perm_map[i].p_perm);
     2973+                       if (r == -1) {
     2974+                               archive_set_error(&a->archive, errno,
     2975+                                   "Failed to check permission in an ACL "
     2976+                                   "permission set");
     2977+                               return (ARCHIVE_WARN);
     2978+                       } else if (r)
     2979+                               ae_perm |= acl_posix_perm_map[i].a_perm;
     2980+               }
     2981+
     2982+               archive_entry_acl_add_entry(entry, entry_acl_type,
     2983+                                           ae_perm, ae_tag,
     2984+                                           ae_id, ae_name);
     2985+
     2986+               s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
     2987+               if (s == -1) {
     2988+                       archive_set_error(&a->archive, errno,
     2989+                           "Failed to get next ACL entry");
     2990+                       return (ARCHIVE_WARN);
     2991+               }
     2992+       }
     2993+       return (ARCHIVE_OK);
     2994+}
     2995+#endif /* ARCHIVE_ACL_LIBACL */
     2996+
     2997+#if ARCHIVE_ACL_LIBRICHACL
     2998+/*
     2999+ * Translate RichACL into libarchive internal ACL
     3000+ */
     3001+static int
     3002+translate_richacl(struct archive_read_disk *a, struct archive_entry *entry,
     3003+    struct richacl *richacl)
     3004+{
     3005+       int ae_id, ae_tag, ae_perm;
     3006+       int entry_acl_type, i;
     3007+       const char *ae_name;
     3008+
     3009+       struct richace *richace;
     3010+
     3011+       richacl_for_each_entry(richace, richacl) {
     3012+               ae_name = NULL;
     3013+               ae_tag = 0;
     3014+               ae_perm = 0;
     3015+               ae_id = -1;
     3016+
     3017+               switch (richace->e_type) {
     3018+               case RICHACE_ACCESS_ALLOWED_ACE_TYPE:
     3019+                       entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
     3020+                       break;
     3021+               case RICHACE_ACCESS_DENIED_ACE_TYPE:
     3022+                       entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
     3023+                       break;
     3024+               default: /* Unknown entry type, skip */
     3025+                       continue;
     3026+               }
     3027+
     3028+               /* Unsupported */
     3029+               if (richace->e_flags & RICHACE_UNMAPPED_WHO)
     3030+                       continue;
     3031+
     3032+               if (richace->e_flags & RICHACE_SPECIAL_WHO) {
     3033+                       switch (richace->e_id) {
     3034+                       case RICHACE_OWNER_SPECIAL_ID:
     3035+                               ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
     3036+                               break;
     3037+                       case RICHACE_GROUP_SPECIAL_ID:
     3038+                               ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
     3039+                               break;
     3040+                       case RICHACE_EVERYONE_SPECIAL_ID:
     3041+                               ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
     3042+                               break;
     3043+                       default: /* Unknown special ID type */
     3044+                               continue;
     3045+                       }
     3046+               } else {
     3047+                       ae_id = richace->e_id;
     3048+                       if (richace->e_flags & RICHACE_IDENTIFIER_GROUP) {
     3049+                               ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
     3050+                               ae_name = archive_read_disk_gname(&a->archive,
     3051+                                   (gid_t)(richace->e_id));
     3052+                       } else {
     3053+                               ae_tag = ARCHIVE_ENTRY_ACL_USER;
     3054+                               ae_name = archive_read_disk_uname(&a->archive,
     3055+                                   (uid_t)(richace->e_id));
     3056+                       }
     3057+               }
     3058+               for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
     3059+                       if ((richace->e_flags &
     3060+                           acl_nfs4_flag_map[i].p_perm) != 0)
     3061+                               ae_perm |= acl_nfs4_flag_map[i].a_perm;
     3062+               }
     3063+               for (i = 0; i < acl_nfs4_perm_map_size; ++i) {
     3064+                       if ((richace->e_mask &
     3065+                           acl_nfs4_perm_map[i].p_perm) != 0)
     3066+                               ae_perm |=
     3067+                                   acl_nfs4_perm_map[i].a_perm;
     3068+               }
     3069+
     3070+               archive_entry_acl_add_entry(entry, entry_acl_type,
     3071+                   ae_perm, ae_tag, ae_id, ae_name);
     3072+       }
     3073+       return (ARCHIVE_OK);
     3074+}
     3075+#endif /* ARCHIVE_ACL_LIBRICHACL */
     3076+
     3077+int
     3078+archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
     3079+    struct archive_entry *entry, int *fd)
     3080+{
     3081+       const char      *accpath;
     3082+       int             r;
     3083+#if ARCHIVE_ACL_LIBACL
     3084+       acl_t           acl;
     3085+#endif
     3086+#if ARCHIVE_ACL_LIBRICHACL
     3087+       struct richacl *richacl;
     3088+       mode_t          mode;
     3089+#endif
     3090+
     3091+       accpath = NULL;
     3092+       r = ARCHIVE_OK;
     3093+
     3094+       /* For default ACLs we need reachable accpath */
     3095+       if (*fd < 0 || S_ISDIR(archive_entry_mode(entry))) {
     3096+               accpath = archive_read_disk_entry_setup_path(a, entry, fd);
     3097+               if (accpath == NULL)
     3098+                       return (ARCHIVE_WARN);
     3099+       }
     3100+
     3101+       archive_entry_acl_clear(entry);
     3102+
     3103+#if ARCHIVE_ACL_LIBACL
     3104+       acl = NULL;
     3105+#endif
     3106+#if ARCHIVE_ACL_LIBRICHACL
     3107+       richacl = NULL;
     3108+#endif
     3109+
     3110+#if ARCHIVE_ACL_LIBRICHACL
     3111+       /* Try NFSv4 ACL first. */
     3112+       if (*fd >= 0)
     3113+               richacl = richacl_get_fd(*fd);
     3114+       else if ((!a->follow_symlinks)
     3115+           && (archive_entry_filetype(entry) == AE_IFLNK))
     3116+               /* We can't get the ACL of a symlink, so we assume it can't
     3117+                  have one */
     3118+               richacl = NULL;
     3119+       else
     3120+               richacl = richacl_get_file(accpath);
     3121+
     3122+       /* Ignore "trivial" ACLs that just mirror the file mode. */
     3123+       if (richacl != NULL) {
     3124+               mode = archive_entry_mode(entry);
     3125+               if (richacl_equiv_mode(richacl, &mode) == 0) {
     3126+                       richacl_free(richacl);
     3127+                       richacl = NULL;
     3128+                       return (ARCHIVE_OK);
     3129+               }
     3130+       }
     3131+
     3132+       if (richacl != NULL) {
     3133+               r = translate_richacl(a, entry, richacl);
     3134+               richacl_free(richacl);
     3135+               richacl = NULL;
     3136+
     3137+               if (r != ARCHIVE_OK) {
     3138+                       archive_set_error(&a->archive, errno,
     3139+                       "Couldn't translate NFSv4 ACLs");
     3140+               }
     3141+
     3142+               return (r);
     3143+       }
     3144+#endif /* ARCHIVE_ACL_LIBRICHACL */
     3145+
     3146+#if ARCHIVE_ACL_LIBACL
     3147+       /* Retrieve access ACL from file. */
     3148+       if (*fd >= 0)
     3149+               acl = acl_get_fd(*fd);
     3150+       else if ((!a->follow_symlinks)
     3151+           && (archive_entry_filetype(entry) == AE_IFLNK))
     3152+               /* We can't get the ACL of a symlink, so we assume it can't
     3153+                  have one. */
     3154+               acl = NULL;
     3155+       else
     3156+               acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
     3157+
     3158+       if (acl != NULL) {
     3159+               r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
     3160+               acl_free(acl);
     3161+               acl = NULL;
     3162+
     3163+               if (r != ARCHIVE_OK) {
     3164+                       archive_set_error(&a->archive, errno,
     3165+                           "Couldn't translate access ACLs");
     3166+                       return (r);
     3167+               }
     3168+       }
     3169+
     3170+       /* Only directories can have default ACLs. */
     3171+       if (S_ISDIR(archive_entry_mode(entry))) {
     3172+               acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
     3173+               if (acl != NULL) {
     3174+                       r = translate_acl(a, entry, acl,
     3175+                           ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
     3176+                       acl_free(acl);
     3177+                       if (r != ARCHIVE_OK) {
     3178+                               archive_set_error(&a->archive, errno,
     3179+                                   "Couldn't translate default ACLs");
     3180+                               return (r);
     3181+                       }
     3182+               }
     3183+       }
     3184+#endif /* ARCHIVE_ACL_LIBACL */
     3185+       return (r);
     3186+}
     3187diff --git a/libarchive/archive_read_disk_acl_sunos.c b/libarchive/archive_read_disk_acl_sunos.c
     3188new file mode 100644
     3189index 00000000..066c3037
     3190--- /dev/null
     3191+++ b/libarchive/archive_read_disk_acl_sunos.c
     3192@@ -0,0 +1,482 @@
     3193+/*-
     3194+ * Copyright (c) 2017 Martin Matuska
     3195+ * All rights reserved.
     3196+ *
     3197+ * Redistribution and use in source and binary forms, with or without
     3198+ * modification, are permitted provided that the following conditions
     3199+ * are met:
     3200+ * 1. Redistributions of source code must retain the above copyright
     3201+ *    notice, this list of conditions and the following disclaimer.
     3202+ * 2. Redistributions in binary form must reproduce the above copyright
     3203+ *    notice, this list of conditions and the following disclaimer in the
     3204+ *    documentation and/or other materials provided with the distribution.
     3205+ *
     3206+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
     3207+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     3208+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     3209+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
     3210+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     3211+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     3212+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     3213+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     3214+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     3215+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     3216+ */
     3217+
     3218+#include "archive_platform.h"
     3219+
     3220+#ifdef HAVE_ERRNO_H
     3221+#include <errno.h>
     3222+#endif
     3223+#ifdef HAVE_FCNTL_H
     3224+#include <fcntl.h>
     3225+#endif
     3226+#ifdef HAVE_SYS_TYPES_H
     3227+#include <sys/types.h>
     3228+#endif
     3229+#ifdef HAVE_SYS_ACL_H
     3230+#include <sys/acl.h>
     3231+#endif
     3232+
     3233+#include "archive_entry.h"
     3234+#include "archive_private.h"
     3235+#include "archive_read_disk_private.h"
     3236+#include "archive_acl_maps.h"
     3237+
     3238+/*
     3239+ * Solaris-specific ACL functions and helper functions
     3240+ *
     3241+ * Exported functions:
     3242+ * translate_acl()
     3243+ */
     3244+static void *
     3245+sunacl_get(int cmd, int *aclcnt, int fd, const char *path)
     3246+{
     3247+       int cnt, cntcmd;
     3248+       size_t size;
     3249+       void *aclp;
     3250+
     3251+       if (cmd == GETACL) {
     3252+               cntcmd = GETACLCNT;
     3253+               size = sizeof(aclent_t);
     3254+       }
     3255+#if ARCHIVE_ACL_SUNOS_NFS4
     3256+       else if (cmd == ACE_GETACL) {
     3257+               cntcmd = ACE_GETACLCNT;
     3258+               size = sizeof(ace_t);
     3259+       }
     3260+#endif
     3261+       else {
     3262+               errno = EINVAL;
     3263+               *aclcnt = -1;
     3264+               return (NULL);
     3265+       }
     3266+
     3267+       aclp = NULL;
     3268+       cnt = -2;
     3269+
     3270+       while (cnt == -2 || (cnt == -1 && errno == ENOSPC)) {
     3271+               if (path != NULL)
     3272+                       cnt = acl(path, cntcmd, 0, NULL);
     3273+               else
     3274+                       cnt = facl(fd, cntcmd, 0, NULL);
     3275+
     3276+               if (cnt > 0) {
     3277+                       if (aclp == NULL)
     3278+                               aclp = malloc(cnt * size);
     3279+                       else
     3280+                               aclp = realloc(NULL, cnt * size);
     3281+                       if (aclp != NULL) {
     3282+                               if (path != NULL)
     3283+                                       cnt = acl(path, cmd, cnt, aclp);
     3284+                               else
     3285+                                       cnt = facl(fd, cmd, cnt, aclp);
     3286+                       }
     3287+               } else {
     3288+                       if (aclp != NULL) {
     3289+                               free(aclp);
     3290+                               aclp = NULL;
     3291+                       }
     3292+                       break;
     3293+               }
     3294+       }
     3295+
     3296+       *aclcnt = cnt;
     3297+       return (aclp);
     3298+}
     3299+
     3300+/*
     3301+ * Check if acl is trivial
     3302+ * This is a FreeBSD acl_is_trivial_np() implementation for Solaris
     3303+ */
     3304+static int
     3305+sun_acl_is_trivial(void *aclp, int aclcnt, mode_t mode, int is_nfs4,
     3306+    int is_dir, int *trivialp)
     3307+{
     3308+#if ARCHIVE_ACL_SUNOS_NFS4
     3309+       int i, p;
     3310+       const uint32_t rperm = ACE_READ_DATA;
     3311+       const uint32_t wperm = ACE_WRITE_DATA | ACE_APPEND_DATA;
     3312+       const uint32_t eperm = ACE_EXECUTE;
     3313+       const uint32_t pubset = ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS |
     3314+           ACE_READ_ACL | ACE_SYNCHRONIZE;
     3315+       const uint32_t ownset = pubset | ACE_WRITE_ATTRIBUTES |
     3316+           ACE_WRITE_NAMED_ATTRS | ACE_WRITE_ACL | ACE_WRITE_OWNER;
     3317+
     3318+       ace_t *ace;
     3319+       ace_t tace[6];
     3320+#endif
     3321+
     3322+       if (aclp == NULL || trivialp == NULL)
     3323+               return (-1);
     3324+
     3325+       *trivialp = 0;
     3326+
     3327+       /*
     3328+        * POSIX.1e ACLs marked with ACL_IS_TRIVIAL are compatible with
     3329+        * FreeBSD acl_is_trivial_np(). On Solaris they have 4 entries,
     3330+        * including mask.
     3331+        */
     3332+       if (!is_nfs4) {
     3333+               if (aclcnt == 4)
     3334+                       *trivialp = 1;
     3335+               return (0);
     3336+       }
     3337+
     3338+#if ARCHIVE_ACL_SUNOS_NFS4
     3339+       /*
     3340+        * Continue with checking NFSv4 ACLs
     3341+        *
     3342+        * Create list of trivial ace's to be compared
     3343+        */
     3344+
     3345+       /* owner@ allow pre */
     3346+       tace[0].a_flags = ACE_OWNER;
     3347+       tace[0].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
     3348+       tace[0].a_access_mask = 0;
     3349+
     3350+       /* owner@ deny */
     3351+       tace[1].a_flags = ACE_OWNER;
     3352+       tace[1].a_type = ACE_ACCESS_DENIED_ACE_TYPE;
     3353+       tace[1].a_access_mask = 0;
     3354+
     3355+       /* group@ deny */
     3356+       tace[2].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP;
     3357+       tace[2].a_type = ACE_ACCESS_DENIED_ACE_TYPE;
     3358+       tace[2].a_access_mask = 0;
     3359+
     3360+       /* owner@ allow */
     3361+       tace[3].a_flags = ACE_OWNER;
     3362+       tace[3].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
     3363+       tace[3].a_access_mask = ownset;
     3364+
     3365+       /* group@ allow */
     3366+       tace[4].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP;
     3367+       tace[4].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
     3368+       tace[4].a_access_mask = pubset;
     3369+
     3370+       /* everyone@ allow */
     3371+       tace[5].a_flags = ACE_EVERYONE;
     3372+       tace[5].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
     3373+       tace[5].a_access_mask = pubset;
     3374+
     3375+       /* Permissions for everyone@ */
     3376+       if (mode & 0004)
     3377+               tace[5].a_access_mask |= rperm;
     3378+       if (mode & 0002)
     3379+               tace[5].a_access_mask |= wperm;
     3380+       if (mode & 0001)
     3381+               tace[5].a_access_mask |= eperm;
     3382+
     3383+       /* Permissions for group@ */
     3384+       if (mode & 0040)
     3385+               tace[4].a_access_mask |= rperm;
     3386+       else if (mode & 0004)
     3387+               tace[2].a_access_mask |= rperm;
     3388+       if (mode & 0020)
     3389+               tace[4].a_access_mask |= wperm;
     3390+       else if (mode & 0002)
     3391+               tace[2].a_access_mask |= wperm;
     3392+       if (mode & 0010)
     3393+               tace[4].a_access_mask |= eperm;
     3394+       else if (mode & 0001)
     3395+               tace[2].a_access_mask |= eperm;
     3396+
     3397+       /* Permissions for owner@ */
     3398+       if (mode & 0400) {
     3399+               tace[3].a_access_mask |= rperm;
     3400+               if (!(mode & 0040) && (mode & 0004))
     3401+                       tace[0].a_access_mask |= rperm;
     3402+       } else if ((mode & 0040) || (mode & 0004))
     3403+               tace[1].a_access_mask |= rperm;
     3404+       if (mode & 0200) {
     3405+               tace[3].a_access_mask |= wperm;
     3406+               if (!(mode & 0020) && (mode & 0002))
     3407+                       tace[0].a_access_mask |= wperm;
     3408+       } else if ((mode & 0020) || (mode & 0002))
     3409+               tace[1].a_access_mask |= wperm;
     3410+       if (mode & 0100) {
     3411+               tace[3].a_access_mask |= eperm;
     3412+               if (!(mode & 0010) && (mode & 0001))
     3413+                       tace[0].a_access_mask |= eperm;
     3414+       } else if ((mode & 0010) || (mode & 0001))
     3415+               tace[1].a_access_mask |= eperm;
     3416+
     3417+       /* Check if the acl count matches */
     3418+       p = 3;
     3419+       for (i = 0; i < 3; i++) {
     3420+               if (tace[i].a_access_mask != 0)
     3421+                       p++;
     3422+       }
     3423+       if (aclcnt != p)
     3424+               return (0);
     3425+
     3426+       p = 0;
     3427+       for (i = 0; i < 6; i++) {
     3428+               if (tace[i].a_access_mask != 0) {
     3429+                       ace = &((ace_t *)aclp)[p];
     3430+                       /*
     3431+                        * Illumos added ACE_DELETE_CHILD to write perms for
     3432+                        * directories. We have to check against that, too.
     3433+                        */
     3434+                       if (ace->a_flags != tace[i].a_flags ||
     3435+                           ace->a_type != tace[i].a_type ||
     3436+                           (ace->a_access_mask != tace[i].a_access_mask &&
     3437+                           (!is_dir || (tace[i].a_access_mask & wperm) == 0 ||
     3438+                           ace->a_access_mask !=
     3439+                           (tace[i].a_access_mask | ACE_DELETE_CHILD))))
     3440+                               return (0);
     3441+                       p++;
     3442+               }
     3443+       }
     3444+
     3445+       *trivialp = 1;
     3446+#else  /* !ARCHIVE_ACL_SUNOS_NFS4 */
     3447+       (void)is_dir;   /* UNUSED */
     3448+       (void)aclp;     /* UNUSED */
     3449+#endif /* !ARCHIVE_ACL_SUNOS_NFS4 */
     3450+       return (0);
     3451+}
     3452+
     3453+/*
     3454+ * Translate Solaris POSIX.1e and NFSv4 ACLs into libarchive internal ACL
     3455+ */
     3456+static int
     3457+translate_acl(struct archive_read_disk *a,
     3458+    struct archive_entry *entry, void *aclp, int aclcnt,
     3459+    int default_entry_acl_type)
     3460+{
     3461+       int e, i;
     3462+       int ae_id, ae_tag, ae_perm;
     3463+       int entry_acl_type;
     3464+       const char *ae_name;
     3465+       aclent_t *aclent;
     3466+#if ARCHIVE_ACL_SUNOS_NFS4
     3467+       ace_t *ace;
     3468+#endif
     3469+
     3470+       if (aclcnt <= 0)
     3471+               return (ARCHIVE_OK);
     3472+
     3473+       for (e = 0; e < aclcnt; e++) {
     3474+               ae_name = NULL;
     3475+               ae_tag = 0;
     3476+               ae_perm = 0;
     3477+
     3478+#if ARCHIVE_ACL_SUNOS_NFS4
     3479+               if (default_entry_acl_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
     3480+                       ace = &((ace_t *)aclp)[e];
     3481+                       ae_id = ace->a_who;
     3482+
     3483+                       switch(ace->a_type) {
     3484+                       case ACE_ACCESS_ALLOWED_ACE_TYPE:
     3485+                               entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
     3486+                               break;
     3487+                       case ACE_ACCESS_DENIED_ACE_TYPE:
     3488+                               entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
     3489+                               break;
     3490+                       case ACE_SYSTEM_AUDIT_ACE_TYPE:
     3491+                               entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
     3492+                               break;
     3493+                       case ACE_SYSTEM_ALARM_ACE_TYPE:
     3494+                               entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
     3495+                               break;
     3496+                       default:
     3497+                               /* Unknown entry type, skip */
     3498+                               continue;
     3499+                       }
     3500+
     3501+                       if ((ace->a_flags & ACE_OWNER) != 0)
     3502+                               ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
     3503+                       else if ((ace->a_flags & ACE_GROUP) != 0)
     3504+                               ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
     3505+                       else if ((ace->a_flags & ACE_EVERYONE) != 0)
     3506+                               ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
     3507+                       else if ((ace->a_flags & ACE_IDENTIFIER_GROUP) != 0) {
     3508+                               ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
     3509+                               ae_name = archive_read_disk_gname(&a->archive,
     3510+                                   ae_id);
     3511+                       } else {
     3512+                               ae_tag = ARCHIVE_ENTRY_ACL_USER;
     3513+                               ae_name = archive_read_disk_uname(&a->archive,
     3514+                                   ae_id);
     3515+                       }
     3516+
     3517+                       for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
     3518+                               if ((ace->a_flags &
     3519+                                   acl_nfs4_flag_map[i].p_perm) != 0)
     3520+                                       ae_perm |= acl_nfs4_flag_map[i].a_perm;
     3521+                       }
     3522+
     3523+                       for (i = 0; i < acl_nfs4_perm_map_size; ++i) {
     3524+                               if ((ace->a_access_mask &
     3525+                                   acl_nfs4_perm_map[i].p_perm) != 0)
     3526+                                       ae_perm |= acl_nfs4_perm_map[i].a_perm;
     3527+                       }
     3528+               } else
     3529+#endif /* ARCHIVE_ACL_SUNOS_NFS4 */
     3530+               if (default_entry_acl_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {
     3531+                       aclent = &((aclent_t *)aclp)[e];
     3532+                       if ((aclent->a_type & ACL_DEFAULT) != 0)
     3533+                               entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
     3534+                       else
     3535+                               entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
     3536+                       ae_id = aclent->a_id;
     3537+
     3538+                       switch(aclent->a_type) {
     3539+                       case DEF_USER:
     3540+                       case USER:
     3541+                               ae_name = archive_read_disk_uname(&a->archive,
     3542+                                   ae_id);
     3543+                               ae_tag = ARCHIVE_ENTRY_ACL_USER;
     3544+                               break;
     3545+                       case DEF_GROUP:
     3546+                       case GROUP:
     3547+                               ae_name = archive_read_disk_gname(&a->archive,
     3548+                                   ae_id);
     3549+                               ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
     3550+                               break;
     3551+                       case DEF_CLASS_OBJ:
     3552+                       case CLASS_OBJ:
     3553+                               ae_tag = ARCHIVE_ENTRY_ACL_MASK;
     3554+                               break;
     3555+                       case DEF_USER_OBJ:
     3556+                       case USER_OBJ:
     3557+                               ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
     3558+                               break;
     3559+                       case DEF_GROUP_OBJ:
     3560+                       case GROUP_OBJ:
     3561+                               ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
     3562+                               break;
     3563+                       case DEF_OTHER_OBJ:
     3564+                       case OTHER_OBJ:
     3565+                               ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
     3566+                               break;
     3567+                       default:
     3568+                               /* Unknown tag type, skip */
     3569+                               continue;
     3570+                       }
     3571+
     3572+                       for (i = 0; i < acl_posix_perm_map_size; ++i) {
     3573+                               if ((aclent->a_perm &
     3574+                                   acl_posix_perm_map[i].p_perm) != 0)
     3575+                                       ae_perm |= acl_posix_perm_map[i].a_perm;
     3576+                       }
     3577+               } else
     3578+                       return (ARCHIVE_WARN);
     3579+
     3580+               archive_entry_acl_add_entry(entry, entry_acl_type,
     3581+                   ae_perm, ae_tag, ae_id, ae_name);
     3582+       }
     3583+       return (ARCHIVE_OK);
     3584+}
     3585+
     3586+int
     3587+archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
     3588+    struct archive_entry *entry, int *fd)
     3589+{
     3590+       const char      *accpath;
     3591+       void            *aclp;
     3592+       int             aclcnt;
     3593+       int             r;
     3594+
     3595+       accpath = NULL;
     3596+
     3597+       if (*fd < 0) {
     3598+               accpath = archive_read_disk_entry_setup_path(a, entry, fd);
     3599+               if (accpath == NULL)
     3600+                       return (ARCHIVE_WARN);
     3601+       }
     3602+
     3603+       archive_entry_acl_clear(entry);
     3604+
     3605+       aclp = NULL;
     3606+
     3607+#if ARCHIVE_ACL_SUNOS_NFS4
     3608+       if (*fd >= 0)
     3609+               aclp = sunacl_get(ACE_GETACL, &aclcnt, *fd, NULL);
     3610+       else if ((!a->follow_symlinks)
     3611+           && (archive_entry_filetype(entry) == AE_IFLNK))
     3612+               /* We can't get the ACL of a symlink, so we assume it can't
     3613+                  have one. */
     3614+               aclp = NULL;
     3615+       else
     3616+               aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, accpath);
     3617+
     3618+       if (aclp != NULL && sun_acl_is_trivial(aclp, aclcnt,
     3619+           archive_entry_mode(entry), 1, S_ISDIR(archive_entry_mode(entry)),
     3620+           &r) == 0 && r == 1) {
     3621+               free(aclp);
     3622+               aclp = NULL;
     3623+               return (ARCHIVE_OK);
     3624+       }
     3625+
     3626+       if (aclp != NULL) {
     3627+               r = translate_acl(a, entry, aclp, aclcnt,
     3628+                   ARCHIVE_ENTRY_ACL_TYPE_NFS4);
     3629+               free(aclp);
     3630+               aclp = NULL;
     3631+
     3632+               if (r != ARCHIVE_OK) {
     3633+                       archive_set_error(&a->archive, errno,
     3634+                           "Couldn't translate NFSv4 ACLs");
     3635+               }
     3636+               return (r);
     3637+       }
     3638+#endif /* ARCHIVE_ACL_SUNOS_NFS4 */
     3639+
     3640+       /* Retrieve POSIX.1e ACLs from file. */
     3641+       if (*fd >= 0)
     3642+               aclp = sunacl_get(GETACL, &aclcnt, *fd, NULL);
     3643+       else if ((!a->follow_symlinks)
     3644+           && (archive_entry_filetype(entry) == AE_IFLNK))
     3645+               /* We can't get the ACL of a symlink, so we assume it can't
     3646+                  have one. */
     3647+               aclp = NULL;
     3648+       else
     3649+               aclp = sunacl_get(GETACL, &aclcnt, 0, accpath);
     3650+
     3651+       /* Ignore "trivial" ACLs that just mirror the file mode. */
     3652+       if (aclp != NULL && sun_acl_is_trivial(aclp, aclcnt,
     3653+           archive_entry_mode(entry), 0, S_ISDIR(archive_entry_mode(entry)),
     3654+           &r) == 0 && r == 1) {
     3655+               free(aclp);
     3656+               aclp = NULL;
     3657+       }
     3658+
     3659+       if (aclp != NULL)
     3660+       {
     3661+               r = translate_acl(a, entry, aclp, aclcnt,
     3662+                   ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
     3663+               free(aclp);
     3664+               aclp = NULL;
     3665+
     3666+               if (r != ARCHIVE_OK) {
     3667+                       archive_set_error(&a->archive, errno,
     3668+                           "Couldn't translate access ACLs");
     3669+                       return (r);
     3670+               }
     3671+       }
     3672+
     3673+       return (ARCHIVE_OK);
     3674+}
     3675diff --git a/libarchive/archive_read_disk_entry_from_file.c b/libarchive/archive_read_disk_entry_from_file.c
     3676index b2f1d17d..154dd0f6 100644
     3677--- a/libarchive/archive_read_disk_entry_from_file.c
     3678+++ b/libarchive/archive_read_disk_entry_from_file.c
     3679@@ -26,23 +26,14 @@
     3680  */
     3681 
     3682 #include "archive_platform.h"
     3683-__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 201084 2009-12-28 02:14:09Z kientzle $");
     3684+__FBSDID("$FreeBSD");
     3685 
     3686 /* This is the tree-walking code for POSIX systems. */
     3687 #if !defined(_WIN32) || defined(__CYGWIN__)
     3688 
     3689 #ifdef HAVE_SYS_TYPES_H
     3690-/* Mac OSX requires sys/types.h before sys/acl.h. */
     3691 #include <sys/types.h>
     3692 #endif
     3693-#ifdef HAVE_SYS_ACL_H
     3694-#include <sys/acl.h>
     3695-#endif
     3696-#ifdef HAVE_DARWIN_ACL
     3697-#include <membership.h>
     3698-#include <grp.h>
     3699-#include <pwd.h>
     3700-#endif
     3701 #ifdef HAVE_SYS_EXTATTR_H
     3702 #include <sys/extattr.h>
     3703 #endif
     3704@@ -63,9 +54,6 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010
     3705 #ifdef HAVE_SYS_EA_H
     3706 #include <sys/ea.h>
     3707 #endif
     3708-#ifdef HAVE_ACL_LIBACL_H
     3709-#include <acl/libacl.h>
     3710-#endif
     3711 #ifdef HAVE_COPYFILE_H
     3712 #include <copyfile.h>
     3713 #endif
     3714@@ -113,27 +101,6 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010
     3715 #define O_CLOEXEC      0
     3716 #endif
     3717 
     3718-/*
     3719- * Linux and FreeBSD plug this obvious hole in POSIX.1e in
     3720- * different ways.
     3721- */
     3722-#if HAVE_ACL_GET_PERM
     3723-#define        ACL_GET_PERM acl_get_perm
     3724-#elif HAVE_ACL_GET_PERM_NP
     3725-#define        ACL_GET_PERM acl_get_perm_np
     3726-#endif
     3727-
     3728-/* NFSv4 platform ACL type */
     3729-#if HAVE_SUN_ACL
     3730-#define        ARCHIVE_PLATFORM_ACL_TYPE_NFS4  ACE_T
     3731-#elif HAVE_DARWIN_ACL
     3732-#define        ARCHIVE_PLATFORM_ACL_TYPE_NFS4  ACL_TYPE_EXTENDED
     3733-#elif HAVE_ACL_TYPE_NFS4
     3734-#define        ARCHIVE_PLATFORM_ACL_TYPE_NFS4  ACL_TYPE_NFS4
     3735-#endif
     3736-
     3737-static int setup_acls(struct archive_read_disk *,
     3738-    struct archive_entry *, int *fd);
     3739 static int setup_mac_metadata(struct archive_read_disk *,
     3740     struct archive_entry *, int *fd);
     3741 static int setup_xattrs(struct archive_read_disk *,
     3742@@ -145,6 +112,45 @@ static int setup_sparse_fiemap(struct archive_read_disk *,
     3743     struct archive_entry *, int *fd);
     3744 #endif
     3745 
     3746+#if !ARCHIVE_ACL_SUPPORT
     3747+int
     3748+archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
     3749+    struct archive_entry *entry, int *fd)
     3750+{
     3751+       (void)a;      /* UNUSED */
     3752+       (void)entry;  /* UNUSED */
     3753+       (void)fd;     /* UNUSED */
     3754+       return (ARCHIVE_OK);
     3755+}
     3756+#endif
     3757+
     3758+/*
     3759+ * Enter working directory and return working pathname of archive_entry.
     3760+ * If a pointer to an integer is provided and its value is below zero
     3761+ * open a file descriptor on this pahtname.
     3762+ */
     3763+const char *
     3764+archive_read_disk_entry_setup_path(struct archive_read_disk *a,
     3765+    struct archive_entry *entry, int *fd)
     3766+{
     3767+       const char *path;
     3768+
     3769+       path = archive_entry_sourcepath(entry);
     3770+
     3771+       if (path == NULL || (a->tree != NULL &&
     3772+           a->tree_enter_working_dir(a->tree) != 0))
     3773+               path = archive_entry_pathname(entry);
     3774+       if (path == NULL) {
     3775+               archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
     3776+                  "Couldn't determine path");
     3777+       } else if (fd != NULL && *fd < 0 && a->tree != NULL &&
     3778+           (a->follow_symlinks || archive_entry_filetype(entry) != AE_IFLNK)) {
     3779+               *fd = a->open_on_current_dir(a->tree, path,
     3780+                   O_RDONLY | O_NONBLOCK);
     3781+       }
     3782+       return (path);
     3783+}
     3784+
     3785 int
     3786 archive_read_disk_entry_from_file(struct archive *_a,
     3787     struct archive_entry *entry,
     3788@@ -279,7 +285,7 @@ archive_read_disk_entry_from_file(struct archive *_a,
     3789 
     3790        r = 0;
     3791        if ((a->flags & ARCHIVE_READDISK_NO_ACL) == 0)
     3792-               r = setup_acls(a, entry, &fd);
     3793+               r = archive_read_disk_entry_setup_acls(a, entry, &fd);
     3794        if ((a->flags & ARCHIVE_READDISK_NO_XATTR) == 0) {
     3795                r1 = setup_xattrs(a, entry, &fd);
     3796                if (r1 < r)
     3797@@ -328,19 +334,10 @@ setup_mac_metadata(struct archive_read_disk *a,
     3798        struct archive_string tempfile;
     3799 
     3800        (void)fd; /* UNUSED */
     3801-       name = archive_entry_sourcepath(entry);
     3802+
     3803+       name = archive_read_disk_entry_setup_path(a, entry, NULL);
     3804        if (name == NULL)
     3805-               name = archive_entry_pathname(entry);
     3806-       else if (a->tree != NULL && a->tree_enter_working_dir(a->tree) != 0) {
     3807-               archive_set_error(&a->archive, errno,
     3808-                           "Can't change dir to read extended attributes");
     3809-                       return (ARCHIVE_FAILED);
     3810-       }
     3811-       if (name == NULL) {
     3812-               archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
     3813-                   "Can't open file to read extended attributes: No name");
     3814                return (ARCHIVE_WARN);
     3815-       }
     3816 
     3817        /* Short-circuit if there's nothing to do. */
     3818        have_attrs = copyfile(name, NULL, 0, copyfile_flags | COPYFILE_CHECK);
     3819@@ -426,990 +423,6 @@ setup_mac_metadata(struct archive_read_disk *a,
     3820 }
     3821 #endif
     3822 
     3823-#if HAVE_DARWIN_ACL
     3824-static int translate_guid(struct archive *, acl_entry_t,
     3825-    int *, int *, const char **);
     3826-
     3827-static void add_trivial_nfs4_acl(struct archive_entry *);
     3828-#endif
     3829-
     3830-#if HAVE_SUN_ACL
     3831-static int
     3832-sun_acl_is_trivial(acl_t *, mode_t, int *trivialp);
     3833-#endif
     3834-
     3835-#if HAVE_POSIX_ACL || HAVE_NFS4_ACL
     3836-static int translate_acl(struct archive_read_disk *a,
     3837-    struct archive_entry *entry,
     3838-#if HAVE_SUN_ACL
     3839-    acl_t *acl,
     3840-#else
     3841-    acl_t acl,
     3842-#endif
     3843-    int archive_entry_acl_type);
     3844-
     3845-static int
     3846-setup_acls(struct archive_read_disk *a,
     3847-    struct archive_entry *entry, int *fd)
     3848-{
     3849-       const char      *accpath;
     3850-#if HAVE_SUN_ACL
     3851-       acl_t           *acl;
     3852-#else
     3853-       acl_t           acl;
     3854-#endif
     3855-       int             r;
     3856-
     3857-       accpath = NULL;
     3858-
     3859-#if HAVE_SUN_ACL || HAVE_DARWIN_ACL || HAVE_ACL_GET_FD_NP
     3860-       if (*fd < 0)
     3861-#else
     3862-       /* For default ACLs on Linux we need reachable accpath */
     3863-       if (*fd < 0 || S_ISDIR(archive_entry_mode(entry)))
     3864-#endif
     3865-       {
     3866-               accpath = archive_entry_sourcepath(entry);
     3867-               if (accpath == NULL || (a->tree != NULL &&
     3868-                   a->tree_enter_working_dir(a->tree) != 0))
     3869-                       accpath = archive_entry_pathname(entry);
     3870-               if (accpath == NULL) {
     3871-                       archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
     3872-                           "Couldn't determine file path to read ACLs");
     3873-                       return (ARCHIVE_WARN);
     3874-               }
     3875-               if (a->tree != NULL &&
     3876-#if !HAVE_SUN_ACL && !HAVE_DARWIN_ACL && !HAVE_ACL_GET_FD_NP
     3877-                   *fd < 0 &&
     3878-#endif
     3879-                   (a->follow_symlinks ||
     3880-                   archive_entry_filetype(entry) != AE_IFLNK)) {
     3881-                       *fd = a->open_on_current_dir(a->tree,
     3882-                           accpath, O_RDONLY | O_NONBLOCK);
     3883-               }
     3884-       }
     3885-
     3886-       archive_entry_acl_clear(entry);
     3887-
     3888-       acl = NULL;
     3889-
     3890-#if HAVE_NFS4_ACL
     3891-       /* Try NFSv4 ACL first. */
     3892-       if (*fd >= 0)
     3893-#if HAVE_SUN_ACL
     3894-               /* Solaris reads both POSIX.1e and NFSv4 ACL here */
     3895-               facl_get(*fd, 0, &acl);
     3896-#elif HAVE_ACL_GET_FD_NP
     3897-               acl = acl_get_fd_np(*fd, ARCHIVE_PLATFORM_ACL_TYPE_NFS4);
     3898-#else
     3899-               acl = acl_get_fd(*fd);
     3900-#endif
     3901-#if HAVE_ACL_GET_LINK_NP
     3902-       else if (!a->follow_symlinks)
     3903-               acl = acl_get_link_np(accpath, ARCHIVE_PLATFORM_ACL_TYPE_NFS4);
     3904-#else
     3905-       else if ((!a->follow_symlinks)
     3906-           && (archive_entry_filetype(entry) == AE_IFLNK))
     3907-               /* We can't get the ACL of a symlink, so we assume it can't
     3908-                  have one. */
     3909-               acl = NULL;
     3910-#endif
     3911-       else
     3912-#if HAVE_SUN_ACL
     3913-               /* Solaris reads both POSIX.1e and NFSv4 ACLs here */
     3914-               acl_get(accpath, 0, &acl);
     3915-#else
     3916-               acl = acl_get_file(accpath, ARCHIVE_PLATFORM_ACL_TYPE_NFS4);
     3917-#endif
     3918-
     3919-
     3920-#if HAVE_ACL_IS_TRIVIAL_NP || HAVE_SUN_ACL
     3921-       /* Ignore "trivial" ACLs that just mirror the file mode. */
     3922-       if (acl != NULL) {
     3923-#if HAVE_SUN_ACL
     3924-               if (sun_acl_is_trivial(acl, archive_entry_mode(entry),
     3925-                   &r) == 0 && r == 1)
     3926-#elif HAVE_ACL_IS_TRIVIAL_NP
     3927-               if (acl_is_trivial_np(acl, &r) == 0 && r == 1)
     3928-#endif
     3929-               {
     3930-                       acl_free(acl);
     3931-                       acl = NULL;
     3932-                       /*
     3933-                        * Simultaneous NFSv4 and POSIX.1e ACLs for the same
     3934-                        * entry are not allowed, so we should return here
     3935-                        */
     3936-                       return (ARCHIVE_OK);
     3937-               }
     3938-       }
     3939-#endif /* HAVE_ACL_IS_TRIVIAL_NP || HAVE_SUN_ACL */
     3940-       if (acl != NULL) {
     3941-               r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
     3942-               acl_free(acl);
     3943-               if (r != ARCHIVE_OK) {
     3944-                       archive_set_error(&a->archive, errno,
     3945-                           "Couldn't translate "
     3946-#if !HAVE_SUN_ACL
     3947-                           "NFSv4 "
     3948-#endif
     3949-                           "ACLs");
     3950-               }
     3951-#if HAVE_DARWIN_ACL
     3952-               /*
     3953-                * Because Mac OS doesn't support owner@, group@ and everyone@
     3954-                * ACLs we need to add NFSv4 ACLs mirroring the file mode to
     3955-                * the archive entry. Otherwise extraction on non-Mac platforms
     3956-                * would lead to an invalid file mode.
     3957-                */
     3958-               if ((archive_entry_acl_types(entry) &
     3959-                   ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0)
     3960-                       add_trivial_nfs4_acl(entry);
     3961-#endif
     3962-               return (r);
     3963-       }
     3964-#endif /* HAVE_NFS4_ACL */
     3965-
     3966-#if HAVE_POSIX_ACL
     3967-       /* This code path is skipped on MacOS and Solaris */
     3968-
     3969-       /* Retrieve access ACL from file. */
     3970-       if (*fd >= 0)
     3971-               acl = acl_get_fd(*fd);
     3972-#if HAVE_ACL_GET_LINK_NP
     3973-       else if (!a->follow_symlinks)
     3974-               acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS);
     3975-#else
     3976-       else if ((!a->follow_symlinks)
     3977-           && (archive_entry_filetype(entry) == AE_IFLNK))
     3978-               /* We can't get the ACL of a symlink, so we assume it can't
     3979-                  have one. */
     3980-               acl = NULL;
     3981-#endif
     3982-       else
     3983-               acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
     3984-
     3985-#if HAVE_ACL_IS_TRIVIAL_NP
     3986-       /* Ignore "trivial" ACLs that just mirror the file mode. */
     3987-       if (acl != NULL && acl_is_trivial_np(acl, &r) == 0) {
     3988-               if (r) {
     3989-                       acl_free(acl);
     3990-                       acl = NULL;
     3991-               }
     3992-       }
     3993-#endif
     3994-
     3995-       if (acl != NULL) {
     3996-               r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
     3997-               acl_free(acl);
     3998-               acl = NULL;
     3999-               if (r != ARCHIVE_OK) {
     4000-                       archive_set_error(&a->archive, errno,
     4001-                           "Couldn't translate access ACLs");
     4002-                       return (r);
     4003-               }
     4004-       }
     4005-
     4006-       /* Only directories can have default ACLs. */
     4007-       if (S_ISDIR(archive_entry_mode(entry))) {
     4008-#if HAVE_ACL_GET_FD_NP
     4009-               if (*fd >= 0)
     4010-                       acl = acl_get_fd_np(*fd, ACL_TYPE_DEFAULT);
     4011-               else
     4012-#endif
     4013-               acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
     4014-               if (acl != NULL) {
     4015-                       r = translate_acl(a, entry, acl,
     4016-                           ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
     4017-                       acl_free(acl);
     4018-                       if (r != ARCHIVE_OK) {
     4019-                               archive_set_error(&a->archive, errno,
     4020-                                   "Couldn't translate default ACLs");
     4021-                               return (r);
     4022-                       }
     4023-               }
     4024-       }
     4025-#endif /* HAVE_POSIX_ACL */
     4026-       return (ARCHIVE_OK);
     4027-}
     4028-
     4029-/*
     4030- * Translate system ACL permissions into libarchive internal structure
     4031- */
     4032-static const struct {
     4033-       const int archive_perm;
     4034-       const int platform_perm;
     4035-} acl_perm_map[] = {
     4036-#if HAVE_SUN_ACL       /* Solaris NFSv4 ACL permissions */
     4037-       {ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE},
     4038-       {ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA},
     4039-       {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY},
     4040-       {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA},
     4041-       {ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE},
     4042-       {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA},
     4043-       {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY},
     4044-       {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS},
     4045-       {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS},
     4046-       {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD},
     4047-       {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES},
     4048-       {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES},
     4049-       {ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE},
     4050-       {ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL},
     4051-       {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL},
     4052-       {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER},
     4053-       {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE}
     4054-#elif HAVE_DARWIN_ACL  /* MacOS ACL permissions */
     4055-       {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
     4056-       {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
     4057-       {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
     4058-       {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
     4059-       {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
     4060-       {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
     4061-       {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
     4062-       {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
     4063-       {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
     4064-       {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
     4065-       {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
     4066-       {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES},
     4067-       {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES},
     4068-       {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY},
     4069-       {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY},
     4070-       {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER},
     4071-       {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
     4072-#else  /* POSIX.1e ACL permissions */
     4073-       {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
     4074-       {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
     4075-       {ARCHIVE_ENTRY_ACL_READ, ACL_READ},
     4076-#if HAVE_ACL_TYPE_NFS4 /* FreeBSD NFSv4 ACL permissions */
     4077-       {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
     4078-       {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
     4079-       {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
     4080-       {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
     4081-       {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
     4082-       {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
     4083-       {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
     4084-       {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
     4085-       {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
     4086-       {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
     4087-       {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
     4088-       {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
     4089-       {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
     4090-       {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
     4091-       {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
     4092-       {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
     4093-#endif
     4094-#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
     4095-};
     4096-
     4097-#if HAVE_NFS4_ACL
     4098-/*
     4099- * Translate system NFSv4 inheritance flags into libarchive internal structure
     4100- */
     4101-static const struct {
     4102-       const int archive_inherit;
     4103-       const int platform_inherit;
     4104-} acl_inherit_map[] = {
     4105-#if HAVE_SUN_ACL       /* Solaris ACL inheritance flags */
     4106-       {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE},
     4107-       {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE},
     4108-       {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE},
     4109-       {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE},
     4110-       {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
     4111-       {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG},
     4112-       {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}
     4113-#elif HAVE_DARWIN_ACL  /* MacOS NFSv4 inheritance flags */
     4114-       {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED},
     4115-       {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
     4116-       {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
     4117-       {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_LIMIT_INHERIT},
     4118-       {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT}
     4119-#else  /* FreeBSD NFSv4 ACL inheritance flags */
     4120-       {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
     4121-       {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
     4122-       {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
     4123-       {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY},
     4124-       {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
     4125-       {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
     4126-       {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}
     4127-#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
     4128-};
     4129-#endif /* HAVE_NFS4_ACL */
     4130-
     4131-#if HAVE_DARWIN_ACL
     4132-static int translate_guid(struct archive *a, acl_entry_t acl_entry,
     4133-    int *ae_id, int *ae_tag, const char **ae_name)
     4134-{
     4135-       void *q;
     4136-       uid_t ugid;
     4137-       int r, idtype;
     4138-       struct passwd *pwd;
     4139-       struct group *grp;
     4140-
     4141-       q = acl_get_qualifier(acl_entry);
     4142-       if (q == NULL)
     4143-               return (1);
     4144-       r = mbr_uuid_to_id((const unsigned char *)q, &ugid, &idtype);
     4145-       if (r != 0) {
     4146-               acl_free(q);
     4147-               return (1);
     4148-       }
     4149-       if (idtype == ID_TYPE_UID) {
     4150-               *ae_tag = ARCHIVE_ENTRY_ACL_USER;
     4151-               pwd = getpwuuid(q);
     4152-               if (pwd == NULL) {
     4153-                       *ae_id = ugid;
     4154-                       *ae_name = NULL;
     4155-               } else {
     4156-                       *ae_id = pwd->pw_uid;
     4157-                       *ae_name = archive_read_disk_uname(a, *ae_id);
     4158-               }
     4159-       } else if (idtype == ID_TYPE_GID) {
     4160-               *ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
     4161-               grp = getgruuid(q);
     4162-               if (grp == NULL) {
     4163-                       *ae_id = ugid;
     4164-                       *ae_name = NULL;
     4165-               } else {
     4166-                       *ae_id = grp->gr_gid;
     4167-                       *ae_name = archive_read_disk_gname(a, *ae_id);
     4168-               }
     4169-       } else
     4170-               r = 1;
     4171-
     4172-       acl_free(q);
     4173-       return (r);
     4174-}
     4175-
     4176-/*
     4177- * Add trivial NFSv4 ACL entries from mode
     4178- */
     4179-static void
     4180-add_trivial_nfs4_acl(struct archive_entry *entry)
     4181-{
     4182-       mode_t mode;
     4183-       int i;
     4184-       const int rperm = ARCHIVE_ENTRY_ACL_READ_DATA;
     4185-       const int wperm = ARCHIVE_ENTRY_ACL_WRITE_DATA |
     4186-           ARCHIVE_ENTRY_ACL_APPEND_DATA;
     4187-       const int eperm = ARCHIVE_ENTRY_ACL_EXECUTE;
     4188-       const int pubset = ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
     4189-           ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
     4190-           ARCHIVE_ENTRY_ACL_READ_ACL |
     4191-           ARCHIVE_ENTRY_ACL_SYNCHRONIZE;
     4192-       const int ownset = pubset | ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
     4193-           ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
     4194-           ARCHIVE_ENTRY_ACL_WRITE_ACL |
     4195-           ARCHIVE_ENTRY_ACL_WRITE_OWNER;
     4196-
     4197-       struct {
     4198-           const int type;
     4199-           const int tag;
     4200-           int permset;
     4201-       } tacl_entry[] = {
     4202-           {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, 0},
     4203-           {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_USER_OBJ, 0},
     4204-           {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0},
     4205-           {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, ownset},
     4206-           {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_GROUP_OBJ, pubset},
     4207-           {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EVERYONE, pubset}
     4208-       };
     4209-
     4210-       mode = archive_entry_mode(entry);
     4211-
     4212-       /* Permissions for everyone@ */
     4213-       if (mode & 0004)
     4214-               tacl_entry[5].permset |= rperm;
     4215-       if (mode & 0002)
     4216-               tacl_entry[5].permset |= wperm;
     4217-       if (mode & 0001)
     4218-               tacl_entry[5].permset |= eperm;
     4219-
     4220-       /* Permissions for group@ */
     4221-       if (mode & 0040)
     4222-               tacl_entry[4].permset |= rperm;
     4223-       else if (mode & 0004)
     4224-               tacl_entry[2].permset |= rperm;
     4225-       if (mode & 0020)
     4226-               tacl_entry[4].permset |= wperm;
     4227-       else if (mode & 0002)
     4228-               tacl_entry[2].permset |= wperm;
     4229-       if (mode & 0010)
     4230-               tacl_entry[4].permset |= eperm;
     4231-       else if (mode & 0001)
     4232-               tacl_entry[2].permset |= eperm;
     4233-
     4234-       /* Permissions for owner@ */
     4235-       if (mode & 0400) {
     4236-               tacl_entry[3].permset |= rperm;
     4237-               if (!(mode & 0040) && (mode & 0004))
     4238-                       tacl_entry[0].permset |= rperm;
     4239-       } else if ((mode & 0040) || (mode & 0004))
     4240-               tacl_entry[1].permset |= rperm;
     4241-       if (mode & 0200) {
     4242-               tacl_entry[3].permset |= wperm;
     4243-               if (!(mode & 0020) && (mode & 0002))
     4244-                       tacl_entry[0].permset |= wperm;
     4245-       } else if ((mode & 0020) || (mode & 0002))
     4246-               tacl_entry[1].permset |= wperm;
     4247-       if (mode & 0100) {
     4248-               tacl_entry[3].permset |= eperm;
     4249-               if (!(mode & 0010) && (mode & 0001))
     4250-                       tacl_entry[0].permset |= eperm;
     4251-       } else if ((mode & 0010) || (mode & 0001))
     4252-               tacl_entry[1].permset |= eperm;
     4253-
     4254-       for (i = 0; i < 6; i++) {
     4255-               if (tacl_entry[i].permset != 0) {
     4256-                       archive_entry_acl_add_entry(entry,
     4257-                           tacl_entry[i].type, tacl_entry[i].permset,
     4258-                           tacl_entry[i].tag, -1, NULL);
     4259-               }
     4260-       }
     4261-
     4262-       return;
     4263-}
     4264-#elif HAVE_SUN_ACL
     4265-/*
     4266- * Check if acl is trivial
     4267- * This is a FreeBSD acl_is_trivial_np() implementation for Solaris
     4268- */
     4269-static int
     4270-sun_acl_is_trivial(acl_t *acl, mode_t mode, int *trivialp)
     4271-{
     4272-       int i, p;
     4273-       const uint32_t rperm = ACE_READ_DATA;
     4274-       const uint32_t wperm = ACE_WRITE_DATA | ACE_APPEND_DATA;
     4275-       const uint32_t eperm = ACE_EXECUTE;
     4276-       const uint32_t pubset = ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS |
     4277-           ACE_READ_ACL | ACE_SYNCHRONIZE;
     4278-       const uint32_t ownset = pubset | ACE_WRITE_ATTRIBUTES |
     4279-           ACE_WRITE_NAMED_ATTRS | ACE_WRITE_ACL | ACE_WRITE_OWNER;
     4280-
     4281-       ace_t *ace;
     4282-       ace_t tace[6];
     4283-
     4284-       if (acl == NULL || trivialp == NULL)
     4285-               return (-1);
     4286-
     4287-       *trivialp = 0;
     4288-
     4289-       /* ACL_IS_TRIVIAL flag must be set for both POSIX.1e and NFSv4 ACLs */
     4290-       if ((acl->acl_flags & ACL_IS_TRIVIAL) == 0)
     4291-               return (0);
     4292-
     4293-       /*
     4294-        * POSIX.1e ACLs marked with ACL_IS_TRIVIAL are compatible with
     4295-        * FreeBSD acl_is_trivial_np(). On Solaris they have 4 entries,
     4296-        * including mask.
     4297-        */
     4298-       if (acl->acl_type == ACLENT_T) {
     4299-               if (acl->acl_cnt == 4)
     4300-                       *trivialp = 1;
     4301-               return (0);
     4302-       }
     4303-
     4304-       if (acl->acl_type != ACE_T || acl->acl_entry_size != sizeof(ace_t))
     4305-               return (-1);
     4306-
     4307-       /*
     4308-        * Continue with checking NFSv4 ACLs
     4309-        *
     4310-        * Create list of trivial ace's to be compared
     4311-        */
     4312-
     4313-       /* owner@ allow pre */
     4314-       tace[0].a_flags = ACE_OWNER;
     4315-       tace[0].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
     4316-       tace[0].a_access_mask = 0;
     4317-
     4318-       /* owner@ deny */
     4319-       tace[1].a_flags = ACE_OWNER;
     4320-       tace[1].a_type = ACE_ACCESS_DENIED_ACE_TYPE;
     4321-       tace[1].a_access_mask = 0;
     4322-
     4323-       /* group@ deny */
     4324-       tace[2].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP;
     4325-       tace[2].a_type = ACE_ACCESS_DENIED_ACE_TYPE;
     4326-       tace[2].a_access_mask = 0;
     4327-
     4328-       /* owner@ allow */
     4329-       tace[3].a_flags = ACE_OWNER;
     4330-       tace[3].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
     4331-       tace[3].a_access_mask = ownset;
     4332-
     4333-       /* group@ allow */
     4334-       tace[4].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP;
     4335-       tace[4].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
     4336-       tace[4].a_access_mask = pubset;
     4337-
     4338-       /* everyone@ allow */
     4339-       tace[5].a_flags = ACE_EVERYONE;
     4340-       tace[5].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
     4341-       tace[5].a_access_mask = pubset;
     4342-
     4343-       /* Permissions for everyone@ */
     4344-       if (mode & 0004)
     4345-               tace[5].a_access_mask |= rperm;
     4346-       if (mode & 0002)
     4347-               tace[5].a_access_mask |= wperm;
     4348-       if (mode & 0001)
     4349-               tace[5].a_access_mask |= eperm;
     4350-
     4351-       /* Permissions for group@ */
     4352-       if (mode & 0040)
     4353-               tace[4].a_access_mask |= rperm;
     4354-       else if (mode & 0004)
     4355-               tace[2].a_access_mask |= rperm;
     4356-       if (mode & 0020)
     4357-               tace[4].a_access_mask |= wperm;
     4358-       else if (mode & 0002)
     4359-               tace[2].a_access_mask |= wperm;
     4360-       if (mode & 0010)
     4361-               tace[4].a_access_mask |= eperm;
     4362-       else if (mode & 0001)
     4363-               tace[2].a_access_mask |= eperm;
     4364-
     4365-       /* Permissions for owner@ */
     4366-       if (mode & 0400) {
     4367-               tace[3].a_access_mask |= rperm;
     4368-               if (!(mode & 0040) && (mode & 0004))
     4369-                       tace[0].a_access_mask |= rperm;
     4370-       } else if ((mode & 0040) || (mode & 0004))
     4371-               tace[1].a_access_mask |= rperm;
     4372-       if (mode & 0200) {
     4373-               tace[3].a_access_mask |= wperm;
     4374-               if (!(mode & 0020) && (mode & 0002))
     4375-                       tace[0].a_access_mask |= wperm;
     4376-       } else if ((mode & 0020) || (mode & 0002))
     4377-               tace[1].a_access_mask |= wperm;
     4378-       if (mode & 0100) {
     4379-               tace[3].a_access_mask |= eperm;
     4380-               if (!(mode & 0010) && (mode & 0001))
     4381-                       tace[0].a_access_mask |= eperm;
     4382-       } else if ((mode & 0010) || (mode & 0001))
     4383-               tace[1].a_access_mask |= eperm;
     4384-
     4385-       /* Check if the acl count matches */
     4386-       p = 3;
     4387-       for (i = 0; i < 3; i++) {
     4388-               if (tace[i].a_access_mask != 0)
     4389-                       p++;
     4390-       }
     4391-       if (acl->acl_cnt != p)
     4392-               return (0);
     4393-
     4394-       p = 0;
     4395-       for (i = 0; i < 6; i++) {
     4396-               if (tace[i].a_access_mask != 0) {
     4397-                       ace = &((ace_t *)acl->acl_aclp)[p];
     4398-                       /*
     4399-                        * Illumos added ACE_DELETE_CHILD to write perms for
     4400-                        * directories. We have to check against that, too.
     4401-                        */
     4402-                       if (ace->a_flags != tace[i].a_flags ||
     4403-                           ace->a_type != tace[i].a_type ||
     4404-                           (ace->a_access_mask != tace[i].a_access_mask &&
     4405-                           ((acl->acl_flags & ACL_IS_DIR) == 0 ||
     4406-                           (tace[i].a_access_mask & wperm) == 0 ||
     4407-                           ace->a_access_mask !=
     4408-                           (tace[i].a_access_mask | ACE_DELETE_CHILD))))
     4409-                               return (0);
     4410-                       p++;
     4411-               }
     4412-       }
     4413-
     4414-       *trivialp = 1;
     4415-       return (0);
     4416-}
     4417-#endif /* HAVE_SUN_ACL */
     4418-
     4419-#if HAVE_SUN_ACL
     4420-/*
     4421- * Translate Solaris POSIX.1e and NFSv4 ACLs into libarchive internal ACL
     4422- */
     4423-static int
     4424-translate_acl(struct archive_read_disk *a,
     4425-    struct archive_entry *entry, acl_t *acl, int default_entry_acl_type)
     4426-{
     4427-       int e, i;
     4428-       int ae_id, ae_tag, ae_perm;
     4429-       int entry_acl_type;
     4430-       const char *ae_name;
     4431-       aclent_t *aclent;
     4432-       ace_t *ace;
     4433-
     4434-       (void)default_entry_acl_type;
     4435-
     4436-       if (acl->acl_cnt <= 0)
     4437-               return (ARCHIVE_OK);
     4438-
     4439-       for (e = 0; e < acl->acl_cnt; e++) {
     4440-               ae_name = NULL;
     4441-               ae_tag = 0;
     4442-               ae_perm = 0;
     4443-
     4444-               if (acl->acl_type == ACE_T) {
     4445-                       ace = &((ace_t *)acl->acl_aclp)[e];
     4446-                       ae_id = ace->a_who;
     4447-
     4448-                       switch(ace->a_type) {
     4449-                       case ACE_ACCESS_ALLOWED_ACE_TYPE:
     4450-                               entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
     4451-                               break;
     4452-                       case ACE_ACCESS_DENIED_ACE_TYPE:
     4453-                               entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
     4454-                               break;
     4455-                       case ACE_SYSTEM_AUDIT_ACE_TYPE:
     4456-                               entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
     4457-                               break;
     4458-                       case ACE_SYSTEM_ALARM_ACE_TYPE:
     4459-                               entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
     4460-                               break;
     4461-                       default:
     4462-                               /* Unknown entry type, skip */
     4463-                               continue;
     4464-                       }
     4465-
     4466-                       if ((ace->a_flags & ACE_OWNER) != 0)
     4467-                               ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
     4468-                       else if ((ace->a_flags & ACE_GROUP) != 0)
     4469-                               ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
     4470-                       else if ((ace->a_flags & ACE_EVERYONE) != 0)
     4471-                               ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
     4472-                       else if ((ace->a_flags & ACE_IDENTIFIER_GROUP) != 0) {
     4473-                               ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
     4474-                               ae_name = archive_read_disk_gname(&a->archive,
     4475-                                   ae_id);
     4476-                       } else {
     4477-                               ae_tag = ARCHIVE_ENTRY_ACL_USER;
     4478-                               ae_name = archive_read_disk_uname(&a->archive,
     4479-                                   ae_id);
     4480-                       }
     4481-
     4482-                       for (i = 0; i < (int)(sizeof(acl_inherit_map) /
     4483-                           sizeof(acl_inherit_map[0])); ++i) {
     4484-                               if ((ace->a_flags &
     4485-                                   acl_inherit_map[i].platform_inherit) != 0)
     4486-                                       ae_perm |=
     4487-                                           acl_inherit_map[i].archive_inherit;
     4488-                       }
     4489-
     4490-                       for (i = 0; i < (int)(sizeof(acl_perm_map) /
     4491-                           sizeof(acl_perm_map[0])); ++i) {
     4492-                               if ((ace->a_access_mask &
     4493-                                   acl_perm_map[i].platform_perm) != 0)
     4494-                                       ae_perm |=
     4495-                                           acl_perm_map[i].archive_perm;
     4496-                       }
     4497-               } else {
     4498-                       aclent = &((aclent_t *)acl->acl_aclp)[e];
     4499-                       if ((aclent->a_type & ACL_DEFAULT) != 0)
     4500-                               entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
     4501-                       else
     4502-                               entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
     4503-                       ae_id = aclent->a_id;
     4504-
     4505-                       switch(aclent->a_type) {
     4506-                       case DEF_USER:
     4507-                       case USER:
     4508-                               ae_name = archive_read_disk_uname(&a->archive,
     4509-                                   ae_id);
     4510-                               ae_tag = ARCHIVE_ENTRY_ACL_USER;
     4511-                               break;
     4512-                       case DEF_GROUP:
     4513-                       case GROUP:
     4514-                               ae_name = archive_read_disk_gname(&a->archive,
     4515-                                   ae_id);
     4516-                               ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
     4517-                               break;
     4518-                       case DEF_CLASS_OBJ:
     4519-                       case CLASS_OBJ:
     4520-                               ae_tag = ARCHIVE_ENTRY_ACL_MASK;
     4521-                               break;
     4522-                       case DEF_USER_OBJ:
     4523-                       case USER_OBJ:
     4524-                               ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
     4525-                               break;
     4526-                       case DEF_GROUP_OBJ:
     4527-                       case GROUP_OBJ:
     4528-                               ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
     4529-                               break;
     4530-                       case DEF_OTHER_OBJ:
     4531-                       case OTHER_OBJ:
     4532-                               ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
     4533-                               break;
     4534-                       default:
     4535-                               /* Unknown tag type, skip */
     4536-                               continue;
     4537-                       }
     4538-
     4539-                       if ((aclent->a_perm & 1) != 0)
     4540-                               ae_perm |= ARCHIVE_ENTRY_ACL_EXECUTE;
     4541-                       if ((aclent->a_perm & 2) != 0)
     4542-                               ae_perm |= ARCHIVE_ENTRY_ACL_WRITE;
     4543-                       if ((aclent->a_perm & 4) != 0)
     4544-                               ae_perm |= ARCHIVE_ENTRY_ACL_READ;
     4545-               } /* default_entry_acl_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4 */
     4546-
     4547-               archive_entry_acl_add_entry(entry, entry_acl_type,
     4548-                   ae_perm, ae_tag, ae_id, ae_name);
     4549-       }
     4550-       return (ARCHIVE_OK);
     4551-}
     4552-#else  /* !HAVE_SUN_ACL */
     4553-/*
     4554- * Translate POSIX.1e (Linux), FreeBSD (both POSIX.1e and NFSv4) and
     4555- * MacOS (NFSv4 only) ACLs into libarchive internal structure
     4556- */
     4557-static int
     4558-translate_acl(struct archive_read_disk *a,
     4559-    struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
     4560-{
     4561-       acl_tag_t        acl_tag;
     4562-#if HAVE_ACL_TYPE_NFS4
     4563-       acl_entry_type_t acl_type;
     4564-       int brand;
     4565-#endif
     4566-#if HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL
     4567-       acl_flagset_t    acl_flagset;
     4568-#endif
     4569-       acl_entry_t      acl_entry;
     4570-       acl_permset_t    acl_permset;
     4571-       int              i, entry_acl_type;
     4572-       int              r, s, ae_id, ae_tag, ae_perm;
     4573-#if !HAVE_DARWIN_ACL
     4574-       void            *q;
     4575-#endif
     4576-       const char      *ae_name;
     4577-
     4578-#if HAVE_ACL_TYPE_NFS4
     4579-       // FreeBSD "brands" ACLs as POSIX.1e or NFSv4
     4580-       // Make sure the "brand" on this ACL is consistent
     4581-       // with the default_entry_acl_type bits provided.
     4582-       if (acl_get_brand_np(acl, &brand) != 0) {
     4583-               archive_set_error(&a->archive, errno,
     4584-                   "Failed to read ACL brand");
     4585-               return (ARCHIVE_WARN);
     4586-       }
     4587-       switch (brand) {
     4588-       case ACL_BRAND_POSIX:
     4589-               switch (default_entry_acl_type) {
     4590-               case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
     4591-               case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
     4592-                       break;
     4593-               default:
     4594-                       archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
     4595-                           "Invalid ACL entry type for POSIX.1e ACL");
     4596-                       return (ARCHIVE_WARN);
     4597-               }
     4598-               break;
     4599-       case ACL_BRAND_NFS4:
     4600-               if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
     4601-                       archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
     4602-                           "Invalid ACL entry type for NFSv4 ACL");
     4603-                       return (ARCHIVE_WARN);
     4604-               }
     4605-               break;
     4606-       default:
     4607-               archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
     4608-                   "Unknown ACL brand");
     4609-               return (ARCHIVE_WARN);
     4610-       }
     4611-#endif
     4612-
     4613-       s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
     4614-       if (s == -1) {
     4615-               archive_set_error(&a->archive, errno,
     4616-                   "Failed to get first ACL entry");
     4617-               return (ARCHIVE_WARN);
     4618-       }
     4619-
     4620-#if HAVE_DARWIN_ACL
     4621-       while (s == 0)
     4622-#else  /* FreeBSD, Linux */
     4623-       while (s == 1)
     4624-#endif
     4625-       {
     4626-               ae_id = -1;
     4627-               ae_name = NULL;
     4628-               ae_perm = 0;
     4629-
     4630-               if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
     4631-                       archive_set_error(&a->archive, errno,
     4632-                           "Failed to get ACL tag type");
     4633-                       return (ARCHIVE_WARN);
     4634-               }
     4635-               switch (acl_tag) {
     4636-#if !HAVE_DARWIN_ACL   /* FreeBSD, Linux */
     4637-               case ACL_USER:
     4638-                       q = acl_get_qualifier(acl_entry);
     4639-                       if (q != NULL) {
     4640-                               ae_id = (int)*(uid_t *)q;
     4641-                               acl_free(q);
     4642-                               ae_name = archive_read_disk_uname(&a->archive,
     4643-                                   ae_id);
     4644-                       }
     4645-                       ae_tag = ARCHIVE_ENTRY_ACL_USER;
     4646-                       break;
     4647-               case ACL_GROUP:
     4648-                       q = acl_get_qualifier(acl_entry);
     4649-                       if (q != NULL) {
     4650-                               ae_id = (int)*(gid_t *)q;
     4651-                               acl_free(q);
     4652-                               ae_name = archive_read_disk_gname(&a->archive,
     4653-                                   ae_id);
     4654-                       }
     4655-                       ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
     4656-                       break;
     4657-               case ACL_MASK:
     4658-                       ae_tag = ARCHIVE_ENTRY_ACL_MASK;
     4659-                       break;
     4660-               case ACL_USER_OBJ:
     4661-                       ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
     4662-                       break;
     4663-               case ACL_GROUP_OBJ:
     4664-                       ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
     4665-                       break;
     4666-               case ACL_OTHER:
     4667-                       ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
     4668-                       break;
     4669-#if HAVE_ACL_TYPE_NFS4
     4670-               case ACL_EVERYONE:
     4671-                       ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
     4672-                       break;
     4673-#endif
     4674-#else  /* HAVE_DARWIN_ACL */
     4675-               case ACL_EXTENDED_ALLOW:
     4676-                       entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
     4677-                       r = translate_guid(&a->archive, acl_entry, &ae_id,
     4678-                           &ae_tag, &ae_name);
     4679-                       break;
     4680-               case ACL_EXTENDED_DENY:
     4681-                       entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
     4682-                       r = translate_guid(&a->archive, acl_entry, &ae_id,
     4683-                           &ae_tag, &ae_name);
     4684-                       break;
     4685-#endif /* HAVE_DARWIN_ACL */
     4686-               default:
     4687-                       /* Skip types that libarchive can't support. */
     4688-                       s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
     4689-                       continue;
     4690-               }
     4691-
     4692-#if HAVE_DARWIN_ACL
     4693-               /* Skip if translate_guid() above failed */
     4694-               if (r != 0) {
     4695-                       s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
     4696-                       continue;
     4697-               }
     4698-#endif
     4699-
     4700-#if !HAVE_DARWIN_ACL
     4701-               // XXX acl_type maps to allow/deny/audit/YYYY bits
     4702-               entry_acl_type = default_entry_acl_type;
     4703-#endif
     4704-#if HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL
     4705-               if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
     4706-#if HAVE_ACL_TYPE_NFS4
     4707-                       /*
     4708-                        * acl_get_entry_type_np() fails with non-NFSv4 ACLs
     4709-                        */
     4710-                       if (acl_get_entry_type_np(acl_entry, &acl_type) != 0) {
     4711-                               archive_set_error(&a->archive, errno, "Failed "
     4712-                                   "to get ACL type from a NFSv4 ACL entry");
     4713-                               return (ARCHIVE_WARN);
     4714-                       }
     4715-                       switch (acl_type) {
     4716-                       case ACL_ENTRY_TYPE_ALLOW:
     4717-                               entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
     4718-                               break;
     4719-                       case ACL_ENTRY_TYPE_DENY:
     4720-                               entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
     4721-                               break;
     4722-                       case ACL_ENTRY_TYPE_AUDIT:
     4723-                               entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
     4724-                               break;
     4725-                       case ACL_ENTRY_TYPE_ALARM:
     4726-                               entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
     4727-                               break;
     4728-                       default:
     4729-                               archive_set_error(&a->archive, errno,
     4730-                                   "Invalid NFSv4 ACL entry type");
     4731-                               return (ARCHIVE_WARN);
     4732-                       }
     4733-#endif /* HAVE_ACL_TYPE_NFS4 */
     4734-
     4735-                       /*
     4736-                        * Libarchive stores "flag" (NFSv4 inheritance bits)
     4737-                        * in the ae_perm bitmap.
     4738-                        *
     4739-                        * acl_get_flagset_np() fails with non-NFSv4 ACLs
     4740-                        */
     4741-                       if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
     4742-                               archive_set_error(&a->archive, errno,
     4743-                                   "Failed to get flagset from a NFSv4 ACL entry");
     4744-                               return (ARCHIVE_WARN);
     4745-                       }
     4746-                       for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
     4747-                               r = acl_get_flag_np(acl_flagset,
     4748-                                   acl_inherit_map[i].platform_inherit);
     4749-                               if (r == -1) {
     4750-                                       archive_set_error(&a->archive, errno,
     4751-                                           "Failed to check flag in a NFSv4 "
     4752-                                           "ACL flagset");
     4753-                                       return (ARCHIVE_WARN);
     4754-                               } else if (r)
     4755-                                       ae_perm |= acl_inherit_map[i].archive_inherit;
     4756-                       }
     4757-               }
     4758-#endif /* HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL */
     4759-
     4760-               if (acl_get_permset(acl_entry, &acl_permset) != 0) {
     4761-                       archive_set_error(&a->archive, errno,
     4762-                           "Failed to get ACL permission set");
     4763-                       return (ARCHIVE_WARN);
     4764-               }
     4765-               for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
     4766-                       /*
     4767-                        * acl_get_perm() is spelled differently on different
     4768-                        * platforms; see above.
     4769-                        */
     4770-                       r = ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm);
     4771-                       if (r == -1) {
     4772-                               archive_set_error(&a->archive, errno,
     4773-                                   "Failed to check permission in an ACL permission set");
     4774-                               return (ARCHIVE_WARN);
     4775-                       } else if (r)
     4776-                               ae_perm |= acl_perm_map[i].archive_perm;
     4777-               }
     4778-
     4779-               archive_entry_acl_add_entry(entry, entry_acl_type,
     4780-                                           ae_perm, ae_tag,
     4781-                                           ae_id, ae_name);
     4782-
     4783-               s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
     4784-#if !HAVE_DARWIN_ACL
     4785-               if (s == -1) {
     4786-                       archive_set_error(&a->archive, errno,
     4787-                           "Failed to get next ACL entry");
     4788-                       return (ARCHIVE_WARN);
     4789-               }
     4790-#endif
     4791-       }
     4792-       return (ARCHIVE_OK);
     4793-}
     4794-#endif /* !HAVE_SUN_ACL */
     4795-#else  /* !HAVE_POSIX_ACL && !HAVE_NFS4_ACL */
     4796-static int
     4797-setup_acls(struct archive_read_disk *a,
     4798-    struct archive_entry *entry, int *fd)
     4799-{
     4800-       (void)a;      /* UNUSED */
     4801-       (void)entry;  /* UNUSED */
     4802-       (void)fd;     /* UNUSED */
     4803-       return (ARCHIVE_OK);
     4804-}
     4805-#endif /* !HAVE_POSIX_ACL && !HAVE_NFS4_ACL */
     4806-
     4807 #if (HAVE_FGETXATTR && HAVE_FLISTXATTR && HAVE_LISTXATTR && \
     4808     HAVE_LLISTXATTR && HAVE_GETXATTR && HAVE_LGETXATTR) || \
     4809     (HAVE_FGETEA && HAVE_FLISTEA && HAVE_LISTEA)
     4810@@ -1499,21 +512,9 @@ setup_xattrs(struct archive_read_disk *a,
     4811        path = NULL;
     4812 
     4813        if (*fd < 0) {
     4814-               path = archive_entry_sourcepath(entry);
     4815-               if (path == NULL || (a->tree != NULL &&
     4816-                   a->tree_enter_working_dir(a->tree) != 0))
     4817-                       path = archive_entry_pathname(entry);
     4818-               if (path == NULL) {
     4819-                       archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
     4820-                           "Couldn't determine file path to read "
     4821-                           "extended attributes");
     4822+               path = archive_read_disk_entry_setup_path(a, entry, fd);
     4823+               if (path == NULL)
     4824                        return (ARCHIVE_WARN);
     4825-               }
     4826-               if (a->tree != NULL && (a->follow_symlinks ||
     4827-                   archive_entry_filetype(entry) != AE_IFLNK)) {
     4828-                       *fd = a->open_on_current_dir(a->tree,
     4829-                           path, O_RDONLY | O_NONBLOCK);
     4830-               }
     4831        }
     4832 
     4833 #if HAVE_FLISTXATTR
     4834@@ -1658,21 +659,9 @@ setup_xattrs(struct archive_read_disk *a,
     4835        path = NULL;
     4836 
     4837        if (*fd < 0) {
     4838-               path = archive_entry_sourcepath(entry);
     4839-               if (path == NULL || (a->tree != NULL &&
     4840-                   a->tree_enter_working_dir(a->tree) != 0))
     4841-                       path = archive_entry_pathname(entry);
     4842-               if (path == NULL) {
     4843-                       archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
     4844-                           "Couldn't determine file path to read "
     4845-                           "extended attributes");
     4846+               path = archive_read_disk_entry_setup_path(a, entry, fd);
     4847+               if (path == NULL)
     4848                        return (ARCHIVE_WARN);
     4849-               }
     4850-               if (a->tree != NULL && (a->follow_symlinks ||
     4851-                   archive_entry_filetype(entry) != AE_IFLNK)) {
     4852-                       *fd = a->open_on_current_dir(a->tree,
     4853-                           path, O_RDONLY | O_NONBLOCK);
     4854-               }
     4855        }
     4856 
     4857        if (*fd >= 0)
     4858@@ -1773,6 +762,7 @@ setup_sparse_fiemap(struct archive_read_disk *a,
     4859        int64_t size;
     4860        int count, do_fiemap, iters;
     4861        int exit_sts = ARCHIVE_OK;
     4862+       const char *path;
     4863 
     4864        if (archive_entry_filetype(entry) != AE_IFREG
     4865            || archive_entry_size(entry) <= 0
     4866@@ -1780,11 +770,10 @@ setup_sparse_fiemap(struct archive_read_disk *a,
     4867                return (ARCHIVE_OK);
     4868 
     4869        if (*fd < 0) {
     4870-               const char *path;
     4871-
     4872-               path = archive_entry_sourcepath(entry);
     4873+               path = archive_read_disk_entry_setup_path(a, entry, NULL);
     4874                if (path == NULL)
     4875-                       path = archive_entry_pathname(entry);
     4876+                       return (ARCHIVE_FAILED);
     4877+
     4878                if (a->tree != NULL)
     4879                        *fd = a->open_on_current_dir(a->tree, path,
     4880                                O_RDONLY | O_NONBLOCK | O_CLOEXEC);
     4881@@ -1880,6 +869,7 @@ setup_sparse(struct archive_read_disk *a,
     4882        off_t off_s, off_e;
     4883        int exit_sts = ARCHIVE_OK;
     4884        int check_fully_sparse = 0;
     4885+       const char *path;
     4886 
     4887        if (archive_entry_filetype(entry) != AE_IFREG
     4888            || archive_entry_size(entry) <= 0
     4889@@ -1887,19 +877,10 @@ setup_sparse(struct archive_read_disk *a,
     4890                return (ARCHIVE_OK);
     4891 
     4892        /* Does filesystem support the reporting of hole ? */
     4893-       if (*fd < 0 && a->tree != NULL) {
     4894-               const char *path;
     4895-
     4896-               path = archive_entry_sourcepath(entry);
     4897+       if (*fd < 0) {
     4898+               path = archive_read_disk_entry_setup_path(a, entry, fd);
     4899                if (path == NULL)
     4900-                       path = archive_entry_pathname(entry);
     4901-               *fd = a->open_on_current_dir(a->tree, path,
     4902-                               O_RDONLY | O_NONBLOCK);
     4903-               if (*fd < 0) {
     4904-                       archive_set_error(&a->archive, errno,
     4905-                           "Can't open `%s'", path);
     4906                        return (ARCHIVE_FAILED);
     4907-               }
     4908        }
     4909 
     4910        if (*fd >= 0) {
     4911@@ -1911,12 +892,6 @@ setup_sparse(struct archive_read_disk *a,
     4912                if (initial_off != 0)
     4913                        lseek(*fd, 0, SEEK_SET);
     4914        } else {
     4915-               const char *path;
     4916-
     4917-               path = archive_entry_sourcepath(entry);
     4918-               if (path == NULL)
     4919-                       path = archive_entry_pathname(entry);
     4920-                       
     4921 #ifdef _PC_MIN_HOLE_SIZE
     4922                if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0)
     4923                        return (ARCHIVE_OK);
     4924diff --git a/libarchive/archive_read_disk_private.h b/libarchive/archive_read_disk_private.h
     4925index b5a8328b..f03a0a9c 100644
     4926--- a/libarchive/archive_read_disk_private.h
     4927+++ b/libarchive/archive_read_disk_private.h
     4928@@ -33,6 +33,8 @@
     4929 #ifndef ARCHIVE_READ_DISK_PRIVATE_H_INCLUDED
     4930 #define ARCHIVE_READ_DISK_PRIVATE_H_INCLUDED
     4931 
     4932+#include "archive_platform_acl.h"
     4933+
     4934 struct tree;
     4935 struct archive_entry;
     4936 
     4937@@ -86,4 +88,11 @@ struct archive_read_disk {
     4938        void    *excluded_cb_data;
     4939 };
     4940 
     4941+const char *
     4942+archive_read_disk_entry_setup_path(struct archive_read_disk *,
     4943+    struct archive_entry *, int *);
     4944+
     4945+int
     4946+archive_read_disk_entry_setup_acls(struct archive_read_disk *,
     4947+    struct archive_entry *, int *);
     4948 #endif
     4949diff --git a/libarchive/archive_read_format.3 b/libarchive/archive_read_format.3
     4950index 53b9a7e0..91c5d2cf 100644
     4951--- a/libarchive/archive_read_format.3
     4952+++ b/libarchive/archive_read_format.3
     4953@@ -37,9 +37,9 @@
     4954 .Nm archive_read_support_format_empty ,
     4955 .Nm archive_read_support_format_iso9660 ,
     4956 .Nm archive_read_support_format_lha ,
     4957-.Nm archive_read_support_format_mtree,
     4958-.Nm archive_read_support_format_rar,
     4959-.Nm archive_read_support_format_raw,
     4960+.Nm archive_read_support_format_mtree ,
     4961+.Nm archive_read_support_format_rar ,
     4962+.Nm archive_read_support_format_raw ,
     4963 .Nm archive_read_support_format_tar ,
     4964 .Nm archive_read_support_format_xar ,
     4965 .Nm archive_read_support_format_zip
     4966diff --git a/libarchive/archive_read_open.3 b/libarchive/archive_read_open.3
     4967index 4d8272ca..02494560 100644
     4968--- a/libarchive/archive_read_open.3
     4969+++ b/libarchive/archive_read_open.3
     4970@@ -33,7 +33,7 @@
     4971 .Nm archive_read_open_fd ,
     4972 .Nm archive_read_open_FILE ,
     4973 .Nm archive_read_open_filename ,
     4974-.Nm archive_read_open_memory ,
     4975+.Nm archive_read_open_memory
     4976 .Nd functions for reading streaming archives
     4977 .Sh LIBRARY
     4978 Streaming Archive Library (libarchive, -larchive)
     4979diff --git a/libarchive/archive_read_support_format_mtree.c b/libarchive/archive_read_support_format_mtree.c
     4980index 4231ff50..00d32507 100644
     4981--- a/libarchive/archive_read_support_format_mtree.c
     4982+++ b/libarchive/archive_read_support_format_mtree.c
     4983@@ -1857,33 +1857,38 @@ mtree_atol8(char **p)
     4984  * Note that this implementation does not (and should not!) obey
     4985  * locale settings; you cannot simply substitute strtol here, since
     4986  * it does obey locale.
     4987+ *
     4988+ * Convert the number pointed to by 'p' into a 64-bit signed integer.
     4989+ * On return, 'p' points to the first non-digit following the number.
     4990+ * On overflow, the function returns INT64_MIN or INT64_MAX.
     4991  */
     4992 static int64_t
     4993 mtree_atol10(char **p)
     4994 {
     4995-       int64_t l, limit, last_digit_limit;
     4996-       int base, digit, sign;
     4997-
     4998-       base = 10;
     4999+       const int base = 10;
     5000+       const int64_t limit = INT64_MAX / base;
     5001+       const int64_t last_digit_limit = INT64_MAX % base;
     5002+       int64_t l;
     5003+       int sign;
     5004 
     5005        if (**p == '-') {
     5006                sign = -1;
     5007-               limit = ((uint64_t)(INT64_MAX) + 1) / base;
     5008-               last_digit_limit = ((uint64_t)(INT64_MAX) + 1) % base;
     5009                ++(*p);
     5010        } else {
     5011                sign = 1;
     5012-               limit = INT64_MAX / base;
     5013-               last_digit_limit = INT64_MAX % base;
     5014        }
     5015 
     5016        l = 0;
     5017-       digit = **p - '0';
     5018-       while (digit >= 0 && digit < base) {
     5019-               if (l > limit || (l == limit && digit > last_digit_limit))
     5020+       while (**p >= '0' && **p < '0' + base) {
     5021+               int digit = **p - '0';
     5022+               if (l > limit || (l == limit && digit > last_digit_limit)) {
     5023+                       while (**p >= '0' && **p < '0' + base) {
     5024+                               ++(*p);
     5025+                       }
     5026                        return (sign < 0) ? INT64_MIN : INT64_MAX;
     5027+               }
     5028                l = (l * base) + digit;
     5029-               digit = *++(*p) - '0';
     5030+               ++(*p);
     5031        }
     5032        return (sign < 0) ? -l : l;
     5033 }
     5034diff --git a/libarchive/archive_read_support_format_tar.c b/libarchive/archive_read_support_format_tar.c
     5035index bd7f13d5..30d5bc83 100644
     5036--- a/libarchive/archive_read_support_format_tar.c
     5037+++ b/libarchive/archive_read_support_format_tar.c
     5038@@ -155,6 +155,7 @@ struct tar {
     5039        int                      compat_2x;
     5040        int                      process_mac_extensions;
     5041        int                      read_concatenated_archives;
     5042+       int                      realsize_override;
     5043 };
     5044 
     5045 static int     archive_block_is_null(const char *p);
     5046@@ -527,6 +528,7 @@ archive_read_format_tar_read_header(struct archive_read *a,
     5047        tar->entry_offset = 0;
     5048        gnu_clear_sparse_list(tar);
     5049        tar->realsize = -1; /* Mark this as "unset" */
     5050+       tar->realsize_override = 0;
     5051 
     5052        /* Setup default string conversion. */
     5053        tar->sconv = tar->opt_sconv;
     5054@@ -1894,6 +1896,7 @@ pax_attribute(struct archive_read *a, struct tar *tar,
     5055                if (strcmp(key, "GNU.sparse.size") == 0) {
     5056                        tar->realsize = tar_atol10(value, strlen(value));
     5057                        archive_entry_set_size(entry, tar->realsize);
     5058+                       tar->realsize_override = 1;
     5059                }
     5060 
     5061                /* GNU "0.1" sparse pax format. */
     5062@@ -1925,6 +1928,7 @@ pax_attribute(struct archive_read *a, struct tar *tar,
     5063                if (strcmp(key, "GNU.sparse.realsize") == 0) {
     5064                        tar->realsize = tar_atol10(value, strlen(value));
     5065                        archive_entry_set_size(entry, tar->realsize);
     5066+                       tar->realsize_override = 1;
     5067                }
     5068                break;
     5069        case 'L':
     5070@@ -1977,6 +1981,7 @@ pax_attribute(struct archive_read *a, struct tar *tar,
     5071                            tar_atol10(value, strlen(value)));
     5072                } else if (strcmp(key, "SCHILY.realsize") == 0) {
     5073                        tar->realsize = tar_atol10(value, strlen(value));
     5074+                       tar->realsize_override = 1;
     5075                        archive_entry_set_size(entry, tar->realsize);
     5076                } else if (strncmp(key, "SCHILY.xattr.", 13) == 0) {
     5077                        pax_attribute_schily_xattr(entry, key, value,
     5078@@ -2055,14 +2060,12 @@ pax_attribute(struct archive_read *a, struct tar *tar,
     5079                        tar->entry_bytes_remaining
     5080                            = tar_atol10(value, strlen(value));
     5081                        /*
     5082-                        * But, "size" is not necessarily the size of
     5083-                        * the file on disk; if this is a sparse file,
     5084-                        * the disk size may have already been set from
     5085-                        * GNU.sparse.realsize or GNU.sparse.size or
     5086-                        * an old GNU header field or SCHILY.realsize
     5087-                        * or ....
     5088+                        * The "size" pax header keyword always overrides the
     5089+                        * "size" field in the tar header.
     5090+                        * GNU.sparse.realsize, GNU.sparse.size and
     5091+                        * SCHILY.realsize override this value.
     5092                         */
     5093-                       if (tar->realsize < 0) {
     5094+                       if (!tar->realsize_override) {
     5095                                archive_entry_set_size(entry,
     5096                                    tar->entry_bytes_remaining);
     5097                                tar->realsize
     5098@@ -2206,6 +2209,7 @@ header_gnutar(struct archive_read *a, struct tar *tar,
     5099                tar->realsize
     5100                    = tar_atol(header->realsize, sizeof(header->realsize));
     5101                archive_entry_set_size(entry, tar->realsize);
     5102+               tar->realsize_override = 1;
     5103        }
     5104 
     5105        if (header->sparse[0].offset[0] != 0) {
     5106diff --git a/libarchive/archive_read_support_format_warc.c b/libarchive/archive_read_support_format_warc.c
     5107index b1624651..e8753853 100644
     5108--- a/libarchive/archive_read_support_format_warc.c
     5109+++ b/libarchive/archive_read_support_format_warc.c
     5110@@ -600,9 +600,10 @@ _warc_rdver(const char *buf, size_t bsz)
     5111        /* looks good so far, read the version number for a laugh */
     5112        buf += sizeof(magic) - 1U;
     5113 
     5114-       if (isdigit(buf[0U]) && (buf[1U] == '.') && isdigit(buf[2U])) {
     5115+       if (isdigit((unsigned char)buf[0U]) && (buf[1U] == '.') &&
     5116+           isdigit((unsigned char)buf[2U])) {
     5117                /* we support a maximum of 2 digits in the minor version */
     5118-               if (isdigit(buf[3U]))
     5119+               if (isdigit((unsigned char)buf[3U]))
     5120                        end = 1U;
     5121                /* set up major version */
     5122                ver = (buf[0U] - '0') * 10000U;
     5123@@ -686,7 +687,7 @@ _warc_rduri(const char *buf, size_t bsz)
     5124 
     5125        /* spaces inside uri are not allowed, CRLF should follow */
     5126        for (p = val; p < eol; p++) {
     5127-               if (isspace(*p))
     5128+               if (isspace((unsigned char)*p))
     5129                        return res;
     5130        }
     5131 
     5132@@ -736,7 +737,7 @@ _warc_rdlen(const char *buf, size_t bsz)
     5133        while (val < eol && (*val == ' ' || *val == '\t'))
     5134                val++;
     5135        /* there must be at least one digit */
     5136-       if (!isdigit(*val))
     5137+       if (!isdigit((unsigned char)*val))
     5138                return -1;
     5139        len = strtol(val, &on, 10);
     5140        if (on != eol) {
     5141diff --git a/libarchive/archive_read_support_format_zip.c b/libarchive/archive_read_support_format_zip.c
     5142index 08bcf1f5..e62f99c8 100644
     5143--- a/libarchive/archive_read_support_format_zip.c
     5144+++ b/libarchive/archive_read_support_format_zip.c
     5145@@ -2407,7 +2407,7 @@ read_eocd(struct zip *zip, const char *p, int64_t current_offset)
     5146  * Examine Zip64 EOCD locator:  If it's valid, store the information
     5147  * from it.
     5148  */
     5149-static void
     5150+static int
     5151 read_zip64_eocd(struct archive_read *a, struct zip *zip, const char *p)
     5152 {
     5153        int64_t eocd64_offset;
     5154@@ -2417,35 +2417,37 @@ read_zip64_eocd(struct archive_read *a, struct zip *zip, const char *p)
     5155 
     5156        /* Central dir must be on first volume. */
     5157        if (archive_le32dec(p + 4) != 0)
     5158-               return;
     5159+               return 0;
     5160        /* Must be only a single volume. */
     5161        if (archive_le32dec(p + 16) != 1)
     5162-               return;
     5163+               return 0;
     5164 
     5165        /* Find the Zip64 EOCD record. */
     5166        eocd64_offset = archive_le64dec(p + 8);
     5167        if (__archive_read_seek(a, eocd64_offset, SEEK_SET) < 0)
     5168-               return;
     5169+               return 0;
     5170        if ((p = __archive_read_ahead(a, 56, NULL)) == NULL)
     5171-               return;
     5172+               return 0;
     5173        /* Make sure we can read all of it. */
     5174        eocd64_size = archive_le64dec(p + 4) + 12;
     5175        if (eocd64_size < 56 || eocd64_size > 16384)
     5176-               return;
     5177+               return 0;
     5178        if ((p = __archive_read_ahead(a, (size_t)eocd64_size, NULL)) == NULL)
     5179-               return;
     5180+               return 0;
     5181 
     5182        /* Sanity-check the EOCD64 */
     5183        if (archive_le32dec(p + 16) != 0) /* Must be disk #0 */
     5184-               return;
     5185+               return 0;
     5186        if (archive_le32dec(p + 20) != 0) /* CD must be on disk #0 */
     5187-               return;
     5188+               return 0;
     5189        /* CD can't be split. */
     5190        if (archive_le64dec(p + 24) != archive_le64dec(p + 32))
     5191-               return;
     5192+               return 0;
     5193 
     5194        /* Save the central directory offset for later use. */
     5195        zip->central_directory_offset = archive_le64dec(p + 48);
     5196+
     5197+       return 32;
     5198 }
     5199 
     5200 static int
     5201@@ -2483,15 +2485,14 @@ archive_read_format_zip_seekable_bid(struct archive_read *a, int best_bid)
     5202                        if (memcmp(p + i, "PK\005\006", 4) == 0) {
     5203                                int ret = read_eocd(zip, p + i,
     5204                                    current_offset + i);
     5205-                               if (ret > 0) {
     5206-                                       /* Zip64 EOCD locator precedes
     5207-                                        * regular EOCD if present. */
     5208-                                       if (i >= 20
     5209-                                           && memcmp(p + i - 20, "PK\006\007", 4) == 0) {
     5210-                                               read_zip64_eocd(a, zip, p + i - 20);
     5211-                                       }
     5212-                                       return (ret);
     5213+                               /* Zip64 EOCD locator precedes
     5214+                                * regular EOCD if present. */
     5215+                               if (i >= 20 && memcmp(p + i - 20, "PK\006\007", 4) == 0) {
     5216+                                       int ret_zip64 = read_zip64_eocd(a, zip, p + i - 20);
     5217+                                       if (ret_zip64 > ret)
     5218+                                               ret = ret_zip64;
     5219                                }
     5220+                               return (ret);
     5221                        }
     5222                        i -= 4;
     5223                        break;
     5224diff --git a/libarchive/archive_util.c b/libarchive/archive_util.c
     5225index 6b3bd611..a751868f 100644
     5226--- a/libarchive/archive_util.c
     5227+++ b/libarchive/archive_util.c
     5228@@ -89,88 +89,6 @@ archive_version_string(void)
     5229        return (ARCHIVE_VERSION_STRING);
     5230 }
     5231 
     5232-const char *
     5233-archive_version_details(void)
     5234-{
     5235-       static struct archive_string str;
     5236-       static int init = 0;
     5237-       const char *zlib = archive_zlib_version();
     5238-       const char *liblzma = archive_liblzma_version();
     5239-       const char *bzlib = archive_bzlib_version();
     5240-       const char *liblz4 = archive_liblz4_version();
     5241-
     5242-       if (!init) {
     5243-               archive_string_init(&str);
     5244-
     5245-               archive_strcat(&str, ARCHIVE_VERSION_STRING);
     5246-               if (zlib != NULL) {
     5247-                       archive_strcat(&str, " zlib/");
     5248-                       archive_strcat(&str, zlib);
     5249-               }
     5250-               if (liblzma) {
     5251-                       archive_strcat(&str, " liblzma/");
     5252-                       archive_strcat(&str, liblzma);
     5253-               }
     5254-               if (bzlib) {
     5255-                       const char *p = bzlib;
     5256-                       const char *sep = strchr(p, ',');
     5257-                       if (sep == NULL)
     5258-                               sep = p + strlen(p);
     5259-                       archive_strcat(&str, " bz2lib/");
     5260-                       archive_strncat(&str, p, sep - p);
     5261-               }
     5262-               if (liblz4) {
     5263-                       archive_strcat(&str, " liblz4/");
     5264-                       archive_strcat(&str, liblz4);
     5265-               }
     5266-       }
     5267-       return str.s;
     5268-}
     5269-
     5270-const char *
     5271-archive_zlib_version(void)
     5272-{
     5273-#ifdef HAVE_ZLIB_H
     5274-       return ZLIB_VERSION;
     5275-#else
     5276-       return NULL;
     5277-#endif
     5278-}
     5279-
     5280-const char *
     5281-archive_liblzma_version(void)
     5282-{
     5283-#ifdef HAVE_LZMA_H
     5284-       return LZMA_VERSION_STRING;
     5285-#else
     5286-       return NULL;
     5287-#endif
     5288-}
     5289-
     5290-const char *
     5291-archive_bzlib_version(void)
     5292-{
     5293-#ifdef HAVE_BZLIB_H
     5294-       return BZ2_bzlibVersion();
     5295-#else
     5296-       return NULL;
     5297-#endif
     5298-}
     5299-
     5300-const char *
     5301-archive_liblz4_version(void)
     5302-{
     5303-#if defined(HAVE_LZ4_H) && defined(HAVE_LIBLZ4)
     5304-#define str(s) #s
     5305-#define NUMBER(x) str(x)
     5306-       return NUMBER(LZ4_VERSION_MAJOR) "." NUMBER(LZ4_VERSION_MINOR) "." NUMBER(LZ4_VERSION_RELEASE);
     5307-#undef NUMBER
     5308-#undef str
     5309-#else
     5310-       return NULL;
     5311-#endif
     5312-}
     5313-
     5314 int
     5315 archive_errno(struct archive *a)
     5316 {
     5317diff --git a/libarchive/archive_version_details.c b/libarchive/archive_version_details.c
     5318new file mode 100644
     5319index 00000000..813f0f3f
     5320--- /dev/null
     5321+++ b/libarchive/archive_version_details.c
     5322@@ -0,0 +1,133 @@
     5323+/*-
     5324+ * Copyright (c) 2009-2012,2014 Michihiro NAKAJIMA
     5325+ * Copyright (c) 2003-2007 Tim Kientzle
     5326+ * All rights reserved.
     5327+ *
     5328+ * Redistribution and use in source and binary forms, with or without
     5329+ * modification, are permitted provided that the following conditions
     5330+ * are met:
     5331+ * 1. Redistributions of source code must retain the above copyright
     5332+ *    notice, this list of conditions and the following disclaimer.
     5333+ * 2. Redistributions in binary form must reproduce the above copyright
     5334+ *    notice, this list of conditions and the following disclaimer in the
     5335+ *    documentation and/or other materials provided with the distribution.
     5336+ *
     5337+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
     5338+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     5339+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     5340+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
     5341+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     5342+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     5343+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     5344+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     5345+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     5346+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     5347+ */
     5348+
     5349+#include "archive_platform.h"
     5350+__FBSDID("$FreeBSD: head/lib/libarchive/archive_util.c 201098 2009-12-28 02:58:14Z kientzle $");
     5351+
     5352+#ifdef HAVE_STDLIB_H
     5353+#include <stdlib.h>
     5354+#endif
     5355+#ifdef HAVE_STRING_H
     5356+#include <string.h>
     5357+#endif
     5358+#ifdef HAVE_ZLIB_H
     5359+#include <zlib.h>
     5360+#endif
     5361+#ifdef HAVE_LZMA_H
     5362+#include <lzma.h>
     5363+#endif
     5364+#ifdef HAVE_BZLIB_H
     5365+#include <bzlib.h>
     5366+#endif
     5367+#ifdef HAVE_LZ4_H
     5368+#include <lz4.h>
     5369+#endif
     5370+
     5371+#include "archive.h"
     5372+#include "archive_private.h"
     5373+#include "archive_string.h"
     5374+
     5375+const char *
     5376+archive_version_details(void)
     5377+{
     5378+       static struct archive_string str;
     5379+       static int init = 0;
     5380+       const char *zlib = archive_zlib_version();
     5381+       const char *liblzma = archive_liblzma_version();
     5382+       const char *bzlib = archive_bzlib_version();
     5383+       const char *liblz4 = archive_liblz4_version();
     5384+
     5385+       if (!init) {
     5386+               archive_string_init(&str);
     5387+
     5388+               archive_strcat(&str, ARCHIVE_VERSION_STRING);
     5389+               if (zlib != NULL) {
     5390+                       archive_strcat(&str, " zlib/");
     5391+                       archive_strcat(&str, zlib);
     5392+               }
     5393+               if (liblzma) {
     5394+                       archive_strcat(&str, " liblzma/");
     5395+                       archive_strcat(&str, liblzma);
     5396+               }
     5397+               if (bzlib) {
     5398+                       const char *p = bzlib;
     5399+                       const char *sep = strchr(p, ',');
     5400+                       if (sep == NULL)
     5401+                               sep = p + strlen(p);
     5402+                       archive_strcat(&str, " bz2lib/");
     5403+                       archive_strncat(&str, p, sep - p);
     5404+               }
     5405+               if (liblz4) {
     5406+                       archive_strcat(&str, " liblz4/");
     5407+                       archive_strcat(&str, liblz4);
     5408+               }
     5409+       }
     5410+       return str.s;
     5411+}
     5412+
     5413+const char *
     5414+archive_zlib_version(void)
     5415+{
     5416+#ifdef HAVE_ZLIB_H
     5417+       return ZLIB_VERSION;
     5418+#else
     5419+       return NULL;
     5420+#endif
     5421+}
     5422+
     5423+const char *
     5424+archive_liblzma_version(void)
     5425+{
     5426+#ifdef HAVE_LZMA_H
     5427+       return LZMA_VERSION_STRING;
     5428+#else
     5429+       return NULL;
     5430+#endif
     5431+}
     5432+
     5433+const char *
     5434+archive_bzlib_version(void)
     5435+{
     5436+#ifdef HAVE_BZLIB_H
     5437+       return BZ2_bzlibVersion();
     5438+#else
     5439+       return NULL;
     5440+#endif
     5441+}
     5442+
     5443+const char *
     5444+archive_liblz4_version(void)
     5445+{
     5446+#if defined(HAVE_LZ4_H) && defined(HAVE_LIBLZ4)
     5447+#define str(s) #s
     5448+#define NUMBER(x) str(x)
     5449+       return NUMBER(LZ4_VERSION_MAJOR) "." NUMBER(LZ4_VERSION_MINOR) "." NUMBER(LZ4_VERSION_RELEASE);
     5450+#undef NUMBER
     5451+#undef str
     5452+#else
     5453+       return NULL;
     5454+#endif
     5455+}
     5456diff --git a/libarchive/archive_write_data.3 b/libarchive/archive_write_data.3
     5457index 0cdd25f1..9c16cd9b 100644
     5458--- a/libarchive/archive_write_data.3
     5459+++ b/libarchive/archive_write_data.3
     5460@@ -24,11 +24,12 @@
     5461 .\"
     5462 .\" $FreeBSD$
     5463 .\"
     5464-.Dd February 2, 2012
     5465+.Dd February 28, 2017
     5466 .Dt ARCHIVE_WRITE_DATA 3
     5467 .Os
     5468 .Sh NAME
     5469-.Nm archive_write_data
     5470+.Nm archive_write_data ,
     5471+.Nm archive_write_data_block
     5472 .Nd functions for creating archives
     5473 .Sh LIBRARY
     5474 Streaming Archive Library (libarchive, -larchive)
     5475@@ -36,8 +37,27 @@ Streaming Archive Library (libarchive, -larchive)
     5476 .In archive.h
     5477 .Ft la_ssize_t
     5478 .Fn archive_write_data "struct archive *" "const void *" "size_t"
     5479+.Ft la_ssize_t
     5480+.Fn archive_write_data_block "struct archive *" "const void *" "size_t size" "int64_t offset"
     5481 .Sh DESCRIPTION
     5482+.Bl -tag -width indent
     5483+.It Fn archive_write_data
     5484+Write data corresponding to the header just written.
     5485+.It Fn archive_write_data_block
     5486 Write data corresponding to the header just written.
     5487+This is like
     5488+.Fn archive_write_data
     5489+except that it performs a seek on the file being
     5490+written to the specified offset before writing the data.
     5491+This is useful when restoring sparse files from archive
     5492+formats that support sparse files.
     5493+Returns number of bytes written or -1 on error.
     5494+(Note: This is currently not supported for
     5495+.Tn archive_write
     5496+handles, only for
     5497+.Tn archive_write_disk
     5498+handles.
     5499+.El
     5500 .\" .Sh EXAMPLE
     5501 .\"
     5502 .Sh RETURN VALUES
     5503diff --git a/libarchive/archive_write_disk.3 b/libarchive/archive_write_disk.3
     5504index ba6c9706..4891b857 100644
     5505--- a/libarchive/archive_write_disk.3
     5506+++ b/libarchive/archive_write_disk.3
     5507@@ -24,7 +24,7 @@
     5508 .\"
     5509 .\" $FreeBSD$
     5510 .\"
     5511-.Dd February 2, 2012
     5512+.Dd February 28, 2017
     5513 .Dt ARCHIVE_WRITE_DISK 3
     5514 .Os
     5515 .Sh NAME
     5516@@ -33,14 +33,7 @@
     5517 .Nm archive_write_disk_set_skip_file ,
     5518 .Nm archive_write_disk_set_group_lookup ,
     5519 .Nm archive_write_disk_set_standard_lookup ,
     5520-.Nm archive_write_disk_set_user_lookup ,
     5521-.Nm archive_write_header ,
     5522-.Nm archive_write_data ,
     5523-.Nm archive_write_data_block ,
     5524-.Nm archive_write_finish_entry ,
     5525-.Nm archive_write_close ,
     5526-.Nm archive_write_finish
     5527-.Nm archive_write_free
     5528+.Nm archive_write_disk_set_user_lookup
     5529 .Nd functions for creating objects on disk
     5530 .Sh LIBRARY
     5531 Streaming Archive Library (libarchive, -larchive)
     5532@@ -68,20 +61,6 @@ Streaming Archive Library (libarchive, -larchive)
     5533 .Fa "uid_t (*)(void *, const char *uname, uid_t uid)"
     5534 .Fa "void (*cleanup)(void *)"
     5535 .Fc
     5536-.Ft int
     5537-.Fn archive_write_header "struct archive *" "struct archive_entry *"
     5538-.Ft la_ssize_t
     5539-.Fn archive_write_data "struct archive *" "const void *" "size_t"
     5540-.Ft la_ssize_t
     5541-.Fn archive_write_data_block "struct archive *" "const void *" "size_t size" "int64_t offset"
     5542-.Ft int
     5543-.Fn archive_write_finish_entry "struct archive *"
     5544-.Ft int
     5545-.Fn archive_write_close "struct archive *"
     5546-.Ft int
     5547-.Fn archive_write_finish "struct archive *"
     5548-.Ft int
     5549-.Fn archive_write_free "struct archive *"
     5550 .Sh DESCRIPTION
     5551 These functions provide a complete API for creating objects on
     5552 disk from
     5553@@ -223,60 +202,6 @@ the number of calls to
     5554 .Xr getpwnam 3
     5555 and
     5556 .Xr getgrnam 3 .
     5557-.It Fn archive_write_header
     5558-Build and write a header using the data in the provided
     5559-.Tn struct archive_entry
     5560-structure.
     5561-See
     5562-.Xr archive_entry 3
     5563-for information on creating and populating
     5564-.Tn struct archive_entry
     5565-objects.
     5566-.It Fn archive_write_data
     5567-Write data corresponding to the header just written.
     5568-Returns number of bytes written or -1 on error.
     5569-.It Fn archive_write_data_block
     5570-Write data corresponding to the header just written.
     5571-This is like
     5572-.Fn archive_write_data
     5573-except that it performs a seek on the file being
     5574-written to the specified offset before writing the data.
     5575-This is useful when restoring sparse files from archive
     5576-formats that support sparse files.
     5577-Returns number of bytes written or -1 on error.
     5578-(Note: This is currently not supported for
     5579-.Tn archive_write
     5580-handles, only for
     5581-.Tn archive_write_disk
     5582-handles.)
     5583-.It Fn archive_write_finish_entry
     5584-Close out the entry just written.
     5585-Ordinarily, clients never need to call this, as it
     5586-is called automatically by
     5587-.Fn archive_write_next_header
     5588-and
     5589-.Fn archive_write_close
     5590-as needed.
     5591-However, some file attributes are written to disk only
     5592-after the file is closed, so this can be necessary
     5593-if you need to work with the file on disk right away.
     5594-.It Fn archive_write_close
     5595-Set any attributes that could not be set during the initial restore.
     5596-For example, directory timestamps are not restored initially because
     5597-restoring a subsequent file would alter that timestamp.
     5598-Similarly, non-writable directories are initially created with
     5599-write permissions (so that their contents can be restored).
     5600-The
     5601-.Nm
     5602-library maintains a list of all such deferred attributes and
     5603-sets them when this function is invoked.
     5604-.It Fn archive_write_finish
     5605-This is a deprecated synonym for
     5606-.Fn archive_write_free .
     5607-.It Fn archive_write_free
     5608-Invokes
     5609-.Fn archive_write_close
     5610-if it was not invoked manually, then releases all resources.
     5611 .El
     5612 More information about the
     5613 .Va struct archive
     5614diff --git a/libarchive/archive_write_disk_acl.c b/libarchive/archive_write_disk_acl.c
     5615deleted file mode 100644
     5616index 144ab7e7..00000000
     5617--- a/libarchive/archive_write_disk_acl.c
     5618+++ /dev/null
     5619@@ -1,654 +0,0 @@
     5620-/*-
     5621- * Copyright (c) 2003-2010 Tim Kientzle
     5622- * All rights reserved.
     5623- *
     5624- * Redistribution and use in source and binary forms, with or without
     5625- * modification, are permitted provided that the following conditions
     5626- * are met:
     5627- * 1. Redistributions of source code must retain the above copyright
     5628- *    notice, this list of conditions and the following disclaimer
     5629- *    in this position and unchanged.
     5630- * 2. Redistributions in binary form must reproduce the above copyright
     5631- *    notice, this list of conditions and the following disclaimer in the
     5632- *    documentation and/or other materials provided with the distribution.
     5633- *
     5634- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
     5635- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     5636- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     5637- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
     5638- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     5639- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     5640- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     5641- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     5642- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     5643- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     5644- */
     5645-
     5646-#include "archive_platform.h"
     5647-__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_disk.c 201159 2009-12-29 05:35:40Z kientzle $");
     5648-
     5649-#ifdef HAVE_SYS_TYPES_H
     5650-#include <sys/types.h>
     5651-#endif
     5652-#ifdef HAVE_SYS_ACL_H
     5653-#define _ACL_PRIVATE /* For debugging */
     5654-#include <sys/acl.h>
     5655-#endif
     5656-#if HAVE_DARWIN_ACL
     5657-#include <membership.h>
     5658-#endif
     5659-#ifdef HAVE_ERRNO_H
     5660-#include <errno.h>
     5661-#endif
     5662-
     5663-#include "archive.h"
     5664-#include "archive_entry.h"
     5665-#include "archive_acl_private.h"
     5666-#include "archive_write_disk_private.h"
     5667-
     5668-#if !HAVE_POSIX_ACL && !HAVE_NFS4_ACL
     5669-/* Default empty function body to satisfy mainline code. */
     5670-int
     5671-archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
     5672-        struct archive_acl *abstract_acl)
     5673-{
     5674-       (void)a; /* UNUSED */
     5675-       (void)fd; /* UNUSED */
     5676-       (void)name; /* UNUSED */
     5677-       (void)abstract_acl; /* UNUSED */
     5678-       return (ARCHIVE_OK);
     5679-}
     5680-
     5681-#else /* HAVE_POSIX_ACL || HAVE_NFS4_ACL */
     5682-
     5683-#if HAVE_SUN_ACL
     5684-#define        ARCHIVE_PLATFORM_ACL_TYPE_NFS4  ACE_T
     5685-#elif HAVE_DARWIN_ACL
     5686-#define        ARCHIVE_PLATFORM_ACL_TYPE_NFS4  ACL_TYPE_EXTENDED
     5687-#elif HAVE_ACL_TYPE_NFS4
     5688-#define        ARCHIVE_PLATFORM_ACL_TYPE_NFS4  ACL_TYPE_NFS4
     5689-#endif
     5690-
     5691-static int     set_acl(struct archive *, int fd, const char *,
     5692-                       struct archive_acl *,
     5693-                       acl_type_t, int archive_entry_acl_type, const char *tn);
     5694-
     5695-int
     5696-archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
     5697-        struct archive_acl *abstract_acl)
     5698-{
     5699-       int             ret = ARCHIVE_OK;
     5700-
     5701-#if !HAVE_DARWIN_ACL
     5702-       if ((archive_acl_types(abstract_acl)
     5703-           & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
     5704-#if HAVE_SUN_ACL
     5705-               /* Solaris writes POSIX.1e access and default ACLs together */
     5706-               ret = set_acl(a, fd, name, abstract_acl, ACLENT_T,
     5707-                   ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, "posix1e");
     5708-#else  /* HAVE_POSIX_ACL */
     5709-               if ((archive_acl_types(abstract_acl)
     5710-                   & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
     5711-                       ret = set_acl(a, fd, name, abstract_acl,
     5712-                           ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
     5713-                           "access");
     5714-                       if (ret != ARCHIVE_OK)
     5715-                               return (ret);
     5716-               }
     5717-               if ((archive_acl_types(abstract_acl)
     5718-                   & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
     5719-                       ret = set_acl(a, fd, name, abstract_acl,
     5720-                           ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT,
     5721-                           "default");
     5722-#endif /* !HAVE_SUN_ACL */
     5723-               /* Simultaneous POSIX.1e and NFSv4 is not supported */
     5724-               return (ret);
     5725-       }
     5726-#endif /* !HAVE_DARWIN_ACL */
     5727-#if HAVE_NFS4_ACL
     5728-       if ((archive_acl_types(abstract_acl) &
     5729-           ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
     5730-               ret = set_acl(a, fd, name, abstract_acl,
     5731-                   ARCHIVE_PLATFORM_ACL_TYPE_NFS4,
     5732-                   ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
     5733-       }
     5734-#endif /* HAVE_NFS4_ACL */
     5735-       return (ret);
     5736-}
     5737-
     5738-/*
     5739- * Translate system ACL permissions into libarchive internal structure
     5740- */
     5741-static const struct {
     5742-       const int archive_perm;
     5743-       const int platform_perm;
     5744-} acl_perm_map[] = {
     5745-#if HAVE_SUN_ACL       /* Solaris NFSv4 ACL permissions */
     5746-       {ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE},
     5747-       {ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA},
     5748-       {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY},
     5749-       {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA},
     5750-       {ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE},
     5751-       {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA},
     5752-       {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY},
     5753-       {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS},
     5754-       {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS},
     5755-       {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD},
     5756-       {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES},
     5757-       {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES},
     5758-       {ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE},
     5759-       {ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL},
     5760-       {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL},
     5761-       {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER},
     5762-       {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE}
     5763-#elif HAVE_DARWIN_ACL  /* MacOS ACL permissions */
     5764-       {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
     5765-       {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
     5766-       {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
     5767-       {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
     5768-       {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
     5769-       {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
     5770-       {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
     5771-       {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
     5772-       {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
     5773-       {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
     5774-       {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
     5775-       {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES},
     5776-       {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES},
     5777-       {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY},
     5778-       {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY},
     5779-       {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER},
     5780-       {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
     5781-#else  /* POSIX.1e ACL permissions */
     5782-       {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
     5783-       {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
     5784-       {ARCHIVE_ENTRY_ACL_READ, ACL_READ},
     5785-#if HAVE_ACL_TYPE_NFS4 /* FreeBSD NFSv4 ACL permissions */
     5786-       {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
     5787-       {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
     5788-       {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
     5789-       {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
     5790-       {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
     5791-       {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
     5792-       {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
     5793-       {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
     5794-       {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
     5795-       {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
     5796-       {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
     5797-       {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
     5798-       {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
     5799-       {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
     5800-       {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
     5801-       {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
     5802-#endif
     5803-#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
     5804-};
     5805-
     5806-#if HAVE_NFS4_ACL
     5807-/*
     5808- * Translate system NFSv4 inheritance flags into libarchive internal structure
     5809- */
     5810-static const struct {
     5811-       const int archive_inherit;
     5812-       const int platform_inherit;
     5813-} acl_inherit_map[] = {
     5814-#if HAVE_SUN_ACL       /* Solaris NFSv4 inheritance flags */
     5815-       {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE},
     5816-       {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE},
     5817-       {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE},
     5818-       {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE},
     5819-       {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
     5820-       {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG},
     5821-       {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}
     5822-#elif HAVE_DARWIN_ACL  /* MacOS NFSv4 inheritance flags */
     5823-       {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED},
     5824-       {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
     5825-       {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
     5826-       {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_LIMIT_INHERIT},
     5827-       {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT}
     5828-#else  /* FreeBSD NFSv4 ACL inheritance flags */
     5829-       {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
     5830-       {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
     5831-       {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
     5832-       {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY},
     5833-       {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
     5834-       {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
     5835-       {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}
     5836-#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
     5837-};
     5838-#endif /* HAVE_NFS4_ACL */
     5839-
     5840-static int
     5841-set_acl(struct archive *a, int fd, const char *name,
     5842-    struct archive_acl *abstract_acl,
     5843-    acl_type_t acl_type, int ae_requested_type, const char *tname)
     5844-{
     5845-#if HAVE_SUN_ACL
     5846-       aclent_t         *aclent;
     5847-       ace_t            *ace;
     5848-       int              e, r;
     5849-       acl_t            *acl;
     5850-#else
     5851-       acl_t            acl;
     5852-       acl_entry_t      acl_entry;
     5853-       acl_permset_t    acl_permset;
     5854-#if HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL
     5855-       acl_flagset_t    acl_flagset;
     5856-#endif
     5857-#endif /* HAVE_SUN_ACL */
     5858-#if HAVE_ACL_TYPE_NFS4
     5859-       int             r;
     5860-#endif
     5861-       int              ret;
     5862-       int              ae_type, ae_permset, ae_tag, ae_id;
     5863-#if HAVE_DARWIN_ACL
     5864-       uuid_t          ae_uuid;
     5865-#endif
     5866-       uid_t            ae_uid;
     5867-       gid_t            ae_gid;
     5868-       const char      *ae_name;
     5869-       int              entries;
     5870-       int              i;
     5871-
     5872-       ret = ARCHIVE_OK;
     5873-       entries = archive_acl_reset(abstract_acl, ae_requested_type);
     5874-       if (entries == 0)
     5875-               return (ARCHIVE_OK);
     5876-
     5877-#if HAVE_SUN_ACL
     5878-       acl = NULL;
     5879-       acl = malloc(sizeof(acl_t));
     5880-       if (acl == NULL) {
     5881-               archive_set_error(a, ARCHIVE_ERRNO_MISC,
     5882-                       "Invalid ACL type");
     5883-               return (ARCHIVE_FAILED);
     5884-       }
     5885-       if (acl_type == ACE_T)
     5886-               acl->acl_entry_size = sizeof(ace_t);
     5887-       else if (acl_type == ACLENT_T)
     5888-               acl->acl_entry_size = sizeof(aclent_t);
     5889-       else {
     5890-               archive_set_error(a, ARCHIVE_ERRNO_MISC,
     5891-                       "Invalid ACL type");
     5892-               acl_free(acl);
     5893-               return (ARCHIVE_FAILED);
     5894-       }
     5895-       acl->acl_type = acl_type;
     5896-       acl->acl_cnt = entries;
     5897-
     5898-       acl->acl_aclp = malloc(entries * acl->acl_entry_size);
     5899-       if (acl->acl_aclp == NULL) {
     5900-               archive_set_error(a, errno,
     5901-                   "Can't allocate memory for acl buffer");
     5902-               acl_free(acl);
     5903-               return (ARCHIVE_FAILED);
     5904-       }
     5905-#else  /* !HAVE_SUN_ACL */
     5906-       acl = acl_init(entries);
     5907-       if (acl == (acl_t)NULL) {
     5908-               archive_set_error(a, errno,
     5909-                   "Failed to initialize ACL working storage");
     5910-               return (ARCHIVE_FAILED);
     5911-       }
     5912-#endif /* !HAVE_SUN_ACL */
     5913-#if HAVE_SUN_ACL
     5914-       e = 0;
     5915-#endif
     5916-       while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
     5917-                  &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
     5918-#if HAVE_SUN_ACL
     5919-               ace = NULL;
     5920-               aclent = NULL;
     5921-               if (acl->acl_type == ACE_T)  {
     5922-                       ace = &((ace_t *)acl->acl_aclp)[e];
     5923-                       ace->a_who = -1;
     5924-                       ace->a_access_mask = 0;
     5925-                       ace->a_flags = 0;
     5926-               } else {
     5927-                       aclent = &((aclent_t *)acl->acl_aclp)[e];
     5928-                       aclent->a_id = -1;
     5929-                       aclent->a_type = 0;
     5930-                       aclent->a_perm = 0;
     5931-               }
     5932-#else  /* !HAVE_SUN_ACL  */
     5933-#if HAVE_DARWIN_ACL
     5934-               /*
     5935-                * Mac OS doesn't support NFSv4 ACLs for
     5936-                * owner@, group@ and everyone@.
     5937-                * We skip any of these ACLs found.
     5938-                */
     5939-               if (ae_tag == ARCHIVE_ENTRY_ACL_USER_OBJ ||
     5940-                   ae_tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ ||
     5941-                   ae_tag == ARCHIVE_ENTRY_ACL_EVERYONE)
     5942-                       continue;
     5943-#endif
     5944-               if (acl_create_entry(&acl, &acl_entry) != 0) {
     5945-                       archive_set_error(a, errno,
     5946-                           "Failed to create a new ACL entry");
     5947-                       ret = ARCHIVE_FAILED;
     5948-                       goto exit_free;
     5949-               }
     5950-#endif /* !HAVE_SUN_ACL */
     5951-#if HAVE_DARWIN_ACL
     5952-               switch (ae_type) {
     5953-               case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
     5954-                       acl_set_tag_type(acl_entry, ACL_EXTENDED_ALLOW);
     5955-                       break;
     5956-               case ARCHIVE_ENTRY_ACL_TYPE_DENY:
     5957-                       acl_set_tag_type(acl_entry, ACL_EXTENDED_DENY);
     5958-                       break;
     5959-               default:
     5960-                       /* We don't support any other types on MacOS */
     5961-                       continue;
     5962-               }
     5963-#endif
     5964-               switch (ae_tag) {
     5965-#if HAVE_SUN_ACL
     5966-               case ARCHIVE_ENTRY_ACL_USER:
     5967-                       ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
     5968-                       if (acl->acl_type == ACE_T)
     5969-                               ace->a_who = ae_uid;
     5970-                       else {
     5971-                               aclent->a_id = ae_uid;
     5972-                               aclent->a_type |= USER;
     5973-                       }
     5974-                       break;
     5975-               case ARCHIVE_ENTRY_ACL_GROUP:
     5976-                       ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
     5977-                       if (acl->acl_type == ACE_T) {
     5978-                               ace->a_who = ae_gid;
     5979-                               ace->a_flags |= ACE_IDENTIFIER_GROUP;
     5980-                       } else {
     5981-                               aclent->a_id = ae_gid;
     5982-                               aclent->a_type |= GROUP;
     5983-                       }
     5984-                       break;
     5985-               case ARCHIVE_ENTRY_ACL_USER_OBJ:
     5986-                       if (acl->acl_type == ACE_T)
     5987-                               ace->a_flags |= ACE_OWNER;
     5988-                       else
     5989-                               aclent->a_type |= USER_OBJ;
     5990-                       break;
     5991-               case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
     5992-                       if (acl->acl_type == ACE_T) {
     5993-                               ace->a_flags |= ACE_GROUP;
     5994-                               ace->a_flags |= ACE_IDENTIFIER_GROUP;
     5995-                       } else
     5996-                               aclent->a_type |= GROUP_OBJ;
     5997-                       break;
     5998-               case ARCHIVE_ENTRY_ACL_MASK:
     5999-                       aclent->a_type |= CLASS_OBJ;
     6000-                       break;
     6001-               case ARCHIVE_ENTRY_ACL_OTHER:
     6002-                       aclent->a_type |= OTHER_OBJ;
     6003-                       break;
     6004-               case ARCHIVE_ENTRY_ACL_EVERYONE:
     6005-                       ace->a_flags |= ACE_EVERYONE;
     6006-                       break;
     6007-#else  /* !HAVE_SUN_ACL */
     6008-               case ARCHIVE_ENTRY_ACL_USER:
     6009-                       ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
     6010-#if !HAVE_DARWIN_ACL   /* FreeBSD, Linux */
     6011-                       acl_set_tag_type(acl_entry, ACL_USER);
     6012-                       acl_set_qualifier(acl_entry, &ae_uid);
     6013-#else  /* MacOS */
     6014-                       if (mbr_identifier_to_uuid(ID_TYPE_UID, &ae_uid,
     6015-                           sizeof(uid_t), ae_uuid) != 0)
     6016-                               continue;
     6017-                       if (acl_set_qualifier(acl_entry, &ae_uuid) != 0)
     6018-                               continue;
     6019-#endif /* HAVE_DARWIN_ACL */
     6020-                       break;
     6021-               case ARCHIVE_ENTRY_ACL_GROUP:
     6022-                       ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
     6023-#if !HAVE_DARWIN_ACL   /* FreeBSD, Linux */
     6024-                       acl_set_tag_type(acl_entry, ACL_GROUP);
     6025-                       acl_set_qualifier(acl_entry, &ae_gid);
     6026-#else  /* MacOS */
     6027-                       if (mbr_identifier_to_uuid(ID_TYPE_GID, &ae_gid,
     6028-                           sizeof(gid_t), ae_uuid) != 0)
     6029-                               continue;
     6030-                       if (acl_set_qualifier(acl_entry, &ae_uuid) != 0)
     6031-                               continue;
     6032-#endif /* HAVE_DARWIN_ACL */
     6033-                       break;
     6034-#if !HAVE_DARWIN_ACL   /* FreeBSD, Linux */
     6035-               case ARCHIVE_ENTRY_ACL_USER_OBJ:
     6036-                       acl_set_tag_type(acl_entry, ACL_USER_OBJ);
     6037-                       break;
     6038-               case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
     6039-                       acl_set_tag_type(acl_entry, ACL_GROUP_OBJ);
     6040-                       break;
     6041-               case ARCHIVE_ENTRY_ACL_MASK:
     6042-                       acl_set_tag_type(acl_entry, ACL_MASK);
     6043-                       break;
     6044-               case ARCHIVE_ENTRY_ACL_OTHER:
     6045-                       acl_set_tag_type(acl_entry, ACL_OTHER);
     6046-                       break;
     6047-#if HAVE_ACL_TYPE_NFS4 /* FreeBSD only */
     6048-               case ARCHIVE_ENTRY_ACL_EVERYONE:
     6049-                       acl_set_tag_type(acl_entry, ACL_EVERYONE);
     6050-                       break;
     6051-#endif
     6052-#endif /* !HAVE_DARWIN_ACL */
     6053-#endif /* !HAVE_SUN_ACL */
     6054-               default:
     6055-                       archive_set_error(a, ARCHIVE_ERRNO_MISC,
     6056-                           "Unknown ACL tag");
     6057-                       ret = ARCHIVE_FAILED;
     6058-                       goto exit_free;
     6059-               }
     6060-
     6061-#if HAVE_ACL_TYPE_NFS4 || HAVE_SUN_ACL
     6062-               r = 0;
     6063-               switch (ae_type) {
     6064-#if HAVE_SUN_ACL
     6065-               case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
     6066-                       if (ace != NULL)
     6067-                               ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
     6068-                       else
     6069-                               r = -1;
     6070-                       break;
     6071-               case ARCHIVE_ENTRY_ACL_TYPE_DENY:
     6072-                       if (ace != NULL)
     6073-                               ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
     6074-                       else
     6075-                               r = -1;
     6076-                       break;
     6077-               case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
     6078-                       if (ace != NULL)
     6079-                               ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE;
     6080-                       else
     6081-                               r = -1;
     6082-                       break;
     6083-               case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
     6084-                       if (ace != NULL)
     6085-                               ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE;
     6086-                       else
     6087-                               r = -1;
     6088-                       break;
     6089-               case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
     6090-                       if (aclent == NULL)
     6091-                               r = -1;
     6092-                       break;
     6093-               case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
     6094-                       if (aclent != NULL)
     6095-                               aclent->a_type |= ACL_DEFAULT;
     6096-                       else
     6097-                               r = -1;
     6098-                       break;
     6099-#else  /* !HAVE_SUN_ACL */
     6100-               case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
     6101-                       r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW);
     6102-                       break;
     6103-               case ARCHIVE_ENTRY_ACL_TYPE_DENY:
     6104-                       r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY);
     6105-                       break;
     6106-               case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
     6107-                       r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT);
     6108-                       break;
     6109-               case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
     6110-                       r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALARM);
     6111-                       break;
     6112-               case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
     6113-               case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
     6114-                       // These don't translate directly into the system ACL.
     6115-                       break;
     6116-#endif /* !HAVE_SUN_ACL */
     6117-               default:
     6118-                       archive_set_error(a, ARCHIVE_ERRNO_MISC,
     6119-                           "Unknown ACL entry type");
     6120-                       ret = ARCHIVE_FAILED;
     6121-                       goto exit_free;
     6122-               }
     6123-
     6124-               if (r != 0) {
     6125-#if HAVE_SUN_ACL
     6126-                       errno = EINVAL;
     6127-#endif
     6128-                       archive_set_error(a, errno,
     6129-                           "Failed to set ACL entry type");
     6130-                       ret = ARCHIVE_FAILED;
     6131-                       goto exit_free;
     6132-               }
     6133-#endif /* HAVE_ACL_TYPE_NFS4 || HAVE_SUN_ACL */
     6134-
     6135-#if HAVE_SUN_ACL
     6136-               if (acl->acl_type == ACLENT_T) {
     6137-                       if (ae_permset & ARCHIVE_ENTRY_ACL_EXECUTE)
     6138-                               aclent->a_perm |= 1;
     6139-                       if (ae_permset & ARCHIVE_ENTRY_ACL_WRITE)
     6140-                               aclent->a_perm |= 2;
     6141-                       if (ae_permset & ARCHIVE_ENTRY_ACL_READ)
     6142-                               aclent->a_perm |= 4;
     6143-               } else
     6144-#else
     6145-               if (acl_get_permset(acl_entry, &acl_permset) != 0) {
     6146-                       archive_set_error(a, errno,
     6147-                           "Failed to get ACL permission set");
     6148-                       ret = ARCHIVE_FAILED;
     6149-                       goto exit_free;
     6150-               }
     6151-               if (acl_clear_perms(acl_permset) != 0) {
     6152-                       archive_set_error(a, errno,
     6153-                           "Failed to clear ACL permissions");
     6154-                       ret = ARCHIVE_FAILED;
     6155-                       goto exit_free;
     6156-               }
     6157-#endif /* !HAVE_SUN_ACL */
     6158-               for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
     6159-                       if (ae_permset & acl_perm_map[i].archive_perm) {
     6160-#if HAVE_SUN_ACL
     6161-                               ace->a_access_mask |=
     6162-                                   acl_perm_map[i].platform_perm;
     6163-#else
     6164-                               if (acl_add_perm(acl_permset,
     6165-                                   acl_perm_map[i].platform_perm) != 0) {
     6166-                                       archive_set_error(a, errno,
     6167-                                           "Failed to add ACL permission");
     6168-                                       ret = ARCHIVE_FAILED;
     6169-                                       goto exit_free;
     6170-                               }
     6171-#endif
     6172-                       }
     6173-               }
     6174-
     6175-#if HAVE_NFS4_ACL
     6176-#if HAVE_SUN_ACL
     6177-               if (acl_type == ACE_T)
     6178-#elif HAVE_DARWIN_ACL
     6179-               if (acl_type == ACL_TYPE_EXTENDED)
     6180-#else  /* FreeBSD */
     6181-               if (acl_type == ACL_TYPE_NFS4)
     6182-#endif
     6183-               {
     6184-#if HAVE_POSIX_ACL || HAVE_DARWIN_ACL
     6185-                       /*
     6186-                        * acl_get_flagset_np() fails with non-NFSv4 ACLs
     6187-                        */
     6188-                       if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
     6189-                               archive_set_error(a, errno,
     6190-                                   "Failed to get flagset from an NFSv4 ACL entry");
     6191-                               ret = ARCHIVE_FAILED;
     6192-                               goto exit_free;
     6193-                       }
     6194-                       if (acl_clear_flags_np(acl_flagset) != 0) {
     6195-                               archive_set_error(a, errno,
     6196-                                   "Failed to clear flags from an NFSv4 ACL flagset");
     6197-                               ret = ARCHIVE_FAILED;
     6198-                               goto exit_free;
     6199-                       }
     6200-#endif /* HAVE_POSIX_ACL || HAVE_DARWIN_ACL */
     6201-                       for (i = 0; i < (int)(sizeof(acl_inherit_map) /sizeof(acl_inherit_map[0])); ++i) {
     6202-                               if (ae_permset & acl_inherit_map[i].archive_inherit) {
     6203-#if HAVE_SUN_ACL
     6204-                                       ace->a_flags |=
     6205-                                           acl_inherit_map[i].platform_inherit;
     6206-#else  /* !HAVE_SUN_ACL */
     6207-                                       if (acl_add_flag_np(acl_flagset,
     6208-                                                       acl_inherit_map[i].platform_inherit) != 0) {
     6209-                                               archive_set_error(a, errno,
     6210-                                                   "Failed to add flag to NFSv4 ACL flagset");
     6211-                                               ret = ARCHIVE_FAILED;
     6212-                                               goto exit_free;
     6213-                                       }
     6214-#endif /* HAVE_SUN_ACL */
     6215-                               }
     6216-                       }
     6217-               }
     6218-#endif /* HAVE_NFS4_ACL */
     6219-#if HAVE_SUN_ACL
     6220-       e++;
     6221-#endif
     6222-       }
     6223-
     6224-#if HAVE_ACL_SET_FD_NP || HAVE_ACL_SET_FD || HAVE_SUN_ACL
     6225-       /* Try restoring the ACL through 'fd' if we can. */
     6226-#if HAVE_SUN_ACL || HAVE_ACL_SET_FD_NP
     6227-       if (fd >= 0)
     6228-#else  /* !HAVE_SUN_ACL && !HAVE_ACL_SET_FD_NP */
     6229-       if (fd >= 0 && acl_type == ACL_TYPE_ACCESS)
     6230-#endif
     6231-       {
     6232-#if HAVE_SUN_ACL
     6233-               if (facl_set(fd, acl) == 0)
     6234-#elif HAVE_ACL_SET_FD_NP
     6235-               if (acl_set_fd_np(fd, acl, acl_type) == 0)
     6236-#else  /* !HAVE_SUN_ACL && !HAVE_ACL_SET_FD_NP */
     6237-               if (acl_set_fd(fd, acl) == 0)
     6238-#endif
     6239-                       ret = ARCHIVE_OK;
     6240-               else {
     6241-                       if (errno == EOPNOTSUPP) {
     6242-                               /* Filesystem doesn't support ACLs */
     6243-                               ret = ARCHIVE_OK;
     6244-                       } else {
     6245-                               archive_set_error(a, errno,
     6246-                                   "Failed to set %s acl on fd", tname);
     6247-                       }
     6248-               }
     6249-       } else
     6250-#endif /* HAVE_ACL_SET_FD_NP || HAVE_ACL_SET_FD || HAVE_SUN_ACL */
     6251-#if HAVE_SUN_ACL
     6252-       if (acl_set(name, acl) != 0)
     6253-#elif HAVE_ACL_SET_LINK_NP
     6254-       if (acl_set_link_np(name, acl_type, acl) != 0)
     6255-#else
     6256-       /* TODO: Skip this if 'name' is a symlink. */
     6257-       if (acl_set_file(name, acl_type, acl) != 0)
     6258-#endif
     6259-       {
     6260-               if (errno == EOPNOTSUPP) {
     6261-                       /* Filesystem doesn't support ACLs */
     6262-                       ret = ARCHIVE_OK;
     6263-               } else {
     6264-                       archive_set_error(a, errno, "Failed to set %s acl",
     6265-                           tname);
     6266-                       ret = ARCHIVE_WARN;
     6267-               }
     6268-       }
     6269-exit_free:
     6270-       acl_free(acl);
     6271-       return (ret);
     6272-}
     6273-#endif /* HAVE_POSIX_ACL || HAVE_NFS4_ACL */
     6274diff --git a/libarchive/archive_write_disk_acl_darwin.c b/libarchive/archive_write_disk_acl_darwin.c
     6275new file mode 100644
     6276index 00000000..4ffdd66b
     6277--- /dev/null
     6278+++ b/libarchive/archive_write_disk_acl_darwin.c
     6279@@ -0,0 +1,234 @@
     6280+/*-
     6281+ * Copyright (c) 2017 Martin Matuska
     6282+ * All rights reserved.
     6283+ *
     6284+ * Redistribution and use in source and binary forms, with or without
     6285+ * modification, are permitted provided that the following conditions
     6286+ * are met:
     6287+ * 1. Redistributions of source code must retain the above copyright
     6288+ *    notice, this list of conditions and the following disclaimer
     6289+ *    in this position and unchanged.
     6290+ * 2. Redistributions in binary form must reproduce the above copyright
     6291+ *    notice, this list of conditions and the following disclaimer in the
     6292+ *    documentation and/or other materials provided with the distribution.
     6293+ *
     6294+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
     6295+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     6296+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     6297+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
     6298+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     6299+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     6300+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     6301+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     6302+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     6303+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     6304+ */
     6305+
     6306+#include "archive_platform.h"
     6307+
     6308+#ifdef HAVE_SYS_TYPES_H
     6309+#include <sys/types.h>
     6310+#endif
     6311+#if HAVE_MEMBERSHIP_H
     6312+#include <membership.h>
     6313+#endif
     6314+#ifdef HAVE_ERRNO_H
     6315+#include <errno.h>
     6316+#endif
     6317+#ifdef HAVE_SYS_ACL_H
     6318+#define _ACL_PRIVATE /* For debugging */
     6319+#include <sys/acl.h>
     6320+#endif
     6321+
     6322+#include "archive.h"
     6323+#include "archive_entry.h"
     6324+#include "archive_write_disk_private.h"
     6325+#include "archive_acl_maps.h"
     6326+
     6327+static int
     6328+set_acl(struct archive *a, int fd, const char *name,
     6329+    struct archive_acl *abstract_acl,
     6330+    int ae_requested_type, const char *tname)
     6331+{
     6332+       acl_t            acl;
     6333+       acl_entry_t      acl_entry;
     6334+       acl_permset_t    acl_permset;
     6335+       acl_flagset_t    acl_flagset;
     6336+       int              ret;
     6337+       int              ae_type, ae_permset, ae_tag, ae_id;
     6338+       uuid_t           ae_uuid;
     6339+       uid_t            ae_uid;
     6340+       gid_t            ae_gid;
     6341+       const char      *ae_name;
     6342+       int              entries;
     6343+       int              i;
     6344+
     6345+       ret = ARCHIVE_OK;
     6346+       entries = archive_acl_reset(abstract_acl, ae_requested_type);
     6347+       if (entries == 0)
     6348+               return (ARCHIVE_OK);
     6349+
     6350+       if (ae_requested_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
     6351+               errno = ENOENT;
     6352+               archive_set_error(a, errno, "Unsupported ACL type");
     6353+               return (ARCHIVE_FAILED);
     6354+       }
     6355+
     6356+       acl = acl_init(entries);
     6357+       if (acl == (acl_t)NULL) {
     6358+               archive_set_error(a, errno,
     6359+                   "Failed to initialize ACL working storage");
     6360+               return (ARCHIVE_FAILED);
     6361+       }
     6362+
     6363+       while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
     6364+                  &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
     6365+               /*
     6366+                * Mac OS doesn't support NFSv4 ACLs for
     6367+                * owner@, group@ and everyone@.
     6368+                * We skip any of these ACLs found.
     6369+                */
     6370+               if (ae_tag == ARCHIVE_ENTRY_ACL_USER_OBJ ||
     6371+                   ae_tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ ||
     6372+                   ae_tag == ARCHIVE_ENTRY_ACL_EVERYONE)
     6373+                       continue;
     6374+
     6375+               if (acl_create_entry(&acl, &acl_entry) != 0) {
     6376+                       archive_set_error(a, errno,
     6377+                           "Failed to create a new ACL entry");
     6378+                       ret = ARCHIVE_FAILED;
     6379+                       goto exit_free;
     6380+               }
     6381+
     6382+               switch (ae_type) {
     6383+               case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
     6384+                       acl_set_tag_type(acl_entry, ACL_EXTENDED_ALLOW);
     6385+                       break;
     6386+               case ARCHIVE_ENTRY_ACL_TYPE_DENY:
     6387+                       acl_set_tag_type(acl_entry, ACL_EXTENDED_DENY);
     6388+                       break;
     6389+               default:
     6390+                       /* We don't support any other types on MacOS */
     6391+                       continue;
     6392+               }
     6393+
     6394+               switch (ae_tag) {
     6395+               case ARCHIVE_ENTRY_ACL_USER:
     6396+                       ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
     6397+                       if (mbr_uid_to_uuid(ae_uid, ae_uuid) != 0)
     6398+                               continue;
     6399+                       if (acl_set_qualifier(acl_entry, &ae_uuid) != 0)
     6400+                               continue;
     6401+                       break;
     6402+               case ARCHIVE_ENTRY_ACL_GROUP:
     6403+                       ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
     6404+                       if (mbr_gid_to_uuid(ae_gid, ae_uuid) != 0)
     6405+                               continue;
     6406+                       if (acl_set_qualifier(acl_entry, &ae_uuid) != 0)
     6407+                               continue;
     6408+                       break;
     6409+               default:
     6410+                       archive_set_error(a, ARCHIVE_ERRNO_MISC,
     6411+                           "Unsupported ACL tag");
     6412+                       ret = ARCHIVE_FAILED;
     6413+                       goto exit_free;
     6414+               }
     6415+
     6416+               if (acl_get_permset(acl_entry, &acl_permset) != 0) {
     6417+                       archive_set_error(a, errno,
     6418+                           "Failed to get ACL permission set");
     6419+                       ret = ARCHIVE_FAILED;
     6420+                       goto exit_free;
     6421+               }
     6422+               if (acl_clear_perms(acl_permset) != 0) {
     6423+                       archive_set_error(a, errno,
     6424+                           "Failed to clear ACL permissions");
     6425+                       ret = ARCHIVE_FAILED;
     6426+                       goto exit_free;
     6427+               }
     6428+
     6429+               for (i = 0; i < acl_nfs4_perm_map_size; ++i) {
     6430+                       if (ae_permset & acl_nfs4_perm_map[i].a_perm) {
     6431+                               if (acl_add_perm(acl_permset,
     6432+                                   acl_nfs4_perm_map[i].p_perm) != 0) {
     6433+                                       archive_set_error(a, errno,
     6434+                                           "Failed to add ACL permission");
     6435+                                       ret = ARCHIVE_FAILED;
     6436+                                       goto exit_free;
     6437+                               }
     6438+                       }
     6439+               }
     6440+
     6441+               /*
     6442+                * acl_get_flagset_np() fails with non-NFSv4 ACLs
     6443+                */
     6444+               if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
     6445+                       archive_set_error(a, errno,
     6446+                           "Failed to get flagset from an NFSv4 ACL entry");
     6447+                       ret = ARCHIVE_FAILED;
     6448+                       goto exit_free;
     6449+               }
     6450+               if (acl_clear_flags_np(acl_flagset) != 0) {
     6451+                       archive_set_error(a, errno,
     6452+                           "Failed to clear flags from an NFSv4 ACL flagset");
     6453+                       ret = ARCHIVE_FAILED;
     6454+                       goto exit_free;
     6455+               }
     6456+
     6457+               for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
     6458+                       if (ae_permset & acl_nfs4_flag_map[i].a_perm) {
     6459+                               if (acl_add_flag_np(acl_flagset,
     6460+                                   acl_nfs4_flag_map[i].p_perm) != 0) {
     6461+                                       archive_set_error(a, errno,
     6462+                                           "Failed to add flag to "
     6463+                                           "NFSv4 ACL flagset");
     6464+                                       ret = ARCHIVE_FAILED;
     6465+                                       goto exit_free;
     6466+                               }
     6467+                       }
     6468+               }
     6469+       }
     6470+
     6471+       if (fd >= 0) {
     6472+               if (acl_set_fd_np(fd, acl, ACL_TYPE_EXTENDED) == 0)
     6473+                       ret = ARCHIVE_OK;
     6474+               else {
     6475+                       if (errno == EOPNOTSUPP) {
     6476+                               /* Filesystem doesn't support ACLs */
     6477+                               ret = ARCHIVE_OK;
     6478+                       } else {
     6479+                               archive_set_error(a, errno,
     6480+                                   "Failed to set acl on fd: %s", tname);
     6481+                               ret = ARCHIVE_WARN;
     6482+                       }
     6483+               }
     6484+       } else if (acl_set_link_np(name, ACL_TYPE_EXTENDED, acl) != 0) {
     6485+               if (errno == EOPNOTSUPP) {
     6486+                       /* Filesystem doesn't support ACLs */
     6487+                       ret = ARCHIVE_OK;
     6488+               } else {
     6489+                       archive_set_error(a, errno, "Failed to set acl: %s",
     6490+                           tname);
     6491+                       ret = ARCHIVE_WARN;
     6492+               }
     6493+       }
     6494+exit_free:
     6495+       acl_free(acl);
     6496+       return (ret);
     6497+}
     6498+
     6499+int
     6500+archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
     6501+    struct archive_acl *abstract_acl, __LA_MODE_T mode)
     6502+{
     6503+       int             ret = ARCHIVE_OK;
     6504+
     6505+       (void)mode;     /* UNUSED */
     6506+
     6507+       if ((archive_acl_types(abstract_acl) &
     6508+           ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
     6509+               ret = set_acl(a, fd, name, abstract_acl,
     6510+                   ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
     6511+       }
     6512+       return (ret);
     6513+}
     6514diff --git a/libarchive/archive_write_disk_acl_freebsd.c b/libarchive/archive_write_disk_acl_freebsd.c
     6515new file mode 100644
     6516index 00000000..29e64adf
     6517--- /dev/null
     6518+++ b/libarchive/archive_write_disk_acl_freebsd.c
     6519@@ -0,0 +1,321 @@
     6520+/*-
     6521+ * Copyright (c) 2003-2010 Tim Kientzle
     6522+ * All rights reserved.
     6523+ *
     6524+ * Redistribution and use in source and binary forms, with or without
     6525+ * modification, are permitted provided that the following conditions
     6526+ * are met:
     6527+ * 1. Redistributions of source code must retain the above copyright
     6528+ *    notice, this list of conditions and the following disclaimer
     6529+ *    in this position and unchanged.
     6530+ * 2. Redistributions in binary form must reproduce the above copyright
     6531+ *    notice, this list of conditions and the following disclaimer in the
     6532+ *    documentation and/or other materials provided with the distribution.
     6533+ *
     6534+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
     6535+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     6536+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     6537+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
     6538+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     6539+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     6540+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     6541+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     6542+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     6543+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     6544+ */
     6545+
     6546+#include "archive_platform.h"
     6547+__FBSDID("$FreeBSD$");
     6548+
     6549+#ifdef HAVE_SYS_TYPES_H
     6550+#include <sys/types.h>
     6551+#endif
     6552+#ifdef HAVE_ERRNO_H
     6553+#include <errno.h>
     6554+#endif
     6555+#ifdef HAVE_SYS_ACL_H
     6556+#define _ACL_PRIVATE /* For debugging */
     6557+#include <sys/acl.h>
     6558+#endif
     6559+
     6560+#include "archive.h"
     6561+#include "archive_entry.h"
     6562+#include "archive_write_disk_private.h"
     6563+#include "archive_acl_maps.h"
     6564+
     6565+static int
     6566+set_acl(struct archive *a, int fd, const char *name,
     6567+    struct archive_acl *abstract_acl,
     6568+    int ae_requested_type, const char *tname)
     6569+{
     6570+       int              acl_type = 0;
     6571+       acl_t            acl;
     6572+       acl_entry_t      acl_entry;
     6573+       acl_permset_t    acl_permset;
     6574+#if ARCHIVE_ACL_FREEBSD_NFS4
     6575+       acl_flagset_t    acl_flagset;
     6576+       int              r;
     6577+#endif
     6578+       int              ret;
     6579+       int              ae_type, ae_permset, ae_tag, ae_id;
     6580+       int              perm_map_size;
     6581+       const acl_perm_map_t    *perm_map;
     6582+       uid_t            ae_uid;
     6583+       gid_t            ae_gid;
     6584+       const char      *ae_name;
     6585+       int              entries;
     6586+       int              i;
     6587+
     6588+       ret = ARCHIVE_OK;
     6589+       entries = archive_acl_reset(abstract_acl, ae_requested_type);
     6590+       if (entries == 0)
     6591+               return (ARCHIVE_OK);
     6592+
     6593+
     6594+       switch (ae_requested_type) {
     6595+       case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
     6596+               acl_type = ACL_TYPE_ACCESS;
     6597+               break;
     6598+       case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
     6599+               acl_type = ACL_TYPE_DEFAULT;
     6600+               break;
     6601+#if ARCHIVE_ACL_FREEBSD_NFS4
     6602+       case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
     6603+               acl_type = ACL_TYPE_NFS4;
     6604+               break;
     6605+#endif
     6606+       default:
     6607+               errno = ENOENT;
     6608+               archive_set_error(a, errno, "Unsupported ACL type");
     6609+               return (ARCHIVE_FAILED);
     6610+       }
     6611+
     6612+       acl = acl_init(entries);
     6613+       if (acl == (acl_t)NULL) {
     6614+               archive_set_error(a, errno,
     6615+                   "Failed to initialize ACL working storage");
     6616+               return (ARCHIVE_FAILED);
     6617+       }
     6618+
     6619+       while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
     6620+                  &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
     6621+               if (acl_create_entry(&acl, &acl_entry) != 0) {
     6622+                       archive_set_error(a, errno,
     6623+                           "Failed to create a new ACL entry");
     6624+                       ret = ARCHIVE_FAILED;
     6625+                       goto exit_free;
     6626+               }
     6627+               switch (ae_tag) {
     6628+               case ARCHIVE_ENTRY_ACL_USER:
     6629+                       ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
     6630+                       acl_set_tag_type(acl_entry, ACL_USER);
     6631+                       acl_set_qualifier(acl_entry, &ae_uid);
     6632+                       break;
     6633+               case ARCHIVE_ENTRY_ACL_GROUP:
     6634+                       ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
     6635+                       acl_set_tag_type(acl_entry, ACL_GROUP);
     6636+                       acl_set_qualifier(acl_entry, &ae_gid);
     6637+                       break;
     6638+               case ARCHIVE_ENTRY_ACL_USER_OBJ:
     6639+                       acl_set_tag_type(acl_entry, ACL_USER_OBJ);
     6640+                       break;
     6641+               case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
     6642+                       acl_set_tag_type(acl_entry, ACL_GROUP_OBJ);
     6643+                       break;
     6644+               case ARCHIVE_ENTRY_ACL_MASK:
     6645+                       acl_set_tag_type(acl_entry, ACL_MASK);
     6646+                       break;
     6647+               case ARCHIVE_ENTRY_ACL_OTHER:
     6648+                       acl_set_tag_type(acl_entry, ACL_OTHER);
     6649+                       break;
     6650+#if ARCHIVE_ACL_FREEBSD_NFS4
     6651+               case ARCHIVE_ENTRY_ACL_EVERYONE:
     6652+                       acl_set_tag_type(acl_entry, ACL_EVERYONE);
     6653+                       break;
     6654+#endif
     6655+               default:
     6656+                       archive_set_error(a, ARCHIVE_ERRNO_MISC,
     6657+                           "Unsupported ACL tag");
     6658+                       ret = ARCHIVE_FAILED;
     6659+                       goto exit_free;
     6660+               }
     6661+
     6662+#if ARCHIVE_ACL_FREEBSD_NFS4
     6663+               r = 0;
     6664+               switch (ae_type) {
     6665+               case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
     6666+                       r = acl_set_entry_type_np(acl_entry,
     6667+                           ACL_ENTRY_TYPE_ALLOW);
     6668+                       break;
     6669+               case ARCHIVE_ENTRY_ACL_TYPE_DENY:
     6670+                       r = acl_set_entry_type_np(acl_entry,
     6671+                           ACL_ENTRY_TYPE_DENY);
     6672+                       break;
     6673+               case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
     6674+                       r = acl_set_entry_type_np(acl_entry,
     6675+                           ACL_ENTRY_TYPE_AUDIT);
     6676+                       break;
     6677+               case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
     6678+                       r = acl_set_entry_type_np(acl_entry,
     6679+                           ACL_ENTRY_TYPE_ALARM);
     6680+                       break;
     6681+               case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
     6682+               case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
     6683+                       // These don't translate directly into the system ACL.
     6684+                       break;
     6685+               default:
     6686+                       archive_set_error(a, ARCHIVE_ERRNO_MISC,
     6687+                           "Unsupported ACL entry type");
     6688+                       ret = ARCHIVE_FAILED;
     6689+                       goto exit_free;
     6690+               }
     6691+
     6692+               if (r != 0) {
     6693+                       archive_set_error(a, errno,
     6694+                           "Failed to set ACL entry type");
     6695+                       ret = ARCHIVE_FAILED;
     6696+                       goto exit_free;
     6697+               }
     6698+#endif
     6699+
     6700+               if (acl_get_permset(acl_entry, &acl_permset) != 0) {
     6701+                       archive_set_error(a, errno,
     6702+                           "Failed to get ACL permission set");
     6703+                       ret = ARCHIVE_FAILED;
     6704+                       goto exit_free;
     6705+               }
     6706+               if (acl_clear_perms(acl_permset) != 0) {
     6707+                       archive_set_error(a, errno,
     6708+                           "Failed to clear ACL permissions");
     6709+                       ret = ARCHIVE_FAILED;
     6710+                       goto exit_free;
     6711+               }
     6712+#if ARCHIVE_ACL_FREEBSD_NFS4
     6713+               if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
     6714+                       perm_map_size = acl_nfs4_perm_map_size;
     6715+                       perm_map = acl_nfs4_perm_map;
     6716+               } else {
     6717+#endif
     6718+                       perm_map_size = acl_posix_perm_map_size;
     6719+                       perm_map = acl_posix_perm_map;
     6720+#if ARCHIVE_ACL_FREEBSD_NFS4
     6721+               }
     6722+#endif
     6723+
     6724+               for (i = 0; i < perm_map_size; ++i) {
     6725+                       if (ae_permset & perm_map[i].a_perm) {
     6726+                               if (acl_add_perm(acl_permset,
     6727+                                   perm_map[i].p_perm) != 0) {
     6728+                                       archive_set_error(a, errno,
     6729+                                           "Failed to add ACL permission");
     6730+                                       ret = ARCHIVE_FAILED;
     6731+                                       goto exit_free;
     6732+                               }
     6733+                       }
     6734+               }
     6735+
     6736+#if ARCHIVE_ACL_FREEBSD_NFS4
     6737+               if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
     6738+                       /*
     6739+                        * acl_get_flagset_np() fails with non-NFSv4 ACLs
     6740+                        */
     6741+                       if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
     6742+                               archive_set_error(a, errno,
     6743+                                   "Failed to get flagset from an NFSv4 "
     6744+                                   "ACL entry");
     6745+                               ret = ARCHIVE_FAILED;
     6746+                               goto exit_free;
     6747+                       }
     6748+                       if (acl_clear_flags_np(acl_flagset) != 0) {
     6749+                               archive_set_error(a, errno,
     6750+                                   "Failed to clear flags from an NFSv4 "
     6751+                                   "ACL flagset");
     6752+                               ret = ARCHIVE_FAILED;
     6753+                               goto exit_free;
     6754+                       }
     6755+                       for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
     6756+                               if (ae_permset & acl_nfs4_flag_map[i].a_perm) {
     6757+                                       if (acl_add_flag_np(acl_flagset,
     6758+                                           acl_nfs4_flag_map[i].p_perm) != 0) {
     6759+                                               archive_set_error(a, errno,
     6760+                                                   "Failed to add flag to "
     6761+                                                   "NFSv4 ACL flagset");
     6762+                                               ret = ARCHIVE_FAILED;
     6763+                                               goto exit_free;
     6764+                                       }
     6765+                               }
     6766+                       }
     6767+               }
     6768+#endif
     6769+       }
     6770+
     6771+       /* Try restoring the ACL through 'fd' if we can. */
     6772+       if (fd >= 0) {
     6773+               if (acl_set_fd_np(fd, acl, acl_type) == 0)
     6774+                       ret = ARCHIVE_OK;
     6775+               else {
     6776+                       if (errno == EOPNOTSUPP) {
     6777+                               /* Filesystem doesn't support ACLs */
     6778+                               ret = ARCHIVE_OK;
     6779+                       } else {
     6780+                               archive_set_error(a, errno,
     6781+                                   "Failed to set acl on fd: %s", tname);
     6782+                               ret = ARCHIVE_WARN;
     6783+                       }
     6784+               }
     6785+       }
     6786+#if HAVE_ACL_SET_LINK_NP
     6787+       else if (acl_set_link_np(name, acl_type, acl) != 0)
     6788+#else
     6789+       /* FreeBSD older than 8.0 */
     6790+       else if (acl_set_file(name, acl_type, acl) != 0)
     6791+#endif
     6792+       {
     6793+               if (errno == EOPNOTSUPP) {
     6794+                       /* Filesystem doesn't support ACLs */
     6795+                       ret = ARCHIVE_OK;
     6796+               } else {
     6797+                       archive_set_error(a, errno, "Failed to set acl: %s",
     6798+                           tname);
     6799+                       ret = ARCHIVE_WARN;
     6800+               }
     6801+       }
     6802+exit_free:
     6803+       acl_free(acl);
     6804+       return (ret);
     6805+}
     6806+
     6807+int
     6808+archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
     6809+    struct archive_acl *abstract_acl, __LA_MODE_T mode)
     6810+{
     6811+       int             ret = ARCHIVE_OK;
     6812+
     6813+       (void)mode;     /* UNUSED */
     6814+
     6815+       if ((archive_acl_types(abstract_acl)
     6816+           & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
     6817+               if ((archive_acl_types(abstract_acl)
     6818+                   & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
     6819+                       ret = set_acl(a, fd, name, abstract_acl,
     6820+                           ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
     6821+                       if (ret != ARCHIVE_OK)
     6822+                               return (ret);
     6823+               }
     6824+               if ((archive_acl_types(abstract_acl)
     6825+                   & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
     6826+                       ret = set_acl(a, fd, name, abstract_acl,
     6827+                           ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
     6828+
     6829+               /* Simultaneous POSIX.1e and NFSv4 is not supported */
     6830+               return (ret);
     6831+       }
     6832+#if ARCHIVE_ACL_FREEBSD_NFS4
     6833+       else if ((archive_acl_types(abstract_acl) &
     6834+           ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
     6835+               ret = set_acl(a, fd, name, abstract_acl,
     6836+                   ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
     6837+       }
     6838+#endif
     6839+       return (ret);
     6840+}
     6841diff --git a/libarchive/archive_write_disk_acl_linux.c b/libarchive/archive_write_disk_acl_linux.c
     6842new file mode 100644
     6843index 00000000..2239df6c
     6844--- /dev/null
     6845+++ b/libarchive/archive_write_disk_acl_linux.c
     6846@@ -0,0 +1,388 @@
     6847+/*-
     6848+ * Copyright (c) 2003-2010 Tim Kientzle
     6849+ * All rights reserved.
     6850+ *
     6851+ * Redistribution and use in source and binary forms, with or without
     6852+ * modification, are permitted provided that the following conditions
     6853+ * are met:
     6854+ * 1. Redistributions of source code must retain the above copyright
     6855+ *    notice, this list of conditions and the following disclaimer
     6856+ *    in this position and unchanged.
     6857+ * 2. Redistributions in binary form must reproduce the above copyright
     6858+ *    notice, this list of conditions and the following disclaimer in the
     6859+ *    documentation and/or other materials provided with the distribution.
     6860+ *
     6861+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
     6862+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     6863+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     6864+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
     6865+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     6866+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     6867+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     6868+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     6869+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     6870+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     6871+ */
     6872+
     6873+#include "archive_platform.h"
     6874+
     6875+#ifdef HAVE_ERRNO_H
     6876+#include <errno.h>
     6877+#endif
     6878+#ifdef HAVE_FCNTL_H
     6879+#include <fcntl.h>
     6880+#endif
     6881+#if HAVE_ACL_LIBACL_H
     6882+#include <acl/libacl.h>
     6883+#endif
     6884+#ifdef HAVE_SYS_ACL_H
     6885+#include <sys/acl.h>
     6886+#endif
     6887+#if HAVE_SYS_RICHACL_H
     6888+#include <sys/richacl.h>
     6889+#endif
     6890+
     6891+#include "archive.h"
     6892+#include "archive_entry.h"
     6893+#include "archive_write_disk_private.h"
     6894+#include "archive_acl_maps.h"
     6895+
     6896+#if ARCHIVE_ACL_LIBRICHACL
     6897+static int
     6898+_richacl_mode_to_mask(short mode)
     6899+{
     6900+       int mask = 0;
     6901+
     6902+       if (mode & S_IROTH)
     6903+               mask |= RICHACE_POSIX_MODE_READ;
     6904+       if (mode & S_IWOTH)
     6905+               mask |= RICHACE_POSIX_MODE_WRITE;
     6906+       if (mode & S_IXOTH)
     6907+               mask |= RICHACE_POSIX_MODE_EXEC;
     6908+
     6909+       return (mask);
     6910+}
     6911+
     6912+static void
     6913+_richacl_mode_to_masks(struct richacl *richacl, __LA_MODE_T mode)
     6914+{
     6915+       richacl->a_owner_mask = _richacl_mode_to_mask((mode & 0700) >> 6);
     6916+       richacl->a_group_mask = _richacl_mode_to_mask((mode & 0070) >> 3);
     6917+       richacl->a_other_mask = _richacl_mode_to_mask(mode & 0007);
     6918+}
     6919+#endif /* ARCHIVE_ACL_LIBRICHACL */
     6920+
     6921+#if ARCHIVE_ACL_LIBRICHACL
     6922+static int
     6923+set_richacl(struct archive *a, int fd, const char *name,
     6924+    struct archive_acl *abstract_acl, __LA_MODE_T mode,
     6925+    int ae_requested_type, const char *tname)
     6926+{
     6927+       int              ae_type, ae_permset, ae_tag, ae_id;
     6928+       uid_t            ae_uid;
     6929+       gid_t            ae_gid;
     6930+       const char      *ae_name;
     6931+       int              entries;
     6932+       int              i;
     6933+       int              ret;
     6934+       int              e = 0;
     6935+       struct richacl  *richacl = NULL;
     6936+       struct richace  *richace;
     6937+
     6938+       ret = ARCHIVE_OK;
     6939+       entries = archive_acl_reset(abstract_acl, ae_requested_type);
     6940+       if (entries == 0)
     6941+               return (ARCHIVE_OK);
     6942+
     6943+       if (ae_requested_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
     6944+               errno = ENOENT;
     6945+               archive_set_error(a, errno, "Unsupported ACL type");
     6946+               return (ARCHIVE_FAILED);
     6947+       }
     6948+
     6949+       richacl = richacl_alloc(entries);
     6950+       if (richacl == NULL) {
     6951+               archive_set_error(a, errno,
     6952+                       "Failed to initialize RichACL working storage");
     6953+               return (ARCHIVE_FAILED);
     6954+       }
     6955+
     6956+       e = 0;
     6957+
     6958+       while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
     6959+                  &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
     6960+               richace = &(richacl->a_entries[e]);
     6961+
     6962+               richace->e_flags = 0;
     6963+               richace->e_mask = 0;
     6964+
     6965+               switch (ae_tag) {
     6966+               case ARCHIVE_ENTRY_ACL_USER:
     6967+                       ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
     6968+                       richace->e_id = ae_uid;
     6969+                       break;
     6970+               case ARCHIVE_ENTRY_ACL_GROUP:
     6971+                       ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
     6972+                       richace->e_id = ae_gid;
     6973+                       richace->e_flags |= RICHACE_IDENTIFIER_GROUP;
     6974+                       break;
     6975+               case ARCHIVE_ENTRY_ACL_USER_OBJ:
     6976+                       richace->e_flags |= RICHACE_SPECIAL_WHO;
     6977+                       richace->e_id = RICHACE_OWNER_SPECIAL_ID;
     6978+                       break;
     6979+               case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
     6980+                       richace->e_flags |= RICHACE_SPECIAL_WHO;
     6981+                       richace->e_id = RICHACE_GROUP_SPECIAL_ID;
     6982+                       break;
     6983+               case ARCHIVE_ENTRY_ACL_EVERYONE:
     6984+                       richace->e_flags |= RICHACE_SPECIAL_WHO;
     6985+                       richace->e_id = RICHACE_EVERYONE_SPECIAL_ID;
     6986+                       break;
     6987+               default:
     6988+                       archive_set_error(a, ARCHIVE_ERRNO_MISC,
     6989+                           "Unsupported ACL tag");
     6990+                       ret = ARCHIVE_FAILED;
     6991+                       goto exit_free;
     6992+               }
     6993+
     6994+               switch (ae_type) {
     6995+                       case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
     6996+                               richace->e_type =
     6997+                                   RICHACE_ACCESS_ALLOWED_ACE_TYPE;
     6998+                               break;
     6999+                       case ARCHIVE_ENTRY_ACL_TYPE_DENY:
     7000+                               richace->e_type =
     7001+                                   RICHACE_ACCESS_DENIED_ACE_TYPE;
     7002+                               break;
     7003+                       case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
     7004+                       case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
     7005+                               break;
     7006+               default:
     7007+                       archive_set_error(a, ARCHIVE_ERRNO_MISC,
     7008+                           "Unsupported ACL entry type");
     7009+                       ret = ARCHIVE_FAILED;
     7010+                       goto exit_free;
     7011+               }
     7012+
     7013+               for (i = 0; i < acl_nfs4_perm_map_size; ++i) {
     7014+                       if (ae_permset & acl_nfs4_perm_map[i].a_perm)
     7015+                               richace->e_mask |= acl_nfs4_perm_map[i].p_perm;
     7016+               }
     7017+
     7018+               for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
     7019+                       if (ae_permset &
     7020+                           acl_nfs4_flag_map[i].a_perm)
     7021+                               richace->e_flags |= acl_nfs4_flag_map[i].p_perm;
     7022+               }
     7023+       e++;
     7024+       }
     7025+
     7026+       /* Fill RichACL masks */
     7027+       _richacl_mode_to_masks(richacl, mode);
     7028+
     7029+       if (fd >= 0) {
     7030+               if (richacl_set_fd(fd, richacl) == 0)
     7031+                       ret = ARCHIVE_OK;
     7032+               else {
     7033+                       if (errno == EOPNOTSUPP) {
     7034+                               /* Filesystem doesn't support ACLs */
     7035+                               ret = ARCHIVE_OK;
     7036+                       } else {
     7037+                               archive_set_error(a, errno,
     7038+                                   "Failed to set richacl on fd: %s", tname);
     7039+                               ret = ARCHIVE_WARN;
     7040+                       }
     7041+               }
     7042+       } else if (richacl_set_file(name, richacl) != 0) {
     7043+               if (errno == EOPNOTSUPP) {
     7044+                       /* Filesystem doesn't support ACLs */
     7045+                       ret = ARCHIVE_OK;
     7046+               } else {
     7047+                       archive_set_error(a, errno, "Failed to set richacl: %s",
     7048+                           tname);
     7049+                       ret = ARCHIVE_WARN;
     7050+               }
     7051+       }
     7052+exit_free:
     7053+       richacl_free(richacl);
     7054+       return (ret);
     7055+}
     7056+#endif /* ARCHIVE_ACL_RICHACL */
     7057+
     7058+#if ARCHIVE_ACL_LIBACL
     7059+static int
     7060+set_acl(struct archive *a, int fd, const char *name,
     7061+    struct archive_acl *abstract_acl,
     7062+    int ae_requested_type, const char *tname)
     7063+{
     7064+       int              acl_type = 0;
     7065+       int              ae_type, ae_permset, ae_tag, ae_id;
     7066+       uid_t            ae_uid;
     7067+       gid_t            ae_gid;
     7068+       const char      *ae_name;
     7069+       int              entries;
     7070+       int              i;
     7071+       int              ret;
     7072+       acl_t            acl = NULL;
     7073+       acl_entry_t      acl_entry;
     7074+       acl_permset_t    acl_permset;
     7075+
     7076+       ret = ARCHIVE_OK;
     7077+       entries = archive_acl_reset(abstract_acl, ae_requested_type);
     7078+       if (entries == 0)
     7079+               return (ARCHIVE_OK);
     7080+
     7081+       switch (ae_requested_type) {
     7082+       case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
     7083+               acl_type = ACL_TYPE_ACCESS;
     7084+               break;
     7085+       case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
     7086+               acl_type = ACL_TYPE_DEFAULT;
     7087+               break;
     7088+       default:
     7089+               errno = ENOENT;
     7090+               archive_set_error(a, errno, "Unsupported ACL type");
     7091+               return (ARCHIVE_FAILED);
     7092+       }
     7093+
     7094+       acl = acl_init(entries);
     7095+       if (acl == (acl_t)NULL) {
     7096+               archive_set_error(a, errno,
     7097+                   "Failed to initialize ACL working storage");
     7098+               return (ARCHIVE_FAILED);
     7099+       }
     7100+
     7101+       while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
     7102+                  &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
     7103+
     7104+               if (acl_create_entry(&acl, &acl_entry) != 0) {
     7105+                       archive_set_error(a, errno,
     7106+                           "Failed to create a new ACL entry");
     7107+                       ret = ARCHIVE_FAILED;
     7108+                       goto exit_free;
     7109+               }
     7110+
     7111+               switch (ae_tag) {
     7112+               case ARCHIVE_ENTRY_ACL_USER:
     7113+                       ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
     7114+                       acl_set_tag_type(acl_entry, ACL_USER);
     7115+                       acl_set_qualifier(acl_entry, &ae_uid);
     7116+                       break;
     7117+               case ARCHIVE_ENTRY_ACL_GROUP:
     7118+                       ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
     7119+                       acl_set_tag_type(acl_entry, ACL_GROUP);
     7120+                       acl_set_qualifier(acl_entry, &ae_gid);
     7121+                       break;
     7122+               case ARCHIVE_ENTRY_ACL_USER_OBJ:
     7123+                       acl_set_tag_type(acl_entry, ACL_USER_OBJ);
     7124+                       break;
     7125+               case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
     7126+                       acl_set_tag_type(acl_entry, ACL_GROUP_OBJ);
     7127+                       break;
     7128+               case ARCHIVE_ENTRY_ACL_MASK:
     7129+                       acl_set_tag_type(acl_entry, ACL_MASK);
     7130+                       break;
     7131+               case ARCHIVE_ENTRY_ACL_OTHER:
     7132+                       acl_set_tag_type(acl_entry, ACL_OTHER);
     7133+                       break;
     7134+               default:
     7135+                       archive_set_error(a, ARCHIVE_ERRNO_MISC,
     7136+                           "Unsupported ACL tag");
     7137+                       ret = ARCHIVE_FAILED;
     7138+                       goto exit_free;
     7139+               }
     7140+
     7141+               if (acl_get_permset(acl_entry, &acl_permset) != 0) {
     7142+                       archive_set_error(a, errno,
     7143+                           "Failed to get ACL permission set");
     7144+                       ret = ARCHIVE_FAILED;
     7145+                       goto exit_free;
     7146+               }
     7147+               if (acl_clear_perms(acl_permset) != 0) {
     7148+                       archive_set_error(a, errno,
     7149+                           "Failed to clear ACL permissions");
     7150+                       ret = ARCHIVE_FAILED;
     7151+                       goto exit_free;
     7152+               }
     7153+
     7154+               for (i = 0; i < acl_posix_perm_map_size; ++i) {
     7155+                       if (ae_permset & acl_posix_perm_map[i].a_perm) {
     7156+                               if (acl_add_perm(acl_permset,
     7157+                                   acl_posix_perm_map[i].p_perm) != 0) {
     7158+                                       archive_set_error(a, errno,
     7159+                                           "Failed to add ACL permission");
     7160+                                       ret = ARCHIVE_FAILED;
     7161+                                       goto exit_free;
     7162+                               }
     7163+                       }
     7164+               }
     7165+
     7166+       }
     7167+
     7168+       if (fd >= 0 && ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {
     7169+               if (acl_set_fd(fd, acl) == 0)
     7170+                       ret = ARCHIVE_OK;
     7171+               else {
     7172+                       if (errno == EOPNOTSUPP) {
     7173+                               /* Filesystem doesn't support ACLs */
     7174+                               ret = ARCHIVE_OK;
     7175+                       } else {
     7176+                               archive_set_error(a, errno,
     7177+                                   "Failed to set acl on fd: %s", tname);
     7178+                               ret = ARCHIVE_WARN;
     7179+                       }
     7180+               }
     7181+       } else if (acl_set_file(name, acl_type, acl) != 0) {
     7182+               if (errno == EOPNOTSUPP) {
     7183+                       /* Filesystem doesn't support ACLs */
     7184+                       ret = ARCHIVE_OK;
     7185+               } else {
     7186+                       archive_set_error(a, errno, "Failed to set acl: %s",
     7187+                           tname);
     7188+                       ret = ARCHIVE_WARN;
     7189+               }
     7190+       }
     7191+exit_free:
     7192+       acl_free(acl);
     7193+       return (ret);
     7194+}
     7195+#endif /* ARCHIVE_ACL_LIBACL */
     7196+
     7197+int
     7198+archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
     7199+    struct archive_acl *abstract_acl, __LA_MODE_T mode)
     7200+{
     7201+       int             ret = ARCHIVE_OK;
     7202+
     7203+#if !ARCHIVE_ACL_LIBRICHACL
     7204+       (void)mode;     /* UNUSED */
     7205+#endif
     7206+
     7207+#if ARCHIVE_ACL_LIBRICHACL
     7208+       if ((archive_acl_types(abstract_acl)
     7209+           & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
     7210+               ret = set_richacl(a, fd, name, abstract_acl, mode,
     7211+                   ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
     7212+       }
     7213+#if ARCHIVE_ACL_LIBACL
     7214+       else
     7215+#endif
     7216+#endif /* ARCHIVE_ACL_LIBRICHACL */
     7217+#if ARCHIVE_ACL_LIBACL
     7218+       if ((archive_acl_types(abstract_acl)
     7219+           & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
     7220+               if ((archive_acl_types(abstract_acl)
     7221+                   & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
     7222+                       ret = set_acl(a, fd, name, abstract_acl,
     7223+                           ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
     7224+                       if (ret != ARCHIVE_OK)
     7225+                               return (ret);
     7226+               }
     7227+               if ((archive_acl_types(abstract_acl)
     7228+                   & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
     7229+                       ret = set_acl(a, fd, name, abstract_acl,
     7230+                           ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
     7231+       }
     7232+#endif /* ARCHIVE_ACL_LIBACL */
     7233+       return (ret);
     7234+}
     7235diff --git a/libarchive/archive_write_disk_acl_sunos.c b/libarchive/archive_write_disk_acl_sunos.c
     7236new file mode 100644
     7237index 00000000..ebc0b095
     7238--- /dev/null
     7239+++ b/libarchive/archive_write_disk_acl_sunos.c
     7240@@ -0,0 +1,329 @@
     7241+/*-
     7242+ * Copyright (c) 2017 Martin Matuska
     7243+ * All rights reserved.
     7244+ *
     7245+ * Redistribution and use in source and binary forms, with or without
     7246+ * modification, are permitted provided that the following conditions
     7247+ * are met:
     7248+ * 1. Redistributions of source code must retain the above copyright
     7249+ *    notice, this list of conditions and the following disclaimer
     7250+ *    in this position and unchanged.
     7251+ * 2. Redistributions in binary form must reproduce the above copyright
     7252+ *    notice, this list of conditions and the following disclaimer in the
     7253+ *    documentation and/or other materials provided with the distribution.
     7254+ *
     7255+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
     7256+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     7257+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     7258+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
     7259+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     7260+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     7261+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     7262+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     7263+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     7264+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     7265+ */
     7266+
     7267+#include "archive_platform.h"
     7268+
     7269+#ifdef HAVE_SYS_TYPES_H
     7270+#include <sys/types.h>
     7271+#endif
     7272+#ifdef HAVE_ERRNO_H
     7273+#include <errno.h>
     7274+#endif
     7275+#ifdef HAVE_SYS_ACL_H
     7276+#define _ACL_PRIVATE /* For debugging */
     7277+#include <sys/acl.h>
     7278+#endif
     7279+
     7280+#include "archive.h"
     7281+#include "archive_entry.h"
     7282+#include "archive_write_disk_private.h"
     7283+#include "archive_acl_maps.h"
     7284+
     7285+static int
     7286+set_acl(struct archive *a, int fd, const char *name,
     7287+    struct archive_acl *abstract_acl,
     7288+    int ae_requested_type, const char *tname)
     7289+{
     7290+       aclent_t         *aclent;
     7291+#if ARCHIVE_ACL_SUNOS_NFS4
     7292+       ace_t            *ace;
     7293+#endif
     7294+       int              cmd, e, r;
     7295+       void             *aclp;
     7296+       int              ret;
     7297+       int              ae_type, ae_permset, ae_tag, ae_id;
     7298+       int              perm_map_size;
     7299+       const acl_perm_map_t    *perm_map;
     7300+       uid_t            ae_uid;
     7301+       gid_t            ae_gid;
     7302+       const char      *ae_name;
     7303+       int              entries;
     7304+       int              i;
     7305+
     7306+       ret = ARCHIVE_OK;
     7307+       entries = archive_acl_reset(abstract_acl, ae_requested_type);
     7308+       if (entries == 0)
     7309+               return (ARCHIVE_OK);
     7310+
     7311+
     7312+       switch (ae_requested_type) {
     7313+       case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
     7314+               cmd = SETACL;
     7315+               aclp = malloc(entries * sizeof(aclent_t));
     7316+               break;
     7317+#if ARCHIVE_ACL_SUNOS_NFS4
     7318+       case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
     7319+               cmd = ACE_SETACL;
     7320+               aclp = malloc(entries * sizeof(ace_t));
     7321+
     7322+               break;
     7323+#endif
     7324+       default:
     7325+               errno = ENOENT;
     7326+               archive_set_error(a, errno, "Unsupported ACL type");
     7327+               return (ARCHIVE_FAILED);
     7328+       }
     7329+
     7330+       if (aclp == NULL) {
     7331+               archive_set_error(a, errno,
     7332+                   "Can't allocate memory for acl buffer");
     7333+               return (ARCHIVE_FAILED);
     7334+       }
     7335+
     7336+       e = 0;
     7337+
     7338+       while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
     7339+                  &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
     7340+               aclent = NULL;
     7341+#if ARCHIVE_ACL_SUNOS_NFS4
     7342+               ace = NULL;
     7343+#endif
     7344+               if (cmd == SETACL) {
     7345+                       aclent = &((aclent_t *)aclp)[e];
     7346+                       aclent->a_id = -1;
     7347+                       aclent->a_type = 0;
     7348+                       aclent->a_perm = 0;
     7349+               }
     7350+#if ARCHIVE_ACL_SUNOS_NFS4
     7351+               else {  /* cmd == ACE_SETACL */
     7352+                       ace = &((ace_t *)aclp)[e];
     7353+                       ace->a_who = -1;
     7354+                       ace->a_access_mask = 0;
     7355+                       ace->a_flags = 0;
     7356+               }
     7357+#endif /* ARCHIVE_ACL_SUNOS_NFS4 */
     7358+
     7359+               switch (ae_tag) {
     7360+               case ARCHIVE_ENTRY_ACL_USER:
     7361+                       ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
     7362+                       if (aclent != NULL) {
     7363+                               aclent->a_id = ae_uid;
     7364+                               aclent->a_type |= USER;
     7365+                       }
     7366+#if ARCHIVE_ACL_SUNOS_NFS4
     7367+                       else {
     7368+                               ace->a_who = ae_uid;
     7369+                       }
     7370+#endif
     7371+                       break;
     7372+               case ARCHIVE_ENTRY_ACL_GROUP:
     7373+                       ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
     7374+                       if (aclent != NULL) {
     7375+                               aclent->a_id = ae_gid;
     7376+                               aclent->a_type |= GROUP;
     7377+                       }
     7378+#if ARCHIVE_ACL_SUNOS_NFS4
     7379+                       else {
     7380+                               ace->a_who = ae_gid;
     7381+                               ace->a_flags |= ACE_IDENTIFIER_GROUP;
     7382+                       }
     7383+#endif
     7384+                       break;
     7385+               case ARCHIVE_ENTRY_ACL_USER_OBJ:
     7386+                       if (aclent != NULL)
     7387+                               aclent->a_type |= USER_OBJ;
     7388+#if ARCHIVE_ACL_SUNOS_NFS4
     7389+                       else {
     7390+                               ace->a_flags |= ACE_OWNER;
     7391+                       }
     7392+#endif
     7393+                       break;
     7394+               case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
     7395+                       if (aclent != NULL)
     7396+                               aclent->a_type |= GROUP_OBJ;
     7397+#if ARCHIVE_ACL_SUNOS_NFS4
     7398+                       else {
     7399+                               ace->a_flags |= ACE_GROUP;
     7400+                               ace->a_flags |= ACE_IDENTIFIER_GROUP;
     7401+                       }
     7402+#endif
     7403+                       break;
     7404+               case ARCHIVE_ENTRY_ACL_MASK:
     7405+                       if (aclent != NULL)
     7406+                               aclent->a_type |= CLASS_OBJ;
     7407+                       break;
     7408+               case ARCHIVE_ENTRY_ACL_OTHER:
     7409+                       if (aclent != NULL)
     7410+                               aclent->a_type |= OTHER_OBJ;
     7411+                       break;
     7412+#if ARCHIVE_ACL_SUNOS_NFS4
     7413+               case ARCHIVE_ENTRY_ACL_EVERYONE:
     7414+                       if (ace != NULL)
     7415+                               ace->a_flags |= ACE_EVERYONE;
     7416+                       break;
     7417+#endif
     7418+               default:
     7419+                       archive_set_error(a, ARCHIVE_ERRNO_MISC,
     7420+                           "Unsupported ACL tag");
     7421+                       ret = ARCHIVE_FAILED;
     7422+                       goto exit_free;
     7423+               }
     7424+
     7425+               r = 0;
     7426+               switch (ae_type) {
     7427+#if ARCHIVE_ACL_SUNOS_NFS4
     7428+               case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
     7429+                       if (ace != NULL)
     7430+                               ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
     7431+                       else
     7432+                               r = -1;
     7433+                       break;
     7434+               case ARCHIVE_ENTRY_ACL_TYPE_DENY:
     7435+                       if (ace != NULL)
     7436+                               ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
     7437+                       else
     7438+                               r = -1;
     7439+                       break;
     7440+               case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
     7441+                       if (ace != NULL)
     7442+                               ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE;
     7443+                       else
     7444+                               r = -1;
     7445+                       break;
     7446+               case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
     7447+                       if (ace != NULL)
     7448+                               ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE;
     7449+                       else
     7450+                               r = -1;
     7451+                       break;
     7452+#endif
     7453+               case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
     7454+                       if (aclent == NULL)
     7455+                               r = -1;
     7456+                       break;
     7457+               case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
     7458+                       if (aclent != NULL)
     7459+                               aclent->a_type |= ACL_DEFAULT;
     7460+                       else
     7461+                               r = -1;
     7462+                       break;
     7463+               default:
     7464+                       archive_set_error(a, ARCHIVE_ERRNO_MISC,
     7465+                           "Unsupported ACL entry type");
     7466+                       ret = ARCHIVE_FAILED;
     7467+                       goto exit_free;
     7468+               }
     7469+
     7470+               if (r != 0) {
     7471+                       errno = EINVAL;
     7472+                       archive_set_error(a, errno,
     7473+                           "Failed to set ACL entry type");
     7474+                       ret = ARCHIVE_FAILED;
     7475+                       goto exit_free;
     7476+               }
     7477+
     7478+#if ARCHIVE_ACL_SUNOS_NFS4
     7479+               if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
     7480+                       perm_map_size = acl_nfs4_perm_map_size;
     7481+                       perm_map = acl_nfs4_perm_map;
     7482+               } else {
     7483+#endif
     7484+                       perm_map_size = acl_posix_perm_map_size;
     7485+                       perm_map = acl_posix_perm_map;
     7486+#if ARCHIVE_ACL_SUNOS_NFS4
     7487+               }
     7488+#endif
     7489+               for (i = 0; i < perm_map_size; ++i) {
     7490+                       if (ae_permset & perm_map[i].a_perm) {
     7491+#if ARCHIVE_ACL_SUNOS_NFS4
     7492+                               if (ae_requested_type ==
     7493+                                   ARCHIVE_ENTRY_ACL_TYPE_NFS4)
     7494+                                       ace->a_access_mask |=
     7495+                                           perm_map[i].p_perm;
     7496+                               else
     7497+#endif
     7498+                                       aclent->a_perm |= perm_map[i].p_perm;
     7499+                       }
     7500+               }
     7501+
     7502+#if ARCHIVE_ACL_SUNOS_NFS4
     7503+               if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
     7504+                       for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
     7505+                               if (ae_permset & acl_nfs4_flag_map[i].a_perm) {
     7506+                                       ace->a_flags |=
     7507+                                           acl_nfs4_flag_map[i].p_perm;
     7508+                               }
     7509+                       }
     7510+               }
     7511+#endif
     7512+       e++;
     7513+       }
     7514+
     7515+       /* Try restoring the ACL through 'fd' if we can. */
     7516+       if (fd >= 0) {
     7517+               if (facl(fd, cmd, entries, aclp) == 0)
     7518+                       ret = ARCHIVE_OK;
     7519+               else {
     7520+                       if (errno == EOPNOTSUPP) {
     7521+                               /* Filesystem doesn't support ACLs */
     7522+                               ret = ARCHIVE_OK;
     7523+                       } else {
     7524+                               archive_set_error(a, errno,
     7525+                                   "Failed to set acl on fd: %s", tname);
     7526+                               ret = ARCHIVE_WARN;
     7527+                       }
     7528+               }
     7529+       } else if (acl(name, cmd, entries, aclp) != 0) {
     7530+               if (errno == EOPNOTSUPP) {
     7531+                       /* Filesystem doesn't support ACLs */
     7532+                       ret = ARCHIVE_OK;
     7533+               } else {
     7534+                       archive_set_error(a, errno, "Failed to set acl: %s",
     7535+                           tname);
     7536+                       ret = ARCHIVE_WARN;
     7537+               }
     7538+       }
     7539+exit_free:
     7540+       free(aclp);
     7541+       return (ret);
     7542+}
     7543+
     7544+int
     7545+archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
     7546+    struct archive_acl *abstract_acl, __LA_MODE_T mode)
     7547+{
     7548+       int             ret = ARCHIVE_OK;
     7549+
     7550+       (void)mode;     /* UNUSED */
     7551+
     7552+       if ((archive_acl_types(abstract_acl)
     7553+           & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
     7554+               /* Solaris writes POSIX.1e access and default ACLs together */
     7555+               ret = set_acl(a, fd, name, abstract_acl,
     7556+                   ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, "posix1e");
     7557+
     7558+               /* Simultaneous POSIX.1e and NFSv4 is not supported */
     7559+               return (ret);
     7560+       }
     7561+#if ARCHIVE_ACL_SUNOS_NFS4
     7562+       else if ((archive_acl_types(abstract_acl) &
     7563+           ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
     7564+               ret = set_acl(a, fd, name, abstract_acl,
     7565+                   ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
     7566+       }
     7567+#endif
     7568+       return (ret);
     7569+}
     7570diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c
     7571index 5a01e845..adb15c0e 100644
     7572--- a/libarchive/archive_write_disk_posix.c
     7573+++ b/libarchive/archive_write_disk_posix.c
     7574@@ -575,10 +575,55 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
     7575        if (a->flags & ARCHIVE_EXTRACT_TIME)
     7576                a->todo |= TODO_TIMES;
     7577        if (a->flags & ARCHIVE_EXTRACT_ACL) {
     7578+#if ARCHIVE_ACL_DARWIN
     7579+               /*
     7580+                * On MacOS, platform ACLs get stored in mac_metadata, too.
     7581+                * If we intend to extract mac_metadata and it is present
     7582+                * we skip extracting libarchive NFSv4 ACLs.
     7583+                */
     7584+               size_t metadata_size;
     7585+
     7586+               if ((a->flags & ARCHIVE_EXTRACT_MAC_METADATA) == 0 ||
     7587+                   archive_entry_mac_metadata(a->entry,
     7588+                   &metadata_size) == NULL || metadata_size == 0)
     7589+#endif
     7590+#if ARCHIVE_ACL_LIBRICHACL
     7591+               /*
     7592+                * RichACLs are stored in an extended attribute.
     7593+                * If we intend to extract extended attributes and have this
     7594+                * attribute we skip extracting libarchive NFSv4 ACLs.
     7595+                */
     7596+               short extract_acls = 1;
     7597+               if (a->flags & ARCHIVE_EXTRACT_XATTR && (
     7598+                   archive_entry_acl_types(a->entry) &
     7599+                   ARCHIVE_ENTRY_ACL_TYPE_NFS4)) {
     7600+                       const char *attr_name;
     7601+                       const void *attr_value;
     7602+                       size_t attr_size;
     7603+                       int i = archive_entry_xattr_reset(a->entry);
     7604+                       while (i--) {
     7605+                               archive_entry_xattr_next(a->entry, &attr_name,
     7606+                                   &attr_value, &attr_size);
     7607+                               if (attr_name != NULL && attr_value != NULL &&
     7608+                                   attr_size > 0 && strcmp(attr_name,
     7609+                                   "trusted.richacl") == 0) {
     7610+                                       extract_acls = 0;
     7611+                                       break;
     7612+                               }
     7613+                       }
     7614+               }
     7615+               if (extract_acls)
     7616+#endif
     7617+#if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBRICHACL
     7618+               {
     7619+#endif
     7620                if (archive_entry_filetype(a->entry) == AE_IFDIR)
     7621                        a->deferred |= TODO_ACLS;
     7622                else
     7623                        a->todo |= TODO_ACLS;
     7624+#if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBRICHACL
     7625+               }
     7626+#endif
     7627        }
     7628        if (a->flags & ARCHIVE_EXTRACT_MAC_METADATA) {
     7629                if (archive_entry_filetype(a->entry) == AE_IFDIR)
     7630@@ -1703,25 +1748,11 @@ _archive_write_disk_finish_entry(struct archive *_a)
     7631         */
     7632        if (a->todo & TODO_ACLS) {
     7633                int r2;
     7634-#ifdef HAVE_DARWIN_ACL
     7635-               /*
     7636-                * On Mac OS, platform ACLs are stored also in mac_metadata by
     7637-                * the operating system. If mac_metadata is present it takes
     7638-                * precedence and we skip extracting libarchive NFSv4 ACLs
     7639-                */
     7640-               const void *metadata;
     7641-               size_t metadata_size;
     7642-               metadata = archive_entry_mac_metadata(a->entry, &metadata_size);
     7643-               if ((a->todo & TODO_MAC_METADATA) == 0 ||
     7644-                   metadata == NULL || metadata_size == 0) {
     7645-#endif
     7646                r2 = archive_write_disk_set_acls(&a->archive, a->fd,
     7647                    archive_entry_pathname(a->entry),
     7648-                   archive_entry_acl(a->entry));
     7649+                   archive_entry_acl(a->entry),
     7650+                   archive_entry_mode(a->entry));
     7651                if (r2 < ret) ret = r2;
     7652-#ifdef HAVE_DARWIN_ACL
     7653-               }
     7654-#endif
     7655        }
     7656 
     7657 finish_metadata:
     7658@@ -2293,13 +2324,8 @@ _archive_write_disk_close(struct archive *_a)
     7659                if (p->fixup & TODO_MODE_BASE)
     7660                        chmod(p->name, p->mode);
     7661                if (p->fixup & TODO_ACLS)
     7662-#ifdef HAVE_DARWIN_ACL
     7663-                       if ((p->fixup & TODO_MAC_METADATA) == 0 ||
     7664-                           p->mac_metadata == NULL ||
     7665-                           p->mac_metadata_size == 0)
     7666-#endif
     7667-                               archive_write_disk_set_acls(&a->archive,
     7668-                                   -1, p->name, &p->acl);
     7669+                       archive_write_disk_set_acls(&a->archive, -1, p->name,
     7670+                           &p->acl, p->mode);
     7671                if (p->fixup & TODO_FFLAGS)
     7672                        set_fflags_platform(a, -1, p->name,
     7673                            p->mode, p->fflags_set, 0);
     7674@@ -2467,7 +2493,7 @@ fsobj_error(int *a_eno, struct archive_string *a_estr,
     7675        if (a_eno)
     7676                *a_eno = err;
     7677        if (a_estr)
     7678-               archive_string_sprintf(a_estr, errstr, path);
     7679+               archive_string_sprintf(a_estr, "%s%s", errstr, path);
     7680 }
     7681 
     7682 /*
     7683@@ -2573,7 +2599,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
     7684                                 * with the deep-directory editing.
     7685                                 */
     7686                                fsobj_error(a_eno, a_estr, errno,
     7687-                                   "Could not stat %s", path);
     7688+                                   "Could not stat ", path);
     7689                                res = ARCHIVE_FAILED;
     7690                                break;
     7691                        }
     7692@@ -2582,7 +2608,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
     7693                                if (chdir(head) != 0) {
     7694                                        tail[0] = c;
     7695                                        fsobj_error(a_eno, a_estr, errno,
     7696-                                           "Could not chdir %s", path);
     7697+                                           "Could not chdir ", path);
     7698                                        res = (ARCHIVE_FATAL);
     7699                                        break;
     7700                                }
     7701@@ -2599,7 +2625,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
     7702                                if (unlink(head)) {
     7703                                        tail[0] = c;
     7704                                        fsobj_error(a_eno, a_estr, errno,
     7705-                                           "Could not remove symlink %s",
     7706+                                           "Could not remove symlink ",
     7707                                            path);
     7708                                        res = ARCHIVE_FAILED;
     7709                                        break;
     7710@@ -2618,7 +2644,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
     7711                                /*
     7712                                if (!S_ISLNK(path)) {
     7713                                        fsobj_error(a_eno, a_estr, 0,
     7714-                                           "Removing symlink %s", path);
     7715+                                           "Removing symlink ", path);
     7716                                }
     7717                                */
     7718                                /* Symlink gone.  No more problem! */
     7719@@ -2630,7 +2656,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
     7720                                        tail[0] = c;
     7721                                        fsobj_error(a_eno, a_estr, 0,
     7722                                            "Cannot remove intervening "
     7723-                                           "symlink %s", path);
     7724+                                           "symlink ", path);
     7725                                        res = ARCHIVE_FAILED;
     7726                                        break;
     7727                                }
     7728@@ -2652,7 +2678,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
     7729                                        } else {
     7730                                                fsobj_error(a_eno, a_estr,
     7731                                                    errno,
     7732-                                                   "Could not stat %s", path);
     7733+                                                   "Could not stat ", path);
     7734                                                res = (ARCHIVE_FAILED);
     7735                                                break;
     7736                                        }
     7737@@ -2661,7 +2687,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
     7738                                                tail[0] = c;
     7739                                                fsobj_error(a_eno, a_estr,
     7740                                                    errno,
     7741-                                                   "Could not chdir %s", path);
     7742+                                                   "Could not chdir ", path);
     7743                                                res = (ARCHIVE_FATAL);
     7744                                                break;
     7745                                        }
     7746@@ -2674,14 +2700,14 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
     7747                                        tail[0] = c;
     7748                                        fsobj_error(a_eno, a_estr, 0,
     7749                                            "Cannot extract through "
     7750-                                           "symlink %s", path);
     7751+                                           "symlink ", path);
     7752                                        res = ARCHIVE_FAILED;
     7753                                        break;
     7754                                }
     7755                        } else {
     7756                                tail[0] = c;
     7757                                fsobj_error(a_eno, a_estr, 0,
     7758-                                   "Cannot extract through symlink %s", path);
     7759+                                   "Cannot extract through symlink ", path);
     7760                                res = ARCHIVE_FAILED;
     7761                                break;
     7762                        }
     7763@@ -4239,5 +4265,19 @@ older(struct stat *st, struct archive_entry *entry)
     7764        return (0);
     7765 }
     7766 
     7767+#ifndef ARCHIVE_ACL_SUPPORT
     7768+int
     7769+archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
     7770+    struct archive_acl *abstract_acl, __LA_MODE_T mode)
     7771+{
     7772+       (void)a; /* UNUSED */
     7773+       (void)fd; /* UNUSED */
     7774+       (void)name; /* UNUSED */
     7775+       (void)abstract_acl; /* UNUSED */
     7776+       (void)mode; /* UNUSED */
     7777+       return (ARCHIVE_OK);
     7778+}
     7779+#endif
     7780+
     7781 #endif /* !_WIN32 || __CYGWIN__ */
     7782 
     7783diff --git a/libarchive/archive_write_disk_private.h b/libarchive/archive_write_disk_private.h
     7784index d84e7e1c..b655dea2 100644
     7785--- a/libarchive/archive_write_disk_private.h
     7786+++ b/libarchive/archive_write_disk_private.h
     7787@@ -33,11 +33,13 @@
     7788 #ifndef ARCHIVE_WRITE_DISK_PRIVATE_H_INCLUDED
     7789 #define ARCHIVE_WRITE_DISK_PRIVATE_H_INCLUDED
     7790 
     7791+#include "archive_platform_acl.h"
     7792 #include "archive_acl_private.h"
     7793+#include "archive_entry.h"
     7794 
     7795 struct archive_write_disk;
     7796 
     7797-int
     7798-archive_write_disk_set_acls(struct archive *, int /* fd */, const char * /* pathname */, struct archive_acl *);
     7799+int archive_write_disk_set_acls(struct archive *, int, const char *,
     7800+    struct archive_acl *, __LA_MODE_T);
     7801 
     7802 #endif
     7803diff --git a/libarchive/archive_write_finish_entry.3 b/libarchive/archive_write_finish_entry.3
     7804index c5ef69eb..dc1b94b8 100644
     7805--- a/libarchive/archive_write_finish_entry.3
     7806+++ b/libarchive/archive_write_finish_entry.3
     7807@@ -24,7 +24,7 @@
     7808 .\"
     7809 .\" $FreeBSD$
     7810 .\"
     7811-.Dd February 2, 2012
     7812+.Dd February 28, 2017
     7813 .Dt ARCHIVE_WRITE_FINISH_ENTRY 3
     7814 .Os
     7815 .Sh NAME
     7816@@ -45,6 +45,9 @@ is called automatically by
     7817 and
     7818 .Fn archive_write_close
     7819 as needed.
     7820+For
     7821+.Tn archive_write_disk
     7822+handles, this flushes pending file attribute changes like modification time.
     7823 .\" .Sh EXAMPLE
     7824 .Sh RETURN VALUES
     7825 This function returns
     7826diff --git a/libarchive/archive_write_format.3 b/libarchive/archive_write_format.3
     7827index d4ba6abf..aaafb0a8 100644
     7828--- a/libarchive/archive_write_format.3
     7829+++ b/libarchive/archive_write_format.3
     7830@@ -108,7 +108,6 @@ Streaming Archive Library (libarchive, -larchive)
     7831 These functions set the format that will be used for the archive.
     7832 .Pp
     7833 The library can write a variety of common archive formats.
     7834-
     7835 .Bl -tag -width indent
     7836 .It Fn archive_write_set_format
     7837 Sets the format based on the format code (see
     7838diff --git a/libarchive/mtree.5 b/libarchive/mtree.5
     7839index 16c8abec..e607e4a8 100644
     7840--- a/libarchive/mtree.5
     7841+++ b/libarchive/mtree.5
     7842@@ -48,7 +48,7 @@ Leading whitespace is always ignored.
     7843 .Pp
     7844 When encoding file or pathnames, any backslash character or
     7845 character outside of the 95 printable ASCII characters must be
     7846-encoded as a a backslash followed by three
     7847+encoded as a backslash followed by three
     7848 octal digits.
     7849 When reading mtree files, any appearance of a backslash
     7850 followed by three octal digits should be converted into the
     7851diff --git a/libarchive/test/test_acl_platform_nfs4.c b/libarchive/test/test_acl_platform_nfs4.c
     7852index 01c1dc58..a3868a62 100644
     7853--- a/libarchive/test/test_acl_platform_nfs4.c
     7854+++ b/libarchive/test/test_acl_platform_nfs4.c
     7855@@ -26,15 +26,18 @@
     7856 #include "test.h"
     7857 __FBSDID("$FreeBSD$");
     7858 
     7859-#if HAVE_POSIX_ACL || HAVE_NFS4_ACL
     7860+#if ARCHIVE_ACL_NFS4
     7861+#if HAVE_SYS_ACL_H
     7862 #define _ACL_PRIVATE
     7863 #include <sys/acl.h>
     7864-#if HAVE_DARWIN_ACL
     7865-#include <membership.h>
     7866 #endif
     7867+#if HAVE_SYS_RICHACL_H
     7868+#include <sys/richacl.h>
     7869+#endif
     7870+#if HAVE_MEMBERSHIP_H
     7871+#include <membership.h>
     7872 #endif
     7873 
     7874-#if HAVE_NFS4_ACL
     7875 struct myacl_t {
     7876        int type;
     7877        int permset;
     7878@@ -44,7 +47,7 @@ struct myacl_t {
     7879 };
     7880 
     7881 static struct myacl_t acls_reg[] = {
     7882-#if !HAVE_DARWIN_ACL
     7883+#if !ARCHIVE_ACL_DARWIN
     7884        /* For this test, we need the file owner to be able to read and write the ACL. */
     7885        { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
     7886          ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_READ_ACL | ARCHIVE_ENTRY_ACL_WRITE_ACL | ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES,
     7887@@ -91,7 +94,7 @@ static struct myacl_t acls_reg[] = {
     7888 //       ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
     7889        { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
     7890          ARCHIVE_ENTRY_ACL_GROUP, 136, "group136" },
     7891-#if !HAVE_DARWIN_ACL
     7892+#if !ARCHIVE_ACL_DARWIN
     7893        { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
     7894          ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
     7895        { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
     7896@@ -134,7 +137,7 @@ static const int acls_reg_cnt = (int)(sizeof(acls_reg)/sizeof(acls_reg[0]));
     7897 
     7898 static struct myacl_t acls_dir[] = {
     7899        /* For this test, we need to be able to read and write the ACL. */
     7900-#if !HAVE_DARWIN_ACL
     7901+#if !ARCHIVE_ACL_DARWIN
     7902        { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_READ_ACL,
     7903          ARCHIVE_ENTRY_ACL_USER_OBJ, -1, ""},
     7904 #endif
     7905@@ -180,13 +183,17 @@ static struct myacl_t acls_dir[] = {
     7906        { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
     7907          ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT,
     7908          ARCHIVE_ENTRY_ACL_USER, 302, "user302" },
     7909-#if 0
     7910        { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
     7911-         ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT,
     7912+         ARCHIVE_ENTRY_ACL_READ_DATA |
     7913+         ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT |
     7914+         ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT,
     7915          ARCHIVE_ENTRY_ACL_USER, 303, "user303" },
     7916        { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
     7917-         ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY,
     7918+         ARCHIVE_ENTRY_ACL_READ_DATA |
     7919+         ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT |
     7920+         ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY,
     7921          ARCHIVE_ENTRY_ACL_USER, 304, "user304" },
     7922+#if !defined(ARCHIVE_ACL_SUNOS_NFS4) || defined(ACE_INHERITED_ACE)
     7923        { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
     7924          ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_INHERITED,
     7925          ARCHIVE_ENTRY_ACL_USER, 305, "user305" },
     7926@@ -207,7 +214,7 @@ static struct myacl_t acls_dir[] = {
     7927          ARCHIVE_ENTRY_ACL_USER, 501, "user501" },
     7928        { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
     7929          ARCHIVE_ENTRY_ACL_GROUP, 502, "group502" },
     7930-#if !HAVE_DARWIN_ACL
     7931+#if !ARCHIVE_ACL_DARWIN
     7932        { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
     7933          ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
     7934        { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
     7935@@ -254,12 +261,14 @@ set_acls(struct archive_entry *ae, struct myacl_t *acls, int start, int end)
     7936        int i;
     7937 
     7938        archive_entry_acl_clear(ae);
     7939+#if !ARCHIVE_ACL_DARWIN
     7940        if (start > 0) {
     7941                assertEqualInt(ARCHIVE_OK,
     7942                        archive_entry_acl_add_entry(ae,
     7943                            acls[0].type, acls[0].permset, acls[0].tag,
     7944                            acls[0].qual, acls[0].name));
     7945        }
     7946+#endif
     7947        for (i = start; i < end; i++) {
     7948                assertEqualInt(ARCHIVE_OK,
     7949                    archive_entry_acl_add_entry(ae,
     7950@@ -269,76 +278,96 @@ set_acls(struct archive_entry *ae, struct myacl_t *acls, int start, int end)
     7951 }
     7952 
     7953 static int
     7954-#ifdef HAVE_SUN_ACL
     7955-acl_permset_to_bitmap(uint32_t a_access_mask)
     7956+#if ARCHIVE_ACL_SUNOS_NFS4
     7957+acl_permset_to_bitmap(uint32_t mask)
     7958+#elif ARCHIVE_ACL_LIBRICHACL
     7959+acl_permset_to_bitmap(unsigned int mask)
     7960 #else
     7961 acl_permset_to_bitmap(acl_permset_t opaque_ps)
     7962 #endif
     7963 {
     7964-       static struct { int machine; int portable; } perms[] = {
     7965-#ifdef HAVE_SUN_ACL    /* Solaris NFSv4 ACL permissions */
     7966-               {ACE_EXECUTE, ARCHIVE_ENTRY_ACL_EXECUTE},
     7967-               {ACE_READ_DATA, ARCHIVE_ENTRY_ACL_READ_DATA},
     7968-               {ACE_LIST_DIRECTORY, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY},
     7969-               {ACE_WRITE_DATA, ARCHIVE_ENTRY_ACL_WRITE_DATA},
     7970-               {ACE_ADD_FILE, ARCHIVE_ENTRY_ACL_ADD_FILE},
     7971-               {ACE_APPEND_DATA, ARCHIVE_ENTRY_ACL_APPEND_DATA},
     7972-               {ACE_ADD_SUBDIRECTORY, ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY},
     7973-               {ACE_READ_NAMED_ATTRS, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS},
     7974-               {ACE_WRITE_NAMED_ATTRS, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS},
     7975-               {ACE_DELETE_CHILD, ARCHIVE_ENTRY_ACL_DELETE_CHILD},
     7976-               {ACE_READ_ATTRIBUTES, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES},
     7977-               {ACE_WRITE_ATTRIBUTES, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES},
     7978-               {ACE_DELETE, ARCHIVE_ENTRY_ACL_DELETE},
     7979-               {ACE_READ_ACL, ARCHIVE_ENTRY_ACL_READ_ACL},
     7980-               {ACE_WRITE_ACL, ARCHIVE_ENTRY_ACL_WRITE_ACL},
     7981-               {ACE_WRITE_OWNER, ARCHIVE_ENTRY_ACL_WRITE_OWNER},
     7982-               {ACE_SYNCHRONIZE, ARCHIVE_ENTRY_ACL_SYNCHRONIZE}
     7983-#elif HAVE_DARWIN_ACL  /* MacOS NFSv4 ACL permissions */
     7984-               {ACL_READ_DATA, ARCHIVE_ENTRY_ACL_READ_DATA},
     7985-               {ACL_LIST_DIRECTORY, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY},
     7986-               {ACL_WRITE_DATA, ARCHIVE_ENTRY_ACL_WRITE_DATA},
     7987-               {ACL_ADD_FILE, ARCHIVE_ENTRY_ACL_ADD_FILE},
     7988-               {ACL_EXECUTE, ARCHIVE_ENTRY_ACL_EXECUTE},
     7989-               {ACL_DELETE, ARCHIVE_ENTRY_ACL_DELETE},
     7990-               {ACL_APPEND_DATA, ARCHIVE_ENTRY_ACL_APPEND_DATA},
     7991-               {ACL_ADD_SUBDIRECTORY, ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY},
     7992-               {ACL_DELETE_CHILD, ARCHIVE_ENTRY_ACL_DELETE_CHILD},
     7993-               {ACL_READ_ATTRIBUTES, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES},
     7994-               {ACL_WRITE_ATTRIBUTES, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES},
     7995-               {ACL_READ_EXTATTRIBUTES, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS},
     7996-               {ACL_WRITE_EXTATTRIBUTES, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS},
     7997-               {ACL_READ_SECURITY, ARCHIVE_ENTRY_ACL_READ_ACL},
     7998-               {ACL_WRITE_SECURITY, ARCHIVE_ENTRY_ACL_WRITE_ACL},
     7999-               {ACL_CHANGE_OWNER, ARCHIVE_ENTRY_ACL_WRITE_OWNER},
     8000-               {ACL_SYNCHRONIZE, ARCHIVE_ENTRY_ACL_SYNCHRONIZE},
     8001+       static struct { int portable; int machine; } perms[] = {
     8002+#ifdef ARCHIVE_ACL_SUNOS_NFS4  /* Solaris NFSv4 ACL permissions */
     8003+               {ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE},
     8004+               {ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA},
     8005+               {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY},
     8006+               {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA},
     8007+               {ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE},
     8008+               {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA},
     8009+               {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY},
     8010+               {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS},
     8011+               {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS},
     8012+               {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD},
     8013+               {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES},
     8014+               {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES},
     8015+               {ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE},
     8016+               {ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL},
     8017+               {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL},
     8018+               {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER},
     8019+               {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE}
     8020+#elif ARCHIVE_ACL_DARWIN       /* MacOS NFSv4 ACL permissions */
     8021+               {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
     8022+               {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
     8023+               {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
     8024+               {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
     8025+               {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
     8026+               {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
     8027+               {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
     8028+               {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
     8029+               {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
     8030+               {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
     8031+               {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
     8032+               {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES},
     8033+               {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES},
     8034+               {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY},
     8035+               {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY},
     8036+               {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER},
     8037+#if HAVE_DECL_ACL_SYNCHRONIZE
     8038+               {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
     8039+#endif
     8040+#elif ARCHIVE_ACL_LIBRICHACL
     8041+               {ARCHIVE_ENTRY_ACL_EXECUTE, RICHACE_EXECUTE},
     8042+               {ARCHIVE_ENTRY_ACL_READ_DATA, RICHACE_READ_DATA},
     8043+               {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, RICHACE_LIST_DIRECTORY},
     8044+               {ARCHIVE_ENTRY_ACL_WRITE_DATA, RICHACE_WRITE_DATA},
     8045+               {ARCHIVE_ENTRY_ACL_ADD_FILE, RICHACE_ADD_FILE},
     8046+               {ARCHIVE_ENTRY_ACL_APPEND_DATA, RICHACE_APPEND_DATA},
     8047+               {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, RICHACE_ADD_SUBDIRECTORY},
     8048+               {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, RICHACE_READ_NAMED_ATTRS},
     8049+               {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, RICHACE_WRITE_NAMED_ATTRS},
     8050+               {ARCHIVE_ENTRY_ACL_DELETE_CHILD, RICHACE_DELETE_CHILD},
     8051+               {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, RICHACE_READ_ATTRIBUTES},
     8052+               {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, RICHACE_WRITE_ATTRIBUTES},
     8053+               {ARCHIVE_ENTRY_ACL_DELETE, RICHACE_DELETE},
     8054+               {ARCHIVE_ENTRY_ACL_READ_ACL, RICHACE_READ_ACL},
     8055+               {ARCHIVE_ENTRY_ACL_WRITE_ACL, RICHACE_WRITE_ACL},
     8056+               {ARCHIVE_ENTRY_ACL_WRITE_OWNER, RICHACE_WRITE_OWNER},
     8057+               {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, RICHACE_SYNCHRONIZE}
     8058 #else  /* FreeBSD NFSv4 ACL permissions */
     8059-               {ACL_EXECUTE, ARCHIVE_ENTRY_ACL_EXECUTE},
     8060-               {ACL_WRITE, ARCHIVE_ENTRY_ACL_WRITE},
     8061-               {ACL_READ, ARCHIVE_ENTRY_ACL_READ},
     8062-               {ACL_READ_DATA, ARCHIVE_ENTRY_ACL_READ_DATA},
     8063-               {ACL_LIST_DIRECTORY, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY},
     8064-               {ACL_WRITE_DATA, ARCHIVE_ENTRY_ACL_WRITE_DATA},
     8065-               {ACL_ADD_FILE, ARCHIVE_ENTRY_ACL_ADD_FILE},
     8066-               {ACL_APPEND_DATA, ARCHIVE_ENTRY_ACL_APPEND_DATA},
     8067-               {ACL_ADD_SUBDIRECTORY, ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY},
     8068-               {ACL_READ_NAMED_ATTRS, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS},
     8069-               {ACL_WRITE_NAMED_ATTRS, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS},
     8070-               {ACL_DELETE_CHILD, ARCHIVE_ENTRY_ACL_DELETE_CHILD},
     8071-               {ACL_READ_ATTRIBUTES, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES},
     8072-               {ACL_WRITE_ATTRIBUTES, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES},
     8073-               {ACL_DELETE, ARCHIVE_ENTRY_ACL_DELETE},
     8074-               {ACL_READ_ACL, ARCHIVE_ENTRY_ACL_READ_ACL},
     8075-               {ACL_WRITE_ACL, ARCHIVE_ENTRY_ACL_WRITE_ACL},
     8076-               {ACL_WRITE_OWNER, ARCHIVE_ENTRY_ACL_WRITE_OWNER},
     8077-               {ACL_SYNCHRONIZE, ARCHIVE_ENTRY_ACL_SYNCHRONIZE}
     8078+               {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
     8079+               {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
     8080+               {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
     8081+               {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
     8082+               {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
     8083+               {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
     8084+               {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
     8085+               {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
     8086+               {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
     8087+               {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
     8088+               {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
     8089+               {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
     8090+               {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
     8091+               {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
     8092+               {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
     8093+               {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
     8094+               {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
     8095 #endif
     8096        };
     8097        int i, permset = 0;
     8098 
     8099        for (i = 0; i < (int)(sizeof(perms)/sizeof(perms[0])); ++i)
     8100-#if HAVE_SUN_ACL
     8101-               if (a_access_mask & perms[i].machine)
     8102+#if ARCHIVE_ACL_SUNOS_NFS4 || ARCHIVE_ACL_LIBRICHACL
     8103+               if (mask & perms[i].machine)
     8104 #else
     8105                if (acl_get_perm_np(opaque_ps, perms[i].machine))
     8106 #endif
     8107@@ -347,88 +376,70 @@ acl_permset_to_bitmap(acl_permset_t opaque_ps)
     8108 }
     8109 
     8110 static int
     8111-#if HAVE_SUN_ACL
     8112-acl_flagset_to_bitmap(uint16_t a_flags)
     8113+#if ARCHIVE_ACL_SUNOS_NFS4
     8114+acl_flagset_to_bitmap(uint16_t flags)
     8115+#elif ARCHIVE_ACL_LIBRICHACL
     8116+acl_flagset_to_bitmap(int flags)
     8117 #else
     8118 acl_flagset_to_bitmap(acl_flagset_t opaque_fs)
     8119 #endif
     8120 {
     8121-       static struct { int machine; int portable; } flags[] = {
     8122-#if HAVE_SUN_ACL       /* Solaris NFSv4 ACL inheritance flags */
     8123-               {ACE_FILE_INHERIT_ACE, ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT},
     8124-               {ACE_DIRECTORY_INHERIT_ACE, ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT},
     8125-               {ACE_NO_PROPAGATE_INHERIT_ACE, ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT},
     8126-               {ACE_INHERIT_ONLY_ACE, ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY},
     8127-               {ACE_SUCCESSFUL_ACCESS_ACE_FLAG, ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS},
     8128-               {ACE_FAILED_ACCESS_ACE_FLAG, ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS},
     8129-               {ACE_INHERITED_ACE, ARCHIVE_ENTRY_ACL_ENTRY_INHERITED}
     8130-#elif HAVE_DARWIN_ACL  /* MacOS NFSv4 ACL inheritance flags */
     8131-               {ACL_ENTRY_INHERITED, ARCHIVE_ENTRY_ACL_ENTRY_INHERITED},
     8132-               {ACL_ENTRY_FILE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT},
     8133-               {ACL_ENTRY_DIRECTORY_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT},
     8134-               {ACL_ENTRY_LIMIT_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT},
     8135-               {ACL_ENTRY_ONLY_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY}
     8136+       static struct { int portable; int machine; } perms[] = {
     8137+#if ARCHIVE_ACL_SUNOS_NFS4     /* Solaris NFSv4 ACL inheritance flags */
     8138+               {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE},
     8139+               {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE},
     8140+               {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE},
     8141+               {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE},
     8142+               {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
     8143+               {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG},
     8144+#ifdef ACE_INHERITED_ACE
     8145+               {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}
     8146+#endif
     8147+#elif ARCHIVE_ACL_DARWIN       /* MacOS NFSv4 ACL inheritance flags */
     8148+               {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED},
     8149+               {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
     8150+               {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
     8151+               {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_LIMIT_INHERIT},
     8152+               {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT}
     8153+#elif ARCHIVE_ACL_LIBRICHACL
     8154+               {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, RICHACE_FILE_INHERIT_ACE},
     8155+               {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, RICHACE_DIRECTORY_INHERIT_ACE},
     8156+               {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, RICHACE_NO_PROPAGATE_INHERIT_ACE},
     8157+               {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, RICHACE_INHERIT_ONLY_ACE},
     8158+               {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, RICHACE_INHERITED_ACE}
     8159 #else  /* FreeBSD NFSv4 ACL inheritance flags */
     8160-               {ACL_ENTRY_FILE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT},
     8161-               {ACL_ENTRY_DIRECTORY_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT},
     8162-               {ACL_ENTRY_NO_PROPAGATE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT},
     8163-               {ACL_ENTRY_SUCCESSFUL_ACCESS, ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS},
     8164-               {ACL_ENTRY_NO_PROPAGATE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS},
     8165-               {ACL_ENTRY_INHERIT_ONLY, ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY},
     8166+               {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED},
     8167+               {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
     8168+               {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
     8169+               {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
     8170+               {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
     8171+               {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
     8172+               {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}
     8173 #endif
     8174        };
     8175        int i, flagset = 0;
     8176 
     8177-       for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); ++i)
     8178-#if HAVE_SUN_ACL
     8179-               if (a_flags & flags[i].machine)
     8180+       for (i = 0; i < (int)(sizeof(perms)/sizeof(perms[0])); ++i)
     8181+#if ARCHIVE_ACL_SUNOS_NFS4 || ARCHIVE_ACL_LIBRICHACL
     8182+               if (flags & perms[i].machine)
     8183 #else
     8184-               if (acl_get_flag_np(opaque_fs, flags[i].machine))
     8185+               if (acl_get_flag_np(opaque_fs, perms[i].machine))
     8186 #endif
     8187-                       flagset |= flags[i].portable;
     8188+                       flagset |= perms[i].portable;
     8189        return flagset;
     8190 }
     8191 
     8192+#if ARCHIVE_ACL_SUNOS_NFS4
     8193 static int
     8194-#if HAVE_SUN_ACL
     8195 acl_match(ace_t *ace, struct myacl_t *myacl)
     8196-#else
     8197-acl_match(acl_entry_t aclent, struct myacl_t *myacl)
     8198-#endif
     8199 {
     8200-#if !HAVE_SUN_ACL
     8201-#if HAVE_DARWIN_ACL
     8202-       void *q;
     8203-       uid_t ugid;
     8204-       int r, idtype;
     8205-#else
     8206-       gid_t g, *gp;
     8207-       uid_t u, *up;
     8208-       acl_entry_type_t entry_type;
     8209-#endif /* !HAVE_DARWIN_ACL */
     8210-       acl_tag_t tag_type;
     8211-       acl_permset_t opaque_ps;
     8212-       acl_flagset_t opaque_fs;
     8213-#endif /* !HAVE_SUN_ACL */
     8214        int perms;
     8215 
     8216-#if HAVE_SUN_ACL
     8217        perms = acl_permset_to_bitmap(ace->a_access_mask) | acl_flagset_to_bitmap(ace->a_flags);
     8218-#else
     8219-       acl_get_tag_type(aclent, &tag_type);
     8220-#if !HAVE_DARWIN_ACL
     8221-       acl_get_entry_type_np(aclent, &entry_type);
     8222-#endif
     8223 
     8224-       /* translate the silly opaque permset to a bitmap */
     8225-       acl_get_permset(aclent, &opaque_ps);
     8226-       acl_get_flagset_np(aclent, &opaque_fs);
     8227-       perms = acl_permset_to_bitmap(opaque_ps) | acl_flagset_to_bitmap(opaque_fs);
     8228-#endif
     8229        if (perms != myacl->permset)
     8230                return (0);
     8231 
     8232-#if HAVE_SUN_ACL
     8233        switch (ace->a_type) {
     8234        case ACE_ACCESS_ALLOWED_ACE_TYPE:
     8235                if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW)
     8236@@ -470,7 +481,85 @@ acl_match(acl_entry_t aclent, struct myacl_t *myacl)
     8237                if ((uid_t)myacl->qual != ace->a_who)
     8238                        return (0);
     8239        }
     8240-#elif HAVE_DARWIN_ACL
     8241+       return (1);
     8242+}
     8243+#elif ARCHIVE_ACL_LIBRICHACL
     8244+static int
     8245+acl_match(struct richace *richace, struct myacl_t *myacl)
     8246+{
     8247+       int perms;
     8248+
     8249+       perms = acl_permset_to_bitmap(richace->e_mask) |
     8250+           acl_flagset_to_bitmap(richace->e_flags);
     8251+
     8252+       if (perms != myacl->permset)
     8253+               return (0);
     8254+
     8255+       switch (richace->e_type) {
     8256+       case RICHACE_ACCESS_ALLOWED_ACE_TYPE:
     8257+               if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW)
     8258+                       return (0);
     8259+               break;
     8260+       case RICHACE_ACCESS_DENIED_ACE_TYPE:
     8261+               if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_DENY)
     8262+                       return (0);
     8263+               break;
     8264+       default:
     8265+               return (0);
     8266+       }
     8267+
     8268+       if (richace->e_flags & RICHACE_SPECIAL_WHO) {
     8269+               switch (richace->e_id) {
     8270+               case RICHACE_OWNER_SPECIAL_ID:
     8271+                       if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ)
     8272+                               return (0);
     8273+                       break;
     8274+               case RICHACE_GROUP_SPECIAL_ID:
     8275+                       if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ)
     8276+                               return (0);
     8277+                       break;
     8278+               case RICHACE_EVERYONE_SPECIAL_ID:
     8279+                       if (myacl->tag != ARCHIVE_ENTRY_ACL_EVERYONE)
     8280+                               return (0);
     8281+                       break;
     8282+               default:
     8283+                       /* Invalid e_id */
     8284+                       return (0);
     8285+               }
     8286+       } else if (richace->e_flags & RICHACE_IDENTIFIER_GROUP) {
     8287+               if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
     8288+                       return (0);
     8289+               if ((gid_t)myacl->qual != richace->e_id)
     8290+                       return (0);
     8291+       } else {
     8292+               if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
     8293+                       return (0);
     8294+               if ((uid_t)myacl->qual != richace->e_id)
     8295+                       return (0);
     8296+       }
     8297+       return (1);
     8298+}
     8299+#elif ARCHIVE_ACL_DARWIN
     8300+static int
     8301+acl_match(acl_entry_t aclent, struct myacl_t *myacl)
     8302+{
     8303+       void *q;
     8304+       uid_t ugid;
     8305+       int r, idtype;
     8306+       acl_tag_t tag_type;
     8307+       acl_permset_t opaque_ps;
     8308+       acl_flagset_t opaque_fs;
     8309+       int perms;
     8310+
     8311+       acl_get_tag_type(aclent, &tag_type);
     8312+
     8313+       /* translate the silly opaque permset to a bitmap */
     8314+       acl_get_permset(aclent, &opaque_ps);
     8315+       acl_get_flagset_np(aclent, &opaque_fs);
     8316+       perms = acl_permset_to_bitmap(opaque_ps) | acl_flagset_to_bitmap(opaque_fs);
     8317+       if (perms != myacl->permset)
     8318+               return (0);
     8319+
     8320        r = 0;
     8321        switch (tag_type) {
     8322        case ACL_EXTENDED_ALLOW:
     8323@@ -507,7 +596,30 @@ acl_match(acl_entry_t aclent, struct myacl_t *myacl)
     8324                default:
     8325                        return (0);
     8326        }
     8327-#else  /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
     8328+       return (1);
     8329+}
     8330+#else /* ARCHIVE_ACL_FREEBSD_NFS4 */
     8331+static int
     8332+acl_match(acl_entry_t aclent, struct myacl_t *myacl)
     8333+{
     8334+       gid_t g, *gp;
     8335+       uid_t u, *up;
     8336+       acl_entry_type_t entry_type;
     8337+       acl_tag_t tag_type;
     8338+       acl_permset_t opaque_ps;
     8339+       acl_flagset_t opaque_fs;
     8340+       int perms;
     8341+
     8342+       acl_get_tag_type(aclent, &tag_type);
     8343+       acl_get_entry_type_np(aclent, &entry_type);
     8344+
     8345+       /* translate the silly opaque permset to a bitmap */
     8346+       acl_get_permset(aclent, &opaque_ps);
     8347+       acl_get_flagset_np(aclent, &opaque_fs);
     8348+       perms = acl_permset_to_bitmap(opaque_ps) | acl_flagset_to_bitmap(opaque_fs);
     8349+       if (perms != myacl->permset)
     8350+               return (0);
     8351+
     8352        switch (entry_type) {
     8353        case ACL_ENTRY_TYPE_ALLOW:
     8354                if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW)
     8355@@ -559,14 +671,17 @@ acl_match(acl_entry_t aclent, struct myacl_t *myacl)
     8356                if (myacl->tag != ARCHIVE_ENTRY_ACL_EVERYONE) return (0);
     8357                break;
     8358        }
     8359-#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
     8360        return (1);
     8361 }
     8362+#endif /* various ARCHIVE_ACL_NFS4 implementations */
     8363 
     8364 static void
     8365 compare_acls(
     8366-#if HAVE_SUN_ACL
     8367-    acl_t *acl,
     8368+#if ARCHIVE_ACL_SUNOS_NFS4
     8369+    void *aclp,
     8370+    int aclcnt,
     8371+#elif ARCHIVE_ACL_LIBRICHACL
     8372+    struct richacl *richacl,
     8373 #else
     8374     acl_t acl,
     8375 #endif
     8376@@ -575,38 +690,61 @@ compare_acls(
     8377        int *marker;
     8378        int matched;
     8379        int i, n;
     8380-#if HAVE_SUN_ACL
     8381+#if ARCHIVE_ACL_SUNOS_NFS4
     8382        int e;
     8383        ace_t *acl_entry;
     8384+#elif ARCHIVE_ACL_LIBRICHACL
     8385+       int e;
     8386+       struct richace *acl_entry;
     8387+       int aclcnt;
     8388 #else
     8389        int entry_id = ACL_FIRST_ENTRY;
     8390        acl_entry_t acl_entry;
     8391+#if ARCHIVE_ACL_DARWIN
     8392+       const int acl_get_entry_ret = 0;
     8393+#else
     8394+       const int acl_get_entry_ret = 1;
     8395+#endif
     8396+#endif
     8397+
     8398+#if ARCHIVE_ACL_SUNOS_NFS4
     8399+       if (aclp == NULL)
     8400+               return;
     8401+#elif ARCHIVE_ACL_LIBRICHACL
     8402+       if (richacl == NULL)
     8403+               return;
     8404+       aclcnt = richacl->a_count;
     8405+#else
     8406+       if (acl == NULL)
     8407+               return;
     8408 #endif
     8409 
     8410        n = end - start;
     8411        marker = malloc(sizeof(marker[0]) * (n + 1));
     8412        for (i = 0; i < n; i++)
     8413                marker[i] = i + start;
     8414+#if !ARCHIVE_ACL_DARWIN
     8415        /* Always include the first ACE. */
     8416        if (start > 0) {
     8417          marker[n] = 0;
     8418          ++n;
     8419        }
     8420+#endif
     8421 
     8422        /*
     8423         * Iterate over acls in system acl object, try to match each
     8424         * one with an item in the myacls array.
     8425         */
     8426-#if HAVE_SUN_ACL
     8427-       for (e = 0; e < acl->acl_cnt; e++)
     8428-#elif HAVE_DARWIN_ACL
     8429-       while (0 == acl_get_entry(acl, entry_id, &acl_entry))
     8430+#if ARCHIVE_ACL_SUNOS_NFS4 || ARCHIVE_ACL_LIBRICHACL
     8431+       for (e = 0; e < aclcnt; e++)
     8432 #else
     8433-       while (1 == acl_get_entry(acl, entry_id, &acl_entry))
     8434+       while (acl_get_entry_ret == acl_get_entry(acl, entry_id, &acl_entry))
     8435 #endif
     8436        {
     8437-#if HAVE_SUN_ACL
     8438-               acl_entry = &((ace_t *)acl->acl_aclp)[e];
     8439+#if ARCHIVE_ACL_SUNOS_NFS4
     8440+               acl_entry = &((ace_t *)aclp)[e];
     8441+#elif ARCHIVE_ACL_LIBRICHACL
     8442+               acl_entry = &(richacl->a_entries[e]);
     8443 #else
     8444                /* After the first time... */
     8445                entry_id = ACL_NEXT_ENTRY;
     8446@@ -699,7 +837,7 @@ compare_entry_acls(struct archive_entry *ae, struct myacl_t *myacls, const char
     8447        }
     8448        free(marker);
     8449 }
     8450-#endif /* HAVE_NFS4_ACL */
     8451+#endif /* ARCHIVE_ACL_NFS4 */
     8452 
     8453 /*
     8454  * Verify ACL restore-to-disk.  This test is Platform-specific.
     8455@@ -707,101 +845,36 @@ compare_entry_acls(struct archive_entry *ae, struct myacl_t *myacls, const char
     8456 
     8457 DEFINE_TEST(test_acl_platform_nfs4)
     8458 {
     8459-#if !HAVE_NFS4_ACL
     8460+#if !ARCHIVE_ACL_NFS4
     8461        skipping("NFS4 ACLs are not supported on this platform");
     8462-#else
     8463+#else /* ARCHIVE_ACL_NFS4 */
     8464        char buff[64];
     8465+       int i;
     8466        struct stat st;
     8467        struct archive *a;
     8468        struct archive_entry *ae;
     8469-       int i, n;
     8470-       char *func;
     8471-#if HAVE_DARWIN_ACL /* On MacOS we skip trivial ACLs in some tests */
     8472+#if ARCHIVE_ACL_DARWIN /* On MacOS we skip trivial ACLs in some tests */
     8473        const int regcnt = acls_reg_cnt - 4;
     8474        const int dircnt = acls_dir_cnt - 4;
     8475 #else
     8476        const int regcnt = acls_reg_cnt;
     8477        const int dircnt = acls_dir_cnt;
     8478 #endif
     8479-#if HAVE_SUN_ACL
     8480-       acl_t *acl;
     8481-#else  /* !HAVE_SUN_ACL */
     8482-#if HAVE_DARWIN_ACL
     8483-       acl_entry_t aclent;
     8484-       acl_permset_t permset;
     8485-       const uid_t uid = 1000;
     8486-       uuid_t uuid;
     8487-#endif /* HAVE_DARWIN_ACL */
     8488+#if ARCHIVE_ACL_SUNOS_NFS4
     8489+       void *aclp;
     8490+       int aclcnt;
     8491+#elif ARCHIVE_ACL_LIBRICHACL
     8492+       struct richacl *richacl;
     8493+#else  /* !ARCHIVE_ACL_SUNOS_NFS4 */
     8494        acl_t acl;
     8495-#endif /* !HAVE_SUN_ACL */
     8496-
     8497-       /*
     8498-        * First, do a quick manual set/read of ACL data to
     8499-        * verify that the local filesystem does support ACLs.
     8500-        * If it doesn't, we'll simply skip the remaining tests.
     8501-        */
     8502-#if HAVE_POSIX_ACL && HAVE_ACL_TYPE_NFS4
     8503-       acl = acl_from_text("owner@:rwxp::allow,group@:rwp:f:allow");
     8504-       failure("acl_from_text(): errno = %d (%s)", errno, strerror(errno));
     8505-       assert((void *)acl != NULL);
     8506-#elif HAVE_DARWIN_ACL
     8507-       acl = acl_init(1);
     8508-       assert((void *)acl != NULL);
     8509-       assertEqualInt(0, acl_create_entry(&acl, &aclent));
     8510-       assertEqualInt(0, acl_set_tag_type(aclent, ACL_EXTENDED_ALLOW));
     8511-       assertEqualInt(0, acl_get_permset(aclent, &permset));
     8512-       assertEqualInt(0, acl_add_perm(permset, ACL_READ_DATA));
     8513-       assertEqualInt(0, acl_add_perm(permset, ACL_WRITE_DATA));
     8514-       assertEqualInt(0, acl_add_perm(permset, ACL_APPEND_DATA));
     8515-       assertEqualInt(0, acl_add_perm(permset, ACL_EXECUTE));
     8516-       assertEqualInt(0, acl_set_permset(aclent, permset));
     8517-       assertEqualInt(0, mbr_identifier_to_uuid(ID_TYPE_UID, &uid,
     8518-           sizeof(uid_t), uuid));
     8519-       assertEqualInt(0, acl_set_qualifier(aclent, uuid));
     8520-#endif
     8521-
     8522-       /* Create a test dir and try to set an ACL on it. */
     8523-       if (!assertMakeDir("pretest", 0755)) {
     8524-#if !HAVE_SUN_ACL
     8525-               acl_free(acl);
     8526 #endif
     8527-               return;
     8528-       }
     8529 
     8530-#if HAVE_SUN_ACL
     8531-       func = "acl_get()";
     8532-       n = acl_get("pretest", 0, &acl);
     8533-#else
     8534-       func = "acl_set_file()";
     8535-#if HAVE_DARWIN_ACL
     8536-       n = acl_set_file("pretest", ACL_TYPE_EXTENDED, acl);
     8537-#else
     8538-       n = acl_set_file("pretest", ACL_TYPE_NFS4, acl);
     8539-#endif
     8540-       acl_free(acl);
     8541-#endif
     8542-       if (n != 0) {
     8543-#if HAVE_SUN_ACL
     8544-               if (errno == ENOSYS)
     8545-#else
     8546-               if (errno == EOPNOTSUPP || errno == EINVAL)
     8547-#endif
     8548-               {
     8549-                       skipping("NFS4 ACL is not supported on this filesystem");
     8550-                       return;
     8551-               }
     8552-       }
     8553-       failure("%s: errno = %d (%s)", func, errno, strerror(errno));
     8554-       assertEqualInt(0, n);
     8555+       assertMakeFile("pretest", 0644, "a");
     8556 
     8557-#if HAVE_SUN_ACL
     8558-       if (acl->acl_type != ACE_T) {
     8559-               acl_free(acl);
     8560-               skipping("NFS4 ACL is not supported on this filesystem");
     8561+       if (setTestAcl("pretest") != ARCHIVE_TEST_ACL_TYPE_NFS4) {
     8562+               skipping("NFS4 ACLs are not writable on this filesystem");
     8563                return;
     8564        }
     8565-       acl_free(acl);
     8566-#endif
     8567 
     8568        /* Create a write-to-disk object. */
     8569        assert(NULL != (a = archive_write_disk_new()));
     8570@@ -848,63 +921,115 @@ DEFINE_TEST(test_acl_platform_nfs4)
     8571        /* Verify the data on disk. */
     8572        assertEqualInt(0, stat("testall", &st));
     8573        assertEqualInt(st.st_mtime, 123456);
     8574-#if HAVE_SUN_ACL
     8575-       n = acl_get("testall", 0, &acl);
     8576-       failure("acl_get(): errno = %d (%s)", errno, strerror(errno));
     8577-       assertEqualInt(0, n);
     8578+#if ARCHIVE_ACL_SUNOS_NFS4
     8579+       aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, "testall");
     8580+       failure("acl(\"%s\"): errno = %d (%s)", "testall", errno,
     8581+           strerror(errno));
     8582+       assert(aclp != NULL);
     8583+#elif ARCHIVE_ACL_LIBRICHACL
     8584+       richacl = richacl_get_file("testall");
     8585+       failure("richacl_get_file(\"%s\"): errno = %d (%s)", "testall", errno,
     8586+           strerror(errno));
     8587+       assert(richacl != NULL);
     8588 #else
     8589-#if HAVE_DARWIN_ACL
     8590+#if ARCHIVE_ACL_DARWIN
     8591        acl = acl_get_file("testall", ACL_TYPE_EXTENDED);
     8592 #else
     8593        acl = acl_get_file("testall", ACL_TYPE_NFS4);
     8594 #endif
     8595-       failure("acl_get_file(): errno = %d (%s)", errno, strerror(errno));
     8596+       failure("acl_get_file(\"%s\"): errno = %d (%s)", "testall", errno,
     8597+           strerror(errno));
     8598        assert(acl != (acl_t)NULL);
     8599 #endif
     8600+#if ARCHIVE_ACL_SUNOS_NFS4
     8601+       compare_acls(aclp, aclcnt, acls_reg, "testall", 0, regcnt);
     8602+       free(aclp);
     8603+       aclp = NULL;
     8604+#elif ARCHIVE_ACL_LIBRICHACL
     8605+       compare_acls(richacl, acls_reg, "testall", 0, regcnt);
     8606+       richacl_free(richacl);
     8607+#else
     8608        compare_acls(acl, acls_reg, "testall", 0, regcnt);
     8609        acl_free(acl);
     8610+#endif
     8611+
     8612 
     8613        /* Verify single-permission dirs on disk. */
     8614        for (i = 0; i < dircnt; ++i) {
     8615                sprintf(buff, "dir%d", i);
     8616                assertEqualInt(0, stat(buff, &st));
     8617                assertEqualInt(st.st_mtime, 123456 + i);
     8618-#if HAVE_SUN_ACL
     8619-               n = acl_get(buff, 0, &acl);
     8620-               failure("acl_get(): errno = %d (%s)", errno, strerror(errno));
     8621-               assertEqualInt(0, n);
     8622+#if ARCHIVE_ACL_SUNOS_NFS4
     8623+               aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, buff);
     8624+               failure("acl(\"%s\"): errno = %d (%s)", buff, errno,
     8625+                   strerror(errno));
     8626+               assert(aclp != NULL);
     8627+#elif ARCHIVE_ACL_LIBRICHACL
     8628+               richacl = richacl_get_file(buff);
     8629+               /* First and last two dir do not return a richacl */
     8630+               if ((i == 0 || i >= dircnt - 2) && richacl == NULL &&
     8631+                   errno == ENODATA)
     8632+                       continue;
     8633+               failure("richacl_get_file(\"%s\"): errno = %d (%s)", buff,
     8634+                   errno, strerror(errno));
     8635+               assert(richacl != NULL);
     8636 #else
     8637-#if HAVE_DARWIN_ACL
     8638+#if ARCHIVE_ACL_DARWIN
     8639                acl = acl_get_file(buff, ACL_TYPE_EXTENDED);
     8640 #else
     8641                acl = acl_get_file(buff, ACL_TYPE_NFS4);
     8642 #endif
     8643-               failure("acl_get_file(): errno = %d (%s)", errno,
     8644+               failure("acl_get_file(\"%s\"): errno = %d (%s)", buff, errno,
     8645                    strerror(errno));
     8646                assert(acl != (acl_t)NULL);
     8647 #endif
     8648+#if ARCHIVE_ACL_SUNOS_NFS4
     8649+               compare_acls(aclp, aclcnt, acls_dir, buff, i, i + 1);
     8650+               free(aclp);
     8651+               aclp = NULL;
     8652+#elif ARCHIVE_ACL_LIBRICHACL
     8653+               compare_acls(richacl, acls_dir, buff, i, i + 1);
     8654+               richacl_free(richacl);
     8655+#else
     8656                compare_acls(acl, acls_dir, buff, i, i + 1);
     8657                acl_free(acl);
     8658+#endif
     8659        }
     8660 
     8661        /* Verify "dirall" on disk. */
     8662        assertEqualInt(0, stat("dirall", &st));
     8663        assertEqualInt(st.st_mtime, 123456);
     8664-#if HAVE_SUN_ACL
     8665-       n = acl_get("dirall", 0, &acl);
     8666-       failure("acl_get(): errno = %d (%s)", errno, strerror(errno));
     8667-       assertEqualInt(0, n);
     8668+#if ARCHIVE_ACL_SUNOS_NFS4
     8669+       aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, "dirall");
     8670+       failure("acl(\"%s\"): errno = %d (%s)", "dirall", errno,
     8671+           strerror(errno));
     8672+       assert(aclp != NULL);
     8673+#elif ARCHIVE_ACL_LIBRICHACL
     8674+       richacl = richacl_get_file("dirall");
     8675+       failure("richacl_get_file(\"%s\"): errno = %d (%s)", "dirall",
     8676+           errno, strerror(errno));
     8677+       assert(richacl != NULL);
     8678 #else
     8679-#if HAVE_DARWIN_ACL
     8680+#if ARCHIVE_ACL_DARWIN
     8681        acl = acl_get_file("dirall", ACL_TYPE_EXTENDED);
     8682 #else
     8683        acl = acl_get_file("dirall", ACL_TYPE_NFS4);
     8684 #endif
     8685-       failure("acl_get_file(): errno = %d (%s)", errno, strerror(errno));
     8686+       failure("acl_get_file(\"%s\"): errno = %d (%s)", "dirall", errno,
     8687+           strerror(errno));
     8688        assert(acl != (acl_t)NULL);
     8689 #endif
     8690+#if ARCHIVE_ACL_SUNOS_NFS4
     8691+       compare_acls(aclp, aclcnt, acls_dir, "dirall", 0, dircnt);
     8692+       free(aclp);
     8693+       aclp = NULL;
     8694+#elif ARCHIVE_ACL_LIBRICHACL
     8695+       compare_acls(richacl, acls_dir, "dirall", 0, dircnt);
     8696+       richacl_free(richacl);
     8697+#else
     8698        compare_acls(acl, acls_dir, "dirall", 0, dircnt);
     8699        acl_free(acl);
     8700+#endif
     8701 
     8702        /* Read and compare ACL via archive_read_disk */
     8703        a = archive_read_disk_new();
     8704@@ -929,5 +1054,5 @@ DEFINE_TEST(test_acl_platform_nfs4)
     8705        compare_entry_acls(ae, acls_dir, "dirall", 0, acls_dir_cnt);
     8706        archive_entry_free(ae);
     8707        assertEqualInt(ARCHIVE_OK, archive_read_free(a));
     8708-#endif /* HAVE_NFS4_ACL */
     8709+#endif /* ARCHIVE_ACL_NFS4 */
     8710 }
     8711diff --git a/libarchive/test/test_acl_platform_posix1e.c b/libarchive/test/test_acl_platform_posix1e.c
     8712index b46f6581..801a7acf 100644
     8713--- a/libarchive/test/test_acl_platform_posix1e.c
     8714+++ b/libarchive/test/test_acl_platform_posix1e.c
     8715@@ -26,7 +26,7 @@
     8716 #include "test.h"
     8717 __FBSDID("$FreeBSD: head/lib/libarchive/test/test_acl_freebsd.c 189427 2009-03-06 04:21:23Z kientzle $");
     8718 
     8719-#if HAVE_POSIX_ACL || HAVE_SUN_ACL
     8720+#if ARCHIVE_ACL_POSIX1E
     8721 #include <sys/acl.h>
     8722 #if HAVE_ACL_GET_PERM
     8723 #include <acl/libacl.h>
     8724@@ -55,18 +55,18 @@ static struct archive_test_acl_t acls2[] = {
     8725 };
     8726 
     8727 static int
     8728-#if HAVE_SUN_ACL
     8729+#if ARCHIVE_ACL_SUNOS
     8730 acl_entry_get_perm(aclent_t *aclent)
     8731 #else
     8732 acl_entry_get_perm(acl_entry_t aclent)
     8733 #endif
     8734 {
     8735        int permset = 0;
     8736-#if HAVE_POSIX_ACL
     8737+#if ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL
     8738        acl_permset_t opaque_ps;
     8739 #endif
     8740 
     8741-#if HAVE_SUN_ACL
     8742+#if ARCHIVE_ACL_SUNOS
     8743        if (aclent->a_perm & 1)
     8744                permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
     8745        if (aclent->a_perm & 2)
     8746@@ -127,114 +127,108 @@ acl_get_specific_entry(acl_t acl, acl_tag_t requested_tag_type, int requested_ta
     8747 }
     8748 #endif
     8749 
     8750+#if ARCHIVE_ACL_SUNOS
     8751 static int
     8752-#if HAVE_SUN_ACL
     8753 acl_match(aclent_t *aclent, struct archive_test_acl_t *myacl)
     8754-#else
     8755+{
     8756+
     8757+       if (myacl->permset != acl_entry_get_perm(aclent))
     8758+               return (0);
     8759+
     8760+       switch (aclent->a_type) {
     8761+       case DEF_USER_OBJ:
     8762+       case USER_OBJ:
     8763+               if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) return (0);
     8764+               break;
     8765+               if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
     8766+                       return (0);
     8767+               if ((uid_t)myacl->qual != aclent->a_id)
     8768+                       return (0);
     8769+               break;
     8770+       case DEF_GROUP_OBJ:
     8771+       case GROUP_OBJ:
     8772+               if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ) return (0);
     8773+               break;
     8774+       case DEF_GROUP:
     8775+       case GROUP:
     8776+               if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
     8777+                       return (0);
     8778+               if ((gid_t)myacl->qual != aclent->a_id)
     8779+                       return (0);
     8780+               break;
     8781+       case DEF_CLASS_OBJ:
     8782+       case CLASS_OBJ:
     8783+               if (myacl->tag != ARCHIVE_ENTRY_ACL_MASK) return (0);
     8784+               break;
     8785+       case DEF_OTHER_OBJ:
     8786+       case OTHER_OBJ:
     8787+               if (myacl->tag != ARCHIVE_ENTRY_ACL_OTHER) return (0);
     8788+               break;
     8789+       }
     8790+       return (1);
     8791+}
     8792+
     8793+#else  /* ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL */
     8794+static int
     8795 acl_match(acl_entry_t aclent, struct archive_test_acl_t *myacl)
     8796-#endif
     8797 {
     8798-#if HAVE_POSIX_ACL
     8799        gid_t g, *gp;
     8800        uid_t u, *up;
     8801        acl_tag_t tag_type;
     8802-#endif
     8803 
     8804        if (myacl->permset != acl_entry_get_perm(aclent))
     8805                return (0);
     8806 
     8807-#if HAVE_SUN_ACL
     8808-       switch (aclent->a_type)
     8809-#else
     8810        acl_get_tag_type(aclent, &tag_type);
     8811-       switch (tag_type)
     8812-#endif
     8813-       {
     8814-#if HAVE_SUN_ACL
     8815-       case DEF_USER_OBJ:
     8816-       case USER_OBJ:
     8817-#else
     8818+       switch (tag_type) {
     8819        case ACL_USER_OBJ:
     8820-#endif
     8821                if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) return (0);
     8822                break;
     8823-#if HAVE_SUN_ACL
     8824-       case DEF_USER:
     8825-       case USER:
     8826-#else
     8827        case ACL_USER:
     8828-#endif
     8829                if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
     8830                        return (0);
     8831-#if HAVE_SUN_ACL
     8832-               if ((uid_t)myacl->qual != aclent->a_id)
     8833-                       return (0);
     8834-#else
     8835                up = acl_get_qualifier(aclent);
     8836                u = *up;
     8837                acl_free(up);
     8838                if ((uid_t)myacl->qual != u)
     8839                        return (0);
     8840-#endif
     8841                break;
     8842-#if HAVE_SUN_ACL
     8843-       case DEF_GROUP_OBJ:
     8844-       case GROUP_OBJ:
     8845-#else
     8846        case ACL_GROUP_OBJ:
     8847-#endif
     8848                if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ) return (0);
     8849                break;
     8850-#if HAVE_SUN_ACL
     8851-       case DEF_GROUP:
     8852-       case GROUP:
     8853-#else
     8854        case ACL_GROUP:
     8855-#endif
     8856                if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
     8857                        return (0);
     8858-#if HAVE_SUN_ACL
     8859-               if ((gid_t)myacl->qual != aclent->a_id)
     8860-                       return (0);
     8861-#else
     8862                gp = acl_get_qualifier(aclent);
     8863                g = *gp;
     8864                acl_free(gp);
     8865                if ((gid_t)myacl->qual != g)
     8866                        return (0);
     8867-#endif
     8868                break;
     8869-#if HAVE_SUN_ACL
     8870-       case DEF_CLASS_OBJ:
     8871-       case CLASS_OBJ:
     8872-#else
     8873        case ACL_MASK:
     8874-#endif
     8875                if (myacl->tag != ARCHIVE_ENTRY_ACL_MASK) return (0);
     8876                break;
     8877-#if HAVE_SUN_ACL
     8878-       case DEF_OTHER_OBJ:
     8879-       case OTHER_OBJ:
     8880-#else
     8881        case ACL_OTHER:
     8882-#endif
     8883                if (myacl->tag != ARCHIVE_ENTRY_ACL_OTHER) return (0);
     8884                break;
     8885        }
     8886        return (1);
     8887 }
     8888+#endif
     8889 
     8890 static void
     8891-#if HAVE_SUN_ACL
     8892-compare_acls(acl_t *acl, struct archive_test_acl_t *myacls, int n)
     8893+compare_acls(
     8894+#if ARCHIVE_ACL_SUNOS
     8895+    void *aclp, int aclcnt,
     8896 #else
     8897-compare_acls(acl_t acl, struct archive_test_acl_t *myacls, int n)
     8898+    acl_t acl,
     8899 #endif
     8900+    struct archive_test_acl_t *myacls, int n)
     8901 {
     8902        int *marker;
     8903        int matched;
     8904        int i;
     8905-#if HAVE_SUN_ACL
     8906+#if ARCHIVE_ACL_SUNOS
     8907        int e;
     8908        aclent_t *acl_entry;
     8909 #else
     8910@@ -253,9 +247,9 @@ compare_acls(acl_t acl, struct archive_test_acl_t *myacls, int n)
     8911         * Iterate over acls in system acl object, try to match each
     8912         * one with an item in the myacls array.
     8913         */
     8914-#if HAVE_SUN_ACL
     8915-       for(e = 0; e < acl->acl_cnt; e++) {
     8916-               acl_entry = &((aclent_t *)acl->acl_aclp)[e];
     8917+#if ARCHIVE_ACL_SUNOS
     8918+       for(e = 0; e < aclcnt; e++) {
     8919+               acl_entry = &((aclent_t *)aclp)[e];
     8920 #else
     8921        while (1 == acl_get_entry(acl, entry_id, &acl_entry)) {
     8922                /* After the first time... */
     8923@@ -288,99 +282,33 @@ compare_acls(acl_t acl, struct archive_test_acl_t *myacls, int n)
     8924        }
     8925        free(marker);
     8926 }
     8927-
     8928 #endif
     8929 
     8930-
     8931 /*
     8932  * Verify ACL restore-to-disk.  This test is Platform-specific.
     8933  */
     8934 
     8935 DEFINE_TEST(test_acl_platform_posix1e_restore)
     8936 {
     8937-#if !HAVE_SUN_ACL && !HAVE_POSIX_ACL
     8938+#if !ARCHIVE_ACL_POSIX1E
     8939        skipping("POSIX.1e ACLs are not supported on this platform");
     8940-#else  /* HAVE_SUN_ACL || HAVE_POSIX_ACL */
     8941+#else  /* ARCHIVE_ACL_POSIX1E */
     8942        struct stat st;
     8943        struct archive *a;
     8944        struct archive_entry *ae;
     8945-       int n, fd;
     8946-       char *func;
     8947-#if HAVE_SUN_ACL
     8948-       acl_t *acl, *acl2;
     8949+#if ARCHIVE_ACL_SUNOS
     8950+       void *aclp;
     8951+       int aclcnt;
     8952 #else
     8953        acl_t acl;
     8954 #endif
     8955 
     8956-       /*
     8957-        * First, do a quick manual set/read of ACL data to
     8958-        * verify that the local filesystem does support ACLs.
     8959-        * If it doesn't, we'll simply skip the remaining tests.
     8960-        */
     8961-#if HAVE_SUN_ACL
     8962-       n = acl_fromtext("user::rwx,user:1:rw-,group::rwx,group:15:r-x,other:rwx,mask:rwx", &acl);
     8963-       failure("acl_fromtext(): errno = %d (%s)", errno, strerror(errno));
     8964-       assertEqualInt(0, n);
     8965-#else
     8966-       acl = acl_from_text("u::rwx,u:1:rw,g::rwx,g:15:rx,o::rwx,m::rwx");
     8967-       failure("acl_from_text(): errno = %d (%s)", errno, strerror(errno));
     8968-       assert((void *)acl != NULL);
     8969-#endif
     8970-
     8971-       /* Create a test file and try ACL on it. */
     8972-       fd = open("pretest", O_WRONLY | O_CREAT | O_EXCL, 0777);
     8973-       failure("Could not create test file?!");
     8974-       if (!assert(fd >= 0)) {
     8975-               acl_free(acl);
     8976-               return;
     8977-       }
     8978-
     8979-#if HAVE_SUN_ACL
     8980-       n = facl_get(fd, 0, &acl2);
     8981-       if (n != 0) {
     8982-               close(fd);
     8983-               acl_free(acl);
     8984-       }
     8985-       if (errno == ENOSYS) {
     8986-               skipping("POSIX.1e ACLs are not supported on this filesystem");
     8987-               return;
     8988-       }
     8989-       failure("facl_get(): errno = %d (%s)", errno, strerror(errno));
     8990-       assertEqualInt(0, n);
     8991+       assertMakeFile("pretest", 0644, "a");
     8992 
     8993-       if (acl2->acl_type != ACLENT_T) {
     8994-               acl_free(acl2);
     8995-               skipping("POSIX.1e ACLs are not supported on this filesystem");
     8996+       if (setTestAcl("pretest") != ARCHIVE_TEST_ACL_TYPE_POSIX1E) {
     8997+               skipping("POSIX.1e ACLs are not writable on this filesystem");
     8998                return;
     8999        }
     9000-       acl_free(acl2);
     9001-
     9002-       func = "facl_set()";
     9003-       n = facl_set(fd, acl);
     9004-#else
     9005-       func = "acl_set_fd()";
     9006-       n = acl_set_fd(fd, acl);
     9007-#endif
     9008-       acl_free(acl);
     9009-       if (n != 0) {
     9010-#if HAVE_SUN_ACL
     9011-               if (errno == ENOSYS)
     9012-#else
     9013-               if (errno == EOPNOTSUPP || errno == EINVAL)
     9014-#endif
     9015-               {
     9016-                       close(fd);
     9017-                       skipping("POSIX.1e ACLs are not supported on this filesystem");
     9018-                       return;
     9019-               }
     9020-       }
     9021-       failure("%s: errno = %d (%s)", func, errno, strerror(errno));
     9022-       assertEqualInt(0, n);
     9023-
     9024-#if HAVE_SUN_ACL
     9025-
     9026-#endif
     9027-       close(fd);
     9028 
     9029        /* Create a write-to-disk object. */
     9030        assert(NULL != (a = archive_write_disk_new()));
     9031@@ -404,18 +332,25 @@ DEFINE_TEST(test_acl_platform_posix1e_restore)
     9032        /* Verify the data on disk. */
     9033        assertEqualInt(0, stat("test0", &st));
     9034        assertEqualInt(st.st_mtime, 123456);
     9035-#if HAVE_SUN_ACL
     9036-       n = acl_get("test0", 0, &acl);
     9037-       failure("acl_get(): errno = %d (%s)", errno, strerror(errno));
     9038-       assertEqualInt(0, n);
     9039+#if ARCHIVE_ACL_SUNOS
     9040+       aclp = sunacl_get(GETACL, &aclcnt, 0, "test0");
     9041+       failure("acl(): errno = %d (%s)", errno, strerror(errno));
     9042+       assert(aclp != NULL);
     9043 #else
     9044        acl = acl_get_file("test0", ACL_TYPE_ACCESS);
     9045        failure("acl_get_file(): errno = %d (%s)", errno, strerror(errno));
     9046        assert(acl != (acl_t)NULL);
     9047 #endif
     9048+#if ARCHIVE_ACL_SUNOS
     9049+       compare_acls(aclp, aclcnt, acls2, sizeof(acls2)/sizeof(acls2[0]));
     9050+       free(aclp);
     9051+       aclp = NULL;
     9052+#else
     9053        compare_acls(acl, acls2, sizeof(acls2)/sizeof(acls2[0]));
     9054        acl_free(acl);
     9055-#endif /* HAVE_SUN_ACL || HAVE_POSIX_ACL */
     9056+#endif
     9057+
     9058+#endif /* ARCHIVE_ACL_POSIX1E */
     9059 }
     9060 
     9061 /*
     9062@@ -423,16 +358,17 @@ DEFINE_TEST(test_acl_platform_posix1e_restore)
     9063  */
     9064 DEFINE_TEST(test_acl_platform_posix1e_read)
     9065 {
     9066-#if !HAVE_SUN_ACL && !HAVE_POSIX_ACL
     9067+#if !ARCHIVE_ACL_POSIX1E
     9068        skipping("POSIX.1e ACLs are not supported on this platform");
     9069-#else
     9070+#else /* ARCHIVE_ACL_POSIX1E */
     9071        struct archive *a;
     9072        struct archive_entry *ae;
     9073        int n, fd, flags, dflags;
     9074        char *func, *acl_text;
     9075        const char *acl1_text, *acl2_text, *acl3_text;
     9076-#if HAVE_SUN_ACL
     9077-       acl_t *acl, *acl1, *acl2, *acl3;
     9078+#if ARCHIVE_ACL_SUNOS
     9079+       void *aclp;
     9080+       int aclcnt;
     9081 #else
     9082        acl_t acl1, acl2, acl3;
     9083 #endif
     9084@@ -444,16 +380,21 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
     9085         */
     9086 
     9087        /* Create a test file f1 with acl1 */
     9088-#if HAVE_SUN_ACL
     9089+#if ARCHIVE_ACL_SUNOS
     9090        acl1_text = "user::rwx,"
     9091            "group::rwx,"
     9092            "other:rwx,"
     9093            "user:1:rw-,"
     9094            "group:15:r-x,"
     9095            "mask:rwx";
     9096-       n = acl_fromtext(acl1_text, &acl1);
     9097-       failure("acl_fromtext(): errno = %d (%s)", errno, strerror(errno));
     9098-       assertEqualInt(0, n);
     9099+       aclent_t aclp1[] = {
     9100+           { USER_OBJ, -1, 4 | 2 | 1 },
     9101+           { USER, 1, 4 | 2 },
     9102+           { GROUP_OBJ, -1, 4 | 2 | 1 },
     9103+           { GROUP, 15, 4 | 1 },
     9104+           { CLASS_OBJ, -1, 4 | 2 | 1 },
     9105+           { OTHER_OBJ, -1, 4 | 2 | 1 }
     9106+       };
     9107 #else
     9108        acl1_text = "user::rwx\n"
     9109            "group::rwx\n"
     9110@@ -468,41 +409,36 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
     9111        fd = open("f1", O_WRONLY | O_CREAT | O_EXCL, 0777);
     9112        failure("Could not create test file?!");
     9113        if (!assert(fd >= 0)) {
     9114+#if !ARCHIVE_ACL_SUNOS
     9115                acl_free(acl1);
     9116+#endif
     9117                return;
     9118        }
     9119-#if HAVE_SUN_ACL
     9120+#if ARCHIVE_ACL_SUNOS
     9121        /* Check if Solaris filesystem supports POSIX.1e ACLs */
     9122-       n = facl_get(fd, 0, &acl);
     9123-       if (n != 0)
     9124+       aclp = sunacl_get(GETACL, &aclcnt, fd, NULL);
     9125+       if (aclp == 0)
     9126                close(fd);
     9127-       if (n != 0 && errno == ENOSYS) {
     9128-               acl_free(acl1);
     9129+       if (errno == ENOSYS || errno == ENOTSUP) {
     9130                skipping("POSIX.1e ACLs are not supported on this filesystem");
     9131                return;
     9132        }
     9133-       failure("facl_get(): errno = %d (%s)", errno, strerror(errno));
     9134-       assertEqualInt(0, n);
     9135+       failure("facl(): errno = %d (%s)", errno, strerror(errno));
     9136+       assert(aclp != NULL);
     9137 
     9138-       if (acl->acl_type != ACLENT_T) {
     9139-               acl_free(acl);
     9140-               acl_free(acl1);
     9141-               close(fd);
     9142-               skipping("POSIX.1e ACLs are not supported on this filesystem");
     9143-               return;
     9144-       }
     9145-
     9146-       func = "facl_set()";
     9147-       n = facl_set(fd, acl1);
     9148+       func = "facl()";
     9149+       n = facl(fd, SETACL, (int)(sizeof(aclp1)/sizeof(aclp1[0])), aclp1);
     9150 #else
     9151        func = "acl_set_fd()";
     9152        n = acl_set_fd(fd, acl1);
     9153 #endif
     9154+#if !ARCHIVE_ACL_SUNOS
     9155        acl_free(acl1);
     9156+#endif
     9157 
     9158        if (n != 0) {
     9159-#if HAVE_SUN_ACL
     9160-               if (errno == ENOSYS)
     9161+#if ARCHIVE_ACL_SUNOS
     9162+               if (errno == ENOSYS || errno == ENOTSUP)
     9163 #else
     9164                if (errno == EOPNOTSUPP || errno == EINVAL)
     9165 #endif
     9166@@ -530,16 +466,21 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
     9167         * to read ACLs, resulting in reading the ACL from a like-named
     9168         * file in the wrong directory.
     9169         */
     9170-#if HAVE_SUN_ACL
     9171+#if ARCHIVE_ACL_SUNOS
     9172        acl2_text = "user::rwx,"
     9173            "group::rwx,"
     9174            "other:---,"
     9175            "user:1:r--,"
     9176            "group:15:r--,"
     9177            "mask:rwx";
     9178-       n = acl_fromtext(acl2_text, &acl2);
     9179-       failure("acl_fromtext(): errno = %d (%s)", errno, strerror(errno));
     9180-       assertEqualInt(0, n);
     9181+       aclent_t aclp2[] = {
     9182+           { USER_OBJ, -1, 4 | 2 | 1 },
     9183+           { USER, 1, 4 },
     9184+           { GROUP_OBJ, -1, 4 | 2 | 1},
     9185+           { GROUP, 15, 4 },
     9186+           { CLASS_OBJ, -1, 4 | 2 | 1},
     9187+           { OTHER_OBJ, -1, 0 }
     9188+       };
     9189 #else
     9190        acl2_text = "user::rwx\n"
     9191            "group::rwx\n"
     9192@@ -554,17 +495,19 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
     9193        fd = open("d/f1", O_WRONLY | O_CREAT | O_EXCL, 0777);
     9194        failure("Could not create test file?!");
     9195        if (!assert(fd >= 0)) {
     9196+#if !ARCHIVE_ACL_SUNOS
     9197                acl_free(acl2);
     9198+#endif
     9199                return;
     9200        }
     9201-#if HAVE_SUN_ACL
     9202-       func = "facl_set()";
     9203-       n = facl_set(fd, acl2);
     9204+#if ARCHIVE_ACL_SUNOS
     9205+       func = "facl()";
     9206+       n = facl(fd, SETACL, (int)(sizeof(aclp2) / sizeof(aclp2[0])), aclp2);
     9207 #else
     9208        func = "acl_set_fd()";
     9209        n = acl_set_fd(fd, acl2);
     9210-#endif
     9211        acl_free(acl2);
     9212+#endif
     9213        if (n != 0)
     9214                close(fd);
     9215        failure("%s: errno = %d (%s)", func, errno, strerror(errno));
     9216@@ -574,7 +517,7 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
     9217        /* Create nested directory d2 with default ACLs */
     9218        assertMakeDir("d/d2", 0755);
     9219 
     9220-#if HAVE_SUN_ACL
     9221+#if ARCHIVE_ACL_SUNOS
     9222        acl3_text = "user::rwx,"
     9223            "group::r-x,"
     9224            "other:r-x,"
     9225@@ -587,9 +530,20 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
     9226            "default:group:15:r--,"
     9227            "default:mask:rwx,"
     9228            "default:other:r-x";
     9229-       n = acl_fromtext(acl3_text, &acl3);
     9230-       failure("acl_fromtext(): errno = %d (%s)", errno, strerror(errno));
     9231-       assertEqualInt(0, n);
     9232+       aclent_t aclp3[] = {
     9233+           { USER_OBJ, -1, 4 | 2 | 1 },
     9234+           { USER, 2, 4 },
     9235+           { GROUP_OBJ, -1, 4 | 1 },
     9236+           { GROUP, 16, 2 },
     9237+           { CLASS_OBJ, -1, 4 | 2 | 1 },
     9238+           { OTHER_OBJ, -1, 4 | 1 },
     9239+           { USER_OBJ | ACL_DEFAULT, -1, 4 | 2 | 1 },
     9240+           { USER | ACL_DEFAULT, 1, 4 },
     9241+           { GROUP_OBJ | ACL_DEFAULT, -1, 4 | 1 },
     9242+           { GROUP | ACL_DEFAULT, 15, 4 },
     9243+           { CLASS_OBJ | ACL_DEFAULT, -1, 4 | 2 | 1},
     9244+           { OTHER_OBJ | ACL_DEFAULT, -1, 4 | 1 }
     9245+       };
     9246 #else
     9247        acl3_text = "user::rwx\n"
     9248            "user:1:r--\n"
     9249@@ -602,15 +556,14 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
     9250        assert((void *)acl3 != NULL);
     9251 #endif
     9252 
     9253-#if HAVE_SUN_ACL
     9254-       func = "acl_set()";
     9255-       n = acl_set("d/d2", acl3);
     9256+#if ARCHIVE_ACL_SUNOS
     9257+       func = "acl()";
     9258+       n = acl("d/d2", SETACL, (int)(sizeof(aclp3) / sizeof(aclp3[0])), aclp3);
     9259 #else
     9260        func = "acl_set_file()";
     9261        n = acl_set_file("d/d2", ACL_TYPE_DEFAULT, acl3);
     9262-#endif
     9263        acl_free(acl3);
     9264-
     9265+#endif
     9266        failure("%s: errno = %d (%s)", func, errno, strerror(errno));
     9267        assertEqualInt(0, n);
     9268 
     9269@@ -619,7 +572,7 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
     9270        assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "."));
     9271        assert(NULL != (ae = archive_entry_new()));
     9272 
     9273-#if HAVE_SUN_ACL
     9274+#if ARCHIVE_ACL_SUNOS
     9275        flags = ARCHIVE_ENTRY_ACL_TYPE_POSIX1E
     9276            | ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA
     9277            | ARCHIVE_ENTRY_ACL_STYLE_SOLARIS;
     9278@@ -649,5 +602,5 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
     9279 
     9280        archive_entry_free(ae);
     9281        assertEqualInt(ARCHIVE_OK, archive_free(a));
     9282-#endif
     9283+#endif /* ARCHIVE_ACL_POSIX1E */
     9284 }
     9285diff --git a/libarchive/test/test_read_disk_directory_traversals.c b/libarchive/test/test_read_disk_directory_traversals.c
     9286index fdbfbec9..705b3d98 100644
     9287--- a/libarchive/test/test_read_disk_directory_traversals.c
     9288+++ b/libarchive/test/test_read_disk_directory_traversals.c
     9289@@ -1231,8 +1231,8 @@ test_restore_atime(void)
     9290         * Test4: Traversals with ARCHIVE_READDISK_RESTORE_ATIME and
     9291         * ARCHIVE_READDISK_HONOR_NODUMP
     9292         */
     9293-       assertNodump("at/f1");
     9294-       assertNodump("at/f2");
     9295+       assertSetNodump("at/f1");
     9296+       assertSetNodump("at/f2");
     9297        assertUtimes("at/f1", 886600, 0, 886600, 0);
     9298        assertUtimes("at/f2", 886611, 0, 886611, 0);
     9299        assertUtimes("at/fe", 886611, 0, 886611, 0);
     9300@@ -1450,7 +1450,7 @@ test_nodump(void)
     9301        assertMakeFile("nd/f1", 0644, "0123456789");
     9302        assertMakeFile("nd/f2", 0644, "hello world");
     9303        assertMakeFile("nd/fe", 0644, NULL);
     9304-       assertNodump("nd/f2");
     9305+       assertSetNodump("nd/f2");
     9306        assertUtimes("nd/f1", 886600, 0, 886600, 0);
     9307        assertUtimes("nd/f2", 886611, 0, 886611, 0);
     9308        assertUtimes("nd/fe", 886611, 0, 886611, 0);
     9309diff --git a/tar/bsdtar.1 b/tar/bsdtar.1
     9310index b60f09c5..0537bf36 100644
     9311--- a/tar/bsdtar.1
     9312+++ b/tar/bsdtar.1
     9313@@ -25,7 +25,7 @@
     9314 .\"
     9315 .\" $FreeBSD$
     9316 .\"
     9317-.Dd February 24, 2017
     9318+.Dd February 25, 2017
     9319 .Dt TAR 1
     9320 .Os
     9321 .Sh NAME
     9322@@ -450,14 +450,7 @@ This is the reverse of
     9323 .Fl p
     9324 and the default behavior if
     9325 .Nm
     9326-is run as non-root and can be overridden by also specifying
     9327-.Fl Fl acls ,
     9328-.Fl Fl fflags ,
     9329-.Fl Fl mac-metadata,
     9330-.Fl Fl same-owner ,
     9331-.Fl Fl same-permissions
     9332-and
     9333-.Fl Fl xattrs .
     9334+is run as non-root.
     9335 .It Fl Fl no-xattrs
     9336 (c, r, u, x modes only)
     9337 Do not archive or extract extended attributes. This is the reverse of
     9338@@ -647,16 +640,16 @@ This option suppresses these behaviors.
     9339 (x mode only)
     9340 Preserve file permissions.
     9341 Attempt to restore the full permissions, including owner, file modes, ACLs,
     9342-extended atributes and extended file flags, if available, for each item
     9343-extracted from the archive. This is the default, if
     9344+extended attributes and extended file flags, if available, for each item
     9345+extracted from the archive. This is te reverse of
     9346+.Fl Fl no-same-permissions
     9347+and the default if
     9348 .Nm
     9349-is being run by root and can be overridden by also specifying
     9350+is being run by root and can be partially overridden by also specifying
     9351 .Fl Fl no-acls ,
     9352 .Fl Fl no-fflags ,
     9353-.Fl Fl no-mac-metadata,
     9354-.Fl Fl no-same-owner ,
     9355-.Fl Fl no-same-permissions
     9356-and
     9357+.Fl Fl no-mac-metadata
     9358+or
     9359 .Fl Fl no-xattrs .
     9360 .It Fl Fl passphrase Ar passphrase
     9361 The
     9362diff --git a/tar/bsdtar.c b/tar/bsdtar.c
     9363index a9252a5c..9fc68332 100644
     9364--- a/tar/bsdtar.c
     9365+++ b/tar/bsdtar.c
     9366@@ -118,11 +118,11 @@ need_report(void)
     9367 }
     9368 #endif
     9369 
     9370-static void             long_help(void);
     9371+static void             long_help(void) __LA_DEAD;
     9372 static void             only_mode(struct bsdtar *, const char *opt,
     9373                             const char *valid);
     9374 static void             set_mode(struct bsdtar *, char opt);
     9375-static void             version(void);
     9376+static void             version(void) __LA_DEAD;
     9377 
     9378 /* A basic set of security flags to request from libarchive. */
     9379 #define        SECURITY                                        \
     9380diff --git a/tar/bsdtar.h b/tar/bsdtar.h
     9381index ee9c6485..10a2cf2f 100644
     9382--- a/tar/bsdtar.h
     9383+++ b/tar/bsdtar.h
     9384@@ -189,7 +189,7 @@ void        do_chdir(struct bsdtar *);
     9385 int    edit_pathname(struct bsdtar *, struct archive_entry *);
     9386 int    need_report(void);
     9387 int    pathcmp(const char *a, const char *b);
     9388-void   safe_fprintf(FILE *, const char *fmt, ...);
     9389+void   safe_fprintf(FILE *, const char *fmt, ...) __LA_PRINTF(2, 3);
     9390 void   set_chdir(struct bsdtar *, const char *newdir);
     9391 const char *tar_i64toa(int64_t);
     9392 void   tar_mode_c(struct bsdtar *bsdtar);
     9393@@ -197,8 +197,8 @@ void        tar_mode_r(struct bsdtar *bsdtar);
     9394 void   tar_mode_t(struct bsdtar *bsdtar);
     9395 void   tar_mode_u(struct bsdtar *bsdtar);
     9396 void   tar_mode_x(struct bsdtar *bsdtar);
     9397-void   usage(void);
     9398-int    yes(const char *fmt, ...);
     9399+void   usage(void) __LA_DEAD;
     9400+int    yes(const char *fmt, ...) __LA_PRINTF(1, 2);
     9401 
     9402 #if defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H)
     9403 void   add_substitution(struct bsdtar *, const char *);
     9404diff --git a/tar/test/CMakeLists.txt b/tar/test/CMakeLists.txt
     9405index 3dd36019..318eb06e 100644
     9406--- a/tar/test/CMakeLists.txt
     9407+++ b/tar/test/CMakeLists.txt
     9408@@ -34,9 +34,11 @@ IF(ENABLE_TAR AND ENABLE_TEST)
     9409     test_option_U_upper.c
     9410     test_option_X_upper.c
     9411     test_option_a.c
     9412+    test_option_acls.c
     9413     test_option_b.c
     9414     test_option_b64encode.c
     9415     test_option_exclude.c
     9416+    test_option_fflags.c
     9417     test_option_gid_gname.c
     9418     test_option_grzip.c
     9419     test_option_j.c
     9420@@ -71,6 +73,16 @@ IF(ENABLE_TAR AND ENABLE_TEST)
     9421   # Register target
     9422   #
     9423   ADD_EXECUTABLE(bsdtar_test ${bsdtar_test_SOURCES})
     9424+  IF(ENABLE_ACL)
     9425+    SET(TEST_ACL_LIBS "")
     9426+    IF(HAVE_LIBACL)
     9427+      LIST(APPEND TEST_ACL_LIBS ${ACL_LIBRARY})
     9428+    ENDIF(HAVE_LIBACL)
     9429+    IF(HAVE_LIBRICHACL)
     9430+      LIST(APPEND TEST_ACL_LIBS ${RICHACL_LIBRARY})
     9431+    ENDIF(HAVE_LIBRICHACL)
     9432+    TARGET_LINK_LIBRARIES(bsdtar_test ${TEST_ACL_LIBS})
     9433+  ENDIF(ENABLE_ACL)
     9434   SET_PROPERTY(TARGET bsdtar_test PROPERTY COMPILE_DEFINITIONS LIST_H)
     9435 
     9436   #
     9437diff --git a/tar/test/test_option_acls.c b/tar/test/test_option_acls.c
     9438new file mode 100644
     9439index 00000000..bfe2b994
     9440--- /dev/null
     9441+++ b/tar/test/test_option_acls.c
     9442@@ -0,0 +1,469 @@
     9443+/*-
     9444+ * Copyright (c) 2017 Martin Matuska
     9445+ * All rights reserved.
     9446+ *
     9447+ * Redistribution and use in source and binary forms, with or without
     9448+ * modification, are permitted provided that the following conditions
     9449+ * are met:
     9450+ * 1. Redistributions of source code must retain the above copyright
     9451+ *    notice, this list of conditions and the following disclaimer.
     9452+ * 2. Redistributions in binary form must reproduce the above copyright
     9453+ *    notice, this list of conditions and the following disclaimer in the
     9454+ *    documentation and/or other materials provided with the distribution.
     9455+ *
     9456+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
     9457+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     9458+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     9459+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
     9460+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     9461+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     9462+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     9463+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     9464+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     9465+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     9466+ */
     9467+#include "test.h"
     9468+__FBSDID("$FreeBSD$");
     9469+
     9470+#if HAVE_POSIX_ACL || HAVE_DARWIN_ACL
     9471+static const acl_perm_t acl_perms[] = {
     9472+#if HAVE_DARWIN_ACL
     9473+    ACL_READ_DATA,
     9474+    ACL_LIST_DIRECTORY,
     9475+    ACL_WRITE_DATA,
     9476+    ACL_ADD_FILE,
     9477+    ACL_EXECUTE,
     9478+    ACL_SEARCH,
     9479+    ACL_DELETE,
     9480+    ACL_APPEND_DATA,
     9481+    ACL_ADD_SUBDIRECTORY,
     9482+    ACL_DELETE_CHILD,
     9483+    ACL_READ_ATTRIBUTES,
     9484+    ACL_WRITE_ATTRIBUTES,
     9485+    ACL_READ_EXTATTRIBUTES,
     9486+    ACL_WRITE_EXTATTRIBUTES,
     9487+    ACL_READ_SECURITY,
     9488+    ACL_WRITE_SECURITY,
     9489+    ACL_CHANGE_OWNER,
     9490+    ACL_SYNCHRONIZE
     9491+#else /* !HAVE_DARWIN_ACL */
     9492+    ACL_EXECUTE,
     9493+    ACL_WRITE,
     9494+    ACL_READ,
     9495+#if HAVE_FREEBSD_NFS4_ACL
     9496+    ACL_READ_DATA,
     9497+    ACL_LIST_DIRECTORY,
     9498+    ACL_WRITE_DATA,
     9499+    ACL_ADD_FILE,
     9500+    ACL_APPEND_DATA,
     9501+    ACL_ADD_SUBDIRECTORY,
     9502+    ACL_READ_NAMED_ATTRS,
     9503+    ACL_WRITE_NAMED_ATTRS,
     9504+    ACL_DELETE_CHILD,
     9505+    ACL_READ_ATTRIBUTES,
     9506+    ACL_WRITE_ATTRIBUTES,
     9507+    ACL_DELETE,
     9508+    ACL_READ_ACL,
     9509+    ACL_WRITE_ACL,
     9510+    ACL_WRITE_OWNER,
     9511+    ACL_SYNCHRONIZE
     9512+#endif /* HAVE_FREEBSD_NFS4_ACL */
     9513+#endif /* !HAVE_DARWIN_ACL */
     9514+};
     9515+#if HAVE_DARWIN_ACL || HAVE_FREEBSD_NFS4_ACL
     9516+static const acl_flag_t acl_flags[] = {
     9517+#if HAVE_DARWIN_ACL
     9518+    ACL_ENTRY_INHERITED,
     9519+    ACL_ENTRY_FILE_INHERIT,
     9520+    ACL_ENTRY_DIRECTORY_INHERIT,
     9521+    ACL_ENTRY_LIMIT_INHERIT,
     9522+    ACL_ENTRY_ONLY_INHERIT
     9523+#else  /* HAVE_FREEBSD_NFS4_ACL */
     9524+    ACL_ENTRY_FILE_INHERIT,
     9525+    ACL_ENTRY_DIRECTORY_INHERIT,
     9526+    ACL_ENTRY_NO_PROPAGATE_INHERIT,
     9527+    ACL_ENTRY_INHERIT_ONLY,
     9528+    ACL_ENTRY_SUCCESSFUL_ACCESS,
     9529+    ACL_ENTRY_FAILED_ACCESS,
     9530+    ACL_ENTRY_INHERITED
     9531+#endif /* HAVE_FREEBSD_NFS4_ACL */
     9532+};
     9533+#endif /* HAVE_DARWIN_ACL || HAVE_FREEBSD_NFS4_ACL */
     9534+
     9535+/*
     9536+ * Compare two ACL entries on FreeBSD or on Mac OS X
     9537+ */
     9538+static int
     9539+compare_acl_entry(acl_entry_t ae_a, acl_entry_t ae_b, int is_nfs4)
     9540+{
     9541+       acl_tag_t tag_a, tag_b;
     9542+       acl_permset_t permset_a, permset_b;
     9543+       int perm_a, perm_b, perm_start, perm_end;
     9544+       void *qual_a, *qual_b;
     9545+#if HAVE_FREEBSD_NFS4_ACL
     9546+       acl_entry_type_t type_a, type_b;
     9547+#endif
     9548+#if HAVE_FREEBSD_NFS4_ACL || HAVE_DARWIN_ACL
     9549+       acl_flagset_t flagset_a, flagset_b;
     9550+       int flag_a, flag_b;
     9551+#endif
     9552+       int i, r;
     9553+
     9554+
     9555+       /* Compare ACL tag */
     9556+       r = acl_get_tag_type(ae_a, &tag_a);
     9557+       failure("acl_get_tag_type() error: %s", strerror(errno));
     9558+       if (assertEqualInt(r, 0) == 0)
     9559+               return (-1);
     9560+       r = acl_get_tag_type(ae_b, &tag_b);
     9561+       failure("acl_get_tag_type() error: %s", strerror(errno));
     9562+       if (assertEqualInt(r, 0) == 0)
     9563+               return (-1);
     9564+       if (tag_a != tag_b)
     9565+               return (0);
     9566+
     9567+       /* Compare ACL qualifier */
     9568+#if HAVE_DARWIN_ACL
     9569+       if (tag_a == ACL_EXTENDED_ALLOW || tag_b == ACL_EXTENDED_DENY)
     9570+#else
     9571+       if (tag_a == ACL_USER || tag_a == ACL_GROUP)
     9572+#endif
     9573+       {
     9574+               qual_a = acl_get_qualifier(ae_a);
     9575+               failure("acl_get_qualifier() error: %s", strerror(errno));
     9576+               if (assert(qual_a != NULL) == 0)
     9577+                       return (-1);
     9578+               qual_b = acl_get_qualifier(ae_b);
     9579+               failure("acl_get_qualifier() error: %s", strerror(errno));
     9580+               if (assert(qual_b != NULL) == 0) {
     9581+                       acl_free(qual_a);
     9582+                       return (-1);
     9583+               }
     9584+#if HAVE_DARWIN_ACL
     9585+               if (memcmp(((guid_t *)qual_a)->g_guid,
     9586+                   ((guid_t *)qual_b)->g_guid, KAUTH_GUID_SIZE) != 0)
     9587+#else
     9588+               if ((tag_a == ACL_USER &&
     9589+                   (*(uid_t *)qual_a != *(uid_t *)qual_b)) ||
     9590+                   (tag_a == ACL_GROUP &&
     9591+                   (*(gid_t *)qual_a != *(gid_t *)qual_b)))
     9592+#endif
     9593+               {
     9594+                       acl_free(qual_a);
     9595+                       acl_free(qual_b);
     9596+                       return (0);
     9597+               }
     9598+               acl_free(qual_a);
     9599+               acl_free(qual_b);
     9600+       }
     9601+
     9602+#if HAVE_FREEBSD_NFS4_ACL
     9603+       if (is_nfs4) {
     9604+               /* Compare NFS4 ACL type */
     9605+               r = acl_get_entry_type_np(ae_a, &type_a);
     9606+               failure("acl_get_entry_type_np() error: %s", strerror(errno));
     9607+               if (assertEqualInt(r, 0) == 0)
     9608+                       return (-1);
     9609+               r = acl_get_entry_type_np(ae_b, &type_b);
     9610+               failure("acl_get_entry_type_np() error: %s", strerror(errno));
     9611+               if (assertEqualInt(r, 0) == 0)
     9612+                       return (-1);
     9613+               if (type_a != type_b)
     9614+                       return (0);
     9615+       }
     9616+#endif
     9617+
     9618+       /* Compare ACL perms */
     9619+       r = acl_get_permset(ae_a, &permset_a);
     9620+       failure("acl_get_permset() error: %s", strerror(errno));
     9621+       if (assertEqualInt(r, 0) == 0)
     9622+               return (-1);
     9623+       r = acl_get_permset(ae_b, &permset_b);
     9624+       failure("acl_get_permset() error: %s", strerror(errno));
     9625+       if (assertEqualInt(r, 0) == 0)
     9626+               return (-1);
     9627+
     9628+       perm_start = 0;
     9629+       perm_end = (int)(sizeof(acl_perms) / sizeof(acl_perms[0]));
     9630+#if HAVE_FREEBSD_NFS4_ACL
     9631+       if (is_nfs4)
     9632+               perm_start = 3;
     9633+       else
     9634+               perm_end = 3;
     9635+#endif
     9636+       /* Cycle through all perms and compare their value */
     9637+       for (i = perm_start; i < perm_end; i++) {
     9638+#if HAVE_LIBACL
     9639+               perm_a = acl_get_perm(permset_a, acl_perms[i]);
     9640+               perm_b = acl_get_perm(permset_b, acl_perms[i]);
     9641+#else
     9642+               perm_a = acl_get_perm_np(permset_a, acl_perms[i]);
     9643+               perm_b = acl_get_perm_np(permset_b, acl_perms[i]);
     9644+#endif
     9645+               if (perm_a == -1 || perm_b == -1)
     9646+                       return (-1);
     9647+               if (perm_a != perm_b)
     9648+                       return (0);
     9649+       }
     9650+
     9651+#if HAVE_FREEBSD_NFS4_ACL || HAVE_DARWIN_ACL
     9652+       if (is_nfs4) {
     9653+               r = acl_get_flagset_np(ae_a, &flagset_a);
     9654+               failure("acl_get_flagset_np() error: %s", strerror(errno));
     9655+               if (assertEqualInt(r, 0) == 0)
     9656+                       return (-1);
     9657+               r = acl_get_flagset_np(ae_b, &flagset_b);
     9658+               failure("acl_get_flagset_np() error: %s", strerror(errno));
     9659+               if (assertEqualInt(r, 0) == 0)
     9660+                       return (-1);
     9661+               /* Cycle through all flags and compare their status */
     9662+               for (i = 0; i < (int)(sizeof(acl_flags) / sizeof(acl_flags[0]));
     9663+                   i++) {
     9664+                       flag_a = acl_get_flag_np(flagset_a, acl_flags[i]);
     9665+                       flag_b = acl_get_flag_np(flagset_b, acl_flags[i]);
     9666+                       if (flag_a == -1 || flag_b == -1)
     9667+                               return (-1);
     9668+                       if (flag_a != flag_b)
     9669+                               return (0);
     9670+               }
     9671+       }
     9672+#else  /* HAVE_FREEBSD_NFS4_ACL || HAVE_DARWIN_ACL*/
     9673+       (void)is_nfs4;  /* UNUSED */
     9674+#endif
     9675+       return (1);
     9676+}
     9677+#endif /* HAVE_POSIX_ACL || HAVE_DARWIN_ACL */
     9678+
     9679+#if HAVE_SUN_ACL || HAVE_DARWIN_ACL || HAVE_POSIX_ACL
     9680+/*
     9681+ * Clear default ACLs or inheritance flags
     9682+ */
     9683+static void
     9684+clear_inheritance_flags(const char *path, int type)
     9685+{
     9686+       switch (type) {
     9687+       case ARCHIVE_TEST_ACL_TYPE_POSIX1E:
     9688+#if HAVE_POSIX_ACL
     9689+               acl_delete_def_file(path);
     9690+#else
     9691+               /* Solaris */
     9692+               setTestAcl(path);
     9693+#endif
     9694+               break;
     9695+       case ARCHIVE_TEST_ACL_TYPE_NFS4:
     9696+#if HAVE_NFS4_ACL
     9697+               setTestAcl(path);
     9698+#endif
     9699+               break;
     9700+       default:
     9701+               (void)path;     /* UNUSED */
     9702+               break;
     9703+       }
     9704+}
     9705+
     9706+static int
     9707+compare_acls(const char *path_a, const char *path_b)
     9708+{
     9709+       int ret = 1;
     9710+       int is_nfs4 = 0;
     9711+#if HAVE_SUN_ACL
     9712+       void *acl_a, *acl_b;
     9713+       int aclcnt_a, aclcnt_b;
     9714+        aclent_t *aclent_a, *aclent_b;
     9715+        ace_t *ace_a, *ace_b;
     9716+       int e;
     9717+#else
     9718+       acl_t acl_a, acl_b;
     9719+       acl_entry_t aclent_a, aclent_b;
     9720+       int a, b, r;
     9721+#endif
     9722+
     9723+       acl_a = NULL;
     9724+       acl_b = NULL;
     9725+#if HAVE_SUN_ACL
     9726+       acl_a = sunacl_get(GETACL, &aclcnt_a, 0, path_a);
     9727+       if (acl_a == NULL) {
     9728+#if HAVE_SUN_NFS4_ACL
     9729+               is_nfs4 = 1;
     9730+               acl_a = sunacl_get(ACE_GETACL, &aclcnt_a, 0, path_a);
     9731+#endif
     9732+               failure("acl_get() error: %s", strerror(errno));
     9733+               if (assert(acl_a != NULL) == 0)
     9734+                       return (-1);
     9735+#if HAVE_SUN_NFS4_ACL
     9736+               acl_b = sunacl_get(ACE_GETACL, &aclcnt_b, 0, path_b);
     9737+#endif
     9738+       } else
     9739+               acl_b = sunacl_get(GETACL, &aclcnt_b, 0, path_b);
     9740+       if (acl_b == NULL && (errno == ENOSYS || errno == ENOTSUP)) {
     9741+               free(acl_a);
     9742+               return (0);
     9743+       }
     9744+       failure("acl_get() error: %s", strerror(errno));
     9745+       if (assert(acl_b != NULL) == 0) {
     9746+               free(acl_a);
     9747+               return (-1);
     9748+       }
     9749+
     9750+       if (aclcnt_a != aclcnt_b) {
     9751+               ret = 0;
     9752+               goto exit_free;
     9753+       }
     9754+
     9755+       for (e = 0; e < aclcnt_a; e++) {
     9756+               if (!is_nfs4) {
     9757+                       aclent_a = &((aclent_t *)acl_a)[e];
     9758+                       aclent_b = &((aclent_t *)acl_b)[e];
     9759+                       if (aclent_a->a_type != aclent_b->a_type ||
     9760+                           aclent_a->a_id != aclent_b->a_id ||
     9761+                           aclent_a->a_perm != aclent_b->a_perm) {
     9762+                               ret = 0;
     9763+                               goto exit_free;
     9764+                       }
     9765+               }
     9766+#if HAVE_SUN_NFS4_ACL
     9767+               else {
     9768+                       ace_a = &((ace_t *)acl_a)[e];
     9769+                       ace_b = &((ace_t *)acl_b)[e];
     9770+                       if (ace_a->a_who != ace_b->a_who ||
     9771+                           ace_a->a_access_mask != ace_b->a_access_mask ||
     9772+                           ace_a->a_flags != ace_b->a_flags ||
     9773+                           ace_a->a_type != ace_b->a_type) {
     9774+                               ret = 0;
     9775+                               goto exit_free;
     9776+                       }
     9777+               }
     9778+#endif
     9779+       }
     9780+#else  /* !HAVE_SUN_ACL */
     9781+#if HAVE_DARWIN_ACL
     9782+       is_nfs4 = 1;
     9783+       acl_a = acl_get_file(path_a, ACL_TYPE_EXTENDED);
     9784+#elif HAVE_FREEBSD_NFS4_ACL
     9785+       acl_a = acl_get_file(path_a, ACL_TYPE_NFS4);
     9786+       if (acl_a != NULL)
     9787+               is_nfs4 = 1;
     9788+#endif
     9789+#if !HAVE_DARWIN_ACL
     9790+       if (acl_a == NULL)
     9791+               acl_a = acl_get_file(path_a, ACL_TYPE_ACCESS);
     9792+#endif
     9793+       failure("acl_get_file() error: %s (%s)", path_a, strerror(errno));
     9794+       if (assert(acl_a != NULL) == 0)
     9795+               return (-1);
     9796+#if HAVE_DARWIN_ACL
     9797+       acl_b = acl_get_file(path_b, ACL_TYPE_EXTENDED);
     9798+#elif HAVE_FREEBSD_NFS4_ACL
     9799+       acl_b = acl_get_file(path_b, ACL_TYPE_NFS4);
     9800+#endif
     9801+#if !HAVE_DARWIN_ACL
     9802+       if (acl_b == NULL) {
     9803+#if HAVE_FREEBSD_NFS4_ACL
     9804+               if (is_nfs4) {
     9805+                       acl_free(acl_a);
     9806+                       return (0);
     9807+               }
     9808+#endif
     9809+               acl_b = acl_get_file(path_b, ACL_TYPE_ACCESS);
     9810+       }
     9811+       failure("acl_get_file() error: %s (%s)", path_b, strerror(errno));
     9812+       if (assert(acl_b != NULL) == 0) {
     9813+               acl_free(acl_a);
     9814+               return (-1);
     9815+       }
     9816+#endif
     9817+       a = acl_get_entry(acl_a, ACL_FIRST_ENTRY, &aclent_a);
     9818+       if (a == -1) {
     9819+               ret = 0;
     9820+               goto exit_free;
     9821+       }
     9822+       b = acl_get_entry(acl_b, ACL_FIRST_ENTRY, &aclent_b);
     9823+       if (b == -1) {
     9824+               ret = 0;
     9825+               goto exit_free;
     9826+       }
     9827+#if HAVE_DARWIN_ACL
     9828+       while (a == 0 && b == 0)
     9829+#else  /* FreeBSD, Linux */
     9830+       while (a == 1 && b == 1)
     9831+#endif
     9832+       {
     9833+               r = compare_acl_entry(aclent_a, aclent_b, is_nfs4);
     9834+               if (r != 1) {
     9835+                       ret = r;
     9836+                       goto exit_free;
     9837+               }
     9838+               a = acl_get_entry(acl_a, ACL_NEXT_ENTRY, &aclent_a);
     9839+               b = acl_get_entry(acl_b, ACL_NEXT_ENTRY, &aclent_b);
     9840+       }
     9841+       /* Entry count must match */
     9842+       if (a != b)
     9843+               ret = 0;
     9844+#endif /* !HAVE_SUN_ACL */
     9845+exit_free:
     9846+#if HAVE_SUN_ACL
     9847+       free(acl_a);
     9848+       free(acl_b);
     9849+#else
     9850+       acl_free(acl_a);
     9851+       acl_free(acl_b);
     9852+#endif
     9853+       return (ret);
     9854+}
     9855+#endif /* HAVE_SUN_ACL || HAVE_DARWIN_ACL || HAVE_POSIX_ACL */
     9856+
     9857+DEFINE_TEST(test_option_acls)
     9858+{
     9859+#if !HAVE_SUN_ACL && !HAVE_DARWIN_ACL && !HAVE_POSIX_ACL
     9860+        skipping("ACLs are not supported on this platform");
     9861+#else   /* HAVE_SUN_ACL || HAVE_DARWIN_ACL || HAVE_POSIX_ACL */
     9862+       int acltype, r;
     9863+
     9864+       assertMakeFile("f", 0644, "a");
     9865+       acltype = setTestAcl("f");
     9866+       if (acltype == 0) {
     9867+               skipping("Can't write ACLs on the filesystem");
     9868+               return;
     9869+       }
     9870+
     9871+       /* Archive it with acls */
     9872+        r = systemf("%s -c --no-mac-metadata --acls -f acls.tar f >acls.out 2>acls.err", testprog);
     9873+        assertEqualInt(r, 0);
     9874+
     9875+       /* Archive it without acls */
     9876+       r = systemf("%s -c --no-mac-metadata --no-acls -f noacls.tar f >noacls.out 2>noacls.err", testprog);
     9877+       assertEqualInt(r, 0);
     9878+
     9879+       /* Extract acls with acls */
     9880+       assertMakeDir("acls_acls", 0755);
     9881+       clear_inheritance_flags("acls_acls", acltype);
     9882+       r = systemf("%s -x -C acls_acls --no-same-permissions --acls -f acls.tar >acls_acls.out 2>acls_acls.err", testprog);
     9883+       assertEqualInt(r, 0);
     9884+       r = compare_acls("f", "acls_acls/f");
     9885+       assertEqualInt(r, 1);
     9886+
     9887+       /* Extractl acls without acls */
     9888+       assertMakeDir("acls_noacls", 0755);
     9889+       clear_inheritance_flags("acls_noacls", acltype);
     9890+       r = systemf("%s -x -C acls_noacls -p --no-acls -f acls.tar >acls_noacls.out 2>acls_noacls.err", testprog);
     9891+       assertEqualInt(r, 0);
     9892+       r = compare_acls("f", "acls_noacls/f");
     9893+       assertEqualInt(r, 0);
     9894+
     9895+       /* Extract noacls with acls flag */
     9896+       assertMakeDir("noacls_acls", 0755);
     9897+       clear_inheritance_flags("noacls_acls", acltype);
     9898+       r = systemf("%s -x -C noacls_acls --no-same-permissions --acls -f noacls.tar >noacls_acls.out 2>noacls_acls.err", testprog);
     9899+       assertEqualInt(r, 0);
     9900+       r = compare_acls("f", "noacls_acls/f");
     9901+       assertEqualInt(r, 0);
     9902+
     9903+       /* Extract noacls with noacls */
     9904+       assertMakeDir("noacls_noacls", 0755);
     9905+       clear_inheritance_flags("noacls_noacls", acltype);
     9906+       r = systemf("%s -x -C noacls_noacls -p --no-acls -f noacls.tar >noacls_noacls.out 2>noacls_noacls.err", testprog);
     9907+       assertEqualInt(r, 0);
     9908+       r = compare_acls("f", "noacls_noacls/f");
     9909+       assertEqualInt(r, 0);
     9910+#endif /* HAVE_SUN_ACL || HAVE_DARWIN_ACL || HAVE_POSIX_ACL */
     9911+}
     9912diff --git a/tar/test/test_option_fflags.c b/tar/test/test_option_fflags.c
     9913new file mode 100644
     9914index 00000000..77a4e3e1
     9915--- /dev/null
     9916+++ b/tar/test/test_option_fflags.c
     9917@@ -0,0 +1,106 @@
     9918+/*-
     9919+ * Copyright (c) 2017 Martin Matuska
     9920+ * All rights reserved.
     9921+ *
     9922+ * Redistribution and use in source and binary forms, with or without
     9923+ * modification, are permitted provided that the following conditions
     9924+ * are met:
     9925+ * 1. Redistributions of source code must retain the above copyright
     9926+ *    notice, this list of conditions and the following disclaimer.
     9927+ * 2. Redistributions in binary form must reproduce the above copyright
     9928+ *    notice, this list of conditions and the following disclaimer in the
     9929+ *    documentation and/or other materials provided with the distribution.
     9930+ *
     9931+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
     9932+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     9933+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     9934+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
     9935+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     9936+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     9937+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     9938+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     9939+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     9940+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     9941+ */
     9942+#include "test.h"
     9943+__FBSDID("$FreeBSD$");
     9944+
     9945+static void
     9946+clear_fflags(const char *pathname)
     9947+{
     9948+#if defined(HAVE_STRUCT_STAT_ST_FLAGS)
     9949+       chflags(pathname, 0);
     9950+#elif (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \
     9951+      (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS))
     9952+       int fd;
     9953+
     9954+       fd = open(pathname, O_RDONLY | O_NONBLOCK);
     9955+       if (fd < 0)
     9956+               return;
     9957+       ioctl(fd,
     9958+#ifdef FS_IOC_GETFLAGS
     9959+           FS_IOC_GETFLAGS,
     9960+#else
     9961+           EXT2_IOC_GETFLAGS,
     9962+#endif
     9963+           0);
     9964+#else
     9965+       (void)pathname; /* UNUSED */
     9966+#endif
     9967+       return;
     9968+}
     9969+
     9970+DEFINE_TEST(test_option_fflags)
     9971+{
     9972+       int r;
     9973+
     9974+       if (!canNodump()) {
     9975+               skipping("Can't test nodump flag on this filesystem");
     9976+               return;
     9977+       }
     9978+
     9979+       /* Create a file. */
     9980+       assertMakeFile("f", 0644, "a");
     9981+
     9982+       /* Set nodump flag on the file */
     9983+       assertSetNodump("f");
     9984+
     9985+       /* FreeBSD ZFS workaround: ZFS sets uarch on all touched files and dirs */
     9986+       chmod("f", 0644);
     9987+
     9988+       /* Archive it with fflags */
     9989+       r = systemf("%s -c --fflags -f fflags.tar f >fflags.out 2>fflags.err", testprog);
     9990+       assertEqualInt(r, 0);
     9991+
     9992+       /* Archive it without fflags */
     9993+       r = systemf("%s -c --no-fflags -f nofflags.tar f >nofflags.out 2>nofflags.err", testprog);
     9994+       assertEqualInt(r, 0);
     9995+
     9996+       /* Extract fflags with fflags */
     9997+       assertMakeDir("fflags_fflags", 0755);
     9998+       clear_fflags("fflags_fflags");
     9999+       r = systemf("%s -x -C fflags_fflags --no-same-permissions --fflags -f fflags.tar >fflags_fflags.out 2>fflags_fflags.err", testprog);
     10000+       assertEqualInt(r, 0);
     10001+       assertEqualFflags("f", "fflags_fflags/f");
     10002+
     10003+       /* Extract fflags without fflags */
     10004+       assertMakeDir("fflags_nofflags", 0755);
     10005+       clear_fflags("fflags_nofflags");
     10006+       r = systemf("%s -x -C fflags_nofflags -p --no-fflags -f fflags.tar >fflags_nofflags.out 2>fflags_nofflags.err", testprog);
     10007+       assertEqualInt(r, 0);
     10008+       assertUnequalFflags("f", "fflags_nofflags/f");
     10009+
     10010+       /* Extract nofflags with fflags */
     10011+       assertMakeDir("nofflags_fflags", 0755);
     10012+       clear_fflags("nofflags_fflags");
     10013+       r = systemf("%s -x -C nofflags_fflags --no-same-permissions --fflags -f nofflags.tar >nofflags_fflags.out 2>nofflags_fflags.err", testprog);
     10014+       assertEqualInt(r, 0);   
     10015+       assertUnequalFflags("f", "nofflags_fflags/f");
     10016+
     10017+       /* Extract nofflags with nofflags */
     10018+       assertMakeDir("nofflags_nofflags", 0755);
     10019+       clear_fflags("nofflags_nofflags");
     10020+       r = systemf("%s -x -C nofflags_nofflags -p --no-fflags -f nofflags.tar >nofflags_nofflags.out 2>nofflags_nofflags.err", testprog);
     10021+       assertEqualInt(r, 0);
     10022+       assertUnequalFflags("f", "nofflags_nofflags/f");
     10023+}
     10024diff --git a/tar/test/test_option_nodump.c b/tar/test/test_option_nodump.c
     10025index 768f64a6..815b08ed 100644
     10026--- a/tar/test/test_option_nodump.c
     10027+++ b/tar/test/test_option_nodump.c
     10028@@ -36,7 +36,7 @@ DEFINE_TEST(test_option_nodump)
     10029        assertMakeFile("file1", 0644, "file1");
     10030        assertMakeFile("file2", 0644, "file2");
     10031        assertMakeFile("file3", 0644, "file3");
     10032-       assertNodump("file2");
     10033+       assertSetNodump("file2");
     10034 
     10035        /* Test 1: Without --nodump */
     10036        assertEqualInt(0, systemf("%s -cf test1.tar file1 file2 file3",
     10037diff --git a/test_utils/test_common.h b/test_utils/test_common.h
     10038index 82e8483f..43cbc5ed 100644
     10039--- a/test_utils/test_common.h
     10040+++ b/test_utils/test_common.h
     10041@@ -73,6 +73,12 @@
     10042 #include <unistd.h>
     10043 #endif
     10044 #include <wchar.h>
     10045+#ifdef HAVE_ACL_LIBACL_H
     10046+#include <acl/libacl.h>
     10047+#endif
     10048+#ifdef HAVE_SYS_ACL_H
     10049+#include <sys/acl.h>
     10050+#endif
     10051 #ifdef HAVE_WINDOWS_H
     10052 #include <windows.h>
     10053 #endif
     10054@@ -121,31 +127,10 @@
     10055 #define        O_BINARY 0
     10056 #endif
     10057 
     10058-/*
     10059- * If this platform has <sys/acl.h>, acl_create(), acl_init(),
     10060- * acl_set_file(), and ACL_USER, we assume it has the rest of the
     10061- * POSIX.1e draft functions used in archive_read_extract.c.
     10062- */
     10063-#if HAVE_SYS_ACL_H && HAVE_ACL_CREATE_ENTRY && HAVE_ACL_INIT && HAVE_ACL_SET_FILE
     10064-#if HAVE_ACL_USER
     10065-#define        HAVE_POSIX_ACL  1
     10066-#elif HAVE_ACL_TYPE_EXTENDED
     10067-#define        HAVE_DARWIN_ACL 1
     10068-#endif
     10069-#endif
     10070-
     10071-/*
     10072- * If this platform has <sys/acl.h>, acl_get(), facl_get(), acl_set(),
     10073- * facl_set() and types aclent_t and ace_t it uses Solaris-style ACL functions
     10074- */
     10075-#if HAVE_SYS_ACL_H && HAVE_ACL_GET && HAVE_FACL_GET && HAVE_ACL_SET && HAVE_FACL_SET && HAVE_ACLENT_T && HAVE_ACE_T
     10076-#define        HAVE_SUN_ACL    1
     10077-#endif
     10078+#include "archive_platform_acl.h"
     10079+#define        ARCHIVE_TEST_ACL_TYPE_POSIX1E   1
     10080+#define        ARCHIVE_TEST_ACL_TYPE_NFS4      2
     10081 
     10082-/* Define if platform supports NFSv4 ACLs */
     10083-#if (HAVE_POSIX_ACL && HAVE_ACL_TYPE_NFS4) || HAVE_SUN_ACL || HAVE_DARWIN_ACL
     10084-#define        HAVE_NFS4_ACL   1
     10085-#endif
     10086 
     10087 /*
     10088  * Redefine DEFINE_TEST for use in defining the test functions.
     10089@@ -158,6 +143,9 @@
     10090 /* chdir() and error if it fails */
     10091 #define assertChdir(path)  \
     10092   assertion_chdir(__FILE__, __LINE__, path)
     10093+/* Assert two files have the same file flags */
     10094+#define assertEqualFflags(patha, pathb)        \
     10095+  assertion_compare_fflags(__FILE__, __LINE__, patha, pathb, 0)
     10096 /* Assert two integers are the same.  Reports value of each one if not. */
     10097 #define assertEqualInt(v1,v2) \
     10098   assertion_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
     10099@@ -239,10 +227,13 @@
     10100   assertion_make_hardlink(__FILE__, __LINE__, newfile, oldfile)
     10101 #define assertMakeSymlink(newfile, linkto)     \
     10102   assertion_make_symlink(__FILE__, __LINE__, newfile, linkto)
     10103-#define assertNodump(path)      \
     10104-  assertion_nodump(__FILE__, __LINE__, path)
     10105+#define assertSetNodump(path)  \
     10106+  assertion_set_nodump(__FILE__, __LINE__, path)
     10107 #define assertUmask(mask)      \
     10108   assertion_umask(__FILE__, __LINE__, mask)
     10109+/* Assert that two files have unequal file flags */
     10110+#define assertUnequalFflags(patha, pathb)      \
     10111+  assertion_compare_fflags(__FILE__, __LINE__, patha, pathb, 1)
     10112 #define assertUtimes(pathname, atime, atime_nsec, mtime, mtime_nsec)   \
     10113   assertion_utimes(__FILE__, __LINE__, pathname, atime, atime_nsec, mtime, mtime_nsec)
     10114 #ifndef PROGRAM
     10115@@ -265,6 +256,8 @@
     10116 void failure(const char *fmt, ...);
     10117 int assertion_assert(const char *, int, int, const char *, void *);
     10118 int assertion_chdir(const char *, int, const char *);
     10119+int assertion_compare_fflags(const char *, int, const char *, const char *,
     10120+    int);
     10121 int assertion_empty_file(const char *, int, const char *);
     10122 int assertion_equal_file(const char *, int, const char *, const char *);
     10123 int assertion_equal_int(const char *, int, long long, const char *, long long, const char *, void *);
     10124@@ -295,8 +288,8 @@ int assertion_make_dir(const char *, int, const char *, int);
     10125 int assertion_make_file(const char *, int, const char *, int, int, const void *);
     10126 int assertion_make_hardlink(const char *, int, const char *newpath, const char *);
     10127 int assertion_make_symlink(const char *, int, const char *newpath, const char *);
     10128-int assertion_nodump(const char *, int, const char *);
     10129 int assertion_non_empty_file(const char *, int, const char *);
     10130+int assertion_set_nodump(const char *, int, const char *);
     10131 int assertion_text_file_contents(const char *, int, const char *buff, const char *f);
     10132 int assertion_umask(const char *, int, int);
     10133 int assertion_utimes(const char *, int, const char *, long, long, long, long );
     10134@@ -347,9 +340,17 @@ int canXz(void);
     10135 /* Return true if this filesystem can handle nodump flags. */
     10136 int canNodump(void);
     10137 
     10138+/* Set test ACLs */
     10139+int setTestAcl(const char *path);
     10140+
     10141 /* Return true if the file has large i-node number(>0xffffffff). */
     10142 int is_LargeInode(const char *);
     10143 
     10144+#if ARCHIVE_ACL_SUNOS
     10145+/* Fetch ACLs on Solaris using acl() or facl() */
     10146+void *sunacl_get(int cmd, int *aclcnt, int fd, const char *path);
     10147+#endif
     10148+
     10149 /* Suck file into string allocated via malloc(). Call free() when done. */
     10150 /* Supports printf-style args: slurpfile(NULL, "%s/myfile", refdir); */
     10151 char *slurpfile(size_t *, const char *fmt, ...);
     10152diff --git a/test_utils/test_main.c b/test_utils/test_main.c
     10153index 2ae6b38d..0ef6d6fc 100644
     10154--- a/test_utils/test_main.c
     10155+++ b/test_utils/test_main.c
     10156@@ -56,6 +56,24 @@
     10157 #include <stdarg.h>
     10158 #include <time.h>
     10159 
     10160+#ifdef HAVE_SIGNAL_H
     10161+#endif
     10162+#ifdef HAVE_ACL_LIBACL_H
     10163+#include <acl/libacl.h>
     10164+#endif
     10165+#ifdef HAVE_SYS_TYPES_H
     10166+#include <sys/types.h>
     10167+#endif
     10168+#ifdef HAVE_SYS_ACL_H
     10169+#include <sys/acl.h>
     10170+#endif
     10171+#ifdef HAVE_SYS_RICHACL_H
     10172+#include <sys/richacl.h>
     10173+#endif
     10174+#if HAVE_MEMBERSHIP_H
     10175+#include <membership.h>
     10176+#endif
     10177+
     10178 /*
     10179  *
     10180  * Windows support routines
     10181@@ -1883,9 +1901,103 @@ assertion_utimes(const char *file, int line,
     10182 #endif /* defined(_WIN32) && !defined(__CYGWIN__) */
     10183 }
     10184 
     10185+/* Compare file flags */
     10186+int
     10187+assertion_compare_fflags(const char *file, int line, const char *patha,
     10188+    const char *pathb, int nomatch)
     10189+{
     10190+#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
     10191+       struct stat sa, sb;
     10192+
     10193+       assertion_count(file, line);
     10194+
     10195+       if (stat(patha, &sa) < 0)
     10196+               return (0);
     10197+       if (stat(pathb, &sb) < 0)
     10198+               return (0);
     10199+       if (!nomatch && sa.st_flags != sb.st_flags) {
     10200+               failure_start(file, line, "File flags should be identical: "
     10201+                   "%s=%#010x %s=%#010x", patha, sa.st_flags, pathb,
     10202+                   sb.st_flags);
     10203+               failure_finish(NULL);
     10204+               return (0);
     10205+       }
     10206+       if (nomatch && sa.st_flags == sb.st_flags) {
     10207+               failure_start(file, line, "File flags should be different: "
     10208+                   "%s=%#010x %s=%#010x", patha, sa.st_flags, pathb,
     10209+                   sb.st_flags);
     10210+               failure_finish(NULL);
     10211+               return (0);
     10212+       }
     10213+#elif (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS) && \
     10214+       defined(FS_NODUMP_FL)) || \
     10215+      (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS) \
     10216+         && defined(EXT2_NODUMP_FL))
     10217+       int fd, r, flagsa, flagsb;
     10218+
     10219+       assertion_count(file, line);
     10220+       fd = open(patha, O_RDONLY | O_NONBLOCK);
     10221+       if (fd < 0) {
     10222+               failure_start(file, line, "Can't open %s\n", patha);
     10223+               failure_finish(NULL);
     10224+               return (0);
     10225+       }
     10226+       r = ioctl(fd,
     10227+#ifdef FS_IOC_GETFLAGS
     10228+           FS_IOC_GETFLAGS,
     10229+#else
     10230+           EXT2_IOC_GETFLAGS,
     10231+#endif
     10232+           &flagsa);
     10233+       close(fd);
     10234+       if (r < 0) {
     10235+               failure_start(file, line, "Can't get flags %s\n", patha);
     10236+               failure_finish(NULL);
     10237+               return (0);
     10238+       }
     10239+       fd = open(pathb, O_RDONLY | O_NONBLOCK);
     10240+       if (fd < 0) {
     10241+               failure_start(file, line, "Can't open %s\n", pathb);
     10242+               failure_finish(NULL);
     10243+               return (0);
     10244+       }
     10245+       r = ioctl(fd,
     10246+#ifdef FS_IOC_GETFLAGS
     10247+           FS_IOC_GETFLAGS,
     10248+#else
     10249+           EXT2_IOC_GETFLAGS,
     10250+#endif
     10251+           &flagsb);
     10252+       close(fd);
     10253+       if (r < 0) {
     10254+               failure_start(file, line, "Can't get flags %s\n", pathb);
     10255+               failure_finish(NULL);
     10256+               return (0);
     10257+       }
     10258+       if (!nomatch && flagsa != flagsb) {
     10259+               failure_start(file, line, "File flags should be identical: "
     10260+                   "%s=%#010x %s=%#010x", patha, flagsa, pathb, flagsb);
     10261+               failure_finish(NULL);
     10262+               return (0);
     10263+       }
     10264+       if (nomatch && flagsa == flagsb) {
     10265+               failure_start(file, line, "File flags should be different: "
     10266+                   "%s=%#010x %s=%#010x", patha, flagsa, pathb, flagsb);
     10267+               failure_finish(NULL);
     10268+               return (0);
     10269+       }
     10270+#else
     10271+       (void)patha; /* UNUSED */
     10272+       (void)pathb; /* UNUSED */
     10273+       (void)nomatch; /* UNUSED */
     10274+       assertion_count(file, line);
     10275+#endif
     10276+       return (1);
     10277+}
     10278+
     10279 /* Set nodump, report failures. */
     10280 int
     10281-assertion_nodump(const char *file, int line, const char *pathname)
     10282+assertion_set_nodump(const char *file, int line, const char *pathname)
     10283 {
     10284 #if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
     10285        int r;
     10286@@ -2256,11 +2368,10 @@ canXz(void)
     10287 /*
     10288  * Can this filesystem handle nodump flags.
     10289  */
     10290-#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
     10291-
     10292 int
     10293 canNodump(void)
     10294 {
     10295+#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
     10296        const char *path = "cannodumptest";
     10297        struct stat sb;
     10298 
     10299@@ -2271,16 +2382,10 @@ canNodump(void)
     10300                return (0);
     10301        if (sb.st_flags & UF_NODUMP)
     10302                return (1);
     10303-       return (0);
     10304-}
     10305-
     10306 #elif (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS) \
     10307         && defined(FS_NODUMP_FL)) || \
     10308       (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS) \
     10309         && defined(EXT2_NODUMP_FL))
     10310-int
     10311-canNodump(void)
     10312-{
     10313        const char *path = "cannodumptest";
     10314        int fd, r, flags;
     10315 
     10316@@ -2331,18 +2436,250 @@ canNodump(void)
     10317        if (flags & EXT2_NODUMP_FL)
     10318 #endif
     10319                return (1);
     10320+#endif
     10321        return (0);
     10322 }
     10323 
     10324-#else
     10325-
     10326-int
     10327-canNodump()
     10328+#if ARCHIVE_ACL_SUNOS
     10329+/* Fetch ACLs on Solaris using acl() or facl() */
     10330+void *
     10331+sunacl_get(int cmd, int *aclcnt, int fd, const char *path)
     10332 {
     10333-       return (0);
     10334+       int cnt, cntcmd;
     10335+       size_t size;
     10336+       void *aclp;
     10337+
     10338+       if (cmd == GETACL) {
     10339+               cntcmd = GETACLCNT;
     10340+               size = sizeof(aclent_t);
     10341+       }
     10342+#if ARCHIVE_ACL_SUNOS_NFS4
     10343+       else if (cmd == ACE_GETACL) {
     10344+               cntcmd = ACE_GETACLCNT;
     10345+               size = sizeof(ace_t);
     10346+       }
     10347+#endif
     10348+       else {
     10349+               errno = EINVAL;
     10350+               *aclcnt = -1;
     10351+               return (NULL);
     10352+       }
     10353+
     10354+       aclp = NULL;
     10355+       cnt = -2;
     10356+       while (cnt == -2 || (cnt == -1 && errno == ENOSPC)) {
     10357+               if (path != NULL)
     10358+                       cnt = acl(path, cntcmd, 0, NULL);
     10359+               else
     10360+                       cnt = facl(fd, cntcmd, 0, NULL);
     10361+
     10362+               if (cnt > 0) {
     10363+                       if (aclp == NULL)
     10364+                               aclp = malloc(cnt * size);
     10365+                       else
     10366+                               aclp = realloc(NULL, cnt * size);
     10367+                       if (aclp != NULL) {
     10368+                               if (path != NULL)
     10369+                                       cnt = acl(path, cmd, cnt, aclp);
     10370+                               else
     10371+                                       cnt = facl(fd, cmd, cnt, aclp);
     10372+                       }
     10373+               } else {
     10374+                       if (aclp != NULL) {
     10375+                               free(aclp);
     10376+                               aclp = NULL;
     10377+                       }
     10378+                       break;
     10379+               }
     10380+       }
     10381+
     10382+       *aclcnt = cnt;
     10383+       return (aclp);
     10384 }
     10385+#endif /* ARCHIVE_ACL_SUNOS */
     10386+
     10387+/*
     10388+ * Set test ACLs on a path
     10389+ * Return values:
     10390+ * 0: error setting ACLs
     10391+ * ARCHIVE_TEST_ACL_TYPE_POSIX1E: POSIX.1E ACLs have been set
     10392+ * ARCHIVE_TEST_ACL_TYPE_NFS4: NFSv4 or extended ACLs have been set
     10393+ */
     10394+int
     10395+setTestAcl(const char *path)
     10396+{
     10397+#if ARCHIVE_ACL_SUPPORT
     10398+       int r = 1;
     10399+#if ARCHIVE_ACL_LIBACL || ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_DARWIN
     10400+       acl_t acl;
     10401+#endif
     10402+#if ARCHIVE_ACL_LIBRICHACL
     10403+       struct richacl *richacl;
     10404+#endif
     10405+#if ARCHIVE_ACL_LIBACL || ARCHIVE_ACL_FREEBSD
     10406+       const char *acltext_posix1e = "user:1:rw-,"
     10407+           "group:15:r-x,"
     10408+           "user::rwx,"
     10409+           "group::rwx,"
     10410+           "other::r-x,"
     10411+           "mask::rwx";
     10412+#elif ARCHIVE_ACL_SUNOS /* Solaris POSIX.1e */
     10413+       aclent_t aclp_posix1e[] = {
     10414+           { USER_OBJ, -1, 4 | 2 | 1 },
     10415+           { USER, 1, 4 | 2 },
     10416+           { GROUP_OBJ, -1, 4 | 2 | 1 },
     10417+           { GROUP, 15, 4 | 1 },
     10418+           { CLASS_OBJ, -1, 4 | 2 | 1 },
     10419+           { OTHER_OBJ, -1, 4 | 2 | 1 }
     10420+       };
     10421+#endif
     10422+#if ARCHIVE_ACL_FREEBSD /* FreeBSD NFS4 */
     10423+       const char *acltext_nfs4 = "user:1:rwpaRcs::allow:1,"
     10424+           "group:15:rxaRcs::allow:15,"
     10425+           "owner@:rwpxaARWcCos::allow,"
     10426+           "group@:rwpxaRcs::allow,"
     10427+           "everyone@:rxaRcs::allow";
     10428+#elif ARCHIVE_ACL_LIBRICHACL
     10429+       const char *acltext_nfs4 = "owner:rwpxaARWcCoS::mask,"
     10430+           "group:rwpxaRcS::mask,"
     10431+           "other:rxaRcS::mask,"
     10432+           "user:1:rwpaRcS::allow,"
     10433+           "group:15:rxaRcS::allow,"
     10434+           "owner@:rwpxaARWcCoS::allow,"
     10435+           "group@:rwpxaRcS::allow,"
     10436+           "everyone@:rxaRcS::allow";
     10437+#elif ARCHIVE_ACL_SUNOS_NFS4 /* Solaris NFS4 */
     10438+       ace_t aclp_nfs4[] = {
     10439+           { 1, ACE_READ_DATA | ACE_WRITE_DATA | ACE_APPEND_DATA |
     10440+             ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS | ACE_READ_ACL |
     10441+             ACE_SYNCHRONIZE, 0, ACE_ACCESS_ALLOWED_ACE_TYPE },
     10442+           { 15, ACE_READ_DATA | ACE_EXECUTE | ACE_READ_ATTRIBUTES |
     10443+             ACE_READ_NAMED_ATTRS | ACE_READ_ACL | ACE_SYNCHRONIZE,
     10444+             ACE_IDENTIFIER_GROUP, ACE_ACCESS_ALLOWED_ACE_TYPE },
     10445+           { -1, ACE_READ_DATA | ACE_WRITE_DATA | ACE_APPEND_DATA |
     10446+             ACE_EXECUTE | ACE_READ_ATTRIBUTES | ACE_WRITE_ATTRIBUTES |
     10447+             ACE_READ_NAMED_ATTRS | ACE_WRITE_NAMED_ATTRS |
     10448+             ACE_READ_ACL | ACE_WRITE_ACL | ACE_WRITE_OWNER | ACE_SYNCHRONIZE,
     10449+             ACE_OWNER, ACE_ACCESS_ALLOWED_ACE_TYPE },
     10450+           { -1, ACE_READ_DATA | ACE_WRITE_DATA | ACE_APPEND_DATA |
     10451+             ACE_EXECUTE | ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS |
     10452+             ACE_READ_ACL | ACE_SYNCHRONIZE, ACE_GROUP | ACE_IDENTIFIER_GROUP,
     10453+             ACE_ACCESS_ALLOWED_ACE_TYPE },
     10454+           { -1, ACE_READ_DATA | ACE_EXECUTE | ACE_READ_ATTRIBUTES |
     10455+             ACE_READ_NAMED_ATTRS | ACE_READ_ACL | ACE_SYNCHRONIZE,
     10456+             ACE_EVERYONE, ACE_ACCESS_ALLOWED_ACE_TYPE }
     10457+       };
     10458+#elif ARCHIVE_ACL_DARWIN /* Mac OS X */
     10459+       acl_entry_t aclent;
     10460+       acl_permset_t permset;
     10461+       const uid_t uid = 1;
     10462+       uuid_t uuid;
     10463+       int i;
     10464+       const acl_perm_t acl_perms[] = {
     10465+               ACL_READ_DATA,
     10466+               ACL_WRITE_DATA,
     10467+               ACL_APPEND_DATA,
     10468+               ACL_EXECUTE,
     10469+               ACL_READ_ATTRIBUTES,
     10470+               ACL_READ_EXTATTRIBUTES,
     10471+               ACL_READ_SECURITY,
     10472+#if HAVE_DECL_ACL_SYNCHRONIZE
     10473+               ACL_SYNCHRONIZE
     10474+#endif
     10475+       };
     10476+#endif /* ARCHIVE_ACL_DARWIN */
     10477 
     10478+#if ARCHIVE_ACL_FREEBSD
     10479+       acl = acl_from_text(acltext_nfs4);
     10480+       failure("acl_from_text() error: %s", strerror(errno));
     10481+       if (assert(acl != NULL) == 0)
     10482+               return (0);
     10483+#elif ARCHIVE_ACL_LIBRICHACL
     10484+       richacl = richacl_from_text(acltext_nfs4, NULL, NULL);
     10485+       failure("richacl_from_text() error: %s", strerror(errno));
     10486+       if (assert(richacl != NULL) == 0)
     10487+               return (0);
     10488+#elif ARCHIVE_ACL_DARWIN
     10489+       acl = acl_init(1);
     10490+       failure("acl_init() error: %s", strerror(errno));
     10491+       if (assert(acl != NULL) == 0)
     10492+               return (0);
     10493+       r = acl_create_entry(&acl, &aclent);
     10494+       failure("acl_create_entry() error: %s", strerror(errno));
     10495+       if (assertEqualInt(r, 0) == 0)
     10496+               goto testacl_free;
     10497+       r = acl_set_tag_type(aclent, ACL_EXTENDED_ALLOW);
     10498+       failure("acl_set_tag_type() error: %s", strerror(errno));
     10499+       if (assertEqualInt(r, 0) == 0)
     10500+               goto testacl_free;
     10501+       r = acl_get_permset(aclent, &permset);
     10502+       failure("acl_get_permset() error: %s", strerror(errno));
     10503+       if (assertEqualInt(r, 0) == 0)
     10504+               goto testacl_free;
     10505+       for (i = 0; i < (int)(sizeof(acl_perms) / sizeof(acl_perms[0])); i++) {
     10506+               r = acl_add_perm(permset, acl_perms[i]);
     10507+               failure("acl_add_perm() error: %s", strerror(errno));
     10508+               if (assertEqualInt(r, 0) == 0)
     10509+                       goto testacl_free;
     10510+       }
     10511+       r = acl_set_permset(aclent, permset);
     10512+       failure("acl_set_permset() error: %s", strerror(errno));
     10513+       if (assertEqualInt(r, 0) == 0)
     10514+               goto testacl_free;
     10515+       r = mbr_uid_to_uuid(uid, uuid);
     10516+       failure("mbr_uid_to_uuid() error: %s", strerror(errno));
     10517+       if (assertEqualInt(r, 0) == 0)
     10518+               goto testacl_free;
     10519+       r = acl_set_qualifier(aclent, uuid);
     10520+       failure("acl_set_qualifier() error: %s", strerror(errno));
     10521+       if (assertEqualInt(r, 0) == 0)
     10522+               goto testacl_free;
     10523+#endif /* ARCHIVE_ACL_DARWIN */
     10524+
     10525+#if ARCHIVE_ACL_NFS4
     10526+#if ARCHIVE_ACL_FREEBSD
     10527+       r = acl_set_file(path, ACL_TYPE_NFS4, acl);
     10528+       acl_free(acl);
     10529+#elif ARCHIVE_ACL_LIBRICHACL
     10530+       r = richacl_set_file(path, richacl);
     10531+       richacl_free(richacl);
     10532+#elif ARCHIVE_ACL_SUNOS_NFS4
     10533+       r = acl(path, ACE_SETACL,
     10534+           (int)(sizeof(aclp_nfs4)/sizeof(aclp_nfs4[0])), aclp_nfs4);
     10535+#elif ARCHIVE_ACL_DARWIN
     10536+       r = acl_set_file(path, ACL_TYPE_EXTENDED, acl);
     10537+       acl_free(acl);
     10538+#endif
     10539+       if (r == 0)
     10540+               return (ARCHIVE_TEST_ACL_TYPE_NFS4);
     10541+#endif /* ARCHIVE_ACL_NFS4 */
     10542+
     10543+#if ARCHIVE_ACL_POSIX1E
     10544+#if ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL
     10545+       acl = acl_from_text(acltext_posix1e);
     10546+       failure("acl_from_text() error: %s", strerror(errno));
     10547+       if (assert(acl != NULL) == 0)
     10548+               return (0);
     10549+
     10550+       r = acl_set_file(path, ACL_TYPE_ACCESS, acl);
     10551+       acl_free(acl);
     10552+#elif ARCHIVE_ACL_SUNOS
     10553+       r = acl(path, SETACL,
     10554+           (int)(sizeof(aclp_posix1e)/sizeof(aclp_posix1e[0])), aclp_posix1e);
     10555 #endif
     10556+       if (r == 0)
     10557+               return (ARCHIVE_TEST_ACL_TYPE_POSIX1E);
     10558+       else
     10559+               return (0);
     10560+#endif /* ARCHIVE_ACL_POSIX1E */
     10561+#if ARCHIVE_ACL_DARWIN
     10562+testacl_free:
     10563+       acl_free(acl);
     10564+#endif
     10565+#endif /* ARCHIVE_ACL_SUPPORT */
     10566+       (void)path;     /* UNUSED */
     10567+       return (0);
     10568+}
     10569 
     10570 /*
     10571  * Sleep as needed; useful for verifying disk timestamp changes by
  • new file archivers/libarchive/files/patch-Makefile.am.diff

    diff --git a/archivers/libarchive/files/patch-Makefile.am.diff b/archivers/libarchive/files/patch-Makefile.am.diff
    new file mode 100644
    index 0000000000..17c1f4ba15
    - +  
     1diff --git a/Makefile.am b/Makefile.am
     2index 1cbdff5..f7adcbd 100644
     3--- a/Makefile.am
     4+++ b/Makefile.am
     5@@ -23,7 +23,7 @@
     6 DISTCHECK_CONFIGURE_FLAGS = --enable-bsdtar --enable-bsdcpio
     7 # The next line is commented out by default in shipping libarchive releases.
     8 # It is uncommented by default in trunk.
     9-DEV_CFLAGS=-Werror -Wextra -Wunused -Wshadow -Wmissing-prototypes -Wcast-qual -g
     10+# DEV_CFLAGS=-Werror -Wextra -Wunused -Wshadow -Wmissing-prototypes -Wcast-qual -g
     11 AM_CFLAGS=$(DEV_CFLAGS)
     12 PLATFORMCPPFLAGS = @PLATFORMCPPFLAGS@
     13 AM_CPPFLAGS=$(PLATFORMCPPFLAGS)
  • new file archivers/libarchive/files/patch-libarchive__archive_read_support_format_lha.c_p1.diff

    diff --git a/archivers/libarchive/files/patch-libarchive__archive_read_support_format_lha.c_p1.diff b/archivers/libarchive/files/patch-libarchive__archive_read_support_format_lha.c_p1.diff
    new file mode 100644
    index 0000000000..f8e638dd28
    - +  
     1diff --git a/libarchive/archive_read_support_format_lha.c b/libarchive/archive_read_support_format_lha.c
     2index d77a7c2..7056b02 100644
     3--- a/libarchive/archive_read_support_format_lha.c
     4+++ b/libarchive/archive_read_support_format_lha.c
     5@@ -1716,13 +1716,15 @@ lha_crc16(uint16_t crc, const void *pp, size_t len)
     6                /* This if statement expects compiler optimization will
     7                 * remove the statement which will not be executed. */
     8 #undef bswap16
     9+#ifndef __has_builtin
     10+#define __has_builtin(x) 0
     11+#endif
     12 #if defined(_MSC_VER) && _MSC_VER >= 1400  /* Visual Studio */
     13 #  define bswap16(x) _byteswap_ushort(x)
     14 #elif defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || __GNUC__ > 4)
     15 /* GCC 4.8 and later has __builtin_bswap16() */
     16 #  define bswap16(x) __builtin_bswap16(x)
     17-#elif defined(__clang__)
     18-/* All clang versions have __builtin_bswap16() */
     19+#elif defined(__clang__) && __has_builtin(__builtin_bswap16)
     20 #  define bswap16(x) __builtin_bswap16(x)
     21 #else
     22 #  define bswap16(x) ((((x) >> 8) & 0xff) | ((x) << 8))