Ticket #53712: patch-Makefile.am.diff

File patch-Makefile.am.diff, 306.2 KB (added by ballapete (Peter "Pete" Dyballa), 8 years ago)
  • new file libarchive/files/patch-Makefile.am.diff

    +--- Makefile.am.orig
    ++++ Makefile.am
    +@@ -23,7 +23,7 @@ TESTS_ENVIRONMENT= $(libarchive_TESTS_ENVIRONMENT) $(bsdtar_TESTS_ENVIRONMENT) $
    + DISTCHECK_CONFIGURE_FLAGS = --enable-bsdtar --enable-bsdcpio
    + # The next line is commented out by default in shipping libarchive releases.
    + # It is uncommented by default in trunk.
    +-# DEV_CFLAGS=-Werror -Wextra -Wunused -Wshadow -Wmissing-prototypes -Wcast-qual -g
    ++DEV_CFLAGS=-Werror -Wextra -Wunused -Wshadow -Wmissing-prototypes -Wcast-qual -g
    + AM_CFLAGS=$(DEV_CFLAGS)
    + PLATFORMCPPFLAGS = @PLATFORMCPPFLAGS@
    + AM_CPPFLAGS=$(PLATFORMCPPFLAGS)
    +@@ -127,6 +127,7 @@ libarchive_la_SOURCES= \
    + 	libarchive/archive_pathmatch.c \
    + 	libarchive/archive_pathmatch.h \
    + 	libarchive/archive_platform.h \
    ++	libarchive/archive_platform_acl.h \
    + 	libarchive/archive_ppmd_private.h \
    + 	libarchive/archive_ppmd7.c \
    + 	libarchive/archive_ppmd7_private.h \
    +@@ -186,9 +187,9 @@ libarchive_la_SOURCES= \
    + 	libarchive/archive_string_composition.h \
    + 	libarchive/archive_string_sprintf.c \
    + 	libarchive/archive_util.c \
    ++	libarchive/archive_version_details.c \
    + 	libarchive/archive_virtual.c \
    + 	libarchive/archive_write.c \
    +-	libarchive/archive_write_disk_acl.c \
    + 	libarchive/archive_write_disk_posix.c \
    + 	libarchive/archive_write_disk_private.h \
    + 	libarchive/archive_write_disk_set_standard_lookup.c \
    +@@ -247,6 +248,38 @@ libarchive_la_SOURCES+= \
    + 	libarchive/filter_fork_windows.c
    + endif
    + 
    ++if INC_LINUX_ACL
    ++libarchive_la_SOURCES+= \
    ++	libarchive/archive_acl_maps.h \
    ++	libarchive/archive_acl_maps_linux.c \
    ++	libarchive/archive_read_disk_acl_linux.c \
    ++	libarchive/archive_write_disk_acl_linux.c
    ++else
    ++if INC_SUNOS_ACL
    ++libarchive_la_SOURCES+= \
    ++	libarchive/archive_acl_maps.h \
    ++	libarchive/archive_acl_maps_sunos.c \
    ++	libarchive/archive_read_disk_acl_sunos.c \
    ++	libarchive/archive_write_disk_acl_sunos.c
    ++else
    ++if INC_DARWIN_ACL
    ++libarchive_la_SOURCES+= \
    ++	libarchive/archive_acl_maps.h \
    ++	libarchive/archive_acl_maps_darwin.c \
    ++	libarchive/archive_read_disk_acl_darwin.c \
    ++	libarchive/archive_write_disk_acl_darwin.c
    ++else
    ++if INC_FREEBSD_ACL
    ++libarchive_la_SOURCES+= \
    ++	libarchive/archive_acl_maps.h \
    ++	libarchive/archive_acl_maps_freebsd.c \
    ++	libarchive/archive_read_disk_acl_freebsd.c \
    ++	libarchive/archive_write_disk_acl_freebsd.c
    ++endif
    ++endif
    ++endif
    ++endif
    ++
    + # -no-undefined marks that libarchive doesn't rely on symbols
    + # defined in the application.  This is mandatory for cygwin.
    + libarchive_la_LDFLAGS= -no-undefined -version-info $(ARCHIVE_LIBTOOL_VERSION)
    +@@ -951,10 +984,12 @@ bsdtar_test_SOURCES= \
    + 	tar/test/test_option_T_upper.c \
    + 	tar/test/test_option_U_upper.c \
    + 	tar/test/test_option_X_upper.c \
    ++	tar/test/test_option_acls.c \
    + 	tar/test/test_option_a.c \
    + 	tar/test/test_option_b.c \
    + 	tar/test/test_option_b64encode.c \
    + 	tar/test/test_option_exclude.c \
    ++	tar/test/test_option_fflags.c \
    + 	tar/test/test_option_gid_gname.c \
    + 	tar/test/test_option_grzip.c \
    + 	tar/test/test_option_j.c \
    +--- NEWS.orig
    ++++ NEWS
    +@@ -1,3 +1,5 @@
    ++Mar 16, 2017: NFSv4 ACL support for Linux (librichacl)
    ++
    + Feb 26, 2017: libarchive 3.3.1 released
    +     Security & Feature release
    + 
    +@@ -293,7 +295,7 @@ May 04, 2008: libarchive 2.5.3b released
    + 	* libarchive: Mark which entry strings are set; be accurate about
    + 	  distinguishing empty strings ("") from unset ones (NULL)
    + 	* tar: Don't crash reading entries with empty filenames
    +-	* libarchive_test, bsdtar_test, bsdcpio_test:  Better detaults:
    ++	* libarchive_test, bsdtar_test, bsdcpio_test:  Better defaults:
    + 	  run all tests, delete temp dirs, summarize repeated failures
    + 	* -no-undefined to libtool for Cygwin
    + 	* libarchive_test: Skip large file tests on systems with 32-bit off_t
    +--- build/cmake/config.h.in.orig
    ++++ build/cmake/config.h.in
    +@@ -179,6 +179,27 @@ typedef uint64_t uintmax_t;
    + /* Define ZLIB_WINAPI if zlib was built on Visual Studio. */
    + #cmakedefine ZLIB_WINAPI 1
    + 
    ++/* Darwin ACL support */
    ++#cmakedefine ARCHIVE_ACL_DARWIN 1
    ++
    ++/* FreeBSD ACL support */
    ++#cmakedefine ARCHIVE_ACL_FREEBSD 1
    ++
    ++/* FreeBSD NFSv4 ACL support */
    ++#cmakedefine ARCHIVE_ACL_FREEBSD_NFS4 1
    ++
    ++/* Linux POSIX.1e ACL support via libacl */
    ++#cmakedefine ARCHIVE_ACL_LIBACL 1
    ++
    ++/* Linux NFSv4 ACL support via librichacl */
    ++#cmakedefine ARCHIVE_ACL_LIBRICHACL 1
    ++
    ++/* Solaris ACL support */
    ++#cmakedefine ARCHIVE_ACL_SUNOS 1
    ++
    ++/* Solaris NFSv4 ACL support */
    ++#cmakedefine ARCHIVE_ACL_SUNOS_NFS4 1
    ++
    + /* MD5 via ARCHIVE_CRYPTO_MD5_LIBC supported. */
    + #cmakedefine ARCHIVE_CRYPTO_MD5_LIBC 1
    + 
    +@@ -326,15 +347,6 @@ typedef uint64_t uintmax_t;
    + /* Define to 1 if you have the `acl_set_file' function. */
    + #cmakedefine HAVE_ACL_SET_FILE 1
    + 
    +-/* True for FreeBSD with NFSv4 ACL support */
    +-#cmakedefine HAVE_ACL_TYPE_NFS4 1
    +-
    +-/* True for MacOS ACL support */
    +-#cmakedefine HAVE_ACL_TYPE_EXTENDED 1
    +-
    +-/* True for systems with POSIX ACL support */
    +-#cmakedefine HAVE_ACL_USER 1
    +-
    + /* Define to 1 if you have the `arc4random_buf' function. */
    + #cmakedefine HAVE_ARC4RANDOM_BUF 1
    + 
    +@@ -371,6 +383,34 @@ typedef uint64_t uintmax_t;
    + /* Define to 1 if you have the `cygwin_conv_path' function. */
    + #cmakedefine HAVE_CYGWIN_CONV_PATH 1
    + 
    ++/* Define to 1 if you have the declaration of `ACE_GETACL', and to 0 if you
    ++   don't. */
    ++#cmakedefine HAVE_DECL_ACE_GETACL 1
    ++
    ++/* Define to 1 if you have the declaration of `ACE_GETACLCNT', and to 0 if you
    ++   don't. */
    ++#cmakedefine HAVE_DECL_ACE_GETACLCNT 1
    ++
    ++/* Define to 1 if you have the declaration of `ACE_SETACL', and to 0 if you
    ++   don't. */
    ++#cmakedefine HAVE_DECL_ACE_SETACL 1
    ++
    ++/* Define to 1 if you have the declaration of `ACL_SYNCHRONIZE', and to 0 if
    ++   you don't. */
    ++#cmakedefine HAVE_DECL_ACL_SYNCHRONIZE 1
    ++
    ++/* Define to 1 if you have the declaration of `ACL_TYPE_EXTENDED', and to 0 if
    ++   you don't. */
    ++#cmakedefine HAVE_DECL_ACL_TYPE_EXTENDED 1
    ++
    ++/* Define to 1 if you have the declaration of `ACL_TYPE_NFS4', and to 0 if you
    ++   don't. */
    ++#cmakedefine HAVE_DECL_ACL_TYPE_NFS4 1
    ++
    ++/* Define to 1 if you have the declaration of `ACL_USER', and to 0 if you
    ++   don't. */
    ++#cmakedefine HAVE_DECL_ACL_USER 1
    ++
    + /* Define to 1 if you have the declaration of `INT32_MAX', and to 0 if you
    +    don't. */
    + #cmakedefine HAVE_DECL_INT32_MAX 1
    +@@ -395,6 +435,10 @@ typedef uint64_t uintmax_t;
    +    don't. */
    + #cmakedefine HAVE_DECL_INTMAX_MIN 1
    + 
    ++/* Define to 1 if you have the declaration of `SETACL', and to 0 if you don't.
    ++   */
    ++#cmakedefine HAVE_DECL_SETACL 1
    ++
    + /* Define to 1 if you have the declaration of `SIZE_MAX', and to 0 if you
    +    don't. */
    + #cmakedefine HAVE_DECL_SIZE_MAX 1
    +@@ -468,6 +512,14 @@ typedef uint64_t uintmax_t;
    + /* Define to 1 if EXTATTR_NAMESPACE_USER is defined in sys/extattr.h. */
    + #cmakedefine HAVE_DECL_EXTATTR_NAMESPACE_USER 1
    + 
    ++/* Define to 1 if you have the declaration of `GETACL', and to 0 if you don't.
    ++   */
    ++#cmakedefine HAVE_DECL_GETACL 1
    ++
    ++/* Define to 1 if you have the declaration of `GETACLCNT', and to 0 if you
    ++   don't. */
    ++#cmakedefine HAVE_DECL_GETACLCNT 1
    ++
    + /* Define to 1 if you have the `fchdir' function. */
    + #cmakedefine HAVE_FCHDIR 1
    + 
    +@@ -742,6 +794,9 @@ typedef uint64_t uintmax_t;
    + /* Define to 1 if you have the `mbrtowc' function. */
    + #cmakedefine HAVE_MBRTOWC 1
    + 
    ++/* Define to 1 if you have the <membership.h> header file. */
    ++#cmakedefine HAVE_MEMBERSHIP_H 1
    ++
    + /* Define to 1 if you have the `memmove' function. */
    + #cmakedefine HAVE_MEMMOVE 1
    + 
    +@@ -979,6 +1034,9 @@ typedef uint64_t uintmax_t;
    + /* Define to 1 if you have the <sys/poll.h> header file. */
    + #cmakedefine HAVE_SYS_POLL_H 1
    + 
    ++/* Define to 1 if you have the <sys/richacl.h> header file. */
    ++#cmakedefine HAVE_SYS_RICHACL_H 1
    ++
    + /* Define to 1 if you have the <sys/select.h> header file. */
    + #cmakedefine HAVE_SYS_SELECT_H 1
    + 
    +--- build/version.orig
    ++++ build/version
    +@@ -1 +1 @@
    +-3003001
    ++3003002dev
    +--- cat/test/CMakeLists.txt.orig
    ++++ cat/test/CMakeLists.txt
    +@@ -29,6 +29,16 @@ IF(ENABLE_CAT AND ENABLE_TEST)
    +   # Register target
    +   #
    +   ADD_EXECUTABLE(bsdcat_test ${bsdcat_test_SOURCES})
    ++  IF(ENABLE_ACL)
    ++    SET(TEST_ACL_LIBS "")
    ++    IF(HAVE_LIBACL)
    ++      LIST(APPEND TEST_ACL_LIBS ${ACL_LIBRARY})
    ++    ENDIF(HAVE_LIBACL)
    ++    IF(HAVE_LIBRICHACL)
    ++      LIST(APPEND TEST_ACL_LIBS ${RICHACL_LIBRARY})
    ++    ENDIF(HAVE_LIBRICHACL)
    ++    TARGET_LINK_LIBRARIES(bsdcat_test ${TEST_ACL_LIBS})
    ++  ENDIF(ENABLE_ACL)
    +   SET_PROPERTY(TARGET bsdcat_test PROPERTY COMPILE_DEFINITIONS LIST_H)
    + 
    +   #
    +--- configure.ac.orig
    ++++ configure.ac
    +@@ -4,8 +4,8 @@ dnl First, define all of the version numbers up front.
    + dnl In particular, this allows the version macro to be used in AC_INIT
    + 
    + dnl These first two version numbers are updated automatically on each release.
    +-m4_define([LIBARCHIVE_VERSION_S],[3.3.1])
    +-m4_define([LIBARCHIVE_VERSION_N],[3003001])
    ++m4_define([LIBARCHIVE_VERSION_S],[3.3.2dev])
    ++m4_define([LIBARCHIVE_VERSION_N],[3003002])
    + 
    + dnl bsdtar and bsdcpio versioning tracks libarchive
    + m4_define([BSDTAR_VERSION_S],LIBARCHIVE_VERSION_S())
    +@@ -253,6 +253,7 @@ esac
    + # Checks for header files.
    + AC_HEADER_DIRENT
    + AC_HEADER_SYS_WAIT
    ++AC_CHECK_HEADERS([acl/libacl.h])
    + AC_CHECK_HEADERS([copyfile.h ctype.h])
    + AC_CHECK_HEADERS([errno.h ext2fs/ext2_fs.h fcntl.h grp.h])
    + 
    +@@ -283,16 +284,16 @@ AS_VAR_IF([ac_cv_have_decl_FS_IOC_GETFLAGS], [yes],
    +     [AC_DEFINE_UNQUOTED([HAVE_WORKING_FS_IOC_GETFLAGS], [1],
    +                     [Define to 1 if you have a working FS_IOC_GETFLAGS])])
    + 
    +-AC_CHECK_HEADERS([locale.h paths.h poll.h pthread.h pwd.h])
    ++AC_CHECK_HEADERS([locale.h membership.h paths.h poll.h pthread.h pwd.h])
    + AC_CHECK_HEADERS([readpassphrase.h signal.h spawn.h])
    + AC_CHECK_HEADERS([stdarg.h stdint.h stdlib.h string.h])
    +-AC_CHECK_HEADERS([sys/cdefs.h sys/extattr.h])
    ++AC_CHECK_HEADERS([sys/acl.h sys/cdefs.h sys/extattr.h])
    + AC_CHECK_HEADERS([sys/ioctl.h sys/mkdev.h sys/mount.h])
    +-AC_CHECK_HEADERS([sys/param.h sys/poll.h sys/select.h sys/statfs.h sys/statvfs.h])
    ++AC_CHECK_HEADERS([sys/param.h sys/poll.h sys/richacl.h])
    ++AC_CHECK_HEADERS([sys/select.h sys/statfs.h sys/statvfs.h])
    + AC_CHECK_HEADERS([sys/time.h sys/utime.h sys/utsname.h sys/vfs.h])
    + AC_CHECK_HEADERS([time.h unistd.h utime.h wchar.h wctype.h])
    + AC_CHECK_HEADERS([windows.h])
    +-AC_CHECK_HEADERS([Bcrypt.h])
    + # check windows.h first; the other headers require it.
    + AC_CHECK_HEADERS([wincrypt.h winioctl.h],[],[],
    + [[#ifdef HAVE_WINDOWS_H
    +@@ -399,6 +400,9 @@ if test "x$with_lzo2" = "xyes"; then
    +   AC_CHECK_LIB(lzo2,lzo1x_decompress_safe)
    + fi
    + 
    ++AC_ARG_WITH([cng],
    ++  AS_HELP_STRING([--without-cng], [Don't build support of CNG(Crypto Next Generation)]))
    ++
    + AC_ARG_WITH([nettle],
    +   AS_HELP_STRING([--without-nettle], [Don't build with crypto support from Nettle]))
    + AC_ARG_WITH([openssl],
    +@@ -697,72 +701,211 @@ AC_ARG_ENABLE([acl],
    + 		[Disable ACL support (default: check)]))
    + 
    + if test "x$enable_acl" != "xno"; then
    +-   AC_CHECK_HEADERS([acl/libacl.h])
    +-   AC_CHECK_HEADERS([sys/acl.h])
    +-   AC_CHECK_LIB([acl],[acl_get_file])
    +-   AC_CHECK_FUNCS([acl_create_entry acl_get_fd_np])
    +-   AC_CHECK_FUNCS([acl_init acl_set_fd acl_set_fd_np acl_set_file])
    ++    # Libacl
    ++    AC_CHECK_LIB([acl], [acl_get_file])
    ++
    ++    AC_CHECK_TYPES([acl_t, acl_entry_t, acl_permset_t, acl_tag_t], [], [], [
    ++      #if HAVE_SYS_TYPES_H
    ++      #include <sys/types.h>
    ++      #endif
    ++      #if HAVE_SYS_ACL_H
    ++      #include <sys/acl.h>
    ++      #endif
    ++    ])
    ++
    ++    AC_CHECK_LIB([richacl], [richacl_get_file])
    ++
    ++    AC_CHECK_TYPES([[struct richace], [struct richacl]], [], [], [
    ++      #if HAVE_SYS_RICHACL_H
    ++      #include <sys/richacl.h>
    ++      #endif
    ++    ])
    + 
    +-   AC_CHECK_TYPES(acl_permset_t,,,
    +-	[#if HAVE_SYS_TYPES_H
    +-	#include <sys/types.h>
    +-	#endif
    +-	#if HAVE_SYS_ACL_H
    +-	#include <sys/acl.h>
    +-	#endif
    +-	])
    +-
    +-    # The "acl_get_perm()" function was omitted from the POSIX draft.
    +-    # (It's a pretty obvious oversight; otherwise, there's no way to
    +-    # test for specific permissions in a permset.)  Linux uses the obvious
    +-    # name, FreeBSD adds _np to mark it as "non-Posix extension."
    +-    # Test for both as a double-check that we really have POSIX-style ACL
    +-    # support.
    +-    AC_CHECK_FUNCS(acl_get_perm_np acl_get_perm acl_get_link acl_get_link_np,,,
    +-	[#if HAVE_SYS_TYPES_H
    +-	#include <sys/types.h>
    +-	#endif
    +-	#if HAVE_SYS_ACL_H
    +-	#include <sys/acl.h>
    +-	#endif
    +-	])
    ++    # Solaris and derivates ACLs
    ++    AC_CHECK_FUNCS(acl facl)
    ++
    ++    if test "x$ac_cv_lib_richacl_richacl_get_file" = "xyes" \
    ++	 -a "x$ac_cv_type_struct_richace" = "xyes" \
    ++	 -a "x$ac_cv_type_struct_richacl" = "xyes"; then
    ++	AC_CACHE_VAL([ac_cv_archive_acl_librichacl],
    ++	  [AC_CHECK_FUNCS(richacl_alloc \
    ++			  richacl_equiv_mode \
    ++			  richacl_free \
    ++			  richacl_get_fd \
    ++			  richacl_get_file \
    ++			  richacl_set_fd \
    ++			  richacl_set_file,
    ++	  [ac_cv_archive_acl_librichacl=yes], [ac_cv_archive_acl_librichacl=no],	  [#include <sys/richacl.h>])])
    ++    fi
    + 
    +-    # Check for acl_is_trivial_np on FreeBSD
    +-    AC_CHECK_FUNCS(acl_is_trivial_np,,,
    +-	[#if HAVE_SYS_TYPES_H
    +-	#include <sys/types.h>
    +-	#endif
    +-	#if HAVE_SYS_ACL_H
    +-	#include <sys/acl.h>
    +-	#endif
    ++    if test "x$ac_cv_func_acl" = "xyes" \
    ++	 -a "x$ac_cv_func_facl" = "xyes"; then
    ++	AC_CHECK_TYPES([aclent_t], [], [], [[#include <sys/acl.h>]])
    ++	if test "x$ac_cv_type_aclent_t" = "xyes"; then
    ++	    AC_CACHE_VAL([ac_cv_archive_acl_sunos],
    ++	      [AC_CHECK_DECLS([GETACL, SETACL, GETACLCNT],
    ++	      [ac_cv_archive_acl_sunos=yes], [ac_cv_archive_acl_sunos=no],
    ++	      [#include <sys/acl.h>])])
    ++	    AC_CHECK_TYPES([ace_t], [], [], [[#include <sys/acl.h>]])
    ++	    if test "x$ac_cv_type_ace_t" = "xyes"; then
    ++		AC_CACHE_VAL([ac_cv_archive_acl_sunos_nfs4],
    ++		  [AC_CHECK_DECLS([ACE_GETACL, ACE_SETACL, ACE_GETACLCNT],
    ++		  [ac_cv_archive_acl_sunos_nfs4=yes],
    ++		  [ac_cv_archive_acl_sonos_nfs4=no],
    ++		  [#include <sys/acl.h>])])
    ++	    fi
    ++	fi
    ++    elif test "x$ac_cv_type_acl_t" = "xyes" \
    ++	 -a "x$ac_cv_type_acl_entry_t" = "xyes" \
    ++	 -a "x$ac_cv_type_acl_permset_t" = "xyes" \
    ++	 -a "x$ac_cv_type_acl_tag_t" = "xyes"; then
    ++	# POSIX.1e ACL functions
    ++	AC_CACHE_VAL([ac_cv_posix_acl_funcs],
    ++	  [AC_CHECK_FUNCS(acl_add_perm \
    ++			  acl_clear_perms \
    ++			  acl_create_entry \
    ++			  acl_delete_def_file \
    ++			  acl_free \
    ++			  acl_get_entry \
    ++			  acl_get_fd \
    ++			  acl_get_file \
    ++			  acl_get_permset \
    ++			  acl_get_qualifier \
    ++			  acl_get_tag_type \
    ++			  acl_init \
    ++			  acl_set_fd \
    ++			  acl_set_file \
    ++			  acl_set_qualifier \
    ++			  acl_set_tag_type,
    ++	  [ac_cv_posix_acl_funcs=yes], [ac_cv_posix_acl_funcs=no],
    ++	  [#if HAVE_SYS_TYPES_H
    ++	   #include <sys/types.h>
    ++	   #endif
    ++	   #if HAVE_SYS_ACL_H
    ++	   #include <sys/acl.h>
    ++	   #endif
    ++	  ])
    + 	])
    + 
    +-    # Check for ACL_TYPE_NFS4
    +-    AC_CHECK_DECL([ACL_TYPE_NFS4],
    +-		[AC_DEFINE(HAVE_ACL_TYPE_NFS4, 1, [True for FreeBSD with NFSv4 ACL support])],
    +-		[],
    +-		[#include <sys/acl.h>])
    ++	AC_CHECK_FUNCS(acl_get_perm)
    + 
    +-    # MacOS has an acl.h that isn't POSIX.  It can be detected by
    +-    # checking for ACL_USER
    +-    AC_CHECK_DECL([ACL_USER],
    +-		[AC_DEFINE(HAVE_ACL_USER, 1, [True for systems with POSIX ACL support])],
    +-		[],
    +-		[#include <sys/acl.h>])
    ++	if test "x$ac_cv_posix_acl_funcs" = "xyes" \
    ++	     -a "x$ac_cv_header_acl_libacl_h" = "xyes" \
    ++	     -a "x$ac_cv_lib_acl_acl_get_file" = "xyes" \
    ++	     -a "x$ac_cv_func_acl_get_perm"; then
    ++	    AC_CACHE_VAL([ac_cv_archive_acl_libacl],
    ++	      [ac_cv_archive_acl_libacl=yes])
    ++	    AC_DEFINE([ARCHIVE_ACL_LIBACL], [1],
    ++	      [POSIX.1e ACL support via libacl])
    ++	else
    ++	     # FreeBSD/Darwin
    ++	     AC_CHECK_FUNCS(acl_add_flag_np \
    ++			    acl_clear_flags_np \
    ++			    acl_get_brand_np \
    ++			    acl_get_entry_type_np \
    ++			    acl_get_flag_np \
    ++			    acl_get_flagset_np \
    ++			    acl_get_fd_np \
    ++			    acl_get_link_np \
    ++			    acl_get_perm_np \
    ++			    acl_is_trivial_np \
    ++			    acl_set_entry_type_np \
    ++			    acl_set_fd_np \
    ++			    acl_set_link_np,,,
    ++	      [#include <sys/types.h>
    ++	       #include <sys/acl.h>])
    ++
    ++	    AC_CHECK_FUNCS(mbr_uid_to_uuid \
    ++			   mbr_uuid_to_id \
    ++			   mbr_gid_to_uuid,,,
    ++	      [#include <membership.h>])
    ++
    ++	    AC_CHECK_DECLS([ACL_TYPE_EXTENDED, ACL_TYPE_NFS4, ACL_USER,
    ++	      ACL_SYNCHRONIZE], [], [],
    ++	      [#include <sys/types.h>
    ++	       #include <sys/acl.h>])
    ++	    if test "x$ac_cv_posix_acl_funcs" = "xyes" \
    ++	         -a "x$ac_cv_func_acl_get_fd_np" = "xyes" \
    ++                 -a "x$ac_cv_func_acl_get_perm" != "xyes" \
    ++	         -a "x$ac_cv_func_acl_get_perm_np" = "xyes" \
    ++	         -a "x$ac_cv_func_acl_set_fd_np" = "xyes"; then
    ++		if test "x$ac_cv_have_decl_ACL_USER" = "xyes"; then
    ++		    AC_CACHE_VAL([ac_cv_archive_acl_freebsd],
    ++		      [ac_cv_archive_acl_freebsd=yes])
    ++		    if test "x$ac_cv_have_decl_ACL_TYPE_NFS4" = "xyes" \
    ++		         -a "x$ac_cv_func_acl_add_flag_np" = "xyes" \
    ++		         -a "x$ac_cv_func_acl_get_brand_np" = "xyes" \
    ++		         -a "x$ac_cv_func_acl_get_entry_type_np" = "xyes" \
    ++		         -a "x$ac_cv_func_acl_get_flagset_np" = "xyes" \
    ++		         -a "x$ac_cv_func_acl_set_entry_type_np" = "xyes"; then
    ++			AC_CACHE_VAL([ac_cv_archive_acl_freebsd_nfs4],
    ++			  [ac_cv_archive_acl_freebsd_nfs4=yes])
    ++		    fi
    ++	        elif test "x$ac_cv_have_decl_ACL_TYPE_EXTENDED" = "xyes" \
    ++		       -a "x$ac_cv_func_acl_add_flag_np" = "xyes" \
    ++		       -a "x$ac_cv_func_acl_get_flagset_np" = "xyes" \
    ++		       -a "x$ac_cv_func_acl_get_link_np" = "xyes" \
    ++		       -a "x$ac_cv_func_acl_set_link_np" = "xyes" \
    ++		       -a "x$ac_cv_func_mbr_uid_to_uuid" = "xyes" \
    ++		       -a "x$ac_cv_func_mbr_uuid_to_id" = "xyes" \
    ++		       -a "x$ac_cv_func_mbr_gid_to_uuid" = "xyes"; then
    ++		    AC_CACHE_VAL([ac_cv_archive_acl_darwin],
    ++		      [ac_cv_archive_acl_darwin=yes])
    ++	        fi
    ++	    fi
    ++	fi
    ++    fi
    ++    AC_MSG_CHECKING([for ACL support])
    ++    if test "x$ac_cv_archive_acl_libacl" = "xyes" \
    ++	 -a "x$ac_cv_archive_acl_librichacl" = "xyes"; then
    ++	AC_MSG_RESULT([libacl (POSIX.1e) + librichacl (NFSv4)])
    ++	AC_DEFINE([ARCHIVE_ACL_LIBACL], [1],
    ++	  [Linux POSIX.1e ACL support via libacl])
    ++	AC_DEFINE([ARCHIVE_ACL_LIBRICHACL], [1],
    ++	  [Linux NFSv4 ACL support via librichacl])
    ++    elif test "x$ac_cv_archive_acl_libacl" = "xyes"; then
    ++	AC_MSG_RESULT([libacl (POSIX.1e)])
    ++	AC_DEFINE([ARCHIVE_ACL_LIBACL], [1],
    ++	  [Linux POSIX.1e ACL support via libacl])
    ++    elif test "x$ac_cv_archive_acl_librichacl" = "xyes"; then
    ++	AC_MSG_RESULT([librichacl (NFSv4)])
    ++	AC_DEFINE([ARCHIVE_ACL_LIBRICHACL], [1],
    ++	  [Linux NFSv4 ACL support via librichacl])
    ++    elif test "x$ac_cv_archive_acl_darwin" = "xyes"; then
    ++	AC_DEFINE([ARCHIVE_ACL_DARWIN], [1], [Darwin ACL support])
    ++	AC_MSG_RESULT([Darwin (limited NFSv4)])
    ++    elif test "x$ac_cv_archive_acl_sunos" = "xyes"; then
    ++	AC_DEFINE([ARCHIVE_ACL_SUNOS], [1], [Solaris ACL support])
    ++	if test "x$ac_cv_archive_acl_sunos_nfs4" = "xyes"; then
    ++	    AC_DEFINE([ARCHIVE_ACL_SUNOS_NFS4], [1],
    ++	      [Solaris NFSv4 ACL support])
    ++	    AC_MSG_RESULT([Solaris (POSIX.1e and NFSv4)])
    ++	else
    ++	    AC_MSG_RESULT([Solaris (POSIX.1e)])
    ++	fi
    ++    elif test "x$ac_cv_archive_acl_freebsd" = "xyes"; then
    ++	AC_DEFINE([ARCHIVE_ACL_FREEBSD], [1], [FreeBSD ACL support])
    ++	if test "x$ac_cv_archive_acl_freebsd_nfs4" = "xyes"; then
    ++	    AC_DEFINE([ARCHIVE_ACL_FREEBSD_NFS4], [1],
    ++	      [FreeBSD NFSv4 ACL support])
    ++	    AC_MSG_RESULT([FreeBSD (POSIX.1e and NFSv4)])
    ++	else
    ++	    AC_MSG_RESULT([FreeBSD (POSIX.1e)])
    ++	fi
    ++    else
    ++	AC_MSG_RESULT([none])
    ++    fi
    ++fi
    + 
    +-    # MacOS has ACL_TYPE_EXTENDED instead
    +-    AC_CHECK_DECL([ACL_TYPE_EXTENDED],
    +-		[AC_DEFINE(HAVE_ACL_TYPE_EXTENDED, 1, [True for MacOS ACL support])],
    +-		[],
    +-		[#include <sys/types.h>
    +-		#include <sys/acl.h>])
    + 
    +-    # Solaris and derivates ACLs
    +-    AC_CHECK_LIB([sec], [acl_get])
    +-    AC_CHECK_TYPES([aclent_t], [], [], [[#include <sys/acl.h>]])
    +-    AC_CHECK_TYPES([ace_t], [], [], [[#include <sys/acl.h>]])
    +-    AC_CHECK_FUNCS(acl_get facl_get acl_set facl_set)
    +-fi
    ++AM_CONDITIONAL([INC_LINUX_ACL],
    ++  [test "x$ac_cv_archive_acl_libacl" = "xyes" \
    ++     -o "x$ac_cv_archive_acl_librichacl" = "xyes"])
    ++AM_CONDITIONAL([INC_SUNOS_ACL], [test "x$ac_cv_archive_acl_sunos" = "xyes"])
    ++AM_CONDITIONAL([INC_DARWIN_ACL],
    ++	  [test "x$ac_cv_archive_acl_darwin" = "xyes"])
    ++AM_CONDITIONAL([INC_FREEBSD_ACL],
    ++	  [test "x$ac_cv_archive_acl_freebsd" = "xyes"])
    + 
    + # Additional requirements
    + AC_SYS_LARGEFILE
    +@@ -852,6 +995,16 @@ case "$host_os" in
    + 	;;
    + esac
    + 
    ++if test "x$with_cng" != "xno"; then
    ++    AC_CHECK_HEADERS([bcrypt.h],[
    ++        LIBS="$LIBS -lbcrypt"
    ++    ],[],
    ++    [[#ifdef HAVE_WINDOWS_H
    ++    # include <windows.h>
    ++    #endif
    ++    ]])
    ++fi
    ++
    + if test "x$with_nettle" != "xno"; then
    +     AC_CHECK_HEADERS([nettle/md5.h nettle/ripemd160.h nettle/sha.h])
    +     AC_CHECK_HEADERS([nettle/pbkdf2.h nettle/aes.h nettle/hmac.h])
    +--- cpio/cpio.c.orig
    ++++ cpio/cpio.c
    +@@ -108,22 +108,22 @@ static int	entry_to_archive(struct cpio *, struct archive_entry *);
    + static int	file_to_archive(struct cpio *, const char *);
    + static void	free_cache(struct name_cache *cache);
    + static void	list_item_verbose(struct cpio *, struct archive_entry *);
    +-static void	long_help(void);
    ++static void	long_help(void) __LA_DEAD;
    + static const char *lookup_gname(struct cpio *, gid_t gid);
    + static int	lookup_gname_helper(struct cpio *,
    + 		    const char **name, id_t gid);
    + static const char *lookup_uname(struct cpio *, uid_t uid);
    + static int	lookup_uname_helper(struct cpio *,
    + 		    const char **name, id_t uid);
    +-static void	mode_in(struct cpio *);
    +-static void	mode_list(struct cpio *);
    ++static void	mode_in(struct cpio *) __LA_DEAD;
    ++static void	mode_list(struct cpio *) __LA_DEAD;
    + static void	mode_out(struct cpio *);
    + static void	mode_pass(struct cpio *, const char *);
    + static const char *remove_leading_slash(const char *);
    + static int	restore_time(struct cpio *, struct archive_entry *,
    + 		    const char *, int fd);
    +-static void	usage(void);
    +-static void	version(void);
    ++static void	usage(void) __LA_DEAD;
    ++static void	version(void) __LA_DEAD;
    + static const char * passphrase_callback(struct archive *, void *);
    + static void	passphrase_free(char *);
    + 
    +@@ -1344,23 +1344,23 @@ lookup_name(struct cpio *cpio, struct name_cache **name_cache_variable,
    + 		cache->cache[slot].name = NULL;
    + 	}
    + 
    +-	if (lookup_fn(cpio, &name, id) == 0) {
    +-		if (name == NULL || name[0] == '\0') {
    +-			/* If lookup failed, format it as a number. */
    +-			snprintf(asnum, sizeof(asnum), "%u", (unsigned)id);
    +-			name = asnum;
    +-		}
    +-		cache->cache[slot].name = strdup(name);
    +-		if (cache->cache[slot].name != NULL) {
    +-			cache->cache[slot].id = id;
    +-			return (cache->cache[slot].name);
    +-		}
    +-		/*
    +-		 * Conveniently, NULL marks an empty slot, so
    +-		 * if the strdup() fails, we've just failed to
    +-		 * cache it.  No recovery necessary.
    +-		 */
    ++	if (lookup_fn(cpio, &name, id)) {
    ++		/* If lookup failed, format it as a number. */
    ++		snprintf(asnum, sizeof(asnum), "%u", (unsigned)id);
    ++		name = asnum;
    ++	}
    ++
    ++	cache->cache[slot].name = strdup(name);
    ++	if (cache->cache[slot].name != NULL) {
    ++		cache->cache[slot].id = id;
    ++		return (cache->cache[slot].name);
    + 	}
    ++
    ++	/*
    ++	 * Conveniently, NULL marks an empty slot, so
    ++	 * if the strdup() fails, we've just failed to
    ++	 * cache it.  No recovery necessary.
    ++	 */
    + 	return (NULL);
    + }
    + 
    +@@ -1381,15 +1381,14 @@ lookup_uname_helper(struct cpio *cpio, const char **name, id_t id)
    + 	errno = 0;
    + 	pwent = getpwuid((uid_t)id);
    + 	if (pwent == NULL) {
    +-		*name = NULL;
    +-		if (errno != 0 && errno != ENOENT)
    ++		if (errno && errno != ENOENT)
    + 			lafe_warnc(errno, "getpwuid(%s) failed",
    + 			    cpio_i64toa((int64_t)id));
    +-		return (errno);
    ++		return 1;
    + 	}
    + 
    + 	*name = pwent->pw_name;
    +-	return (0);
    ++	return 0;
    + }
    + 
    + static const char *
    +@@ -1409,15 +1408,14 @@ lookup_gname_helper(struct cpio *cpio, const char **name, id_t id)
    + 	errno = 0;
    + 	grent = getgrgid((gid_t)id);
    + 	if (grent == NULL) {
    +-		*name = NULL;
    +-		if (errno != 0)
    ++		if (errno && errno != ENOENT)
    + 			lafe_warnc(errno, "getgrgid(%s) failed",
    + 			    cpio_i64toa((int64_t)id));
    +-		return (errno);
    ++		return 1;
    + 	}
    + 
    + 	*name = grent->gr_name;
    +-	return (0);
    ++	return 0;
    + }
    + 
    + /*
    +--- cpio/test/CMakeLists.txt.orig
    ++++ cpio/test/CMakeLists.txt
    +@@ -62,6 +62,16 @@ IF(ENABLE_CPIO AND ENABLE_TEST)
    +   # Register target
    +   #
    +   ADD_EXECUTABLE(bsdcpio_test ${bsdcpio_test_SOURCES})
    ++  IF(ENABLE_ACL)
    ++    SET(TEST_ACL_LIBS "")
    ++    IF(HAVE_LIBACL)
    ++      LIST(APPEND TEST_ACL_LIBS ${ACL_LIBRARY})
    ++    ENDIF(HAVE_LIBACL)
    ++    IF(HAVE_LIBRICHACL)
    ++      LIST(APPEND TEST_ACL_LIBS ${RICHACL_LIBRARY})
    ++    ENDIF(HAVE_LIBRICHACL)
    ++    TARGET_LINK_LIBRARIES(bsdcpio_test ${TEST_ACL_LIBS})
    ++  ENDIF(ENABLE_ACL)
    +   SET_PROPERTY(TARGET bsdcpio_test PROPERTY COMPILE_DEFINITIONS LIST_H)
    + 
    +   #
    +--- libarchive/CMakeLists.txt.orig
    ++++ libarchive/CMakeLists.txt
    +@@ -14,6 +14,7 @@ SET(include_HEADERS
    + # Sources and private headers
    + SET(libarchive_SOURCES
    +   archive_acl.c
    ++  archive_acl_private.h
    +   archive_check_magic.c
    +   archive_cmdline.c
    +   archive_cmdline_private.h
    +@@ -47,6 +48,7 @@ SET(libarchive_SOURCES
    +   archive_pathmatch.c
    +   archive_pathmatch.h
    +   archive_platform.h
    ++  archive_platform_acl.h
    +   archive_ppmd_private.h
    +   archive_ppmd7.c
    +   archive_ppmd7_private.h
    +@@ -106,9 +108,9 @@ SET(libarchive_SOURCES
    +   archive_string_composition.h
    +   archive_string_sprintf.c
    +   archive_util.c
    ++  archive_version_details.c
    +   archive_virtual.c
    +   archive_write.c
    +-  archive_write_disk_acl.c
    +   archive_write_disk_posix.c
    +   archive_write_disk_private.h
    +   archive_write_disk_set_standard_lookup.c
    +@@ -210,6 +212,28 @@ IF(WIN32 AND NOT CYGWIN)
    +   LIST(APPEND libarchive_SOURCES filter_fork_windows.c)
    + ENDIF(WIN32 AND NOT CYGWIN)
    + 
    ++IF(ARCHIVE_ACL_DARWIN)
    ++  LIST(APPEND libarchive_SOURCES archive_acl_maps.h)
    ++  LIST(APPEND libarchive_SOURCES archive_acl_maps_darwin.c)
    ++  LIST(APPEND libarchive_SOURCES archive_read_disk_acl_darwin.c)
    ++  LIST(APPEND libarchive_SOURCES archive_write_disk_acl_darwin.c)
    ++ELSEIF(ARCHIVE_ACL_FREEBSD)
    ++  LIST(APPEND libarchive_SOURCES archive_acl_maps.h)
    ++  LIST(APPEND libarchive_SOURCES archive_acl_maps_freebsd.c)
    ++  LIST(APPEND libarchive_SOURCES archive_read_disk_acl_freebsd.c)
    ++  LIST(APPEND libarchive_SOURCES archive_write_disk_acl_freebsd.c)
    ++ELSEIF(ARCHIVE_ACL_LIBACL)
    ++  LIST(APPEND libarchive_SOURCES archive_acl_maps.h)
    ++  LIST(APPEND libarchive_SOURCES archive_acl_maps_linux.c)
    ++  LIST(APPEND libarchive_SOURCES archive_read_disk_acl_linux.c)
    ++  LIST(APPEND libarchive_SOURCES archive_write_disk_acl_linux.c)
    ++ELSEIF(ARCHIVE_ACL_SUNOS)
    ++  LIST(APPEND libarchive_SOURCES archive_acl_maps.h)
    ++  LIST(APPEND libarchive_SOURCES archive_acl_maps_sunos.c)
    ++  LIST(APPEND libarchive_SOURCES archive_read_disk_acl_sunos.c)
    ++  LIST(APPEND libarchive_SOURCES archive_write_disk_acl_sunos.c)
    ++ENDIF()
    ++
    + # Libarchive is a shared library
    + ADD_LIBRARY(archive SHARED ${libarchive_SOURCES} ${include_HEADERS})
    + TARGET_LINK_LIBRARIES(archive ${ADDITIONAL_LIBS})
    +--- libarchive/archive.h.orig
    ++++ libarchive/archive.h
    +@@ -36,7 +36,7 @@
    +  * assert that ARCHIVE_VERSION_NUMBER >= 2012108.
    +  */
    + /* Note: Compiler will complain if this does not match archive_entry.h! */
    +-#define	ARCHIVE_VERSION_NUMBER 3003001
    ++#define	ARCHIVE_VERSION_NUMBER 3003002
    + 
    + #include <sys/stat.h>
    + #include <stddef.h>  /* for wchar_t */
    +@@ -155,7 +155,7 @@ __LA_DECL int		archive_version_number(void);
    + /*
    +  * Textual name/version of the library, useful for version displays.
    +  */
    +-#define	ARCHIVE_VERSION_ONLY_STRING "3.3.1"
    ++#define	ARCHIVE_VERSION_ONLY_STRING "3.3.2dev"
    + #define	ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
    + __LA_DECL const char *	archive_version_string(void);
    + 
    +--- /dev/null
    ++++ libarchive/archive_acl_maps.h
    +@@ -0,0 +1,52 @@
    ++/*-
    ++ * Copyright (c) 2017 Martin Matuska
    ++ * All rights reserved.
    ++ *
    ++ * Redistribution and use in source and binary forms, with or without
    ++ * modification, are permitted provided that the following conditions
    ++ * are met:
    ++ * 1. Redistributions of source code must retain the above copyright
    ++ *    notice, this list of conditions and the following disclaimer.
    ++ * 2. Redistributions in binary form must reproduce the above copyright
    ++ *    notice, this list of conditions and the following disclaimer in the
    ++ *    documentation and/or other materials provided with the distribution.
    ++ *
    ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
    ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    ++ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
    ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    ++ */
    ++
    ++#ifndef __LIBARCHIVE_BUILD
    ++#error This header is only to be used internally to libarchive.
    ++#endif
    ++
    ++#ifndef ARCHIVE_ACL_MAPS_H_INCLUDED
    ++#define ARCHIVE_ACL_MAPS_H_INCLUDED
    ++
    ++#include "archive_platform_acl.h"
    ++
    ++typedef struct {
    ++	const int a_perm;	/* Libarchive permission or flag */
    ++	const int p_perm;	/* Platform permission or flag */
    ++} acl_perm_map_t;
    ++
    ++#ifndef _ARCHIVE_ACL_MAPS_DEFS
    ++#if ARCHIVE_ACL_POSIX1E
    ++extern const acl_perm_map_t acl_posix_perm_map[];
    ++extern const int acl_posix_perm_map_size;
    ++#endif
    ++#if ARCHIVE_ACL_NFS4
    ++extern const acl_perm_map_t acl_nfs4_perm_map[];
    ++extern const int acl_nfs4_perm_map_size;
    ++extern const acl_perm_map_t acl_nfs4_flag_map[];
    ++extern const int acl_nfs4_flag_map_size;
    ++#endif
    ++#endif /* !_ARCHIVE_ACL_MAPS_DEFS */
    ++#endif /* ARCHIVE_ACL_MAPS_H_INCLUDED */
    +--- /dev/null
    ++++ libarchive/archive_acl_maps_darwin.c
    +@@ -0,0 +1,76 @@
    ++/*-
    ++ * Copyright (c) 2017 Martin Matuska
    ++ * All rights reserved.
    ++ *
    ++ * Redistribution and use in source and binary forms, with or without
    ++ * modification, are permitted provided that the following conditions
    ++ * are met:
    ++ * 1. Redistributions of source code must retain the above copyright
    ++ *    notice, this list of conditions and the following disclaimer.
    ++ * 2. Redistributions in binary form must reproduce the above copyright
    ++ *    notice, this list of conditions and the following disclaimer in the
    ++ *    documentation and/or other materials provided with the distribution.
    ++ *
    ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
    ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    ++ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
    ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    ++ */
    ++
    ++#include "archive_platform.h"
    ++
    ++#ifdef HAVE_SYS_TYPES_H
    ++#include <sys/types.h>
    ++#endif
    ++#ifdef HAVE_SYS_ACL_H
    ++#define _ACL_PRIVATE /* For debugging */
    ++#include <sys/acl.h>
    ++#endif
    ++
    ++#include "archive_entry.h"
    ++#include "archive_private.h"
    ++#include "archive_read_disk_private.h"
    ++#define _ARCHIVE_ACL_MAPS_DEFS
    ++#include "archive_acl_maps.h"
    ++
    ++const acl_perm_map_t acl_nfs4_perm_map[] = {
    ++	{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
    ++	{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
    ++	{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
    ++	{ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
    ++	{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
    ++	{ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
    ++	{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
    ++	{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
    ++	{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
    ++	{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
    ++	{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
    ++	{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES},
    ++	{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES},
    ++	{ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY},
    ++	{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY},
    ++	{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER},
    ++#if HAVE_DECL_ACL_SYNCHRONIZE
    ++	{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
    ++#endif
    ++};
    ++
    ++const int acl_nfs4_perm_map_size =
    ++    (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));
    ++
    ++const acl_perm_map_t acl_nfs4_flag_map[] = {
    ++	{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED},
    ++	{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
    ++	{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
    ++	{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_LIMIT_INHERIT},
    ++	{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT}
    ++};
    ++
    ++const int acl_nfs4_flag_map_size =
    ++    (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));
    +--- /dev/null
    ++++ libarchive/archive_acl_maps_freebsd.c
    +@@ -0,0 +1,87 @@
    ++/*-
    ++ * Copyright (c) 2017 Martin Matuska
    ++ * All rights reserved.
    ++ *
    ++ * Redistribution and use in source and binary forms, with or without
    ++ * modification, are permitted provided that the following conditions
    ++ * are met:
    ++ * 1. Redistributions of source code must retain the above copyright
    ++ *    notice, this list of conditions and the following disclaimer.
    ++ * 2. Redistributions in binary form must reproduce the above copyright
    ++ *    notice, this list of conditions and the following disclaimer in the
    ++ *    documentation and/or other materials provided with the distribution.
    ++ *
    ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
    ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    ++ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
    ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    ++ */
    ++
    ++#include "archive_platform.h"
    ++
    ++#ifdef HAVE_SYS_TYPES_H
    ++#include <sys/types.h>
    ++#endif
    ++#ifdef HAVE_SYS_ACL_H
    ++#define _ACL_PRIVATE /* For debugging */
    ++#include <sys/acl.h>
    ++#endif
    ++
    ++#include "archive_entry.h"
    ++#include "archive_private.h"
    ++#include "archive_read_disk_private.h"
    ++#define _ARCHIVE_ACL_MAPS_DEFS
    ++#include "archive_acl_maps.h"
    ++
    ++const acl_perm_map_t acl_posix_perm_map[] = {
    ++	{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
    ++	{ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
    ++	{ARCHIVE_ENTRY_ACL_READ, ACL_READ},
    ++};
    ++
    ++const int acl_posix_perm_map_size =
    ++    (int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0]));
    ++
    ++#if ARCHIVE_ACL_FREEBSD_NFS4
    ++const acl_perm_map_t acl_nfs4_perm_map[] = {
    ++	{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
    ++	{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
    ++	{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
    ++	{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
    ++	{ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
    ++	{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
    ++	{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
    ++	{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
    ++	{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
    ++	{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
    ++	{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
    ++	{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
    ++	{ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
    ++	{ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
    ++	{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
    ++	{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
    ++	{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
    ++};
    ++
    ++const int acl_nfs4_perm_map_size =
    ++    (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));
    ++
    ++const acl_perm_map_t acl_nfs4_flag_map[] = {
    ++	{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
    ++	{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
    ++	{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
    ++	{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY},
    ++	{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
    ++	{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
    ++	{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}
    ++};
    ++
    ++const int acl_nfs4_flag_map_size =
    ++    (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));
    ++#endif /* ARCHIVE_ACL_FREEBSD_NFS4 */
    +--- /dev/null
    ++++ libarchive/archive_acl_maps_linux.c
    +@@ -0,0 +1,90 @@
    ++/*-
    ++ * Copyright (c) 2017 Martin Matuska
    ++ * All rights reserved.
    ++ *
    ++ * Redistribution and use in source and binary forms, with or without
    ++ * modification, are permitted provided that the following conditions
    ++ * are met:
    ++ * 1. Redistributions of source code must retain the above copyright
    ++ *    notice, this list of conditions and the following disclaimer.
    ++ * 2. Redistributions in binary form must reproduce the above copyright
    ++ *    notice, this list of conditions and the following disclaimer in the
    ++ *    documentation and/or other materials provided with the distribution.
    ++ *
    ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
    ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    ++ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
    ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    ++ */
    ++
    ++#include "archive_platform.h"
    ++
    ++#ifdef HAVE_SYS_TYPES_H
    ++#include <sys/types.h>
    ++#endif
    ++#ifdef HAVE_SYS_ACL_H
    ++#define _ACL_PRIVATE /* For debugging */
    ++#include <sys/acl.h>
    ++#endif
    ++#ifdef HAVE_SYS_RICHACL_H
    ++#include <sys/richacl.h>
    ++#endif
    ++
    ++#include "archive_entry.h"
    ++#include "archive_private.h"
    ++#include "archive_read_disk_private.h"
    ++#define _ARCHIVE_ACL_MAPS_DEFS
    ++#include "archive_acl_maps.h"
    ++
    ++#if ARCHIVE_ACL_LIBACL
    ++const acl_perm_map_t acl_posix_perm_map[] = {
    ++	{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
    ++	{ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
    ++	{ARCHIVE_ENTRY_ACL_READ, ACL_READ},
    ++};
    ++
    ++const int acl_posix_perm_map_size =
    ++    (int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0]));
    ++#endif /* ARCHIVE_ACL_LIBACL */
    ++
    ++#if ARCHIVE_ACL_LIBRICHACL
    ++const acl_perm_map_t acl_nfs4_perm_map[] = {
    ++	{ARCHIVE_ENTRY_ACL_EXECUTE, RICHACE_EXECUTE},
    ++	{ARCHIVE_ENTRY_ACL_READ_DATA, RICHACE_READ_DATA},
    ++	{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, RICHACE_LIST_DIRECTORY},
    ++	{ARCHIVE_ENTRY_ACL_WRITE_DATA, RICHACE_WRITE_DATA},
    ++	{ARCHIVE_ENTRY_ACL_ADD_FILE, RICHACE_ADD_FILE},
    ++	{ARCHIVE_ENTRY_ACL_APPEND_DATA, RICHACE_APPEND_DATA},
    ++	{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, RICHACE_ADD_SUBDIRECTORY},
    ++	{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, RICHACE_READ_NAMED_ATTRS},
    ++	{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, RICHACE_WRITE_NAMED_ATTRS},
    ++	{ARCHIVE_ENTRY_ACL_DELETE_CHILD, RICHACE_DELETE_CHILD},
    ++	{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, RICHACE_READ_ATTRIBUTES},
    ++	{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, RICHACE_WRITE_ATTRIBUTES},
    ++	{ARCHIVE_ENTRY_ACL_DELETE, RICHACE_DELETE},
    ++	{ARCHIVE_ENTRY_ACL_READ_ACL, RICHACE_READ_ACL},
    ++	{ARCHIVE_ENTRY_ACL_WRITE_ACL, RICHACE_WRITE_ACL},
    ++	{ARCHIVE_ENTRY_ACL_WRITE_OWNER, RICHACE_WRITE_OWNER},
    ++	{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, RICHACE_SYNCHRONIZE}
    ++};
    ++
    ++const int acl_nfs4_perm_map_size =
    ++    (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));
    ++
    ++const acl_perm_map_t acl_nfs4_flag_map[] = {
    ++	{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, RICHACE_FILE_INHERIT_ACE},
    ++	{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, RICHACE_DIRECTORY_INHERIT_ACE},
    ++	{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, RICHACE_NO_PROPAGATE_INHERIT_ACE},
    ++	{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, RICHACE_INHERIT_ONLY_ACE},
    ++	{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, RICHACE_INHERITED_ACE}
    ++};
    ++
    ++const int acl_nfs4_flag_map_size =
    ++    (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));
    ++#endif /* ARCHIVE_ACL_LIBRICHACL */
    +--- /dev/null
    ++++ libarchive/archive_acl_maps_sunos.c
    +@@ -0,0 +1,90 @@
    ++/*-
    ++ * Copyright (c) 2017 Martin Matuska
    ++ * All rights reserved.
    ++ *
    ++ * Redistribution and use in source and binary forms, with or without
    ++ * modification, are permitted provided that the following conditions
    ++ * are met:
    ++ * 1. Redistributions of source code must retain the above copyright
    ++ *    notice, this list of conditions and the following disclaimer.
    ++ * 2. Redistributions in binary form must reproduce the above copyright
    ++ *    notice, this list of conditions and the following disclaimer in the
    ++ *    documentation and/or other materials provided with the distribution.
    ++ *
    ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
    ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    ++ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
    ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    ++ */
    ++
    ++#include "archive_platform.h"
    ++
    ++#ifdef HAVE_SYS_TYPES_H
    ++#include <sys/types.h>
    ++#endif
    ++#ifdef HAVE_SYS_ACL_H
    ++#define _ACL_PRIVATE /* For debugging */
    ++#include <sys/acl.h>
    ++#endif
    ++
    ++#include "archive_entry.h"
    ++#include "archive_private.h"
    ++#include "archive_read_disk_private.h"
    ++#define _ARCHIVE_ACL_MAPS_DEFS
    ++#include "archive_acl_maps.h"
    ++
    ++const acl_perm_map_t acl_posix_perm_map[] = {
    ++	{ARCHIVE_ENTRY_ACL_EXECUTE, S_IXOTH },
    ++	{ARCHIVE_ENTRY_ACL_WRITE, S_IWOTH },
    ++	{ARCHIVE_ENTRY_ACL_READ, S_IROTH }
    ++};
    ++
    ++const int acl_posix_perm_map_size =
    ++    (int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0]));
    ++
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++const acl_perm_map_t acl_nfs4_perm_map[] = {
    ++	{ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE},
    ++	{ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA},
    ++	{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY},
    ++	{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA},
    ++	{ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE},
    ++	{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA},
    ++	{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY},
    ++	{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS},
    ++	{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS},
    ++	{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD},
    ++	{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES},
    ++	{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES},
    ++	{ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE},
    ++	{ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL},
    ++	{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL},
    ++	{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER},
    ++	{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE}
    ++};
    ++
    ++const int acl_nfs4_perm_map_size =
    ++    (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));
    ++
    ++const acl_perm_map_t acl_nfs4_flag_map[] = {
    ++	{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE},
    ++	{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE},
    ++	{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE},
    ++	{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE},
    ++	{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
    ++	{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG},
    ++#ifdef ACE_INHERITED_ACE
    ++	{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}
    ++#endif
    ++};
    ++
    ++const int acl_nfs4_flag_map_size =
    ++    (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));
    ++
    ++#endif /* ARCHIVE_ACL_SUNOS_NFS4 */
    +--- libarchive/archive_check_magic.c.orig
    ++++ libarchive/archive_check_magic.c
    +@@ -62,7 +62,7 @@ errmsg(const char *m)
    + 	}
    + }
    + 
    +-static void
    ++static __LA_DEAD void
    + diediedie(void)
    + {
    + #if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG)
    +--- libarchive/archive_entry.3.orig
    ++++ libarchive/archive_entry.3
    +@@ -25,7 +25,7 @@
    + .\"
    + .\" $FreeBSD$
    + .\"
    +-.Dd Feburary 2, 2012
    ++.Dd February 2, 2012
    + .Dt ARCHIVE_ENTRY 3
    + .Os
    + .Sh NAME
    +--- libarchive/archive_entry.c.orig
    ++++ libarchive/archive_entry.c
    +@@ -401,7 +401,7 @@ archive_entry_fflags_text(struct archive_entry *entry)
    + 	return (NULL);
    + }
    + 
    +-int64_t
    ++la_int64_t
    + archive_entry_gid(struct archive_entry *entry)
    + {
    + 	return (entry->ae_stat.aest_gid);
    +@@ -502,7 +502,7 @@ _archive_entry_hardlink_l(struct archive_entry *entry,
    + 	return (archive_mstring_get_mbs_l(&entry->ae_hardlink, p, len, sc));
    + }
    + 
    +-int64_t
    ++la_int64_t
    + archive_entry_ino(struct archive_entry *entry)
    + {
    + 	return (entry->ae_stat.aest_ino);
    +@@ -514,7 +514,7 @@ archive_entry_ino_is_set(struct archive_entry *entry)
    + 	return (entry->ae_set & AE_SET_INO);
    + }
    + 
    +-int64_t
    ++la_int64_t
    + archive_entry_ino64(struct archive_entry *entry)
    + {
    + 	return (entry->ae_stat.aest_ino);
    +@@ -627,7 +627,7 @@ archive_entry_rdevminor(struct archive_entry *entry)
    + 		return minor(entry->ae_stat.aest_rdev);
    + }
    + 
    +-int64_t
    ++la_int64_t
    + archive_entry_size(struct archive_entry *entry)
    + {
    + 	return (entry->ae_stat.aest_size);
    +@@ -715,7 +715,7 @@ _archive_entry_symlink_l(struct archive_entry *entry,
    + 	return (archive_mstring_get_mbs_l( &entry->ae_symlink, p, len, sc));
    + }
    + 
    +-int64_t
    ++la_int64_t
    + archive_entry_uid(struct archive_entry *entry)
    + {
    + 	return (entry->ae_stat.aest_uid);
    +@@ -819,7 +819,7 @@ archive_entry_copy_fflags_text_w(struct archive_entry *entry,
    + }
    + 
    + void
    +-archive_entry_set_gid(struct archive_entry *entry, int64_t g)
    ++archive_entry_set_gid(struct archive_entry *entry, la_int64_t g)
    + {
    + 	entry->stat_valid = 0;
    + 	entry->ae_stat.aest_gid = g;
    +@@ -868,7 +868,7 @@ _archive_entry_copy_gname_l(struct archive_entry *entry,
    + }
    + 
    + void
    +-archive_entry_set_ino(struct archive_entry *entry, int64_t ino)
    ++archive_entry_set_ino(struct archive_entry *entry, la_int64_t ino)
    + {
    + 	entry->stat_valid = 0;
    + 	entry->ae_set |= AE_SET_INO;
    +@@ -876,7 +876,7 @@ archive_entry_set_ino(struct archive_entry *entry, int64_t ino)
    + }
    + 
    + void
    +-archive_entry_set_ino64(struct archive_entry *entry, int64_t ino)
    ++archive_entry_set_ino64(struct archive_entry *entry, la_int64_t ino)
    + {
    + 	entry->stat_valid = 0;
    + 	entry->ae_set |= AE_SET_INO;
    +@@ -1209,7 +1209,7 @@ archive_entry_set_rdevminor(struct archive_entry *entry, dev_t m)
    + }
    + 
    + void
    +-archive_entry_set_size(struct archive_entry *entry, int64_t s)
    ++archive_entry_set_size(struct archive_entry *entry, la_int64_t s)
    + {
    + 	entry->stat_valid = 0;
    + 	entry->ae_stat.aest_size = s;
    +@@ -1306,7 +1306,7 @@ _archive_entry_copy_symlink_l(struct archive_entry *entry,
    + }
    + 
    + void
    +-archive_entry_set_uid(struct archive_entry *entry, int64_t u)
    ++archive_entry_set_uid(struct archive_entry *entry, la_int64_t u)
    + {
    + 	entry->stat_valid = 0;
    + 	entry->ae_stat.aest_uid = u;
    +--- libarchive/archive_entry.h.orig
    ++++ libarchive/archive_entry.h
    +@@ -30,7 +30,7 @@
    + #define	ARCHIVE_ENTRY_H_INCLUDED
    + 
    + /* Note: Compiler will complain if this does not match archive.h! */
    +-#define	ARCHIVE_VERSION_NUMBER 3003001
    ++#define	ARCHIVE_VERSION_NUMBER 3003002
    + 
    + /*
    +  * Note: archive_entry.h is for use outside of libarchive; the
    +--- libarchive/archive_entry_acl.3.orig
    ++++ libarchive/archive_entry_acl.3
    +@@ -32,7 +32,7 @@
    + .Nm archive_entry_acl_clear ,
    + .Nm archive_entry_acl_count ,
    + .Nm archive_entry_acl_from_text ,
    +-.Nm archive_entry_acl_from_text_w,
    ++.Nm archive_entry_acl_from_text_w ,
    + .Nm archive_entry_acl_next ,
    + .Nm archive_entry_acl_next_w ,
    + .Nm archive_entry_acl_reset ,
    +@@ -267,7 +267,7 @@ Only inherit, do not apply the permission on the directory itself.
    + .It Dv ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT ( Sy n )
    + Do not propagate inherit flags. Only first-level entries inherit ACLs.
    + .It Dv ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS ( Sy S )
    +-Trigger alarm or audit on succesful access.
    ++Trigger alarm or audit on successful access.
    + .It Dv ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS ( Sy F )
    + Trigger alarm or audit on failed access.
    + .It Dv ARCHIVE_ENTRY_ACL_ENTRY_INHERITED ( Sy I )
    +@@ -279,7 +279,7 @@ and
    + .Fn archive_entry_acl_add_entry_w
    + add a single ACL entry.
    + For the access ACL and non-extended principals, the classic Unix permissions
    +-are updated. An archive enry cannot contain both POSIX.1e and NFSv4 ACL
    ++are updated. An archive entry cannot contain both POSIX.1e and NFSv4 ACL
    + entries.
    + .Pp
    + .Fn archive_entry_acl_clear
    +@@ -303,7 +303,7 @@ for POSIX.1e ACLs and
    + for NFSv4 ACLs. For POSIX.1e ACLs if
    + .Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
    + is included and at least one extended ACL entry is found,
    +-the three non-extened ACLs are added.
    ++the three non-extended ACLs are added.
    + .Pp
    + .Fn archive_entry_acl_from_text
    + and
    +@@ -367,7 +367,7 @@ and
    + .Fn archive_entry_acl_to_text_w
    + convert the ACL entries for the given type into a
    + .Pq wide
    +-string of ACL entries separated by newline. If the the pointer
    ++string of ACL entries separated by newline. If the pointer
    + .Fa len_p
    + is not NULL, then the function shall return the length of the string
    + .Pq not including the NULL terminator
    +--- libarchive/archive_entry_paths.3.orig
    ++++ libarchive/archive_entry_paths.3
    +@@ -31,25 +31,25 @@
    + .Nm archive_entry_set_hardlink ,
    + .Nm archive_entry_copy_hardlink ,
    + .Nm archive_entry_copy_hardlink_w ,
    +-.Nm archve_entry_update_hardlink_utf8 ,
    ++.Nm archive_entry_update_hardlink_utf8 ,
    + .Nm archive_entry_set_link ,
    + .Nm archive_entry_copy_link ,
    + .Nm archive_entry_copy_link_w ,
    +-.Nm archve_entry_update_link_utf8 ,
    ++.Nm archive_entry_update_link_utf8 ,
    + .Nm archive_entry_pathname ,
    + .Nm archive_entry_pathname_w ,
    + .Nm archive_entry_set_pathname ,
    + .Nm archive_entry_copy_pathname ,
    + .Nm archive_entry_copy_pathname_w ,
    +-.Nm archve_entry_update_pathname_utf8 ,
    ++.Nm archive_entry_update_pathname_utf8 ,
    + .Nm archive_entry_sourcepath ,
    + .Nm archive_entry_copy_sourcepath ,
    +-.Nm archive_entry_symlink,
    +-.Nm archive_entry_symlink_w,
    ++.Nm archive_entry_symlink ,
    ++.Nm archive_entry_symlink_w ,
    + .Nm archive_entry_set_symlink ,
    + .Nm archive_entry_copy_symlink ,
    + .Nm archive_entry_copy_symlink_w ,
    +-.Nm archve_entry_update_symlink_utf8
    ++.Nm archive_entry_update_symlink_utf8
    + .Nd functions for manipulating path names in archive entry descriptions
    + .Sh LIBRARY
    + Streaming Archive Library (libarchive, -larchive)
    +--- libarchive/archive_entry_perms.3.orig
    ++++ libarchive/archive_entry_perms.3
    +@@ -34,8 +34,8 @@
    + .Nm archive_entry_perm ,
    + .Nm archive_entry_set_perm ,
    + .Nm archive_entry_strmode ,
    +-.Nm archive_entry_uname
    +-.Nm archive_entry_uname_w
    ++.Nm archive_entry_uname ,
    ++.Nm archive_entry_uname_w ,
    + .Nm archive_entry_set_uname ,
    + .Nm archive_entry_copy_uname ,
    + .Nm archive_entry_copy_uname_w ,
    +--- libarchive/archive_platform.h.orig
    ++++ libarchive/archive_platform.h
    +@@ -143,32 +143,6 @@
    + #endif
    + 
    + /*
    +- * If this platform has <sys/acl.h>, acl_create(), acl_init(),
    +- * acl_set_file(), and ACL_USER, we assume it has the rest of the
    +- * POSIX.1e draft functions used in archive_read_extract.c.
    +- */
    +-#if HAVE_SYS_ACL_H && HAVE_ACL_CREATE_ENTRY && HAVE_ACL_INIT && HAVE_ACL_SET_FILE
    +-#if HAVE_ACL_USER
    +-#define	HAVE_POSIX_ACL	1
    +-#elif HAVE_ACL_TYPE_EXTENDED
    +-#define HAVE_DARWIN_ACL 1
    +-#endif
    +-#endif
    +-
    +-/*
    +- * If this platform has <sys/acl.h>, acl_get(), facl_get(), acl_set(),
    +- * facl_set() and types aclent_t and ace_t it uses Solaris-style ACL functions
    +- */
    +-#if HAVE_SYS_ACL_H && HAVE_ACL_GET && HAVE_FACL_GET && HAVE_ACL_SET && HAVE_FACL_SET && HAVE_ACLENT_T && HAVE_ACE_T
    +-#define	HAVE_SUN_ACL	1
    +-#endif
    +-
    +-/* Define if platform supports NFSv4 ACLs */
    +-#if (HAVE_POSIX_ACL && HAVE_ACL_TYPE_NFS4) || HAVE_SUN_ACL || HAVE_DARWIN_ACL
    +-#define HAVE_NFS4_ACL	1
    +-#endif
    +-
    +-/*
    +  * If we can't restore metadata using a file descriptor, then
    +  * for compatibility's sake, close files before trying to restore metadata.
    +  */
    +--- /dev/null
    ++++ libarchive/archive_platform_acl.h
    +@@ -0,0 +1,49 @@
    ++/*-
    ++ * Copyright (c) 2017 Martin Matuska
    ++ * All rights reserved.
    ++ *
    ++ * Redistribution and use in source and binary forms, with or without
    ++ * modification, are permitted provided that the following conditions
    ++ * are met:
    ++ * 1. Redistributions of source code must retain the above copyright
    ++ *    notice, this list of conditions and the following disclaimer.
    ++ * 2. Redistributions in binary form must reproduce the above copyright
    ++ *    notice, this list of conditions and the following disclaimer in the
    ++ *    documentation and/or other materials provided with the distribution.
    ++ *
    ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
    ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    ++ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
    ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    ++ *
    ++ * $FreeBSD$
    ++ */
    ++
    ++/* !!ONLY FOR USE INTERNALLY TO LIBARCHIVE!! */
    ++
    ++#ifndef ARCHIVE_PLATFORM_ACL_H_INCLUDED
    ++#define ARCHIVE_PLATFORM_ACL_H_INCLUDED
    ++
    ++/*
    ++ * Determine what ACL types are supported
    ++ */
    ++#if ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_SUNOS || ARCHIVE_ACL_LIBACL
    ++#define ARCHIVE_ACL_POSIX1E     1
    ++#endif
    ++
    ++#if ARCHIVE_ACL_FREEBSD_NFS4 || ARCHIVE_ACL_SUNOS_NFS4 || \
    ++    ARCHIVE_ACL_DARWIN  || ARCHIVE_ACL_LIBRICHACL
    ++#define ARCHIVE_ACL_NFS4        1
    ++#endif
    ++
    ++#if ARCHIVE_ACL_POSIX1E || ARCHIVE_ACL_NFS4
    ++#define ARCHIVE_ACL_SUPPORT     1
    ++#endif
    ++
    ++#endif	/* ARCHIVE_PLATFORM_ACL_H_INCLUDED */
    +--- libarchive/archive_read_disk.3.orig
    ++++ libarchive/archive_read_disk.3
    +@@ -37,10 +37,7 @@
    + .Nm archive_read_disk_uname ,
    + .Nm archive_read_disk_set_uname_lookup ,
    + .Nm archive_read_disk_set_gname_lookup ,
    +-.Nm archive_read_disk_set_standard_lookup ,
    +-.Nm archive_read_close ,
    +-.Nm archive_read_finish ,
    +-.Nm archive_read_free
    ++.Nm archive_read_disk_set_standard_lookup
    + .Nd functions for reading objects from disk
    + .Sh LIBRARY
    + Streaming Archive Library (libarchive, -larchive)
    +@@ -81,12 +78,6 @@ Streaming Archive Library (libarchive, -larchive)
    + .Fa "int fd"
    + .Fa "const struct stat *"
    + .Fc
    +-.Ft int
    +-.Fn archive_read_close "struct archive *"
    +-.Ft int
    +-.Fn archive_read_finish "struct archive *"
    +-.Ft int
    +-.Fn archive_read_free "struct archive *"
    + .Sh DESCRIPTION
    + These functions provide an API for reading information about
    + objects on disk.
    +@@ -181,17 +172,6 @@ using the currently registered lookup functions above.
    + This affects the file ownership fields and ACL values in the
    + .Tn struct archive_entry
    + object.
    +-.It Fn archive_read_close
    +-Does nothing for
    +-.Tn archive_read_disk
    +-handles.
    +-.It Fn archive_read_finish
    +-This is a deprecated synonym for
    +-.Fn archive_read_free .
    +-.It Fn archive_read_free
    +-Invokes
    +-.Fn archive_read_close
    +-if it was not invoked manually, then releases all resources.
    + .El
    + More information about the
    + .Va struct archive
    +--- /dev/null
    ++++ libarchive/archive_read_disk_acl_darwin.c
    +@@ -0,0 +1,337 @@
    ++/*-
    ++ * Copyright (c) 2017 Martin Matuska
    ++ * All rights reserved.
    ++ *
    ++ * Redistribution and use in source and binary forms, with or without
    ++ * modification, are permitted provided that the following conditions
    ++ * are met:
    ++ * 1. Redistributions of source code must retain the above copyright
    ++ *    notice, this list of conditions and the following disclaimer.
    ++ * 2. Redistributions in binary form must reproduce the above copyright
    ++ *    notice, this list of conditions and the following disclaimer in the
    ++ *    documentation and/or other materials provided with the distribution.
    ++ *
    ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
    ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    ++ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
    ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    ++ */
    ++
    ++#include "archive_platform.h"
    ++
    ++#ifdef HAVE_FCNTL_H
    ++#include <fcntl.h>
    ++#endif
    ++#if HAVE_ERRNO_H
    ++#include <errno.h>
    ++#endif
    ++#if HAVE_MEMBERSHIP_H
    ++#include <membership.h>
    ++#endif
    ++#ifdef HAVE_SYS_TYPES_H
    ++#include <sys/types.h>
    ++#endif
    ++#ifdef HAVE_SYS_ACL_H
    ++#define _ACL_PRIVATE /* For debugging */
    ++#include <sys/acl.h>
    ++#endif
    ++
    ++#include "archive_entry.h"
    ++#include "archive_private.h"
    ++#include "archive_read_disk_private.h"
    ++#include "archive_acl_maps.h"
    ++
    ++
    ++/*
    ++ * Darwin-specific ACL functions and helper functions
    ++ *
    ++ * Exported functions:
    ++ * none
    ++ */
    ++static int translate_guid(struct archive *a, acl_entry_t acl_entry,
    ++    int *ae_id, int *ae_tag, const char **ae_name)
    ++{
    ++	void *q;
    ++	uid_t ugid;
    ++	int r, idtype;
    ++
    ++	q = acl_get_qualifier(acl_entry);
    ++	if (q == NULL)
    ++		return (1);
    ++	r = mbr_uuid_to_id((const unsigned char *)q, &ugid, &idtype);
    ++	if (r != 0) {
    ++		acl_free(q);
    ++		return (1);
    ++	}
    ++	if (idtype == ID_TYPE_UID) {
    ++		*ae_tag = ARCHIVE_ENTRY_ACL_USER;
    ++		*ae_id = ugid;
    ++		*ae_name = archive_read_disk_uname(a, *ae_id);
    ++	} else if (idtype == ID_TYPE_GID) {
    ++		*ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
    ++		*ae_id = ugid;
    ++		*ae_name = archive_read_disk_gname(a, *ae_id);
    ++	} else
    ++		r = 1;
    ++
    ++	acl_free(q);
    ++	return (r);
    ++}
    ++
    ++/*
    ++ * Add trivial NFSv4 ACL entries from mode
    ++ */
    ++static void
    ++add_trivial_nfs4_acl(struct archive_entry *entry)
    ++{
    ++	mode_t mode;
    ++	int i;
    ++	const int rperm = ARCHIVE_ENTRY_ACL_READ_DATA;
    ++	const int wperm = ARCHIVE_ENTRY_ACL_WRITE_DATA |
    ++	    ARCHIVE_ENTRY_ACL_APPEND_DATA;
    ++	const int eperm = ARCHIVE_ENTRY_ACL_EXECUTE;
    ++	const int pubset = ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
    ++	    ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
    ++	    ARCHIVE_ENTRY_ACL_READ_ACL |
    ++	    ARCHIVE_ENTRY_ACL_SYNCHRONIZE;
    ++	const int ownset = pubset | ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
    ++	    ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
    ++	    ARCHIVE_ENTRY_ACL_WRITE_ACL |
    ++	    ARCHIVE_ENTRY_ACL_WRITE_OWNER;
    ++
    ++	struct {
    ++	    const int type;
    ++	    const int tag;
    ++	    int permset;
    ++	} tacl_entry[] = {
    ++	    {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, 0},
    ++	    {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_USER_OBJ, 0},
    ++	    {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0},
    ++	    {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, ownset},
    ++	    {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_GROUP_OBJ, pubset},
    ++	    {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EVERYONE, pubset}
    ++	};
    ++
    ++	mode = archive_entry_mode(entry);
    ++
    ++	/* Permissions for everyone@ */
    ++	if (mode & 0004)
    ++		tacl_entry[5].permset |= rperm;
    ++	if (mode & 0002)
    ++		tacl_entry[5].permset |= wperm;
    ++	if (mode & 0001)
    ++		tacl_entry[5].permset |= eperm;
    ++
    ++	/* Permissions for group@ */
    ++	if (mode & 0040)
    ++		tacl_entry[4].permset |= rperm;
    ++	else if (mode & 0004)
    ++		tacl_entry[2].permset |= rperm;
    ++	if (mode & 0020)
    ++		tacl_entry[4].permset |= wperm;
    ++	else if (mode & 0002)
    ++		tacl_entry[2].permset |= wperm;
    ++	if (mode & 0010)
    ++		tacl_entry[4].permset |= eperm;
    ++	else if (mode & 0001)
    ++		tacl_entry[2].permset |= eperm;
    ++
    ++	/* Permissions for owner@ */
    ++	if (mode & 0400) {
    ++		tacl_entry[3].permset |= rperm;
    ++		if (!(mode & 0040) && (mode & 0004))
    ++			tacl_entry[0].permset |= rperm;
    ++	} else if ((mode & 0040) || (mode & 0004))
    ++		tacl_entry[1].permset |= rperm;
    ++	if (mode & 0200) {
    ++		tacl_entry[3].permset |= wperm;
    ++		if (!(mode & 0020) && (mode & 0002))
    ++			tacl_entry[0].permset |= wperm;
    ++	} else if ((mode & 0020) || (mode & 0002))
    ++		tacl_entry[1].permset |= wperm;
    ++	if (mode & 0100) {
    ++		tacl_entry[3].permset |= eperm;
    ++		if (!(mode & 0010) && (mode & 0001))
    ++			tacl_entry[0].permset |= eperm;
    ++	} else if ((mode & 0010) || (mode & 0001))
    ++		tacl_entry[1].permset |= eperm;
    ++
    ++	for (i = 0; i < 6; i++) {
    ++		if (tacl_entry[i].permset != 0) {
    ++			archive_entry_acl_add_entry(entry,
    ++			    tacl_entry[i].type, tacl_entry[i].permset,
    ++			    tacl_entry[i].tag, -1, NULL);
    ++		}
    ++	}
    ++
    ++	return;
    ++}
    ++
    ++static int
    ++translate_acl(struct archive_read_disk *a,
    ++    struct archive_entry *entry, acl_t acl)
    ++{
    ++	acl_tag_t	 acl_tag;
    ++	acl_flagset_t	 acl_flagset;
    ++	acl_entry_t	 acl_entry;
    ++	acl_permset_t	 acl_permset;
    ++	int		 i, entry_acl_type;
    ++	int		 r, s, ae_id, ae_tag, ae_perm;
    ++	const char	*ae_name;
    ++
    ++	s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
    ++	if (s == -1) {
    ++		archive_set_error(&a->archive, errno,
    ++		    "Failed to get first ACL entry");
    ++		return (ARCHIVE_WARN);
    ++	}
    ++
    ++	while (s == 0) {
    ++		ae_id = -1;
    ++		ae_name = NULL;
    ++		ae_perm = 0;
    ++
    ++		if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
    ++			archive_set_error(&a->archive, errno,
    ++			    "Failed to get ACL tag type");
    ++			return (ARCHIVE_WARN);
    ++		}
    ++		switch (acl_tag) {
    ++		case ACL_EXTENDED_ALLOW:
    ++			entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
    ++			r = translate_guid(&a->archive, acl_entry,
    ++			    &ae_id, &ae_tag, &ae_name);
    ++			break;
    ++		case ACL_EXTENDED_DENY:
    ++			entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
    ++			r = translate_guid(&a->archive, acl_entry,
    ++			    &ae_id, &ae_tag, &ae_name);
    ++			break;
    ++		default:
    ++			/* Skip types that libarchive can't support. */
    ++			s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
    ++			continue;
    ++		}
    ++
    ++		/* Skip if translate_guid() above failed */
    ++		if (r != 0) {
    ++			s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
    ++			continue;
    ++		}
    ++
    ++		/*
    ++		 * Libarchive stores "flag" (NFSv4 inheritance bits)
    ++		 * in the ae_perm bitmap.
    ++		 *
    ++		 * acl_get_flagset_np() fails with non-NFSv4 ACLs
    ++		 */
    ++		if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
    ++			archive_set_error(&a->archive, errno,
    ++			    "Failed to get flagset from a NFSv4 ACL entry");
    ++			return (ARCHIVE_WARN);
    ++		}
    ++		for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
    ++			r = acl_get_flag_np(acl_flagset,
    ++			    acl_nfs4_flag_map[i].p_perm);
    ++			if (r == -1) {
    ++				archive_set_error(&a->archive, errno,
    ++				    "Failed to check flag in a NFSv4 "
    ++				    "ACL flagset");
    ++				return (ARCHIVE_WARN);
    ++			} else if (r)
    ++				ae_perm |= acl_nfs4_flag_map[i].a_perm;
    ++		}
    ++
    ++		if (acl_get_permset(acl_entry, &acl_permset) != 0) {
    ++			archive_set_error(&a->archive, errno,
    ++			    "Failed to get ACL permission set");
    ++			return (ARCHIVE_WARN);
    ++		}
    ++
    ++		for (i = 0; i < acl_nfs4_perm_map_size; ++i) {
    ++			/*
    ++			 * acl_get_perm() is spelled differently on different
    ++			 * platforms; see above.
    ++			 */
    ++			r = acl_get_perm_np(acl_permset,
    ++			    acl_nfs4_perm_map[i].p_perm);
    ++			if (r == -1) {
    ++				archive_set_error(&a->archive, errno,
    ++				    "Failed to check permission in an ACL "
    ++				    "permission set");
    ++				return (ARCHIVE_WARN);
    ++			} else if (r)
    ++				ae_perm |= acl_nfs4_perm_map[i].a_perm;
    ++		}
    ++
    ++#if !HAVE_DECL_ACL_SYNCHRONIZE
    ++		/* On Mac OS X without ACL_SYNCHRONIZE assume it is set */
    ++		ae_perm |= ARCHIVE_ENTRY_ACL_SYNCHRONIZE;
    ++#endif
    ++
    ++		archive_entry_acl_add_entry(entry, entry_acl_type,
    ++					    ae_perm, ae_tag,
    ++					    ae_id, ae_name);
    ++
    ++		s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
    ++	}
    ++	return (ARCHIVE_OK);
    ++}
    ++
    ++int
    ++archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
    ++    struct archive_entry *entry, int *fd)
    ++{
    ++	const char	*accpath;
    ++	acl_t		acl;
    ++	int		r;
    ++
    ++	accpath = NULL;
    ++
    ++	if (*fd < 0) {
    ++		accpath = archive_read_disk_entry_setup_path(a, entry, fd);
    ++		if (accpath == NULL)
    ++			return (ARCHIVE_WARN);
    ++	}
    ++
    ++	archive_entry_acl_clear(entry);
    ++
    ++	acl = NULL;
    ++
    ++	if (*fd >= 0)
    ++		acl = acl_get_fd_np(*fd, ACL_TYPE_EXTENDED);
    ++	else if (!a->follow_symlinks)
    ++		acl = acl_get_link_np(accpath, ACL_TYPE_EXTENDED);
    ++	else
    ++		acl = acl_get_file(accpath, ACL_TYPE_EXTENDED);
    ++
    ++	if (acl != NULL) {
    ++		r = translate_acl(a, entry, acl);
    ++		acl_free(acl);
    ++		acl = NULL;
    ++
    ++		if (r != ARCHIVE_OK) {
    ++			archive_set_error(&a->archive, errno,
    ++			    "Couldn't translate NFSv4 ACLs");
    ++		}
    ++
    ++		/*
    ++		 * Because Mac OS doesn't support owner@, group@ and everyone@
    ++		 * ACLs we need to add NFSv4 ACLs mirroring the file mode to
    ++		 * the archive entry. Otherwise extraction on non-Mac platforms
    ++		 * would lead to an invalid file mode.
    ++		 */
    ++		if ((archive_entry_acl_types(entry) &
    ++		    ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0)
    ++			add_trivial_nfs4_acl(entry);
    ++
    ++		return (r);
    ++	}
    ++	return (ARCHIVE_OK);
    ++}
    +--- /dev/null
    ++++ libarchive/archive_read_disk_acl_freebsd.c
    +@@ -0,0 +1,371 @@
    ++/*-
    ++ * Copyright (c) 2003-2009 Tim Kientzle
    ++ * Copyright (c) 2010-2012 Michihiro NAKAJIMA
    ++ * Copyright (c) 2016-2017 Martin Matuska
    ++ * All rights reserved.
    ++ *
    ++ * Redistribution and use in source and binary forms, with or without
    ++ * modification, are permitted provided that the following conditions
    ++ * are met:
    ++ * 1. Redistributions of source code must retain the above copyright
    ++ *    notice, this list of conditions and the following disclaimer.
    ++ * 2. Redistributions in binary form must reproduce the above copyright
    ++ *    notice, this list of conditions and the following disclaimer in the
    ++ *    documentation and/or other materials provided with the distribution.
    ++ *
    ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
    ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    ++ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
    ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    ++ */
    ++
    ++#include "archive_platform.h"
    ++
    ++#ifdef HAVE_ERRNO_H
    ++#include <errno.h>
    ++#endif
    ++#ifdef HAVE_FCNTL_H
    ++#include <fcntl.h>
    ++#endif
    ++#ifdef HAVE_SYS_TYPES_H
    ++#include <sys/types.h>
    ++#endif
    ++#ifdef HAVE_SYS_ACL_H
    ++#define _ACL_PRIVATE /* For debugging */
    ++#include <sys/acl.h>
    ++#endif
    ++
    ++#include "archive_entry.h"
    ++#include "archive_private.h"
    ++#include "archive_read_disk_private.h"
    ++#include "archive_acl_maps.h"
    ++
    ++/*
    ++ * Translate FreeBSD ACLs into libarchive internal structure
    ++ */
    ++static int
    ++translate_acl(struct archive_read_disk *a,
    ++    struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
    ++{
    ++#if ARCHIVE_ACL_FREEBSD_NFS4
    ++	int brand;
    ++	acl_flagset_t	 acl_flagset;
    ++#endif
    ++	acl_tag_t	 acl_tag;
    ++	acl_entry_t	 acl_entry;
    ++	acl_permset_t	 acl_permset;
    ++	acl_entry_type_t acl_type;
    ++	int		 i, entry_acl_type, perm_map_size;
    ++	const acl_perm_map_t	*perm_map;
    ++	int		 r, s, ae_id, ae_tag, ae_perm;
    ++	void		*q;
    ++	const char	*ae_name;
    ++
    ++#if ARCHIVE_ACL_FREEBSD_NFS4
    ++	// FreeBSD "brands" ACLs as POSIX.1e or NFSv4
    ++	// Make sure the "brand" on this ACL is consistent
    ++	// with the default_entry_acl_type bits provided.
    ++	if (acl_get_brand_np(acl, &brand) != 0) {
    ++		archive_set_error(&a->archive, errno,
    ++		    "Failed to read ACL brand");
    ++		return (ARCHIVE_WARN);
    ++	}
    ++	switch (brand) {
    ++	case ACL_BRAND_POSIX:
    ++		switch (default_entry_acl_type) {
    ++		case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
    ++		case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
    ++			break;
    ++		default:
    ++			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
    ++			    "Invalid ACL entry type for POSIX.1e ACL");
    ++			return (ARCHIVE_WARN);
    ++		}
    ++		break;
    ++	case ACL_BRAND_NFS4:
    ++		if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
    ++			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
    ++			    "Invalid ACL entry type for NFSv4 ACL");
    ++			return (ARCHIVE_WARN);
    ++		}
    ++		break;
    ++	default:
    ++		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
    ++		    "Unknown ACL brand");
    ++		return (ARCHIVE_WARN);
    ++	}
    ++#endif
    ++
    ++	s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
    ++	if (s == -1) {
    ++		archive_set_error(&a->archive, errno,
    ++		    "Failed to get first ACL entry");
    ++		return (ARCHIVE_WARN);
    ++	}
    ++
    ++	while (s == 1) {
    ++		ae_id = -1;
    ++		ae_name = NULL;
    ++		ae_perm = 0;
    ++
    ++		if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
    ++			archive_set_error(&a->archive, errno,
    ++			    "Failed to get ACL tag type");
    ++			return (ARCHIVE_WARN);
    ++		}
    ++		switch (acl_tag) {
    ++		case ACL_USER:
    ++			q = acl_get_qualifier(acl_entry);
    ++			if (q != NULL) {
    ++				ae_id = (int)*(uid_t *)q;
    ++				acl_free(q);
    ++				ae_name = archive_read_disk_uname(&a->archive,
    ++				    ae_id);
    ++			}
    ++			ae_tag = ARCHIVE_ENTRY_ACL_USER;
    ++			break;
    ++		case ACL_GROUP:
    ++			q = acl_get_qualifier(acl_entry);
    ++			if (q != NULL) {
    ++				ae_id = (int)*(gid_t *)q;
    ++				acl_free(q);
    ++				ae_name = archive_read_disk_gname(&a->archive,
    ++				    ae_id);
    ++			}
    ++			ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
    ++			break;
    ++		case ACL_MASK:
    ++			ae_tag = ARCHIVE_ENTRY_ACL_MASK;
    ++			break;
    ++		case ACL_USER_OBJ:
    ++			ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
    ++			break;
    ++		case ACL_GROUP_OBJ:
    ++			ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
    ++			break;
    ++		case ACL_OTHER:
    ++			ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
    ++			break;
    ++#if ARCHIVE_ACL_FREEBSD_NFS4
    ++		case ACL_EVERYONE:
    ++			ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
    ++			break;
    ++#endif
    ++		default:
    ++			/* Skip types that libarchive can't support. */
    ++			s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
    ++			continue;
    ++		}
    ++
    ++		// XXX acl_type maps to allow/deny/audit/YYYY bits
    ++		entry_acl_type = default_entry_acl_type;
    ++
    ++#if ARCHIVE_ACL_FREEBSD_NFS4
    ++		if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
    ++			/*
    ++			 * acl_get_entry_type_np() fails with non-NFSv4 ACLs
    ++			 */
    ++			if (acl_get_entry_type_np(acl_entry, &acl_type) != 0) {
    ++				archive_set_error(&a->archive, errno, "Failed "
    ++				    "to get ACL type from a NFSv4 ACL entry");
    ++				return (ARCHIVE_WARN);
    ++			}
    ++			switch (acl_type) {
    ++			case ACL_ENTRY_TYPE_ALLOW:
    ++				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
    ++				break;
    ++			case ACL_ENTRY_TYPE_DENY:
    ++				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
    ++				break;
    ++			case ACL_ENTRY_TYPE_AUDIT:
    ++				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
    ++				break;
    ++			case ACL_ENTRY_TYPE_ALARM:
    ++				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
    ++				break;
    ++			default:
    ++				archive_set_error(&a->archive, errno,
    ++				    "Invalid NFSv4 ACL entry type");
    ++				return (ARCHIVE_WARN);
    ++			}
    ++
    ++			/*
    ++			 * Libarchive stores "flag" (NFSv4 inheritance bits)
    ++			 * in the ae_perm bitmap.
    ++			 *
    ++			 * acl_get_flagset_np() fails with non-NFSv4 ACLs
    ++			 */
    ++			if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
    ++				archive_set_error(&a->archive, errno,
    ++				    "Failed to get flagset from a NFSv4 "
    ++				    "ACL entry");
    ++				return (ARCHIVE_WARN);
    ++			}
    ++			for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
    ++				r = acl_get_flag_np(acl_flagset,
    ++				    acl_nfs4_flag_map[i].p_perm);
    ++				if (r == -1) {
    ++					archive_set_error(&a->archive, errno,
    ++					    "Failed to check flag in a NFSv4 "
    ++					    "ACL flagset");
    ++					return (ARCHIVE_WARN);
    ++				} else if (r)
    ++					ae_perm |= acl_nfs4_flag_map[i].a_perm;
    ++			}
    ++		}
    ++#endif
    ++
    ++		if (acl_get_permset(acl_entry, &acl_permset) != 0) {
    ++			archive_set_error(&a->archive, errno,
    ++			    "Failed to get ACL permission set");
    ++			return (ARCHIVE_WARN);
    ++		}
    ++
    ++#if ARCHIVE_ACL_FREEBSD_NFS4
    ++		if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
    ++			perm_map_size = acl_nfs4_perm_map_size;
    ++			perm_map = acl_nfs4_perm_map;
    ++		} else {
    ++#endif
    ++			perm_map_size = acl_posix_perm_map_size;
    ++			perm_map = acl_posix_perm_map;
    ++#if ARCHIVE_ACL_FREEBSD_NFS4
    ++		}
    ++#endif
    ++
    ++		for (i = 0; i < perm_map_size; ++i) {
    ++			r = acl_get_perm_np(acl_permset, perm_map[i].p_perm);
    ++			if (r == -1) {
    ++				archive_set_error(&a->archive, errno,
    ++				    "Failed to check permission in an ACL "
    ++				    "permission set");
    ++				return (ARCHIVE_WARN);
    ++			} else if (r)
    ++				ae_perm |= perm_map[i].a_perm;
    ++		}
    ++
    ++		archive_entry_acl_add_entry(entry, entry_acl_type,
    ++					    ae_perm, ae_tag,
    ++					    ae_id, ae_name);
    ++
    ++		s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
    ++		if (s == -1) {
    ++			archive_set_error(&a->archive, errno,
    ++			    "Failed to get next ACL entry");
    ++			return (ARCHIVE_WARN);
    ++		}
    ++	}
    ++	return (ARCHIVE_OK);
    ++}
    ++
    ++int
    ++archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
    ++    struct archive_entry *entry, int *fd)
    ++{
    ++	const char	*accpath;
    ++	acl_t		acl;
    ++	int		r;
    ++
    ++	accpath = NULL;
    ++
    ++	if (*fd < 0) {
    ++		accpath = archive_read_disk_entry_setup_path(a, entry, fd);
    ++		if (accpath == NULL)
    ++			return (ARCHIVE_WARN);
    ++	}
    ++
    ++	archive_entry_acl_clear(entry);
    ++
    ++	acl = NULL;
    ++
    ++#if ARCHIVE_ACL_FREEBSD_NFS4
    ++	/* Try NFSv4 ACL first. */
    ++	if (*fd >= 0)
    ++		acl = acl_get_fd_np(*fd, ACL_TYPE_NFS4);
    ++	else if (!a->follow_symlinks)
    ++		acl = acl_get_link_np(accpath, ACL_TYPE_NFS4);
    ++	else
    ++		acl = acl_get_file(accpath, ACL_TYPE_NFS4);
    ++
    ++	/* Ignore "trivial" ACLs that just mirror the file mode. */
    ++	if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) {
    ++		acl_free(acl);
    ++		acl = NULL;
    ++		return (ARCHIVE_OK);
    ++	}
    ++
    ++	if (acl != NULL) {
    ++		r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
    ++		acl_free(acl);
    ++		acl = NULL;
    ++
    ++		if (r != ARCHIVE_OK) {
    ++			archive_set_error(&a->archive, errno,
    ++			    "Couldn't translate NFSv4 ACLs");
    ++		}
    ++
    ++		return (r);
    ++	}
    ++#endif
    ++
    ++	/* Retrieve access ACL from file. */
    ++	if (*fd >= 0)
    ++		acl = acl_get_fd_np(*fd, ACL_TYPE_ACCESS);
    ++#if HAVE_ACL_GET_LINK_NP
    ++	else if (!a->follow_symlinks)
    ++		acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS);
    ++#else
    ++	else if ((!a->follow_symlinks)
    ++	    && (archive_entry_filetype(entry) == AE_IFLNK))
    ++		/* We can't get the ACL of a symlink, so we assume it can't
    ++		   have one. */
    ++		acl = NULL;
    ++#endif
    ++	else
    ++		acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
    ++
    ++#if HAVE_ACL_IS_TRIVIAL_NP
    ++	/* Ignore "trivial" ACLs that just mirror the file mode. */
    ++	if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) {
    ++		acl_free(acl);
    ++		acl = NULL;
    ++	}
    ++#endif
    ++
    ++	if (acl != NULL) {
    ++		r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
    ++		acl_free(acl);
    ++		acl = NULL;
    ++
    ++		if (r != ARCHIVE_OK) {
    ++			archive_set_error(&a->archive, errno,
    ++			    "Couldn't translate access ACLs");
    ++			return (r);
    ++		}
    ++	}
    ++
    ++	/* Only directories can have default ACLs. */
    ++	if (S_ISDIR(archive_entry_mode(entry))) {
    ++		if (*fd >= 0)
    ++			acl = acl_get_fd_np(*fd, ACL_TYPE_DEFAULT);
    ++		else
    ++			acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
    ++		if (acl != NULL) {
    ++			r = translate_acl(a, entry, acl,
    ++			    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
    ++			acl_free(acl);
    ++			if (r != ARCHIVE_OK) {
    ++				archive_set_error(&a->archive, errno,
    ++				    "Couldn't translate default ACLs");
    ++				return (r);
    ++			}
    ++		}
    ++	}
    ++	return (ARCHIVE_OK);
    ++}
    +--- /dev/null
    ++++ libarchive/archive_read_disk_acl_linux.c
    +@@ -0,0 +1,352 @@
    ++/*-
    ++ * Copyright (c) 2003-2009 Tim Kientzle
    ++ * Copyright (c) 2010-2012 Michihiro NAKAJIMA
    ++ * Copyright (c) 2016-2017 Martin Matuska
    ++ * All rights reserved.
    ++ *
    ++ * Redistribution and use in source and binary forms, with or without
    ++ * modification, are permitted provided that the following conditions
    ++ * are met:
    ++ * 1. Redistributions of source code must retain the above copyright
    ++ *    notice, this list of conditions and the following disclaimer.
    ++ * 2. Redistributions in binary form must reproduce the above copyright
    ++ *    notice, this list of conditions and the following disclaimer in the
    ++ *    documentation and/or other materials provided with the distribution.
    ++ *
    ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
    ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    ++ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
    ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    ++ */
    ++
    ++#include "archive_platform.h"
    ++
    ++#ifdef HAVE_ERRNO_H
    ++#include <errno.h>
    ++#endif
    ++#ifdef HAVE_FCNTL_H
    ++#include <fcntl.h>
    ++#endif
    ++#if HAVE_ACL_LIBACL_H
    ++#include <acl/libacl.h>
    ++#endif
    ++#ifdef HAVE_SYS_ACL_H
    ++#include <sys/acl.h>
    ++#endif
    ++#if HAVE_SYS_RICHACL_H
    ++#include <sys/richacl.h>
    ++#endif
    ++
    ++#include "archive_entry.h"
    ++#include "archive_private.h"
    ++#include "archive_read_disk_private.h"
    ++#include "archive_acl_maps.h"
    ++
    ++#if HAVE_LIBACL
    ++#include <acl/libacl.h>
    ++#endif
    ++
    ++#if ARCHIVE_ACL_LIBACL
    ++/*
    ++ * Translate POSIX.1e ACLs into libarchive internal structure
    ++ */
    ++static int
    ++translate_acl(struct archive_read_disk *a,
    ++    struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
    ++{
    ++	acl_tag_t	 acl_tag;
    ++	acl_entry_t	 acl_entry;
    ++	acl_permset_t	 acl_permset;
    ++	int		 i, entry_acl_type;
    ++	int		 r, s, ae_id, ae_tag, ae_perm;
    ++	void		*q;
    ++	const char	*ae_name;
    ++
    ++	s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
    ++	if (s == -1) {
    ++		archive_set_error(&a->archive, errno,
    ++		    "Failed to get first ACL entry");
    ++		return (ARCHIVE_WARN);
    ++	}
    ++
    ++	while (s == 1) {
    ++		ae_id = -1;
    ++		ae_name = NULL;
    ++		ae_perm = 0;
    ++
    ++		if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
    ++			archive_set_error(&a->archive, errno,
    ++			    "Failed to get ACL tag type");
    ++			return (ARCHIVE_WARN);
    ++		}
    ++		switch (acl_tag) {
    ++		case ACL_USER:
    ++			q = acl_get_qualifier(acl_entry);
    ++			if (q != NULL) {
    ++				ae_id = (int)*(uid_t *)q;
    ++				acl_free(q);
    ++				ae_name = archive_read_disk_uname(&a->archive,
    ++				    ae_id);
    ++			}
    ++			ae_tag = ARCHIVE_ENTRY_ACL_USER;
    ++			break;
    ++		case ACL_GROUP:
    ++			q = acl_get_qualifier(acl_entry);
    ++			if (q != NULL) {
    ++				ae_id = (int)*(gid_t *)q;
    ++				acl_free(q);
    ++				ae_name = archive_read_disk_gname(&a->archive,
    ++				    ae_id);
    ++			}
    ++			ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
    ++			break;
    ++		case ACL_MASK:
    ++			ae_tag = ARCHIVE_ENTRY_ACL_MASK;
    ++			break;
    ++		case ACL_USER_OBJ:
    ++			ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
    ++			break;
    ++		case ACL_GROUP_OBJ:
    ++			ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
    ++			break;
    ++		case ACL_OTHER:
    ++			ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
    ++			break;
    ++		default:
    ++			/* Skip types that libarchive can't support. */
    ++			s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
    ++			continue;
    ++		}
    ++
    ++		// XXX acl_type maps to allow/deny/audit/YYYY bits
    ++		entry_acl_type = default_entry_acl_type;
    ++
    ++		if (acl_get_permset(acl_entry, &acl_permset) != 0) {
    ++			archive_set_error(&a->archive, errno,
    ++			    "Failed to get ACL permission set");
    ++			return (ARCHIVE_WARN);
    ++		}
    ++
    ++		for (i = 0; i < acl_posix_perm_map_size; ++i) {
    ++			r = acl_get_perm(acl_permset,
    ++			    acl_posix_perm_map[i].p_perm);
    ++			if (r == -1) {
    ++				archive_set_error(&a->archive, errno,
    ++				    "Failed to check permission in an ACL "
    ++				    "permission set");
    ++				return (ARCHIVE_WARN);
    ++			} else if (r)
    ++				ae_perm |= acl_posix_perm_map[i].a_perm;
    ++		}
    ++
    ++		archive_entry_acl_add_entry(entry, entry_acl_type,
    ++					    ae_perm, ae_tag,
    ++					    ae_id, ae_name);
    ++
    ++		s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
    ++		if (s == -1) {
    ++			archive_set_error(&a->archive, errno,
    ++			    "Failed to get next ACL entry");
    ++			return (ARCHIVE_WARN);
    ++		}
    ++	}
    ++	return (ARCHIVE_OK);
    ++}
    ++#endif /* ARCHIVE_ACL_LIBACL */
    ++
    ++#if ARCHIVE_ACL_LIBRICHACL
    ++/*
    ++ * Translate RichACL into libarchive internal ACL
    ++ */
    ++static int
    ++translate_richacl(struct archive_read_disk *a, struct archive_entry *entry,
    ++    struct richacl *richacl)
    ++{
    ++	int ae_id, ae_tag, ae_perm;
    ++	int entry_acl_type, i;
    ++	const char *ae_name;
    ++
    ++	struct richace *richace;
    ++
    ++	richacl_for_each_entry(richace, richacl) {
    ++		ae_name = NULL;
    ++		ae_tag = 0;
    ++		ae_perm = 0;
    ++		ae_id = -1;
    ++
    ++		switch (richace->e_type) {
    ++		case RICHACE_ACCESS_ALLOWED_ACE_TYPE:
    ++			entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
    ++			break;
    ++		case RICHACE_ACCESS_DENIED_ACE_TYPE:
    ++			entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
    ++			break;
    ++		default: /* Unknown entry type, skip */
    ++			continue;
    ++		}
    ++
    ++		/* Unsupported */
    ++		if (richace->e_flags & RICHACE_UNMAPPED_WHO)
    ++			continue;
    ++
    ++		if (richace->e_flags & RICHACE_SPECIAL_WHO) {
    ++			switch (richace->e_id) {
    ++			case RICHACE_OWNER_SPECIAL_ID:
    ++				ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
    ++				break;
    ++			case RICHACE_GROUP_SPECIAL_ID:
    ++				ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
    ++				break;
    ++			case RICHACE_EVERYONE_SPECIAL_ID:
    ++				ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
    ++				break;
    ++			default: /* Unknown special ID type */
    ++				continue;
    ++			}
    ++		} else {
    ++			ae_id = richace->e_id;
    ++			if (richace->e_flags & RICHACE_IDENTIFIER_GROUP) {
    ++				ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
    ++				ae_name = archive_read_disk_gname(&a->archive,
    ++				    (gid_t)(richace->e_id));
    ++			} else {
    ++				ae_tag = ARCHIVE_ENTRY_ACL_USER;
    ++				ae_name = archive_read_disk_uname(&a->archive,
    ++				    (uid_t)(richace->e_id));
    ++			}
    ++		}
    ++		for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
    ++			if ((richace->e_flags &
    ++			    acl_nfs4_flag_map[i].p_perm) != 0)
    ++				ae_perm |= acl_nfs4_flag_map[i].a_perm;
    ++		}
    ++		for (i = 0; i < acl_nfs4_perm_map_size; ++i) {
    ++			if ((richace->e_mask &
    ++			    acl_nfs4_perm_map[i].p_perm) != 0)
    ++				ae_perm |=
    ++				    acl_nfs4_perm_map[i].a_perm;
    ++		}
    ++
    ++		archive_entry_acl_add_entry(entry, entry_acl_type,
    ++		    ae_perm, ae_tag, ae_id, ae_name);
    ++	}
    ++	return (ARCHIVE_OK);
    ++}
    ++#endif	/* ARCHIVE_ACL_LIBRICHACL */
    ++
    ++int
    ++archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
    ++    struct archive_entry *entry, int *fd)
    ++{
    ++	const char	*accpath;
    ++	int		r;
    ++#if ARCHIVE_ACL_LIBACL
    ++	acl_t		acl;
    ++#endif
    ++#if ARCHIVE_ACL_LIBRICHACL
    ++	struct richacl *richacl;
    ++	mode_t		mode;
    ++#endif
    ++
    ++	accpath = NULL;
    ++	r = ARCHIVE_OK;
    ++
    ++	/* For default ACLs we need reachable accpath */
    ++	if (*fd < 0 || S_ISDIR(archive_entry_mode(entry))) {
    ++		accpath = archive_read_disk_entry_setup_path(a, entry, fd);
    ++		if (accpath == NULL)
    ++			return (ARCHIVE_WARN);
    ++	}
    ++
    ++	archive_entry_acl_clear(entry);
    ++
    ++#if ARCHIVE_ACL_LIBACL
    ++	acl = NULL;
    ++#endif
    ++#if ARCHIVE_ACL_LIBRICHACL
    ++	richacl = NULL;
    ++#endif
    ++
    ++#if ARCHIVE_ACL_LIBRICHACL
    ++	/* Try NFSv4 ACL first. */
    ++	if (*fd >= 0)
    ++		richacl = richacl_get_fd(*fd);
    ++	else if ((!a->follow_symlinks)
    ++	    && (archive_entry_filetype(entry) == AE_IFLNK))
    ++		/* We can't get the ACL of a symlink, so we assume it can't
    ++		   have one */
    ++		richacl = NULL;
    ++	else
    ++		richacl = richacl_get_file(accpath);
    ++
    ++	/* Ignore "trivial" ACLs that just mirror the file mode. */
    ++	if (richacl != NULL) {
    ++		mode = archive_entry_mode(entry);
    ++		if (richacl_equiv_mode(richacl, &mode) == 0) {
    ++			richacl_free(richacl);
    ++			richacl = NULL;
    ++			return (ARCHIVE_OK);
    ++		}
    ++	}
    ++
    ++	if (richacl != NULL) {
    ++		r = translate_richacl(a, entry, richacl);
    ++		richacl_free(richacl);
    ++		richacl = NULL;
    ++
    ++		if (r != ARCHIVE_OK) {
    ++			archive_set_error(&a->archive, errno,
    ++			"Couldn't translate NFSv4 ACLs");
    ++		}
    ++
    ++		return (r);
    ++	}
    ++#endif	/* ARCHIVE_ACL_LIBRICHACL */
    ++
    ++#if ARCHIVE_ACL_LIBACL
    ++	/* Retrieve access ACL from file. */
    ++	if (*fd >= 0)
    ++		acl = acl_get_fd(*fd);
    ++	else if ((!a->follow_symlinks)
    ++	    && (archive_entry_filetype(entry) == AE_IFLNK))
    ++		/* We can't get the ACL of a symlink, so we assume it can't
    ++		   have one. */
    ++		acl = NULL;
    ++	else
    ++		acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
    ++
    ++	if (acl != NULL) {
    ++		r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
    ++		acl_free(acl);
    ++		acl = NULL;
    ++
    ++		if (r != ARCHIVE_OK) {
    ++			archive_set_error(&a->archive, errno,
    ++			    "Couldn't translate access ACLs");
    ++			return (r);
    ++		}
    ++	}
    ++
    ++	/* Only directories can have default ACLs. */
    ++	if (S_ISDIR(archive_entry_mode(entry))) {
    ++		acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
    ++		if (acl != NULL) {
    ++			r = translate_acl(a, entry, acl,
    ++			    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
    ++			acl_free(acl);
    ++			if (r != ARCHIVE_OK) {
    ++				archive_set_error(&a->archive, errno,
    ++				    "Couldn't translate default ACLs");
    ++				return (r);
    ++			}
    ++		}
    ++	}
    ++#endif	/* ARCHIVE_ACL_LIBACL */
    ++	return (r);
    ++}
    +--- /dev/null
    ++++ libarchive/archive_read_disk_acl_sunos.c
    +@@ -0,0 +1,482 @@
    ++/*-
    ++ * Copyright (c) 2017 Martin Matuska
    ++ * All rights reserved.
    ++ *
    ++ * Redistribution and use in source and binary forms, with or without
    ++ * modification, are permitted provided that the following conditions
    ++ * are met:
    ++ * 1. Redistributions of source code must retain the above copyright
    ++ *    notice, this list of conditions and the following disclaimer.
    ++ * 2. Redistributions in binary form must reproduce the above copyright
    ++ *    notice, this list of conditions and the following disclaimer in the
    ++ *    documentation and/or other materials provided with the distribution.
    ++ *
    ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
    ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    ++ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
    ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    ++ */
    ++
    ++#include "archive_platform.h"
    ++
    ++#ifdef HAVE_ERRNO_H
    ++#include <errno.h>
    ++#endif
    ++#ifdef HAVE_FCNTL_H
    ++#include <fcntl.h>
    ++#endif
    ++#ifdef HAVE_SYS_TYPES_H
    ++#include <sys/types.h>
    ++#endif
    ++#ifdef HAVE_SYS_ACL_H
    ++#include <sys/acl.h>
    ++#endif
    ++
    ++#include "archive_entry.h"
    ++#include "archive_private.h"
    ++#include "archive_read_disk_private.h"
    ++#include "archive_acl_maps.h"
    ++
    ++/*
    ++ * Solaris-specific ACL functions and helper functions
    ++ *
    ++ * Exported functions:
    ++ * translate_acl()
    ++ */
    ++static void *
    ++sunacl_get(int cmd, int *aclcnt, int fd, const char *path)
    ++{
    ++	int cnt, cntcmd;
    ++	size_t size;
    ++	void *aclp;
    ++
    ++	if (cmd == GETACL) {
    ++		cntcmd = GETACLCNT;
    ++		size = sizeof(aclent_t);
    ++	}
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++	else if (cmd == ACE_GETACL) {
    ++		cntcmd = ACE_GETACLCNT;
    ++		size = sizeof(ace_t);
    ++	}
    ++#endif
    ++	else {
    ++		errno = EINVAL;
    ++		*aclcnt = -1;
    ++		return (NULL);
    ++	}
    ++
    ++	aclp = NULL;
    ++	cnt = -2;
    ++
    ++	while (cnt == -2 || (cnt == -1 && errno == ENOSPC)) {
    ++		if (path != NULL)
    ++			cnt = acl(path, cntcmd, 0, NULL);
    ++		else
    ++			cnt = facl(fd, cntcmd, 0, NULL);
    ++
    ++		if (cnt > 0) {
    ++			if (aclp == NULL)
    ++				aclp = malloc(cnt * size);
    ++			else
    ++				aclp = realloc(NULL, cnt * size);
    ++			if (aclp != NULL) {
    ++				if (path != NULL)
    ++					cnt = acl(path, cmd, cnt, aclp);
    ++				else
    ++					cnt = facl(fd, cmd, cnt, aclp);
    ++			}
    ++		} else {
    ++			if (aclp != NULL) {
    ++				free(aclp);
    ++				aclp = NULL;
    ++			}
    ++			break;
    ++		}
    ++	}
    ++
    ++	*aclcnt = cnt;
    ++	return (aclp);
    ++}
    ++
    ++/*
    ++ * Check if acl is trivial
    ++ * This is a FreeBSD acl_is_trivial_np() implementation for Solaris
    ++ */
    ++static int
    ++sun_acl_is_trivial(void *aclp, int aclcnt, mode_t mode, int is_nfs4,
    ++    int is_dir, int *trivialp)
    ++{
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++	int i, p;
    ++	const uint32_t rperm = ACE_READ_DATA;
    ++	const uint32_t wperm = ACE_WRITE_DATA | ACE_APPEND_DATA;
    ++	const uint32_t eperm = ACE_EXECUTE;
    ++	const uint32_t pubset = ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS |
    ++	    ACE_READ_ACL | ACE_SYNCHRONIZE;
    ++	const uint32_t ownset = pubset | ACE_WRITE_ATTRIBUTES |
    ++	    ACE_WRITE_NAMED_ATTRS | ACE_WRITE_ACL | ACE_WRITE_OWNER;
    ++
    ++	ace_t *ace;
    ++	ace_t tace[6];
    ++#endif
    ++
    ++	if (aclp == NULL || trivialp == NULL)
    ++		return (-1);
    ++
    ++	*trivialp = 0;
    ++
    ++	/*
    ++	 * POSIX.1e ACLs marked with ACL_IS_TRIVIAL are compatible with
    ++	 * FreeBSD acl_is_trivial_np(). On Solaris they have 4 entries,
    ++	 * including mask.
    ++	 */
    ++	if (!is_nfs4) {
    ++		if (aclcnt == 4)
    ++			*trivialp = 1;
    ++		return (0);
    ++	}
    ++
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++	/*
    ++	 * Continue with checking NFSv4 ACLs
    ++	 *
    ++	 * Create list of trivial ace's to be compared
    ++	 */
    ++
    ++	/* owner@ allow pre */
    ++	tace[0].a_flags = ACE_OWNER;
    ++	tace[0].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
    ++	tace[0].a_access_mask = 0;
    ++
    ++	/* owner@ deny */
    ++	tace[1].a_flags = ACE_OWNER;
    ++	tace[1].a_type = ACE_ACCESS_DENIED_ACE_TYPE;
    ++	tace[1].a_access_mask = 0;
    ++
    ++	/* group@ deny */
    ++	tace[2].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP;
    ++	tace[2].a_type = ACE_ACCESS_DENIED_ACE_TYPE;
    ++	tace[2].a_access_mask = 0;
    ++
    ++	/* owner@ allow */
    ++	tace[3].a_flags = ACE_OWNER;
    ++	tace[3].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
    ++	tace[3].a_access_mask = ownset;
    ++
    ++	/* group@ allow */
    ++	tace[4].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP;
    ++	tace[4].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
    ++	tace[4].a_access_mask = pubset;
    ++
    ++	/* everyone@ allow */
    ++	tace[5].a_flags = ACE_EVERYONE;
    ++	tace[5].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
    ++	tace[5].a_access_mask = pubset;
    ++
    ++	/* Permissions for everyone@ */
    ++	if (mode & 0004)
    ++		tace[5].a_access_mask |= rperm;
    ++	if (mode & 0002)
    ++		tace[5].a_access_mask |= wperm;
    ++	if (mode & 0001)
    ++		tace[5].a_access_mask |= eperm;
    ++
    ++	/* Permissions for group@ */
    ++	if (mode & 0040)
    ++		tace[4].a_access_mask |= rperm;
    ++	else if (mode & 0004)
    ++		tace[2].a_access_mask |= rperm;
    ++	if (mode & 0020)
    ++		tace[4].a_access_mask |= wperm;
    ++	else if (mode & 0002)
    ++		tace[2].a_access_mask |= wperm;
    ++	if (mode & 0010)
    ++		tace[4].a_access_mask |= eperm;
    ++	else if (mode & 0001)
    ++		tace[2].a_access_mask |= eperm;
    ++
    ++	/* Permissions for owner@ */
    ++	if (mode & 0400) {
    ++		tace[3].a_access_mask |= rperm;
    ++		if (!(mode & 0040) && (mode & 0004))
    ++			tace[0].a_access_mask |= rperm;
    ++	} else if ((mode & 0040) || (mode & 0004))
    ++		tace[1].a_access_mask |= rperm;
    ++	if (mode & 0200) {
    ++		tace[3].a_access_mask |= wperm;
    ++		if (!(mode & 0020) && (mode & 0002))
    ++			tace[0].a_access_mask |= wperm;
    ++	} else if ((mode & 0020) || (mode & 0002))
    ++		tace[1].a_access_mask |= wperm;
    ++	if (mode & 0100) {
    ++		tace[3].a_access_mask |= eperm;
    ++		if (!(mode & 0010) && (mode & 0001))
    ++			tace[0].a_access_mask |= eperm;
    ++	} else if ((mode & 0010) || (mode & 0001))
    ++		tace[1].a_access_mask |= eperm;
    ++
    ++	/* Check if the acl count matches */
    ++	p = 3;
    ++	for (i = 0; i < 3; i++) {
    ++		if (tace[i].a_access_mask != 0)
    ++			p++;
    ++	}
    ++	if (aclcnt != p)
    ++		return (0);
    ++
    ++	p = 0;
    ++	for (i = 0; i < 6; i++) {
    ++		if (tace[i].a_access_mask != 0) {
    ++			ace = &((ace_t *)aclp)[p];
    ++			/*
    ++			 * Illumos added ACE_DELETE_CHILD to write perms for
    ++			 * directories. We have to check against that, too.
    ++			 */
    ++			if (ace->a_flags != tace[i].a_flags ||
    ++			    ace->a_type != tace[i].a_type ||
    ++			    (ace->a_access_mask != tace[i].a_access_mask &&
    ++			    (!is_dir || (tace[i].a_access_mask & wperm) == 0 ||
    ++			    ace->a_access_mask !=
    ++			    (tace[i].a_access_mask | ACE_DELETE_CHILD))))
    ++				return (0);
    ++			p++;
    ++		}
    ++	}
    ++
    ++	*trivialp = 1;
    ++#else	/* !ARCHIVE_ACL_SUNOS_NFS4 */
    ++	(void)is_dir;	/* UNUSED */
    ++	(void)aclp;	/* UNUSED */
    ++#endif	/* !ARCHIVE_ACL_SUNOS_NFS4 */
    ++	return (0);
    ++}
    ++
    ++/*
    ++ * Translate Solaris POSIX.1e and NFSv4 ACLs into libarchive internal ACL
    ++ */
    ++static int
    ++translate_acl(struct archive_read_disk *a,
    ++    struct archive_entry *entry, void *aclp, int aclcnt,
    ++    int default_entry_acl_type)
    ++{
    ++	int e, i;
    ++	int ae_id, ae_tag, ae_perm;
    ++	int entry_acl_type;
    ++	const char *ae_name;
    ++	aclent_t *aclent;
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++	ace_t *ace;
    ++#endif
    ++
    ++	if (aclcnt <= 0)
    ++		return (ARCHIVE_OK);
    ++
    ++	for (e = 0; e < aclcnt; e++) {
    ++		ae_name = NULL;
    ++		ae_tag = 0;
    ++		ae_perm = 0;
    ++
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++		if (default_entry_acl_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
    ++			ace = &((ace_t *)aclp)[e];
    ++			ae_id = ace->a_who;
    ++
    ++			switch(ace->a_type) {
    ++			case ACE_ACCESS_ALLOWED_ACE_TYPE:
    ++				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
    ++				break;
    ++			case ACE_ACCESS_DENIED_ACE_TYPE:
    ++				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
    ++				break;
    ++			case ACE_SYSTEM_AUDIT_ACE_TYPE:
    ++				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
    ++				break;
    ++			case ACE_SYSTEM_ALARM_ACE_TYPE:
    ++				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
    ++				break;
    ++			default:
    ++				/* Unknown entry type, skip */
    ++				continue;
    ++			}
    ++
    ++			if ((ace->a_flags & ACE_OWNER) != 0)
    ++				ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
    ++			else if ((ace->a_flags & ACE_GROUP) != 0)
    ++				ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
    ++			else if ((ace->a_flags & ACE_EVERYONE) != 0)
    ++				ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
    ++			else if ((ace->a_flags & ACE_IDENTIFIER_GROUP) != 0) {
    ++				ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
    ++				ae_name = archive_read_disk_gname(&a->archive,
    ++				    ae_id);
    ++			} else {
    ++				ae_tag = ARCHIVE_ENTRY_ACL_USER;
    ++				ae_name = archive_read_disk_uname(&a->archive,
    ++				    ae_id);
    ++			}
    ++
    ++			for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
    ++				if ((ace->a_flags &
    ++				    acl_nfs4_flag_map[i].p_perm) != 0)
    ++					ae_perm |= acl_nfs4_flag_map[i].a_perm;
    ++			}
    ++
    ++			for (i = 0; i < acl_nfs4_perm_map_size; ++i) {
    ++				if ((ace->a_access_mask &
    ++				    acl_nfs4_perm_map[i].p_perm) != 0)
    ++					ae_perm |= acl_nfs4_perm_map[i].a_perm;
    ++			}
    ++		} else
    ++#endif	/* ARCHIVE_ACL_SUNOS_NFS4 */
    ++		if (default_entry_acl_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {
    ++			aclent = &((aclent_t *)aclp)[e];
    ++			if ((aclent->a_type & ACL_DEFAULT) != 0)
    ++				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
    ++			else
    ++				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
    ++			ae_id = aclent->a_id;
    ++
    ++			switch(aclent->a_type) {
    ++			case DEF_USER:
    ++			case USER:
    ++				ae_name = archive_read_disk_uname(&a->archive,
    ++				    ae_id);
    ++				ae_tag = ARCHIVE_ENTRY_ACL_USER;
    ++				break;
    ++			case DEF_GROUP:
    ++			case GROUP:
    ++				ae_name = archive_read_disk_gname(&a->archive,
    ++				    ae_id);
    ++				ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
    ++				break;
    ++			case DEF_CLASS_OBJ:
    ++			case CLASS_OBJ:
    ++				ae_tag = ARCHIVE_ENTRY_ACL_MASK;
    ++				break;
    ++			case DEF_USER_OBJ:
    ++			case USER_OBJ:
    ++				ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
    ++				break;
    ++			case DEF_GROUP_OBJ:
    ++			case GROUP_OBJ:
    ++				ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
    ++				break;
    ++			case DEF_OTHER_OBJ:
    ++			case OTHER_OBJ:
    ++				ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
    ++				break;
    ++			default:
    ++				/* Unknown tag type, skip */
    ++				continue;
    ++			}
    ++
    ++			for (i = 0; i < acl_posix_perm_map_size; ++i) {
    ++				if ((aclent->a_perm &
    ++				    acl_posix_perm_map[i].p_perm) != 0)
    ++					ae_perm |= acl_posix_perm_map[i].a_perm;
    ++			}
    ++		} else
    ++			return (ARCHIVE_WARN);
    ++
    ++		archive_entry_acl_add_entry(entry, entry_acl_type,
    ++		    ae_perm, ae_tag, ae_id, ae_name);
    ++	}
    ++	return (ARCHIVE_OK);
    ++}
    ++
    ++int
    ++archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
    ++    struct archive_entry *entry, int *fd)
    ++{
    ++	const char	*accpath;
    ++	void		*aclp;
    ++	int		aclcnt;
    ++	int		r;
    ++
    ++	accpath = NULL;
    ++
    ++	if (*fd < 0) {
    ++		accpath = archive_read_disk_entry_setup_path(a, entry, fd);
    ++		if (accpath == NULL)
    ++			return (ARCHIVE_WARN);
    ++	}
    ++
    ++	archive_entry_acl_clear(entry);
    ++
    ++	aclp = NULL;
    ++
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++	if (*fd >= 0)
    ++		aclp = sunacl_get(ACE_GETACL, &aclcnt, *fd, NULL);
    ++	else if ((!a->follow_symlinks)
    ++	    && (archive_entry_filetype(entry) == AE_IFLNK))
    ++		/* We can't get the ACL of a symlink, so we assume it can't
    ++		   have one. */
    ++		aclp = NULL;
    ++	else
    ++		aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, accpath);
    ++
    ++	if (aclp != NULL && sun_acl_is_trivial(aclp, aclcnt,
    ++	    archive_entry_mode(entry), 1, S_ISDIR(archive_entry_mode(entry)),
    ++	    &r) == 0 && r == 1) {
    ++		free(aclp);
    ++		aclp = NULL;
    ++		return (ARCHIVE_OK);
    ++	}
    ++
    ++	if (aclp != NULL) {
    ++		r = translate_acl(a, entry, aclp, aclcnt,
    ++		    ARCHIVE_ENTRY_ACL_TYPE_NFS4);
    ++		free(aclp);
    ++		aclp = NULL;
    ++
    ++		if (r != ARCHIVE_OK) {
    ++			archive_set_error(&a->archive, errno,
    ++			    "Couldn't translate NFSv4 ACLs");
    ++		}
    ++		return (r);
    ++	}
    ++#endif	/* ARCHIVE_ACL_SUNOS_NFS4 */
    ++
    ++	/* Retrieve POSIX.1e ACLs from file. */
    ++	if (*fd >= 0)
    ++		aclp = sunacl_get(GETACL, &aclcnt, *fd, NULL);
    ++	else if ((!a->follow_symlinks)
    ++	    && (archive_entry_filetype(entry) == AE_IFLNK))
    ++		/* We can't get the ACL of a symlink, so we assume it can't
    ++		   have one. */
    ++		aclp = NULL;
    ++	else
    ++		aclp = sunacl_get(GETACL, &aclcnt, 0, accpath);
    ++
    ++	/* Ignore "trivial" ACLs that just mirror the file mode. */
    ++	if (aclp != NULL && sun_acl_is_trivial(aclp, aclcnt,
    ++	    archive_entry_mode(entry), 0, S_ISDIR(archive_entry_mode(entry)),
    ++	    &r) == 0 && r == 1) {
    ++		free(aclp);
    ++		aclp = NULL;
    ++	}
    ++
    ++	if (aclp != NULL)
    ++	{
    ++		r = translate_acl(a, entry, aclp, aclcnt,
    ++		    ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
    ++		free(aclp);
    ++		aclp = NULL;
    ++
    ++		if (r != ARCHIVE_OK) {
    ++			archive_set_error(&a->archive, errno,
    ++			    "Couldn't translate access ACLs");
    ++			return (r);
    ++		}
    ++	}
    ++
    ++	return (ARCHIVE_OK);
    ++}
    +--- libarchive/archive_read_disk_entry_from_file.c.orig
    ++++ libarchive/archive_read_disk_entry_from_file.c
    +@@ -26,23 +26,14 @@
    +  */
    + 
    + #include "archive_platform.h"
    +-__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 201084 2009-12-28 02:14:09Z kientzle $");
    ++__FBSDID("$FreeBSD");
    + 
    + /* This is the tree-walking code for POSIX systems. */
    + #if !defined(_WIN32) || defined(__CYGWIN__)
    + 
    + #ifdef HAVE_SYS_TYPES_H
    +-/* Mac OSX requires sys/types.h before sys/acl.h. */
    + #include <sys/types.h>
    + #endif
    +-#ifdef HAVE_SYS_ACL_H
    +-#include <sys/acl.h>
    +-#endif
    +-#ifdef HAVE_DARWIN_ACL
    +-#include <membership.h>
    +-#include <grp.h>
    +-#include <pwd.h>
    +-#endif
    + #ifdef HAVE_SYS_EXTATTR_H
    + #include <sys/extattr.h>
    + #endif
    +@@ -63,9 +54,6 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010
    + #ifdef HAVE_SYS_EA_H
    + #include <sys/ea.h>
    + #endif
    +-#ifdef HAVE_ACL_LIBACL_H
    +-#include <acl/libacl.h>
    +-#endif
    + #ifdef HAVE_COPYFILE_H
    + #include <copyfile.h>
    + #endif
    +@@ -113,27 +101,6 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010
    + #define O_CLOEXEC	0
    + #endif
    + 
    +-/*
    +- * Linux and FreeBSD plug this obvious hole in POSIX.1e in
    +- * different ways.
    +- */
    +-#if HAVE_ACL_GET_PERM
    +-#define	ACL_GET_PERM acl_get_perm
    +-#elif HAVE_ACL_GET_PERM_NP
    +-#define	ACL_GET_PERM acl_get_perm_np
    +-#endif
    +-
    +-/* NFSv4 platform ACL type */
    +-#if HAVE_SUN_ACL
    +-#define	ARCHIVE_PLATFORM_ACL_TYPE_NFS4	ACE_T
    +-#elif HAVE_DARWIN_ACL
    +-#define	ARCHIVE_PLATFORM_ACL_TYPE_NFS4	ACL_TYPE_EXTENDED
    +-#elif HAVE_ACL_TYPE_NFS4
    +-#define	ARCHIVE_PLATFORM_ACL_TYPE_NFS4	ACL_TYPE_NFS4
    +-#endif
    +-
    +-static int setup_acls(struct archive_read_disk *,
    +-    struct archive_entry *, int *fd);
    + static int setup_mac_metadata(struct archive_read_disk *,
    +     struct archive_entry *, int *fd);
    + static int setup_xattrs(struct archive_read_disk *,
    +@@ -145,6 +112,45 @@ static int setup_sparse_fiemap(struct archive_read_disk *,
    +     struct archive_entry *, int *fd);
    + #endif
    + 
    ++#if !ARCHIVE_ACL_SUPPORT
    ++int
    ++archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
    ++    struct archive_entry *entry, int *fd)
    ++{
    ++	(void)a;      /* UNUSED */
    ++	(void)entry;  /* UNUSED */
    ++	(void)fd;     /* UNUSED */
    ++	return (ARCHIVE_OK);
    ++}
    ++#endif
    ++
    ++/*
    ++ * Enter working directory and return working pathname of archive_entry.
    ++ * If a pointer to an integer is provided and its value is below zero
    ++ * open a file descriptor on this pahtname.
    ++ */
    ++const char *
    ++archive_read_disk_entry_setup_path(struct archive_read_disk *a,
    ++    struct archive_entry *entry, int *fd)
    ++{
    ++	const char *path;
    ++
    ++	path = archive_entry_sourcepath(entry);
    ++
    ++	if (path == NULL || (a->tree != NULL &&
    ++	    a->tree_enter_working_dir(a->tree) != 0))
    ++		path = archive_entry_pathname(entry);
    ++	if (path == NULL) {
    ++		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
    ++		   "Couldn't determine path");
    ++	} else if (fd != NULL && *fd < 0 && a->tree != NULL &&
    ++	    (a->follow_symlinks || archive_entry_filetype(entry) != AE_IFLNK)) {
    ++		*fd = a->open_on_current_dir(a->tree, path,
    ++		    O_RDONLY | O_NONBLOCK);
    ++	}
    ++	return (path);
    ++}
    ++
    + int
    + archive_read_disk_entry_from_file(struct archive *_a,
    +     struct archive_entry *entry,
    +@@ -279,7 +285,7 @@ archive_read_disk_entry_from_file(struct archive *_a,
    + 
    + 	r = 0;
    + 	if ((a->flags & ARCHIVE_READDISK_NO_ACL) == 0)
    +-		r = setup_acls(a, entry, &fd);
    ++		r = archive_read_disk_entry_setup_acls(a, entry, &fd);
    + 	if ((a->flags & ARCHIVE_READDISK_NO_XATTR) == 0) {
    + 		r1 = setup_xattrs(a, entry, &fd);
    + 		if (r1 < r)
    +@@ -328,19 +334,10 @@ setup_mac_metadata(struct archive_read_disk *a,
    + 	struct archive_string tempfile;
    + 
    + 	(void)fd; /* UNUSED */
    +-	name = archive_entry_sourcepath(entry);
    ++
    ++	name = archive_read_disk_entry_setup_path(a, entry, NULL);
    + 	if (name == NULL)
    +-		name = archive_entry_pathname(entry);
    +-	else if (a->tree != NULL && a->tree_enter_working_dir(a->tree) != 0) {
    +-		archive_set_error(&a->archive, errno,
    +-			    "Can't change dir to read extended attributes");
    +-			return (ARCHIVE_FAILED);
    +-	}
    +-	if (name == NULL) {
    +-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
    +-		    "Can't open file to read extended attributes: No name");
    + 		return (ARCHIVE_WARN);
    +-	}
    + 
    + 	/* Short-circuit if there's nothing to do. */
    + 	have_attrs = copyfile(name, NULL, 0, copyfile_flags | COPYFILE_CHECK);
    +@@ -426,990 +423,6 @@ setup_mac_metadata(struct archive_read_disk *a,
    + }
    + #endif
    + 
    +-#if HAVE_DARWIN_ACL
    +-static int translate_guid(struct archive *, acl_entry_t,
    +-    int *, int *, const char **);
    +-
    +-static void add_trivial_nfs4_acl(struct archive_entry *);
    +-#endif
    +-
    +-#if HAVE_SUN_ACL
    +-static int
    +-sun_acl_is_trivial(acl_t *, mode_t, int *trivialp);
    +-#endif
    +-
    +-#if HAVE_POSIX_ACL || HAVE_NFS4_ACL
    +-static int translate_acl(struct archive_read_disk *a,
    +-    struct archive_entry *entry,
    +-#if HAVE_SUN_ACL
    +-    acl_t *acl,
    +-#else
    +-    acl_t acl,
    +-#endif
    +-    int archive_entry_acl_type);
    +-
    +-static int
    +-setup_acls(struct archive_read_disk *a,
    +-    struct archive_entry *entry, int *fd)
    +-{
    +-	const char	*accpath;
    +-#if HAVE_SUN_ACL
    +-	acl_t		*acl;
    +-#else
    +-	acl_t		acl;
    +-#endif
    +-	int		r;
    +-
    +-	accpath = NULL;
    +-
    +-#if HAVE_SUN_ACL || HAVE_DARWIN_ACL || HAVE_ACL_GET_FD_NP
    +-	if (*fd < 0)
    +-#else
    +-	/* For default ACLs on Linux we need reachable accpath */
    +-	if (*fd < 0 || S_ISDIR(archive_entry_mode(entry)))
    +-#endif
    +-	{
    +-		accpath = archive_entry_sourcepath(entry);
    +-		if (accpath == NULL || (a->tree != NULL &&
    +-		    a->tree_enter_working_dir(a->tree) != 0))
    +-			accpath = archive_entry_pathname(entry);
    +-		if (accpath == NULL) {
    +-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
    +-			    "Couldn't determine file path to read ACLs");
    +-			return (ARCHIVE_WARN);
    +-		}
    +-		if (a->tree != NULL &&
    +-#if !HAVE_SUN_ACL && !HAVE_DARWIN_ACL && !HAVE_ACL_GET_FD_NP
    +-		    *fd < 0 &&
    +-#endif
    +-		    (a->follow_symlinks ||
    +-		    archive_entry_filetype(entry) != AE_IFLNK)) {
    +-			*fd = a->open_on_current_dir(a->tree,
    +-			    accpath, O_RDONLY | O_NONBLOCK);
    +-		}
    +-	}
    +-
    +-	archive_entry_acl_clear(entry);
    +-
    +-	acl = NULL;
    +-
    +-#if HAVE_NFS4_ACL
    +-	/* Try NFSv4 ACL first. */
    +-	if (*fd >= 0)
    +-#if HAVE_SUN_ACL
    +-		/* Solaris reads both POSIX.1e and NFSv4 ACL here */
    +-		facl_get(*fd, 0, &acl);
    +-#elif HAVE_ACL_GET_FD_NP
    +-		acl = acl_get_fd_np(*fd, ARCHIVE_PLATFORM_ACL_TYPE_NFS4);
    +-#else
    +-		acl = acl_get_fd(*fd);
    +-#endif
    +-#if HAVE_ACL_GET_LINK_NP
    +-	else if (!a->follow_symlinks)
    +-		acl = acl_get_link_np(accpath, ARCHIVE_PLATFORM_ACL_TYPE_NFS4);
    +-#else
    +-	else if ((!a->follow_symlinks)
    +-	    && (archive_entry_filetype(entry) == AE_IFLNK))
    +-		/* We can't get the ACL of a symlink, so we assume it can't
    +-		   have one. */
    +-		acl = NULL;
    +-#endif
    +-	else
    +-#if HAVE_SUN_ACL
    +-		/* Solaris reads both POSIX.1e and NFSv4 ACLs here */
    +-		acl_get(accpath, 0, &acl);
    +-#else
    +-		acl = acl_get_file(accpath, ARCHIVE_PLATFORM_ACL_TYPE_NFS4);
    +-#endif
    +-
    +-
    +-#if HAVE_ACL_IS_TRIVIAL_NP || HAVE_SUN_ACL
    +-	/* Ignore "trivial" ACLs that just mirror the file mode. */
    +-	if (acl != NULL) {
    +-#if HAVE_SUN_ACL
    +-		if (sun_acl_is_trivial(acl, archive_entry_mode(entry),
    +-		    &r) == 0 && r == 1)
    +-#elif HAVE_ACL_IS_TRIVIAL_NP
    +-		if (acl_is_trivial_np(acl, &r) == 0 && r == 1)
    +-#endif
    +-		{
    +-			acl_free(acl);
    +-			acl = NULL;
    +-			/*
    +-			 * Simultaneous NFSv4 and POSIX.1e ACLs for the same
    +-			 * entry are not allowed, so we should return here
    +-			 */
    +-			return (ARCHIVE_OK);
    +-		}
    +-	}
    +-#endif	/* HAVE_ACL_IS_TRIVIAL_NP || HAVE_SUN_ACL */
    +-	if (acl != NULL) {
    +-		r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
    +-		acl_free(acl);
    +-		if (r != ARCHIVE_OK) {
    +-			archive_set_error(&a->archive, errno,
    +-			    "Couldn't translate "
    +-#if !HAVE_SUN_ACL
    +-			    "NFSv4 "
    +-#endif
    +-			    "ACLs");
    +-		}
    +-#if HAVE_DARWIN_ACL
    +-		/*
    +-		 * Because Mac OS doesn't support owner@, group@ and everyone@
    +-		 * ACLs we need to add NFSv4 ACLs mirroring the file mode to
    +-		 * the archive entry. Otherwise extraction on non-Mac platforms
    +-		 * would lead to an invalid file mode.
    +-		 */
    +-		if ((archive_entry_acl_types(entry) &
    +-		    ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0)
    +-			add_trivial_nfs4_acl(entry);
    +-#endif
    +-		return (r);
    +-	}
    +-#endif	/* HAVE_NFS4_ACL */
    +-
    +-#if HAVE_POSIX_ACL
    +-	/* This code path is skipped on MacOS and Solaris */
    +-
    +-	/* Retrieve access ACL from file. */
    +-	if (*fd >= 0)
    +-		acl = acl_get_fd(*fd);
    +-#if HAVE_ACL_GET_LINK_NP
    +-	else if (!a->follow_symlinks)
    +-		acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS);
    +-#else
    +-	else if ((!a->follow_symlinks)
    +-	    && (archive_entry_filetype(entry) == AE_IFLNK))
    +-		/* We can't get the ACL of a symlink, so we assume it can't
    +-		   have one. */
    +-		acl = NULL;
    +-#endif
    +-	else
    +-		acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
    +-
    +-#if HAVE_ACL_IS_TRIVIAL_NP
    +-	/* Ignore "trivial" ACLs that just mirror the file mode. */
    +-	if (acl != NULL && acl_is_trivial_np(acl, &r) == 0) {
    +-		if (r) {
    +-			acl_free(acl);
    +-			acl = NULL;
    +-		}
    +-	}
    +-#endif
    +-
    +-	if (acl != NULL) {
    +-		r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
    +-		acl_free(acl);
    +-		acl = NULL;
    +-		if (r != ARCHIVE_OK) {
    +-			archive_set_error(&a->archive, errno,
    +-			    "Couldn't translate access ACLs");
    +-			return (r);
    +-		}
    +-	}
    +-
    +-	/* Only directories can have default ACLs. */
    +-	if (S_ISDIR(archive_entry_mode(entry))) {
    +-#if HAVE_ACL_GET_FD_NP
    +-		if (*fd >= 0)
    +-			acl = acl_get_fd_np(*fd, ACL_TYPE_DEFAULT);
    +-		else
    +-#endif
    +-		acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
    +-		if (acl != NULL) {
    +-			r = translate_acl(a, entry, acl,
    +-			    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
    +-			acl_free(acl);
    +-			if (r != ARCHIVE_OK) {
    +-				archive_set_error(&a->archive, errno,
    +-				    "Couldn't translate default ACLs");
    +-				return (r);
    +-			}
    +-		}
    +-	}
    +-#endif	/* HAVE_POSIX_ACL */
    +-	return (ARCHIVE_OK);
    +-}
    +-
    +-/*
    +- * Translate system ACL permissions into libarchive internal structure
    +- */
    +-static const struct {
    +-	const int archive_perm;
    +-	const int platform_perm;
    +-} acl_perm_map[] = {
    +-#if HAVE_SUN_ACL	/* Solaris NFSv4 ACL permissions */
    +-	{ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE},
    +-	{ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA},
    +-	{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA},
    +-	{ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE},
    +-	{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA},
    +-	{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY},
    +-	{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS},
    +-	{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD},
    +-	{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES},
    +-	{ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE},
    +-	{ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER},
    +-	{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE}
    +-#elif HAVE_DARWIN_ACL	/* MacOS ACL permissions */
    +-	{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
    +-	{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
    +-	{ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
    +-	{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
    +-	{ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
    +-	{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
    +-	{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
    +-	{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
    +-	{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
    +-	{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES},
    +-	{ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER},
    +-	{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
    +-#else	/* POSIX.1e ACL permissions */
    +-	{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
    +-	{ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
    +-	{ARCHIVE_ENTRY_ACL_READ, ACL_READ},
    +-#if HAVE_ACL_TYPE_NFS4	/* FreeBSD NFSv4 ACL permissions */
    +-	{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
    +-	{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
    +-	{ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
    +-	{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
    +-	{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
    +-	{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
    +-	{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
    +-	{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
    +-	{ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
    +-	{ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
    +-	{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
    +-#endif
    +-#endif	/* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
    +-};
    +-
    +-#if HAVE_NFS4_ACL
    +-/*
    +- * Translate system NFSv4 inheritance flags into libarchive internal structure
    +- */
    +-static const struct {
    +-	const int archive_inherit;
    +-	const int platform_inherit;
    +-} acl_inherit_map[] = {
    +-#if HAVE_SUN_ACL	/* Solaris ACL inheritance flags */
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}
    +-#elif HAVE_DARWIN_ACL	/* MacOS NFSv4 inheritance flags */
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_LIMIT_INHERIT},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT}
    +-#else	/* FreeBSD NFSv4 ACL inheritance flags */
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}
    +-#endif	/* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
    +-};
    +-#endif	/* HAVE_NFS4_ACL */
    +-
    +-#if HAVE_DARWIN_ACL
    +-static int translate_guid(struct archive *a, acl_entry_t acl_entry,
    +-    int *ae_id, int *ae_tag, const char **ae_name)
    +-{
    +-	void *q;
    +-	uid_t ugid;
    +-	int r, idtype;
    +-	struct passwd *pwd;
    +-	struct group *grp;
    +-
    +-	q = acl_get_qualifier(acl_entry);
    +-	if (q == NULL)
    +-		return (1);
    +-	r = mbr_uuid_to_id((const unsigned char *)q, &ugid, &idtype);
    +-	if (r != 0) {
    +-		acl_free(q);
    +-		return (1);
    +-	}
    +-	if (idtype == ID_TYPE_UID) {
    +-		*ae_tag = ARCHIVE_ENTRY_ACL_USER;
    +-		pwd = getpwuuid(q);
    +-		if (pwd == NULL) {
    +-			*ae_id = ugid;
    +-			*ae_name = NULL;
    +-		} else {
    +-			*ae_id = pwd->pw_uid;
    +-			*ae_name = archive_read_disk_uname(a, *ae_id);
    +-		}
    +-	} else if (idtype == ID_TYPE_GID) {
    +-		*ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
    +-		grp = getgruuid(q);
    +-		if (grp == NULL) {
    +-			*ae_id = ugid;
    +-			*ae_name = NULL;
    +-		} else {
    +-			*ae_id = grp->gr_gid;
    +-			*ae_name = archive_read_disk_gname(a, *ae_id);
    +-		}
    +-	} else
    +-		r = 1;
    +-
    +-	acl_free(q);
    +-	return (r);
    +-}
    +-
    +-/*
    +- * Add trivial NFSv4 ACL entries from mode
    +- */
    +-static void
    +-add_trivial_nfs4_acl(struct archive_entry *entry)
    +-{
    +-	mode_t mode;
    +-	int i;
    +-	const int rperm = ARCHIVE_ENTRY_ACL_READ_DATA;
    +-	const int wperm = ARCHIVE_ENTRY_ACL_WRITE_DATA |
    +-	    ARCHIVE_ENTRY_ACL_APPEND_DATA;
    +-	const int eperm = ARCHIVE_ENTRY_ACL_EXECUTE;
    +-	const int pubset = ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
    +-	    ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
    +-	    ARCHIVE_ENTRY_ACL_READ_ACL |
    +-	    ARCHIVE_ENTRY_ACL_SYNCHRONIZE;
    +-	const int ownset = pubset | ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
    +-	    ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
    +-	    ARCHIVE_ENTRY_ACL_WRITE_ACL |
    +-	    ARCHIVE_ENTRY_ACL_WRITE_OWNER;
    +-
    +-	struct {
    +-	    const int type;
    +-	    const int tag;
    +-	    int permset;
    +-	} tacl_entry[] = {
    +-	    {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, 0},
    +-	    {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_USER_OBJ, 0},
    +-	    {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0},
    +-	    {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, ownset},
    +-	    {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_GROUP_OBJ, pubset},
    +-	    {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EVERYONE, pubset}
    +-	};
    +-
    +-	mode = archive_entry_mode(entry);
    +-
    +-	/* Permissions for everyone@ */
    +-	if (mode & 0004)
    +-		tacl_entry[5].permset |= rperm;
    +-	if (mode & 0002)
    +-		tacl_entry[5].permset |= wperm;
    +-	if (mode & 0001)
    +-		tacl_entry[5].permset |= eperm;
    +-
    +-	/* Permissions for group@ */
    +-	if (mode & 0040)
    +-		tacl_entry[4].permset |= rperm;
    +-	else if (mode & 0004)
    +-		tacl_entry[2].permset |= rperm;
    +-	if (mode & 0020)
    +-		tacl_entry[4].permset |= wperm;
    +-	else if (mode & 0002)
    +-		tacl_entry[2].permset |= wperm;
    +-	if (mode & 0010)
    +-		tacl_entry[4].permset |= eperm;
    +-	else if (mode & 0001)
    +-		tacl_entry[2].permset |= eperm;
    +-
    +-	/* Permissions for owner@ */
    +-	if (mode & 0400) {
    +-		tacl_entry[3].permset |= rperm;
    +-		if (!(mode & 0040) && (mode & 0004))
    +-			tacl_entry[0].permset |= rperm;
    +-	} else if ((mode & 0040) || (mode & 0004))
    +-		tacl_entry[1].permset |= rperm;
    +-	if (mode & 0200) {
    +-		tacl_entry[3].permset |= wperm;
    +-		if (!(mode & 0020) && (mode & 0002))
    +-			tacl_entry[0].permset |= wperm;
    +-	} else if ((mode & 0020) || (mode & 0002))
    +-		tacl_entry[1].permset |= wperm;
    +-	if (mode & 0100) {
    +-		tacl_entry[3].permset |= eperm;
    +-		if (!(mode & 0010) && (mode & 0001))
    +-			tacl_entry[0].permset |= eperm;
    +-	} else if ((mode & 0010) || (mode & 0001))
    +-		tacl_entry[1].permset |= eperm;
    +-
    +-	for (i = 0; i < 6; i++) {
    +-		if (tacl_entry[i].permset != 0) {
    +-			archive_entry_acl_add_entry(entry,
    +-			    tacl_entry[i].type, tacl_entry[i].permset,
    +-			    tacl_entry[i].tag, -1, NULL);
    +-		}
    +-	}
    +-
    +-	return;
    +-}
    +-#elif HAVE_SUN_ACL
    +-/*
    +- * Check if acl is trivial
    +- * This is a FreeBSD acl_is_trivial_np() implementation for Solaris
    +- */
    +-static int
    +-sun_acl_is_trivial(acl_t *acl, mode_t mode, int *trivialp)
    +-{
    +-	int i, p;
    +-	const uint32_t rperm = ACE_READ_DATA;
    +-	const uint32_t wperm = ACE_WRITE_DATA | ACE_APPEND_DATA;
    +-	const uint32_t eperm = ACE_EXECUTE;
    +-	const uint32_t pubset = ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS |
    +-	    ACE_READ_ACL | ACE_SYNCHRONIZE;
    +-	const uint32_t ownset = pubset | ACE_WRITE_ATTRIBUTES |
    +-	    ACE_WRITE_NAMED_ATTRS | ACE_WRITE_ACL | ACE_WRITE_OWNER;
    +-
    +-	ace_t *ace;
    +-	ace_t tace[6];
    +-
    +-	if (acl == NULL || trivialp == NULL)
    +-		return (-1);
    +-
    +-	*trivialp = 0;
    +-
    +-	/* ACL_IS_TRIVIAL flag must be set for both POSIX.1e and NFSv4 ACLs */
    +-	if ((acl->acl_flags & ACL_IS_TRIVIAL) == 0)
    +-		return (0);
    +-
    +-	/*
    +-	 * POSIX.1e ACLs marked with ACL_IS_TRIVIAL are compatible with
    +-	 * FreeBSD acl_is_trivial_np(). On Solaris they have 4 entries,
    +-	 * including mask.
    +-	 */
    +-	if (acl->acl_type == ACLENT_T) {
    +-		if (acl->acl_cnt == 4)
    +-			*trivialp = 1;
    +-		return (0);
    +-	}
    +-
    +-	if (acl->acl_type != ACE_T || acl->acl_entry_size != sizeof(ace_t))
    +-		return (-1);
    +-
    +-	/*
    +-	 * Continue with checking NFSv4 ACLs
    +-	 *
    +-	 * Create list of trivial ace's to be compared
    +-	 */
    +-
    +-	/* owner@ allow pre */
    +-	tace[0].a_flags = ACE_OWNER;
    +-	tace[0].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
    +-	tace[0].a_access_mask = 0;
    +-
    +-	/* owner@ deny */
    +-	tace[1].a_flags = ACE_OWNER;
    +-	tace[1].a_type = ACE_ACCESS_DENIED_ACE_TYPE;
    +-	tace[1].a_access_mask = 0;
    +-
    +-	/* group@ deny */
    +-	tace[2].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP;
    +-	tace[2].a_type = ACE_ACCESS_DENIED_ACE_TYPE;
    +-	tace[2].a_access_mask = 0;
    +-
    +-	/* owner@ allow */
    +-	tace[3].a_flags = ACE_OWNER;
    +-	tace[3].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
    +-	tace[3].a_access_mask = ownset;
    +-
    +-	/* group@ allow */
    +-	tace[4].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP;
    +-	tace[4].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
    +-	tace[4].a_access_mask = pubset;
    +-
    +-	/* everyone@ allow */
    +-	tace[5].a_flags = ACE_EVERYONE;
    +-	tace[5].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
    +-	tace[5].a_access_mask = pubset;
    +-
    +-	/* Permissions for everyone@ */
    +-	if (mode & 0004)
    +-		tace[5].a_access_mask |= rperm;
    +-	if (mode & 0002)
    +-		tace[5].a_access_mask |= wperm;
    +-	if (mode & 0001)
    +-		tace[5].a_access_mask |= eperm;
    +-
    +-	/* Permissions for group@ */
    +-	if (mode & 0040)
    +-		tace[4].a_access_mask |= rperm;
    +-	else if (mode & 0004)
    +-		tace[2].a_access_mask |= rperm;
    +-	if (mode & 0020)
    +-		tace[4].a_access_mask |= wperm;
    +-	else if (mode & 0002)
    +-		tace[2].a_access_mask |= wperm;
    +-	if (mode & 0010)
    +-		tace[4].a_access_mask |= eperm;
    +-	else if (mode & 0001)
    +-		tace[2].a_access_mask |= eperm;
    +-
    +-	/* Permissions for owner@ */
    +-	if (mode & 0400) {
    +-		tace[3].a_access_mask |= rperm;
    +-		if (!(mode & 0040) && (mode & 0004))
    +-			tace[0].a_access_mask |= rperm;
    +-	} else if ((mode & 0040) || (mode & 0004))
    +-		tace[1].a_access_mask |= rperm;
    +-	if (mode & 0200) {
    +-		tace[3].a_access_mask |= wperm;
    +-		if (!(mode & 0020) && (mode & 0002))
    +-			tace[0].a_access_mask |= wperm;
    +-	} else if ((mode & 0020) || (mode & 0002))
    +-		tace[1].a_access_mask |= wperm;
    +-	if (mode & 0100) {
    +-		tace[3].a_access_mask |= eperm;
    +-		if (!(mode & 0010) && (mode & 0001))
    +-			tace[0].a_access_mask |= eperm;
    +-	} else if ((mode & 0010) || (mode & 0001))
    +-		tace[1].a_access_mask |= eperm;
    +-
    +-	/* Check if the acl count matches */
    +-	p = 3;
    +-	for (i = 0; i < 3; i++) {
    +-		if (tace[i].a_access_mask != 0)
    +-			p++;
    +-	}
    +-	if (acl->acl_cnt != p)
    +-		return (0);
    +-
    +-	p = 0;
    +-	for (i = 0; i < 6; i++) {
    +-		if (tace[i].a_access_mask != 0) {
    +-			ace = &((ace_t *)acl->acl_aclp)[p];
    +-			/*
    +-			 * Illumos added ACE_DELETE_CHILD to write perms for
    +-			 * directories. We have to check against that, too.
    +-			 */
    +-			if (ace->a_flags != tace[i].a_flags ||
    +-			    ace->a_type != tace[i].a_type ||
    +-			    (ace->a_access_mask != tace[i].a_access_mask &&
    +-			    ((acl->acl_flags & ACL_IS_DIR) == 0 ||
    +-			    (tace[i].a_access_mask & wperm) == 0 ||
    +-			    ace->a_access_mask !=
    +-			    (tace[i].a_access_mask | ACE_DELETE_CHILD))))
    +-				return (0);
    +-			p++;
    +-		}
    +-	}
    +-
    +-	*trivialp = 1;
    +-	return (0);
    +-}
    +-#endif	/* HAVE_SUN_ACL */
    +-
    +-#if HAVE_SUN_ACL
    +-/*
    +- * Translate Solaris POSIX.1e and NFSv4 ACLs into libarchive internal ACL
    +- */
    +-static int
    +-translate_acl(struct archive_read_disk *a,
    +-    struct archive_entry *entry, acl_t *acl, int default_entry_acl_type)
    +-{
    +-	int e, i;
    +-	int ae_id, ae_tag, ae_perm;
    +-	int entry_acl_type;
    +-	const char *ae_name;
    +-	aclent_t *aclent;
    +-	ace_t *ace;
    +-
    +-	(void)default_entry_acl_type;
    +-
    +-	if (acl->acl_cnt <= 0)
    +-		return (ARCHIVE_OK);
    +-
    +-	for (e = 0; e < acl->acl_cnt; e++) {
    +-		ae_name = NULL;
    +-		ae_tag = 0;
    +-		ae_perm = 0;
    +-
    +-		if (acl->acl_type == ACE_T) {
    +-			ace = &((ace_t *)acl->acl_aclp)[e];
    +-			ae_id = ace->a_who;
    +-
    +-			switch(ace->a_type) {
    +-			case ACE_ACCESS_ALLOWED_ACE_TYPE:
    +-				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
    +-				break;
    +-			case ACE_ACCESS_DENIED_ACE_TYPE:
    +-				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
    +-				break;
    +-			case ACE_SYSTEM_AUDIT_ACE_TYPE:
    +-				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
    +-				break;
    +-			case ACE_SYSTEM_ALARM_ACE_TYPE:
    +-				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
    +-				break;
    +-			default:
    +-				/* Unknown entry type, skip */
    +-				continue;
    +-			}
    +-
    +-			if ((ace->a_flags & ACE_OWNER) != 0)
    +-				ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
    +-			else if ((ace->a_flags & ACE_GROUP) != 0)
    +-				ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
    +-			else if ((ace->a_flags & ACE_EVERYONE) != 0)
    +-				ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
    +-			else if ((ace->a_flags & ACE_IDENTIFIER_GROUP) != 0) {
    +-				ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
    +-				ae_name = archive_read_disk_gname(&a->archive,
    +-				    ae_id);
    +-			} else {
    +-				ae_tag = ARCHIVE_ENTRY_ACL_USER;
    +-				ae_name = archive_read_disk_uname(&a->archive,
    +-				    ae_id);
    +-			}
    +-
    +-			for (i = 0; i < (int)(sizeof(acl_inherit_map) /
    +-			    sizeof(acl_inherit_map[0])); ++i) {
    +-				if ((ace->a_flags &
    +-				    acl_inherit_map[i].platform_inherit) != 0)
    +-					ae_perm |=
    +-					    acl_inherit_map[i].archive_inherit;
    +-			}
    +-
    +-			for (i = 0; i < (int)(sizeof(acl_perm_map) /
    +-			    sizeof(acl_perm_map[0])); ++i) {
    +-				if ((ace->a_access_mask &
    +-				    acl_perm_map[i].platform_perm) != 0)
    +-					ae_perm |=
    +-					    acl_perm_map[i].archive_perm;
    +-			}
    +-		} else {
    +-			aclent = &((aclent_t *)acl->acl_aclp)[e];
    +-			if ((aclent->a_type & ACL_DEFAULT) != 0)
    +-				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
    +-			else
    +-				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
    +-			ae_id = aclent->a_id;
    +-
    +-			switch(aclent->a_type) {
    +-			case DEF_USER:
    +-			case USER:
    +-				ae_name = archive_read_disk_uname(&a->archive,
    +-				    ae_id);
    +-				ae_tag = ARCHIVE_ENTRY_ACL_USER;
    +-				break;
    +-			case DEF_GROUP:
    +-			case GROUP:
    +-				ae_name = archive_read_disk_gname(&a->archive,
    +-				    ae_id);
    +-				ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
    +-				break;
    +-			case DEF_CLASS_OBJ:
    +-			case CLASS_OBJ:
    +-				ae_tag = ARCHIVE_ENTRY_ACL_MASK;
    +-				break;
    +-			case DEF_USER_OBJ:
    +-			case USER_OBJ:
    +-				ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
    +-				break;
    +-			case DEF_GROUP_OBJ:
    +-			case GROUP_OBJ:
    +-				ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
    +-				break;
    +-			case DEF_OTHER_OBJ:
    +-			case OTHER_OBJ:
    +-				ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
    +-				break;
    +-			default:
    +-				/* Unknown tag type, skip */
    +-				continue;
    +-			}
    +-
    +-			if ((aclent->a_perm & 1) != 0)
    +-				ae_perm |= ARCHIVE_ENTRY_ACL_EXECUTE;
    +-			if ((aclent->a_perm & 2) != 0)
    +-				ae_perm |= ARCHIVE_ENTRY_ACL_WRITE;
    +-			if ((aclent->a_perm & 4) != 0)
    +-				ae_perm |= ARCHIVE_ENTRY_ACL_READ;
    +-		} /* default_entry_acl_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4 */
    +-
    +-		archive_entry_acl_add_entry(entry, entry_acl_type,
    +-		    ae_perm, ae_tag, ae_id, ae_name);
    +-	}
    +-	return (ARCHIVE_OK);
    +-}
    +-#else	/* !HAVE_SUN_ACL */
    +-/*
    +- * Translate POSIX.1e (Linux), FreeBSD (both POSIX.1e and NFSv4) and
    +- * MacOS (NFSv4 only) ACLs into libarchive internal structure
    +- */
    +-static int
    +-translate_acl(struct archive_read_disk *a,
    +-    struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
    +-{
    +-	acl_tag_t	 acl_tag;
    +-#if HAVE_ACL_TYPE_NFS4
    +-	acl_entry_type_t acl_type;
    +-	int brand;
    +-#endif
    +-#if HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL
    +-	acl_flagset_t	 acl_flagset;
    +-#endif
    +-	acl_entry_t	 acl_entry;
    +-	acl_permset_t	 acl_permset;
    +-	int		 i, entry_acl_type;
    +-	int		 r, s, ae_id, ae_tag, ae_perm;
    +-#if !HAVE_DARWIN_ACL
    +-	void		*q;
    +-#endif
    +-	const char	*ae_name;
    +-
    +-#if HAVE_ACL_TYPE_NFS4
    +-	// FreeBSD "brands" ACLs as POSIX.1e or NFSv4
    +-	// Make sure the "brand" on this ACL is consistent
    +-	// with the default_entry_acl_type bits provided.
    +-	if (acl_get_brand_np(acl, &brand) != 0) {
    +-		archive_set_error(&a->archive, errno,
    +-		    "Failed to read ACL brand");
    +-		return (ARCHIVE_WARN);
    +-	}
    +-	switch (brand) {
    +-	case ACL_BRAND_POSIX:
    +-		switch (default_entry_acl_type) {
    +-		case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
    +-		case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
    +-			break;
    +-		default:
    +-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
    +-			    "Invalid ACL entry type for POSIX.1e ACL");
    +-			return (ARCHIVE_WARN);
    +-		}
    +-		break;
    +-	case ACL_BRAND_NFS4:
    +-		if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
    +-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
    +-			    "Invalid ACL entry type for NFSv4 ACL");
    +-			return (ARCHIVE_WARN);
    +-		}
    +-		break;
    +-	default:
    +-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
    +-		    "Unknown ACL brand");
    +-		return (ARCHIVE_WARN);
    +-	}
    +-#endif
    +-
    +-	s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
    +-	if (s == -1) {
    +-		archive_set_error(&a->archive, errno,
    +-		    "Failed to get first ACL entry");
    +-		return (ARCHIVE_WARN);
    +-	}
    +-
    +-#if HAVE_DARWIN_ACL
    +-	while (s == 0)
    +-#else	/* FreeBSD, Linux */
    +-	while (s == 1)
    +-#endif
    +-	{
    +-		ae_id = -1;
    +-		ae_name = NULL;
    +-		ae_perm = 0;
    +-
    +-		if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
    +-			archive_set_error(&a->archive, errno,
    +-			    "Failed to get ACL tag type");
    +-			return (ARCHIVE_WARN);
    +-		}
    +-		switch (acl_tag) {
    +-#if !HAVE_DARWIN_ACL	/* FreeBSD, Linux */
    +-		case ACL_USER:
    +-			q = acl_get_qualifier(acl_entry);
    +-			if (q != NULL) {
    +-				ae_id = (int)*(uid_t *)q;
    +-				acl_free(q);
    +-				ae_name = archive_read_disk_uname(&a->archive,
    +-				    ae_id);
    +-			}
    +-			ae_tag = ARCHIVE_ENTRY_ACL_USER;
    +-			break;
    +-		case ACL_GROUP:
    +-			q = acl_get_qualifier(acl_entry);
    +-			if (q != NULL) {
    +-				ae_id = (int)*(gid_t *)q;
    +-				acl_free(q);
    +-				ae_name = archive_read_disk_gname(&a->archive,
    +-				    ae_id);
    +-			}
    +-			ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
    +-			break;
    +-		case ACL_MASK:
    +-			ae_tag = ARCHIVE_ENTRY_ACL_MASK;
    +-			break;
    +-		case ACL_USER_OBJ:
    +-			ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
    +-			break;
    +-		case ACL_GROUP_OBJ:
    +-			ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
    +-			break;
    +-		case ACL_OTHER:
    +-			ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
    +-			break;
    +-#if HAVE_ACL_TYPE_NFS4
    +-		case ACL_EVERYONE:
    +-			ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
    +-			break;
    +-#endif
    +-#else	/* HAVE_DARWIN_ACL */
    +-		case ACL_EXTENDED_ALLOW:
    +-			entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
    +-			r = translate_guid(&a->archive, acl_entry, &ae_id,
    +-			    &ae_tag, &ae_name);
    +-			break;
    +-		case ACL_EXTENDED_DENY:
    +-			entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
    +-			r = translate_guid(&a->archive, acl_entry, &ae_id,
    +-			    &ae_tag, &ae_name);
    +-			break;
    +-#endif	/* HAVE_DARWIN_ACL */
    +-		default:
    +-			/* Skip types that libarchive can't support. */
    +-			s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
    +-			continue;
    +-		}
    +-
    +-#if HAVE_DARWIN_ACL
    +-		/* Skip if translate_guid() above failed */
    +-		if (r != 0) {
    +-			s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
    +-			continue;
    +-		}
    +-#endif
    +-
    +-#if !HAVE_DARWIN_ACL
    +-		// XXX acl_type maps to allow/deny/audit/YYYY bits
    +-		entry_acl_type = default_entry_acl_type;
    +-#endif
    +-#if HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL
    +-		if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
    +-#if HAVE_ACL_TYPE_NFS4
    +-			/*
    +-			 * acl_get_entry_type_np() fails with non-NFSv4 ACLs
    +-			 */
    +-			if (acl_get_entry_type_np(acl_entry, &acl_type) != 0) {
    +-				archive_set_error(&a->archive, errno, "Failed "
    +-				    "to get ACL type from a NFSv4 ACL entry");
    +-				return (ARCHIVE_WARN);
    +-			}
    +-			switch (acl_type) {
    +-			case ACL_ENTRY_TYPE_ALLOW:
    +-				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
    +-				break;
    +-			case ACL_ENTRY_TYPE_DENY:
    +-				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
    +-				break;
    +-			case ACL_ENTRY_TYPE_AUDIT:
    +-				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
    +-				break;
    +-			case ACL_ENTRY_TYPE_ALARM:
    +-				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
    +-				break;
    +-			default:
    +-				archive_set_error(&a->archive, errno,
    +-				    "Invalid NFSv4 ACL entry type");
    +-				return (ARCHIVE_WARN);
    +-			}
    +-#endif	/* HAVE_ACL_TYPE_NFS4 */
    +-
    +-			/*
    +-			 * Libarchive stores "flag" (NFSv4 inheritance bits)
    +-			 * in the ae_perm bitmap.
    +-			 *
    +-			 * acl_get_flagset_np() fails with non-NFSv4 ACLs
    +-			 */
    +-			if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
    +-				archive_set_error(&a->archive, errno,
    +-				    "Failed to get flagset from a NFSv4 ACL entry");
    +-				return (ARCHIVE_WARN);
    +-			}
    +-			for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
    +-				r = acl_get_flag_np(acl_flagset,
    +-				    acl_inherit_map[i].platform_inherit);
    +-				if (r == -1) {
    +-					archive_set_error(&a->archive, errno,
    +-					    "Failed to check flag in a NFSv4 "
    +-					    "ACL flagset");
    +-					return (ARCHIVE_WARN);
    +-				} else if (r)
    +-					ae_perm |= acl_inherit_map[i].archive_inherit;
    +-			}
    +-		}
    +-#endif	/* HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL */
    +-
    +-		if (acl_get_permset(acl_entry, &acl_permset) != 0) {
    +-			archive_set_error(&a->archive, errno,
    +-			    "Failed to get ACL permission set");
    +-			return (ARCHIVE_WARN);
    +-		}
    +-		for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
    +-			/*
    +-			 * acl_get_perm() is spelled differently on different
    +-			 * platforms; see above.
    +-			 */
    +-			r = ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm);
    +-			if (r == -1) {
    +-				archive_set_error(&a->archive, errno,
    +-				    "Failed to check permission in an ACL permission set");
    +-				return (ARCHIVE_WARN);
    +-			} else if (r)
    +-				ae_perm |= acl_perm_map[i].archive_perm;
    +-		}
    +-
    +-		archive_entry_acl_add_entry(entry, entry_acl_type,
    +-					    ae_perm, ae_tag,
    +-					    ae_id, ae_name);
    +-
    +-		s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
    +-#if !HAVE_DARWIN_ACL
    +-		if (s == -1) {
    +-			archive_set_error(&a->archive, errno,
    +-			    "Failed to get next ACL entry");
    +-			return (ARCHIVE_WARN);
    +-		}
    +-#endif
    +-	}
    +-	return (ARCHIVE_OK);
    +-}
    +-#endif	/* !HAVE_SUN_ACL */
    +-#else	/* !HAVE_POSIX_ACL && !HAVE_NFS4_ACL */
    +-static int
    +-setup_acls(struct archive_read_disk *a,
    +-    struct archive_entry *entry, int *fd)
    +-{
    +-	(void)a;      /* UNUSED */
    +-	(void)entry;  /* UNUSED */
    +-	(void)fd;     /* UNUSED */
    +-	return (ARCHIVE_OK);
    +-}
    +-#endif	/* !HAVE_POSIX_ACL && !HAVE_NFS4_ACL */
    +-
    + #if (HAVE_FGETXATTR && HAVE_FLISTXATTR && HAVE_LISTXATTR && \
    +     HAVE_LLISTXATTR && HAVE_GETXATTR && HAVE_LGETXATTR) || \
    +     (HAVE_FGETEA && HAVE_FLISTEA && HAVE_LISTEA)
    +@@ -1499,21 +512,9 @@ setup_xattrs(struct archive_read_disk *a,
    + 	path = NULL;
    + 
    + 	if (*fd < 0) {
    +-		path = archive_entry_sourcepath(entry);
    +-		if (path == NULL || (a->tree != NULL &&
    +-		    a->tree_enter_working_dir(a->tree) != 0))
    +-			path = archive_entry_pathname(entry);
    +-		if (path == NULL) {
    +-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
    +-			    "Couldn't determine file path to read "
    +-			    "extended attributes");
    ++		path = archive_read_disk_entry_setup_path(a, entry, fd);
    ++		if (path == NULL)
    + 			return (ARCHIVE_WARN);
    +-		}
    +-		if (a->tree != NULL && (a->follow_symlinks ||
    +-		    archive_entry_filetype(entry) != AE_IFLNK)) {
    +-			*fd = a->open_on_current_dir(a->tree,
    +-			    path, O_RDONLY | O_NONBLOCK);
    +-		}
    + 	}
    + 
    + #if HAVE_FLISTXATTR
    +@@ -1658,21 +659,9 @@ setup_xattrs(struct archive_read_disk *a,
    + 	path = NULL;
    + 
    + 	if (*fd < 0) {
    +-		path = archive_entry_sourcepath(entry);
    +-		if (path == NULL || (a->tree != NULL &&
    +-		    a->tree_enter_working_dir(a->tree) != 0))
    +-			path = archive_entry_pathname(entry);
    +-		if (path == NULL) {
    +-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
    +-			    "Couldn't determine file path to read "
    +-			    "extended attributes");
    ++		path = archive_read_disk_entry_setup_path(a, entry, fd);
    ++		if (path == NULL)
    + 			return (ARCHIVE_WARN);
    +-		}
    +-		if (a->tree != NULL && (a->follow_symlinks ||
    +-		    archive_entry_filetype(entry) != AE_IFLNK)) {
    +-			*fd = a->open_on_current_dir(a->tree,
    +-			    path, O_RDONLY | O_NONBLOCK);
    +-		}
    + 	}
    + 
    + 	if (*fd >= 0)
    +@@ -1773,6 +762,7 @@ setup_sparse_fiemap(struct archive_read_disk *a,
    + 	int64_t size;
    + 	int count, do_fiemap, iters;
    + 	int exit_sts = ARCHIVE_OK;
    ++	const char *path;
    + 
    + 	if (archive_entry_filetype(entry) != AE_IFREG
    + 	    || archive_entry_size(entry) <= 0
    +@@ -1780,11 +770,10 @@ setup_sparse_fiemap(struct archive_read_disk *a,
    + 		return (ARCHIVE_OK);
    + 
    + 	if (*fd < 0) {
    +-		const char *path;
    +-
    +-		path = archive_entry_sourcepath(entry);
    ++		path = archive_read_disk_entry_setup_path(a, entry, NULL);
    + 		if (path == NULL)
    +-			path = archive_entry_pathname(entry);
    ++			return (ARCHIVE_FAILED);
    ++
    + 		if (a->tree != NULL)
    + 			*fd = a->open_on_current_dir(a->tree, path,
    + 				O_RDONLY | O_NONBLOCK | O_CLOEXEC);
    +@@ -1880,6 +869,7 @@ setup_sparse(struct archive_read_disk *a,
    + 	off_t off_s, off_e;
    + 	int exit_sts = ARCHIVE_OK;
    + 	int check_fully_sparse = 0;
    ++	const char *path;
    + 
    + 	if (archive_entry_filetype(entry) != AE_IFREG
    + 	    || archive_entry_size(entry) <= 0
    +@@ -1887,19 +877,10 @@ setup_sparse(struct archive_read_disk *a,
    + 		return (ARCHIVE_OK);
    + 
    + 	/* Does filesystem support the reporting of hole ? */
    +-	if (*fd < 0 && a->tree != NULL) {
    +-		const char *path;
    +-
    +-		path = archive_entry_sourcepath(entry);
    ++	if (*fd < 0) {
    ++		path = archive_read_disk_entry_setup_path(a, entry, fd);
    + 		if (path == NULL)
    +-			path = archive_entry_pathname(entry);
    +-		*fd = a->open_on_current_dir(a->tree, path,
    +-				O_RDONLY | O_NONBLOCK);
    +-		if (*fd < 0) {
    +-			archive_set_error(&a->archive, errno,
    +-			    "Can't open `%s'", path);
    + 			return (ARCHIVE_FAILED);
    +-		}
    + 	}
    + 
    + 	if (*fd >= 0) {
    +@@ -1911,12 +892,6 @@ setup_sparse(struct archive_read_disk *a,
    + 		if (initial_off != 0)
    + 			lseek(*fd, 0, SEEK_SET);
    + 	} else {
    +-		const char *path;
    +-
    +-		path = archive_entry_sourcepath(entry);
    +-		if (path == NULL)
    +-			path = archive_entry_pathname(entry);
    +-			
    + #ifdef _PC_MIN_HOLE_SIZE
    + 		if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0)
    + 			return (ARCHIVE_OK);
    +--- libarchive/archive_read_disk_private.h.orig
    ++++ libarchive/archive_read_disk_private.h
    +@@ -33,6 +33,8 @@
    + #ifndef ARCHIVE_READ_DISK_PRIVATE_H_INCLUDED
    + #define ARCHIVE_READ_DISK_PRIVATE_H_INCLUDED
    + 
    ++#include "archive_platform_acl.h"
    ++
    + struct tree;
    + struct archive_entry;
    + 
    +@@ -86,4 +88,11 @@ struct archive_read_disk {
    + 	void	*excluded_cb_data;
    + };
    + 
    ++const char *
    ++archive_read_disk_entry_setup_path(struct archive_read_disk *,
    ++    struct archive_entry *, int *);
    ++
    ++int
    ++archive_read_disk_entry_setup_acls(struct archive_read_disk *,
    ++    struct archive_entry *, int *);
    + #endif
    +--- libarchive/archive_read_format.3.orig
    ++++ libarchive/archive_read_format.3
    +@@ -37,9 +37,9 @@
    + .Nm archive_read_support_format_empty ,
    + .Nm archive_read_support_format_iso9660 ,
    + .Nm archive_read_support_format_lha ,
    +-.Nm archive_read_support_format_mtree,
    +-.Nm archive_read_support_format_rar,
    +-.Nm archive_read_support_format_raw,
    ++.Nm archive_read_support_format_mtree ,
    ++.Nm archive_read_support_format_rar ,
    ++.Nm archive_read_support_format_raw ,
    + .Nm archive_read_support_format_tar ,
    + .Nm archive_read_support_format_xar ,
    + .Nm archive_read_support_format_zip
    +--- libarchive/archive_read_open.3.orig
    ++++ libarchive/archive_read_open.3
    +@@ -33,7 +33,7 @@
    + .Nm archive_read_open_fd ,
    + .Nm archive_read_open_FILE ,
    + .Nm archive_read_open_filename ,
    +-.Nm archive_read_open_memory ,
    ++.Nm archive_read_open_memory
    + .Nd functions for reading streaming archives
    + .Sh LIBRARY
    + Streaming Archive Library (libarchive, -larchive)
    +--- libarchive/archive_read_support_format_mtree.c.orifg
    ++++ libarchive/archive_read_support_format_mtree.c
    +@@ -1857,33 +1857,38 @@ mtree_atol8(char **p)
    +  * Note that this implementation does not (and should not!) obey
    +  * locale settings; you cannot simply substitute strtol here, since
    +  * it does obey locale.
    ++ *
    ++ * Convert the number pointed to by 'p' into a 64-bit signed integer.
    ++ * On return, 'p' points to the first non-digit following the number.
    ++ * On overflow, the function returns INT64_MIN or INT64_MAX.
    +  */
    + static int64_t
    + mtree_atol10(char **p)
    + {
    +-	int64_t l, limit, last_digit_limit;
    +-	int base, digit, sign;
    +-
    +-	base = 10;
    ++	const int base = 10;
    ++	const int64_t limit = INT64_MAX / base;
    ++	const int64_t last_digit_limit = INT64_MAX % base;
    ++	int64_t l;
    ++	int sign;
    + 
    + 	if (**p == '-') {
    + 		sign = -1;
    +-		limit = ((uint64_t)(INT64_MAX) + 1) / base;
    +-		last_digit_limit = ((uint64_t)(INT64_MAX) + 1) % base;
    + 		++(*p);
    + 	} else {
    + 		sign = 1;
    +-		limit = INT64_MAX / base;
    +-		last_digit_limit = INT64_MAX % base;
    + 	}
    + 
    + 	l = 0;
    +-	digit = **p - '0';
    +-	while (digit >= 0 && digit < base) {
    +-		if (l > limit || (l == limit && digit > last_digit_limit))
    ++	while (**p >= '0' && **p < '0' + base) {
    ++		int digit = **p - '0';
    ++		if (l > limit || (l == limit && digit > last_digit_limit)) {
    ++			while (**p >= '0' && **p < '0' + base) {
    ++				++(*p);
    ++			}
    + 			return (sign < 0) ? INT64_MIN : INT64_MAX;
    ++		}
    + 		l = (l * base) + digit;
    +-		digit = *++(*p) - '0';
    ++		++(*p);
    + 	}
    + 	return (sign < 0) ? -l : l;
    + }
    +--- libarchive/archive_read_support_format_tar.c.orig
    ++++ libarchive/archive_read_support_format_tar.c
    +@@ -155,6 +155,7 @@ struct tar {
    + 	int			 compat_2x;
    + 	int			 process_mac_extensions;
    + 	int			 read_concatenated_archives;
    ++	int			 realsize_override;
    + };
    + 
    + static int	archive_block_is_null(const char *p);
    +@@ -527,6 +528,7 @@ archive_read_format_tar_read_header(struct archive_read *a,
    + 	tar->entry_offset = 0;
    + 	gnu_clear_sparse_list(tar);
    + 	tar->realsize = -1; /* Mark this as "unset" */
    ++	tar->realsize_override = 0;
    + 
    + 	/* Setup default string conversion. */
    + 	tar->sconv = tar->opt_sconv;
    +@@ -1894,6 +1896,7 @@ pax_attribute(struct archive_read *a, struct tar *tar,
    + 		if (strcmp(key, "GNU.sparse.size") == 0) {
    + 			tar->realsize = tar_atol10(value, strlen(value));
    + 			archive_entry_set_size(entry, tar->realsize);
    ++			tar->realsize_override = 1;
    + 		}
    + 
    + 		/* GNU "0.1" sparse pax format. */
    +@@ -1925,6 +1928,7 @@ pax_attribute(struct archive_read *a, struct tar *tar,
    + 		if (strcmp(key, "GNU.sparse.realsize") == 0) {
    + 			tar->realsize = tar_atol10(value, strlen(value));
    + 			archive_entry_set_size(entry, tar->realsize);
    ++			tar->realsize_override = 1;
    + 		}
    + 		break;
    + 	case 'L':
    +@@ -1977,6 +1981,7 @@ pax_attribute(struct archive_read *a, struct tar *tar,
    + 			    tar_atol10(value, strlen(value)));
    + 		} else if (strcmp(key, "SCHILY.realsize") == 0) {
    + 			tar->realsize = tar_atol10(value, strlen(value));
    ++			tar->realsize_override = 1;
    + 			archive_entry_set_size(entry, tar->realsize);
    + 		} else if (strncmp(key, "SCHILY.xattr.", 13) == 0) {
    + 			pax_attribute_schily_xattr(entry, key, value,
    +@@ -2055,14 +2060,12 @@ pax_attribute(struct archive_read *a, struct tar *tar,
    + 			tar->entry_bytes_remaining
    + 			    = tar_atol10(value, strlen(value));
    + 			/*
    +-			 * But, "size" is not necessarily the size of
    +-			 * the file on disk; if this is a sparse file,
    +-			 * the disk size may have already been set from
    +-			 * GNU.sparse.realsize or GNU.sparse.size or
    +-			 * an old GNU header field or SCHILY.realsize
    +-			 * or ....
    ++			 * The "size" pax header keyword always overrides the
    ++			 * "size" field in the tar header.
    ++			 * GNU.sparse.realsize, GNU.sparse.size and
    ++			 * SCHILY.realsize override this value.
    + 			 */
    +-			if (tar->realsize < 0) {
    ++			if (!tar->realsize_override) {
    + 				archive_entry_set_size(entry,
    + 				    tar->entry_bytes_remaining);
    + 				tar->realsize
    +@@ -2206,6 +2209,7 @@ header_gnutar(struct archive_read *a, struct tar *tar,
    + 		tar->realsize
    + 		    = tar_atol(header->realsize, sizeof(header->realsize));
    + 		archive_entry_set_size(entry, tar->realsize);
    ++		tar->realsize_override = 1;
    + 	}
    + 
    + 	if (header->sparse[0].offset[0] != 0) {
    +--- libarchive/archive_read_support_format_warc.c.orig
    ++++ libarchive/archive_read_support_format_warc.c
    +@@ -600,9 +600,10 @@ _warc_rdver(const char *buf, size_t bsz)
    + 	/* looks good so far, read the version number for a laugh */
    + 	buf += sizeof(magic) - 1U;
    + 
    +-	if (isdigit(buf[0U]) && (buf[1U] == '.') && isdigit(buf[2U])) {
    ++	if (isdigit((unsigned char)buf[0U]) && (buf[1U] == '.') &&
    ++	    isdigit((unsigned char)buf[2U])) {
    + 		/* we support a maximum of 2 digits in the minor version */
    +-		if (isdigit(buf[3U]))
    ++		if (isdigit((unsigned char)buf[3U]))
    + 			end = 1U;
    + 		/* set up major version */
    + 		ver = (buf[0U] - '0') * 10000U;
    +@@ -686,7 +687,7 @@ _warc_rduri(const char *buf, size_t bsz)
    + 
    + 	/* spaces inside uri are not allowed, CRLF should follow */
    + 	for (p = val; p < eol; p++) {
    +-		if (isspace(*p))
    ++		if (isspace((unsigned char)*p))
    + 			return res;
    + 	}
    + 
    +@@ -736,7 +737,7 @@ _warc_rdlen(const char *buf, size_t bsz)
    + 	while (val < eol && (*val == ' ' || *val == '\t'))
    + 		val++;
    + 	/* there must be at least one digit */
    +-	if (!isdigit(*val))
    ++	if (!isdigit((unsigned char)*val))
    + 		return -1;
    + 	len = strtol(val, &on, 10);
    + 	if (on != eol) {
    +--- libarchive/archive_read_support_format_zip.c.orig
    ++++ libarchive/archive_read_support_format_zip.c
    +@@ -2407,7 +2407,7 @@ read_eocd(struct zip *zip, const char *p, int64_t current_offset)
    +  * Examine Zip64 EOCD locator:  If it's valid, store the information
    +  * from it.
    +  */
    +-static void
    ++static int
    + read_zip64_eocd(struct archive_read *a, struct zip *zip, const char *p)
    + {
    + 	int64_t eocd64_offset;
    +@@ -2417,35 +2417,37 @@ read_zip64_eocd(struct archive_read *a, struct zip *zip, const char *p)
    + 
    + 	/* Central dir must be on first volume. */
    + 	if (archive_le32dec(p + 4) != 0)
    +-		return;
    ++		return 0;
    + 	/* Must be only a single volume. */
    + 	if (archive_le32dec(p + 16) != 1)
    +-		return;
    ++		return 0;
    + 
    + 	/* Find the Zip64 EOCD record. */
    + 	eocd64_offset = archive_le64dec(p + 8);
    + 	if (__archive_read_seek(a, eocd64_offset, SEEK_SET) < 0)
    +-		return;
    ++		return 0;
    + 	if ((p = __archive_read_ahead(a, 56, NULL)) == NULL)
    +-		return;
    ++		return 0;
    + 	/* Make sure we can read all of it. */
    + 	eocd64_size = archive_le64dec(p + 4) + 12;
    + 	if (eocd64_size < 56 || eocd64_size > 16384)
    +-		return;
    ++		return 0;
    + 	if ((p = __archive_read_ahead(a, (size_t)eocd64_size, NULL)) == NULL)
    +-		return;
    ++		return 0;
    + 
    + 	/* Sanity-check the EOCD64 */
    + 	if (archive_le32dec(p + 16) != 0) /* Must be disk #0 */
    +-		return;
    ++		return 0;
    + 	if (archive_le32dec(p + 20) != 0) /* CD must be on disk #0 */
    +-		return;
    ++		return 0;
    + 	/* CD can't be split. */
    + 	if (archive_le64dec(p + 24) != archive_le64dec(p + 32))
    +-		return;
    ++		return 0;
    + 
    + 	/* Save the central directory offset for later use. */
    + 	zip->central_directory_offset = archive_le64dec(p + 48);
    ++
    ++	return 32;
    + }
    + 
    + static int
    +@@ -2483,15 +2485,14 @@ archive_read_format_zip_seekable_bid(struct archive_read *a, int best_bid)
    + 			if (memcmp(p + i, "PK\005\006", 4) == 0) {
    + 				int ret = read_eocd(zip, p + i,
    + 				    current_offset + i);
    +-				if (ret > 0) {
    +-					/* Zip64 EOCD locator precedes
    +-					 * regular EOCD if present. */
    +-					if (i >= 20
    +-					    && memcmp(p + i - 20, "PK\006\007", 4) == 0) {
    +-						read_zip64_eocd(a, zip, p + i - 20);
    +-					}
    +-					return (ret);
    ++				/* Zip64 EOCD locator precedes
    ++				 * regular EOCD if present. */
    ++				if (i >= 20 && memcmp(p + i - 20, "PK\006\007", 4) == 0) {
    ++					int ret_zip64 = read_zip64_eocd(a, zip, p + i - 20);
    ++					if (ret_zip64 > ret)
    ++						ret = ret_zip64;
    + 				}
    ++				return (ret);
    + 			}
    + 			i -= 4;
    + 			break;
    +--- libarchive/archive_util.c.orig
    ++++ libarchive/archive_util.c
    +@@ -89,88 +89,6 @@ archive_version_string(void)
    + 	return (ARCHIVE_VERSION_STRING);
    + }
    + 
    +-const char *
    +-archive_version_details(void)
    +-{
    +-	static struct archive_string str;
    +-	static int init = 0;
    +-	const char *zlib = archive_zlib_version();
    +-	const char *liblzma = archive_liblzma_version();
    +-	const char *bzlib = archive_bzlib_version();
    +-	const char *liblz4 = archive_liblz4_version();
    +-
    +-	if (!init) {
    +-		archive_string_init(&str);
    +-
    +-		archive_strcat(&str, ARCHIVE_VERSION_STRING);
    +-		if (zlib != NULL) {
    +-			archive_strcat(&str, " zlib/");
    +-			archive_strcat(&str, zlib);
    +-		}
    +-		if (liblzma) {
    +-			archive_strcat(&str, " liblzma/");
    +-			archive_strcat(&str, liblzma);
    +-		}
    +-		if (bzlib) {
    +-			const char *p = bzlib;
    +-			const char *sep = strchr(p, ',');
    +-			if (sep == NULL)
    +-				sep = p + strlen(p);
    +-			archive_strcat(&str, " bz2lib/");
    +-			archive_strncat(&str, p, sep - p);
    +-		}
    +-		if (liblz4) {
    +-			archive_strcat(&str, " liblz4/");
    +-			archive_strcat(&str, liblz4);
    +-		}
    +-	}
    +-	return str.s;
    +-}
    +-
    +-const char *
    +-archive_zlib_version(void)
    +-{
    +-#ifdef HAVE_ZLIB_H
    +-	return ZLIB_VERSION;
    +-#else
    +-	return NULL;
    +-#endif
    +-}
    +-
    +-const char *
    +-archive_liblzma_version(void)
    +-{
    +-#ifdef HAVE_LZMA_H
    +-	return LZMA_VERSION_STRING;
    +-#else
    +-	return NULL;
    +-#endif
    +-}
    +-
    +-const char *
    +-archive_bzlib_version(void)
    +-{
    +-#ifdef HAVE_BZLIB_H
    +-	return BZ2_bzlibVersion();
    +-#else
    +-	return NULL;
    +-#endif
    +-}
    +-
    +-const char *
    +-archive_liblz4_version(void)
    +-{
    +-#if defined(HAVE_LZ4_H) && defined(HAVE_LIBLZ4)
    +-#define str(s) #s
    +-#define NUMBER(x) str(x)
    +-	return NUMBER(LZ4_VERSION_MAJOR) "." NUMBER(LZ4_VERSION_MINOR) "." NUMBER(LZ4_VERSION_RELEASE);
    +-#undef NUMBER
    +-#undef str
    +-#else
    +-	return NULL;
    +-#endif
    +-}
    +-
    + int
    + archive_errno(struct archive *a)
    + {
    +--- /dev/null
    ++++ libarchive/archive_version_details.c
    +@@ -0,0 +1,133 @@
    ++/*-
    ++ * Copyright (c) 2009-2012,2014 Michihiro NAKAJIMA
    ++ * Copyright (c) 2003-2007 Tim Kientzle
    ++ * All rights reserved.
    ++ *
    ++ * Redistribution and use in source and binary forms, with or without
    ++ * modification, are permitted provided that the following conditions
    ++ * are met:
    ++ * 1. Redistributions of source code must retain the above copyright
    ++ *    notice, this list of conditions and the following disclaimer.
    ++ * 2. Redistributions in binary form must reproduce the above copyright
    ++ *    notice, this list of conditions and the following disclaimer in the
    ++ *    documentation and/or other materials provided with the distribution.
    ++ *
    ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
    ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    ++ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
    ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    ++ */
    ++
    ++#include "archive_platform.h"
    ++__FBSDID("$FreeBSD: head/lib/libarchive/archive_util.c 201098 2009-12-28 02:58:14Z kientzle $");
    ++
    ++#ifdef HAVE_STDLIB_H
    ++#include <stdlib.h>
    ++#endif
    ++#ifdef HAVE_STRING_H
    ++#include <string.h>
    ++#endif
    ++#ifdef HAVE_ZLIB_H
    ++#include <zlib.h>
    ++#endif
    ++#ifdef HAVE_LZMA_H
    ++#include <lzma.h>
    ++#endif
    ++#ifdef HAVE_BZLIB_H
    ++#include <bzlib.h>
    ++#endif
    ++#ifdef HAVE_LZ4_H
    ++#include <lz4.h>
    ++#endif
    ++
    ++#include "archive.h"
    ++#include "archive_private.h"
    ++#include "archive_string.h"
    ++
    ++const char *
    ++archive_version_details(void)
    ++{
    ++	static struct archive_string str;
    ++	static int init = 0;
    ++	const char *zlib = archive_zlib_version();
    ++	const char *liblzma = archive_liblzma_version();
    ++	const char *bzlib = archive_bzlib_version();
    ++	const char *liblz4 = archive_liblz4_version();
    ++
    ++	if (!init) {
    ++		archive_string_init(&str);
    ++
    ++		archive_strcat(&str, ARCHIVE_VERSION_STRING);
    ++		if (zlib != NULL) {
    ++			archive_strcat(&str, " zlib/");
    ++			archive_strcat(&str, zlib);
    ++		}
    ++		if (liblzma) {
    ++			archive_strcat(&str, " liblzma/");
    ++			archive_strcat(&str, liblzma);
    ++		}
    ++		if (bzlib) {
    ++			const char *p = bzlib;
    ++			const char *sep = strchr(p, ',');
    ++			if (sep == NULL)
    ++				sep = p + strlen(p);
    ++			archive_strcat(&str, " bz2lib/");
    ++			archive_strncat(&str, p, sep - p);
    ++		}
    ++		if (liblz4) {
    ++			archive_strcat(&str, " liblz4/");
    ++			archive_strcat(&str, liblz4);
    ++		}
    ++	}
    ++	return str.s;
    ++}
    ++
    ++const char *
    ++archive_zlib_version(void)
    ++{
    ++#ifdef HAVE_ZLIB_H
    ++	return ZLIB_VERSION;
    ++#else
    ++	return NULL;
    ++#endif
    ++}
    ++
    ++const char *
    ++archive_liblzma_version(void)
    ++{
    ++#ifdef HAVE_LZMA_H
    ++	return LZMA_VERSION_STRING;
    ++#else
    ++	return NULL;
    ++#endif
    ++}
    ++
    ++const char *
    ++archive_bzlib_version(void)
    ++{
    ++#ifdef HAVE_BZLIB_H
    ++	return BZ2_bzlibVersion();
    ++#else
    ++	return NULL;
    ++#endif
    ++}
    ++
    ++const char *
    ++archive_liblz4_version(void)
    ++{
    ++#if defined(HAVE_LZ4_H) && defined(HAVE_LIBLZ4)
    ++#define str(s) #s
    ++#define NUMBER(x) str(x)
    ++	return NUMBER(LZ4_VERSION_MAJOR) "." NUMBER(LZ4_VERSION_MINOR) "." NUMBER(LZ4_VERSION_RELEASE);
    ++#undef NUMBER
    ++#undef str
    ++#else
    ++	return NULL;
    ++#endif
    ++}
    +--- libarchive/archive_write_data.3.orig
    ++++ libarchive/archive_write_data.3
    +@@ -24,11 +24,12 @@
    + .\"
    + .\" $FreeBSD$
    + .\"
    +-.Dd February 2, 2012
    ++.Dd February 28, 2017
    + .Dt ARCHIVE_WRITE_DATA 3
    + .Os
    + .Sh NAME
    +-.Nm archive_write_data
    ++.Nm archive_write_data ,
    ++.Nm archive_write_data_block
    + .Nd functions for creating archives
    + .Sh LIBRARY
    + Streaming Archive Library (libarchive, -larchive)
    +@@ -36,8 +37,27 @@ Streaming Archive Library (libarchive, -larchive)
    + .In archive.h
    + .Ft la_ssize_t
    + .Fn archive_write_data "struct archive *" "const void *" "size_t"
    ++.Ft la_ssize_t
    ++.Fn archive_write_data_block "struct archive *" "const void *" "size_t size" "int64_t offset"
    + .Sh DESCRIPTION
    ++.Bl -tag -width indent
    ++.It Fn archive_write_data
    ++Write data corresponding to the header just written.
    ++.It Fn archive_write_data_block
    + Write data corresponding to the header just written.
    ++This is like
    ++.Fn archive_write_data
    ++except that it performs a seek on the file being
    ++written to the specified offset before writing the data.
    ++This is useful when restoring sparse files from archive
    ++formats that support sparse files.
    ++Returns number of bytes written or -1 on error.
    ++(Note: This is currently not supported for
    ++.Tn archive_write
    ++handles, only for
    ++.Tn archive_write_disk
    ++handles.
    ++.El
    + .\" .Sh EXAMPLE
    + .\"
    + .Sh RETURN VALUES
    +--- libarchive/archive_write_disk.3.orig
    ++++ libarchive/archive_write_disk.3
    +@@ -24,7 +24,7 @@
    + .\"
    + .\" $FreeBSD$
    + .\"
    +-.Dd February 2, 2012
    ++.Dd February 28, 2017
    + .Dt ARCHIVE_WRITE_DISK 3
    + .Os
    + .Sh NAME
    +@@ -33,14 +33,7 @@
    + .Nm archive_write_disk_set_skip_file ,
    + .Nm archive_write_disk_set_group_lookup ,
    + .Nm archive_write_disk_set_standard_lookup ,
    +-.Nm archive_write_disk_set_user_lookup ,
    +-.Nm archive_write_header ,
    +-.Nm archive_write_data ,
    +-.Nm archive_write_data_block ,
    +-.Nm archive_write_finish_entry ,
    +-.Nm archive_write_close ,
    +-.Nm archive_write_finish
    +-.Nm archive_write_free
    ++.Nm archive_write_disk_set_user_lookup
    + .Nd functions for creating objects on disk
    + .Sh LIBRARY
    + Streaming Archive Library (libarchive, -larchive)
    +@@ -68,20 +61,6 @@ Streaming Archive Library (libarchive, -larchive)
    + .Fa "uid_t (*)(void *, const char *uname, uid_t uid)"
    + .Fa "void (*cleanup)(void *)"
    + .Fc
    +-.Ft int
    +-.Fn archive_write_header "struct archive *" "struct archive_entry *"
    +-.Ft la_ssize_t
    +-.Fn archive_write_data "struct archive *" "const void *" "size_t"
    +-.Ft la_ssize_t
    +-.Fn archive_write_data_block "struct archive *" "const void *" "size_t size" "int64_t offset"
    +-.Ft int
    +-.Fn archive_write_finish_entry "struct archive *"
    +-.Ft int
    +-.Fn archive_write_close "struct archive *"
    +-.Ft int
    +-.Fn archive_write_finish "struct archive *"
    +-.Ft int
    +-.Fn archive_write_free "struct archive *"
    + .Sh DESCRIPTION
    + These functions provide a complete API for creating objects on
    + disk from
    +@@ -223,60 +202,6 @@ the number of calls to
    + .Xr getpwnam 3
    + and
    + .Xr getgrnam 3 .
    +-.It Fn archive_write_header
    +-Build and write a header using the data in the provided
    +-.Tn struct archive_entry
    +-structure.
    +-See
    +-.Xr archive_entry 3
    +-for information on creating and populating
    +-.Tn struct archive_entry
    +-objects.
    +-.It Fn archive_write_data
    +-Write data corresponding to the header just written.
    +-Returns number of bytes written or -1 on error.
    +-.It Fn archive_write_data_block
    +-Write data corresponding to the header just written.
    +-This is like
    +-.Fn archive_write_data
    +-except that it performs a seek on the file being
    +-written to the specified offset before writing the data.
    +-This is useful when restoring sparse files from archive
    +-formats that support sparse files.
    +-Returns number of bytes written or -1 on error.
    +-(Note: This is currently not supported for
    +-.Tn archive_write
    +-handles, only for
    +-.Tn archive_write_disk
    +-handles.)
    +-.It Fn archive_write_finish_entry
    +-Close out the entry just written.
    +-Ordinarily, clients never need to call this, as it
    +-is called automatically by
    +-.Fn archive_write_next_header
    +-and
    +-.Fn archive_write_close
    +-as needed.
    +-However, some file attributes are written to disk only
    +-after the file is closed, so this can be necessary
    +-if you need to work with the file on disk right away.
    +-.It Fn archive_write_close
    +-Set any attributes that could not be set during the initial restore.
    +-For example, directory timestamps are not restored initially because
    +-restoring a subsequent file would alter that timestamp.
    +-Similarly, non-writable directories are initially created with
    +-write permissions (so that their contents can be restored).
    +-The
    +-.Nm
    +-library maintains a list of all such deferred attributes and
    +-sets them when this function is invoked.
    +-.It Fn archive_write_finish
    +-This is a deprecated synonym for
    +-.Fn archive_write_free .
    +-.It Fn archive_write_free
    +-Invokes
    +-.Fn archive_write_close
    +-if it was not invoked manually, then releases all resources.
    + .El
    + More information about the
    + .Va struct archive
    +--- libarchive/archive_write_disk_acl.c
    ++++ /dev/null
    +@@ -1,654 +0,0 @@
    +-/*-
    +- * Copyright (c) 2003-2010 Tim Kientzle
    +- * All rights reserved.
    +- *
    +- * Redistribution and use in source and binary forms, with or without
    +- * modification, are permitted provided that the following conditions
    +- * are met:
    +- * 1. Redistributions of source code must retain the above copyright
    +- *    notice, this list of conditions and the following disclaimer
    +- *    in this position and unchanged.
    +- * 2. Redistributions in binary form must reproduce the above copyright
    +- *    notice, this list of conditions and the following disclaimer in the
    +- *    documentation and/or other materials provided with the distribution.
    +- *
    +- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
    +- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    +- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    +- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
    +- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    +- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    +- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    +- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    +- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    +- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    +- */
    +-
    +-#include "archive_platform.h"
    +-__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_disk.c 201159 2009-12-29 05:35:40Z kientzle $");
    +-
    +-#ifdef HAVE_SYS_TYPES_H
    +-#include <sys/types.h>
    +-#endif
    +-#ifdef HAVE_SYS_ACL_H
    +-#define _ACL_PRIVATE /* For debugging */
    +-#include <sys/acl.h>
    +-#endif
    +-#if HAVE_DARWIN_ACL
    +-#include <membership.h>
    +-#endif
    +-#ifdef HAVE_ERRNO_H
    +-#include <errno.h>
    +-#endif
    +-
    +-#include "archive.h"
    +-#include "archive_entry.h"
    +-#include "archive_acl_private.h"
    +-#include "archive_write_disk_private.h"
    +-
    +-#if !HAVE_POSIX_ACL && !HAVE_NFS4_ACL
    +-/* Default empty function body to satisfy mainline code. */
    +-int
    +-archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
    +-	 struct archive_acl *abstract_acl)
    +-{
    +-	(void)a; /* UNUSED */
    +-	(void)fd; /* UNUSED */
    +-	(void)name; /* UNUSED */
    +-	(void)abstract_acl; /* UNUSED */
    +-	return (ARCHIVE_OK);
    +-}
    +-
    +-#else /* HAVE_POSIX_ACL || HAVE_NFS4_ACL */
    +-
    +-#if HAVE_SUN_ACL
    +-#define	ARCHIVE_PLATFORM_ACL_TYPE_NFS4	ACE_T
    +-#elif HAVE_DARWIN_ACL
    +-#define	ARCHIVE_PLATFORM_ACL_TYPE_NFS4	ACL_TYPE_EXTENDED
    +-#elif HAVE_ACL_TYPE_NFS4
    +-#define	ARCHIVE_PLATFORM_ACL_TYPE_NFS4	ACL_TYPE_NFS4
    +-#endif
    +-
    +-static int	set_acl(struct archive *, int fd, const char *,
    +-			struct archive_acl *,
    +-			acl_type_t, int archive_entry_acl_type, const char *tn);
    +-
    +-int
    +-archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
    +-	 struct archive_acl *abstract_acl)
    +-{
    +-	int		ret = ARCHIVE_OK;
    +-
    +-#if !HAVE_DARWIN_ACL
    +-	if ((archive_acl_types(abstract_acl)
    +-	    & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
    +-#if HAVE_SUN_ACL
    +-		/* Solaris writes POSIX.1e access and default ACLs together */
    +-		ret = set_acl(a, fd, name, abstract_acl, ACLENT_T,
    +-		    ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, "posix1e");
    +-#else	/* HAVE_POSIX_ACL */
    +-		if ((archive_acl_types(abstract_acl)
    +-		    & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
    +-			ret = set_acl(a, fd, name, abstract_acl,
    +-			    ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
    +-			    "access");
    +-			if (ret != ARCHIVE_OK)
    +-				return (ret);
    +-		}
    +-		if ((archive_acl_types(abstract_acl)
    +-		    & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
    +-			ret = set_acl(a, fd, name, abstract_acl,
    +-			    ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT,
    +-			    "default");
    +-#endif	/* !HAVE_SUN_ACL */
    +-		/* Simultaneous POSIX.1e and NFSv4 is not supported */
    +-		return (ret);
    +-	}
    +-#endif	/* !HAVE_DARWIN_ACL */
    +-#if HAVE_NFS4_ACL
    +-	if ((archive_acl_types(abstract_acl) &
    +-	    ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
    +-		ret = set_acl(a, fd, name, abstract_acl,
    +-		    ARCHIVE_PLATFORM_ACL_TYPE_NFS4,
    +-		    ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
    +-	}
    +-#endif	/* HAVE_NFS4_ACL */
    +-	return (ret);
    +-}
    +-
    +-/*
    +- * Translate system ACL permissions into libarchive internal structure
    +- */
    +-static const struct {
    +-	const int archive_perm;
    +-	const int platform_perm;
    +-} acl_perm_map[] = {
    +-#if HAVE_SUN_ACL	/* Solaris NFSv4 ACL permissions */
    +-	{ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE},
    +-	{ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA},
    +-	{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA},
    +-	{ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE},
    +-	{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA},
    +-	{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY},
    +-	{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS},
    +-	{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD},
    +-	{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES},
    +-	{ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE},
    +-	{ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER},
    +-	{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE}
    +-#elif HAVE_DARWIN_ACL	/* MacOS ACL permissions */
    +-	{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
    +-	{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
    +-	{ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
    +-	{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
    +-	{ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
    +-	{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
    +-	{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
    +-	{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
    +-	{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
    +-	{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES},
    +-	{ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER},
    +-	{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
    +-#else	/* POSIX.1e ACL permissions */
    +-	{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
    +-	{ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
    +-	{ARCHIVE_ENTRY_ACL_READ, ACL_READ},
    +-#if HAVE_ACL_TYPE_NFS4	/* FreeBSD NFSv4 ACL permissions */
    +-	{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
    +-	{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
    +-	{ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
    +-	{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
    +-	{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
    +-	{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
    +-	{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
    +-	{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
    +-	{ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
    +-	{ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
    +-	{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
    +-	{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
    +-#endif
    +-#endif	/* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
    +-};
    +-
    +-#if HAVE_NFS4_ACL
    +-/*
    +- * Translate system NFSv4 inheritance flags into libarchive internal structure
    +- */
    +-static const struct {
    +-	const int archive_inherit;
    +-	const int platform_inherit;
    +-} acl_inherit_map[] = {
    +-#if HAVE_SUN_ACL	/* Solaris NFSv4 inheritance flags */
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}
    +-#elif HAVE_DARWIN_ACL	/* MacOS NFSv4 inheritance flags */
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_LIMIT_INHERIT},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT}
    +-#else	/* FreeBSD NFSv4 ACL inheritance flags */
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
    +-	{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}
    +-#endif	/* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
    +-};
    +-#endif	/* HAVE_NFS4_ACL */
    +-
    +-static int
    +-set_acl(struct archive *a, int fd, const char *name,
    +-    struct archive_acl *abstract_acl,
    +-    acl_type_t acl_type, int ae_requested_type, const char *tname)
    +-{
    +-#if HAVE_SUN_ACL
    +-	aclent_t	 *aclent;
    +-	ace_t		 *ace;
    +-	int		 e, r;
    +-	acl_t		 *acl;
    +-#else
    +-	acl_t		 acl;
    +-	acl_entry_t	 acl_entry;
    +-	acl_permset_t	 acl_permset;
    +-#if HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL
    +-	acl_flagset_t	 acl_flagset;
    +-#endif
    +-#endif	/* HAVE_SUN_ACL */
    +-#if HAVE_ACL_TYPE_NFS4
    +-	int		r;
    +-#endif
    +-	int		 ret;
    +-	int		 ae_type, ae_permset, ae_tag, ae_id;
    +-#if HAVE_DARWIN_ACL
    +-	uuid_t		ae_uuid;
    +-#endif
    +-	uid_t		 ae_uid;
    +-	gid_t		 ae_gid;
    +-	const char	*ae_name;
    +-	int		 entries;
    +-	int		 i;
    +-
    +-	ret = ARCHIVE_OK;
    +-	entries = archive_acl_reset(abstract_acl, ae_requested_type);
    +-	if (entries == 0)
    +-		return (ARCHIVE_OK);
    +-
    +-#if HAVE_SUN_ACL
    +-	acl = NULL;
    +-	acl = malloc(sizeof(acl_t));
    +-	if (acl == NULL) {
    +-		archive_set_error(a, ARCHIVE_ERRNO_MISC,
    +-			"Invalid ACL type");
    +-		return (ARCHIVE_FAILED);
    +-	}
    +-	if (acl_type == ACE_T)
    +-		acl->acl_entry_size = sizeof(ace_t);
    +-	else if (acl_type == ACLENT_T)
    +-		acl->acl_entry_size = sizeof(aclent_t);
    +-	else {
    +-		archive_set_error(a, ARCHIVE_ERRNO_MISC,
    +-			"Invalid ACL type");
    +-		acl_free(acl);
    +-		return (ARCHIVE_FAILED);
    +-	}
    +-	acl->acl_type = acl_type;
    +-	acl->acl_cnt = entries;
    +-
    +-	acl->acl_aclp = malloc(entries * acl->acl_entry_size);
    +-	if (acl->acl_aclp == NULL) {
    +-		archive_set_error(a, errno,
    +-		    "Can't allocate memory for acl buffer");
    +-		acl_free(acl);
    +-		return (ARCHIVE_FAILED);
    +-	}
    +-#else	/* !HAVE_SUN_ACL */
    +-	acl = acl_init(entries);
    +-	if (acl == (acl_t)NULL) {
    +-		archive_set_error(a, errno,
    +-		    "Failed to initialize ACL working storage");
    +-		return (ARCHIVE_FAILED);
    +-	}
    +-#endif	/* !HAVE_SUN_ACL */
    +-#if HAVE_SUN_ACL
    +-	e = 0;
    +-#endif
    +-	while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
    +-		   &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
    +-#if HAVE_SUN_ACL
    +-		ace = NULL;
    +-		aclent = NULL;
    +-		if (acl->acl_type == ACE_T)  {
    +-			ace = &((ace_t *)acl->acl_aclp)[e];
    +-			ace->a_who = -1;
    +-			ace->a_access_mask = 0;
    +-			ace->a_flags = 0;
    +-		} else {
    +-			aclent = &((aclent_t *)acl->acl_aclp)[e];
    +-			aclent->a_id = -1;
    +-			aclent->a_type = 0;
    +-			aclent->a_perm = 0;
    +-		}
    +-#else	/* !HAVE_SUN_ACL  */
    +-#if HAVE_DARWIN_ACL
    +-		/*
    +-		 * Mac OS doesn't support NFSv4 ACLs for
    +-		 * owner@, group@ and everyone@.
    +-		 * We skip any of these ACLs found.
    +-		 */
    +-		if (ae_tag == ARCHIVE_ENTRY_ACL_USER_OBJ ||
    +-		    ae_tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ ||
    +-		    ae_tag == ARCHIVE_ENTRY_ACL_EVERYONE)
    +-			continue;
    +-#endif
    +-		if (acl_create_entry(&acl, &acl_entry) != 0) {
    +-			archive_set_error(a, errno,
    +-			    "Failed to create a new ACL entry");
    +-			ret = ARCHIVE_FAILED;
    +-			goto exit_free;
    +-		}
    +-#endif	/* !HAVE_SUN_ACL */
    +-#if HAVE_DARWIN_ACL
    +-		switch (ae_type) {
    +-		case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
    +-			acl_set_tag_type(acl_entry, ACL_EXTENDED_ALLOW);
    +-			break;
    +-		case ARCHIVE_ENTRY_ACL_TYPE_DENY:
    +-			acl_set_tag_type(acl_entry, ACL_EXTENDED_DENY);
    +-			break;
    +-		default:
    +-			/* We don't support any other types on MacOS */
    +-			continue;
    +-		}
    +-#endif
    +-		switch (ae_tag) {
    +-#if HAVE_SUN_ACL
    +-		case ARCHIVE_ENTRY_ACL_USER:
    +-			ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
    +-			if (acl->acl_type == ACE_T)
    +-				ace->a_who = ae_uid;
    +-			else {
    +-				aclent->a_id = ae_uid;
    +-				aclent->a_type |= USER;
    +-			}
    +-			break;
    +-		case ARCHIVE_ENTRY_ACL_GROUP:
    +-			ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
    +-			if (acl->acl_type == ACE_T) {
    +-				ace->a_who = ae_gid;
    +-				ace->a_flags |= ACE_IDENTIFIER_GROUP;
    +-			} else {
    +-				aclent->a_id = ae_gid;
    +-				aclent->a_type |= GROUP;
    +-			}
    +-			break;
    +-		case ARCHIVE_ENTRY_ACL_USER_OBJ:
    +-			if (acl->acl_type == ACE_T)
    +-				ace->a_flags |= ACE_OWNER;
    +-			else
    +-				aclent->a_type |= USER_OBJ;
    +-			break;
    +-		case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
    +-			if (acl->acl_type == ACE_T) {
    +-				ace->a_flags |= ACE_GROUP;
    +-				ace->a_flags |= ACE_IDENTIFIER_GROUP;
    +-			} else
    +-				aclent->a_type |= GROUP_OBJ;
    +-			break;
    +-		case ARCHIVE_ENTRY_ACL_MASK:
    +-			aclent->a_type |= CLASS_OBJ;
    +-			break;
    +-		case ARCHIVE_ENTRY_ACL_OTHER:
    +-			aclent->a_type |= OTHER_OBJ;
    +-			break;
    +-		case ARCHIVE_ENTRY_ACL_EVERYONE:
    +-			ace->a_flags |= ACE_EVERYONE;
    +-			break;
    +-#else	/* !HAVE_SUN_ACL */
    +-		case ARCHIVE_ENTRY_ACL_USER:
    +-			ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
    +-#if !HAVE_DARWIN_ACL	/* FreeBSD, Linux */
    +-			acl_set_tag_type(acl_entry, ACL_USER);
    +-			acl_set_qualifier(acl_entry, &ae_uid);
    +-#else	/* MacOS */
    +-			if (mbr_identifier_to_uuid(ID_TYPE_UID, &ae_uid,
    +-			    sizeof(uid_t), ae_uuid) != 0)
    +-				continue;
    +-			if (acl_set_qualifier(acl_entry, &ae_uuid) != 0)
    +-				continue;
    +-#endif	/* HAVE_DARWIN_ACL */
    +-			break;
    +-		case ARCHIVE_ENTRY_ACL_GROUP:
    +-			ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
    +-#if !HAVE_DARWIN_ACL	/* FreeBSD, Linux */
    +-			acl_set_tag_type(acl_entry, ACL_GROUP);
    +-			acl_set_qualifier(acl_entry, &ae_gid);
    +-#else	/* MacOS */
    +-			if (mbr_identifier_to_uuid(ID_TYPE_GID, &ae_gid,
    +-			    sizeof(gid_t), ae_uuid) != 0)
    +-				continue;
    +-			if (acl_set_qualifier(acl_entry, &ae_uuid) != 0)
    +-				continue;
    +-#endif	/* HAVE_DARWIN_ACL */
    +-			break;
    +-#if !HAVE_DARWIN_ACL	/* FreeBSD, Linux */
    +-		case ARCHIVE_ENTRY_ACL_USER_OBJ:
    +-			acl_set_tag_type(acl_entry, ACL_USER_OBJ);
    +-			break;
    +-		case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
    +-			acl_set_tag_type(acl_entry, ACL_GROUP_OBJ);
    +-			break;
    +-		case ARCHIVE_ENTRY_ACL_MASK:
    +-			acl_set_tag_type(acl_entry, ACL_MASK);
    +-			break;
    +-		case ARCHIVE_ENTRY_ACL_OTHER:
    +-			acl_set_tag_type(acl_entry, ACL_OTHER);
    +-			break;
    +-#if HAVE_ACL_TYPE_NFS4	/* FreeBSD only */
    +-		case ARCHIVE_ENTRY_ACL_EVERYONE:
    +-			acl_set_tag_type(acl_entry, ACL_EVERYONE);
    +-			break;
    +-#endif
    +-#endif	/* !HAVE_DARWIN_ACL */
    +-#endif	/* !HAVE_SUN_ACL */
    +-		default:
    +-			archive_set_error(a, ARCHIVE_ERRNO_MISC,
    +-			    "Unknown ACL tag");
    +-			ret = ARCHIVE_FAILED;
    +-			goto exit_free;
    +-		}
    +-
    +-#if HAVE_ACL_TYPE_NFS4 || HAVE_SUN_ACL
    +-		r = 0;
    +-		switch (ae_type) {
    +-#if HAVE_SUN_ACL
    +-		case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
    +-			if (ace != NULL)
    +-				ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
    +-			else
    +-				r = -1;
    +-			break;
    +-		case ARCHIVE_ENTRY_ACL_TYPE_DENY:
    +-			if (ace != NULL)
    +-				ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
    +-			else
    +-				r = -1;
    +-			break;
    +-		case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
    +-			if (ace != NULL)
    +-				ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE;
    +-			else
    +-				r = -1;
    +-			break;
    +-		case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
    +-			if (ace != NULL)
    +-				ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE;
    +-			else
    +-				r = -1;
    +-			break;
    +-		case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
    +-			if (aclent == NULL)
    +-				r = -1;
    +-			break;
    +-		case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
    +-			if (aclent != NULL)
    +-				aclent->a_type |= ACL_DEFAULT;
    +-			else
    +-				r = -1;
    +-			break;
    +-#else	/* !HAVE_SUN_ACL */
    +-		case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
    +-			r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW);
    +-			break;
    +-		case ARCHIVE_ENTRY_ACL_TYPE_DENY:
    +-			r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY);
    +-			break;
    +-		case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
    +-			r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT);
    +-			break;
    +-		case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
    +-			r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALARM);
    +-			break;
    +-		case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
    +-		case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
    +-			// These don't translate directly into the system ACL.
    +-			break;
    +-#endif	/* !HAVE_SUN_ACL */
    +-		default:
    +-			archive_set_error(a, ARCHIVE_ERRNO_MISC,
    +-			    "Unknown ACL entry type");
    +-			ret = ARCHIVE_FAILED;
    +-			goto exit_free;
    +-		}
    +-
    +-		if (r != 0) {
    +-#if HAVE_SUN_ACL
    +-			errno = EINVAL;
    +-#endif
    +-			archive_set_error(a, errno,
    +-			    "Failed to set ACL entry type");
    +-			ret = ARCHIVE_FAILED;
    +-			goto exit_free;
    +-		}
    +-#endif	/* HAVE_ACL_TYPE_NFS4 || HAVE_SUN_ACL */
    +-
    +-#if HAVE_SUN_ACL
    +-		if (acl->acl_type == ACLENT_T) {
    +-			if (ae_permset & ARCHIVE_ENTRY_ACL_EXECUTE)
    +-				aclent->a_perm |= 1;
    +-			if (ae_permset & ARCHIVE_ENTRY_ACL_WRITE)
    +-				aclent->a_perm |= 2;
    +-			if (ae_permset & ARCHIVE_ENTRY_ACL_READ)
    +-				aclent->a_perm |= 4;
    +-		} else
    +-#else
    +-		if (acl_get_permset(acl_entry, &acl_permset) != 0) {
    +-			archive_set_error(a, errno,
    +-			    "Failed to get ACL permission set");
    +-			ret = ARCHIVE_FAILED;
    +-			goto exit_free;
    +-		}
    +-		if (acl_clear_perms(acl_permset) != 0) {
    +-			archive_set_error(a, errno,
    +-			    "Failed to clear ACL permissions");
    +-			ret = ARCHIVE_FAILED;
    +-			goto exit_free;
    +-		}
    +-#endif	/* !HAVE_SUN_ACL */
    +-		for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
    +-			if (ae_permset & acl_perm_map[i].archive_perm) {
    +-#if HAVE_SUN_ACL
    +-				ace->a_access_mask |=
    +-				    acl_perm_map[i].platform_perm;
    +-#else
    +-				if (acl_add_perm(acl_permset,
    +-				    acl_perm_map[i].platform_perm) != 0) {
    +-					archive_set_error(a, errno,
    +-					    "Failed to add ACL permission");
    +-					ret = ARCHIVE_FAILED;
    +-					goto exit_free;
    +-				}
    +-#endif
    +-			}
    +-		}
    +-
    +-#if HAVE_NFS4_ACL
    +-#if HAVE_SUN_ACL
    +-		if (acl_type == ACE_T)
    +-#elif HAVE_DARWIN_ACL
    +-		if (acl_type == ACL_TYPE_EXTENDED)
    +-#else	/* FreeBSD */
    +-		if (acl_type == ACL_TYPE_NFS4)
    +-#endif
    +-		{
    +-#if HAVE_POSIX_ACL || HAVE_DARWIN_ACL
    +-			/*
    +-			 * acl_get_flagset_np() fails with non-NFSv4 ACLs
    +-			 */
    +-			if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
    +-				archive_set_error(a, errno,
    +-				    "Failed to get flagset from an NFSv4 ACL entry");
    +-				ret = ARCHIVE_FAILED;
    +-				goto exit_free;
    +-			}
    +-			if (acl_clear_flags_np(acl_flagset) != 0) {
    +-				archive_set_error(a, errno,
    +-				    "Failed to clear flags from an NFSv4 ACL flagset");
    +-				ret = ARCHIVE_FAILED;
    +-				goto exit_free;
    +-			}
    +-#endif /* HAVE_POSIX_ACL || HAVE_DARWIN_ACL */
    +-			for (i = 0; i < (int)(sizeof(acl_inherit_map) /sizeof(acl_inherit_map[0])); ++i) {
    +-				if (ae_permset & acl_inherit_map[i].archive_inherit) {
    +-#if HAVE_SUN_ACL
    +-					ace->a_flags |=
    +-					    acl_inherit_map[i].platform_inherit;
    +-#else	/* !HAVE_SUN_ACL */
    +-					if (acl_add_flag_np(acl_flagset,
    +-							acl_inherit_map[i].platform_inherit) != 0) {
    +-						archive_set_error(a, errno,
    +-						    "Failed to add flag to NFSv4 ACL flagset");
    +-						ret = ARCHIVE_FAILED;
    +-						goto exit_free;
    +-					}
    +-#endif	/* HAVE_SUN_ACL */
    +-				}
    +-			}
    +-		}
    +-#endif	/* HAVE_NFS4_ACL */
    +-#if HAVE_SUN_ACL
    +-	e++;
    +-#endif
    +-	}
    +-
    +-#if HAVE_ACL_SET_FD_NP || HAVE_ACL_SET_FD || HAVE_SUN_ACL
    +-	/* Try restoring the ACL through 'fd' if we can. */
    +-#if HAVE_SUN_ACL || HAVE_ACL_SET_FD_NP
    +-	if (fd >= 0)
    +-#else	/* !HAVE_SUN_ACL && !HAVE_ACL_SET_FD_NP */
    +-	if (fd >= 0 && acl_type == ACL_TYPE_ACCESS)
    +-#endif
    +-	{
    +-#if HAVE_SUN_ACL
    +-		if (facl_set(fd, acl) == 0)
    +-#elif HAVE_ACL_SET_FD_NP
    +-		if (acl_set_fd_np(fd, acl, acl_type) == 0)
    +-#else	/* !HAVE_SUN_ACL && !HAVE_ACL_SET_FD_NP */
    +-		if (acl_set_fd(fd, acl) == 0)
    +-#endif
    +-			ret = ARCHIVE_OK;
    +-		else {
    +-			if (errno == EOPNOTSUPP) {
    +-				/* Filesystem doesn't support ACLs */
    +-				ret = ARCHIVE_OK;
    +-			} else {
    +-				archive_set_error(a, errno,
    +-				    "Failed to set %s acl on fd", tname);
    +-			}
    +-		}
    +-	} else
    +-#endif	/* HAVE_ACL_SET_FD_NP || HAVE_ACL_SET_FD || HAVE_SUN_ACL */
    +-#if HAVE_SUN_ACL
    +-	if (acl_set(name, acl) != 0)
    +-#elif HAVE_ACL_SET_LINK_NP
    +-	if (acl_set_link_np(name, acl_type, acl) != 0)
    +-#else
    +-	/* TODO: Skip this if 'name' is a symlink. */
    +-	if (acl_set_file(name, acl_type, acl) != 0)
    +-#endif
    +-	{
    +-		if (errno == EOPNOTSUPP) {
    +-			/* Filesystem doesn't support ACLs */
    +-			ret = ARCHIVE_OK;
    +-		} else {
    +-			archive_set_error(a, errno, "Failed to set %s acl",
    +-			    tname);
    +-			ret = ARCHIVE_WARN;
    +-		}
    +-	}
    +-exit_free:
    +-	acl_free(acl);
    +-	return (ret);
    +-}
    +-#endif	/* HAVE_POSIX_ACL || HAVE_NFS4_ACL */
    +--- /dev/null
    ++++ libarchive/archive_write_disk_acl_darwin.c
    +@@ -0,0 +1,234 @@
    ++/*-
    ++ * Copyright (c) 2017 Martin Matuska
    ++ * All rights reserved.
    ++ *
    ++ * Redistribution and use in source and binary forms, with or without
    ++ * modification, are permitted provided that the following conditions
    ++ * are met:
    ++ * 1. Redistributions of source code must retain the above copyright
    ++ *    notice, this list of conditions and the following disclaimer
    ++ *    in this position and unchanged.
    ++ * 2. Redistributions in binary form must reproduce the above copyright
    ++ *    notice, this list of conditions and the following disclaimer in the
    ++ *    documentation and/or other materials provided with the distribution.
    ++ *
    ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
    ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    ++ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
    ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    ++ */
    ++
    ++#include "archive_platform.h"
    ++
    ++#ifdef HAVE_SYS_TYPES_H
    ++#include <sys/types.h>
    ++#endif
    ++#if HAVE_MEMBERSHIP_H
    ++#include <membership.h>
    ++#endif
    ++#ifdef HAVE_ERRNO_H
    ++#include <errno.h>
    ++#endif
    ++#ifdef HAVE_SYS_ACL_H
    ++#define _ACL_PRIVATE /* For debugging */
    ++#include <sys/acl.h>
    ++#endif
    ++
    ++#include "archive.h"
    ++#include "archive_entry.h"
    ++#include "archive_write_disk_private.h"
    ++#include "archive_acl_maps.h"
    ++
    ++static int
    ++set_acl(struct archive *a, int fd, const char *name,
    ++    struct archive_acl *abstract_acl,
    ++    int ae_requested_type, const char *tname)
    ++{
    ++	acl_t		 acl;
    ++	acl_entry_t	 acl_entry;
    ++	acl_permset_t	 acl_permset;
    ++	acl_flagset_t	 acl_flagset;
    ++	int		 ret;
    ++	int		 ae_type, ae_permset, ae_tag, ae_id;
    ++	uuid_t		 ae_uuid;
    ++	uid_t		 ae_uid;
    ++	gid_t		 ae_gid;
    ++	const char	*ae_name;
    ++	int		 entries;
    ++	int		 i;
    ++
    ++	ret = ARCHIVE_OK;
    ++	entries = archive_acl_reset(abstract_acl, ae_requested_type);
    ++	if (entries == 0)
    ++		return (ARCHIVE_OK);
    ++
    ++	if (ae_requested_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
    ++		errno = ENOENT;
    ++		archive_set_error(a, errno, "Unsupported ACL type");
    ++		return (ARCHIVE_FAILED);
    ++	}
    ++
    ++	acl = acl_init(entries);
    ++	if (acl == (acl_t)NULL) {
    ++		archive_set_error(a, errno,
    ++		    "Failed to initialize ACL working storage");
    ++		return (ARCHIVE_FAILED);
    ++	}
    ++
    ++	while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
    ++		   &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
    ++		/*
    ++		 * Mac OS doesn't support NFSv4 ACLs for
    ++		 * owner@, group@ and everyone@.
    ++		 * We skip any of these ACLs found.
    ++		 */
    ++		if (ae_tag == ARCHIVE_ENTRY_ACL_USER_OBJ ||
    ++		    ae_tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ ||
    ++		    ae_tag == ARCHIVE_ENTRY_ACL_EVERYONE)
    ++			continue;
    ++
    ++		if (acl_create_entry(&acl, &acl_entry) != 0) {
    ++			archive_set_error(a, errno,
    ++			    "Failed to create a new ACL entry");
    ++			ret = ARCHIVE_FAILED;
    ++			goto exit_free;
    ++		}
    ++
    ++		switch (ae_type) {
    ++		case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
    ++			acl_set_tag_type(acl_entry, ACL_EXTENDED_ALLOW);
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_TYPE_DENY:
    ++			acl_set_tag_type(acl_entry, ACL_EXTENDED_DENY);
    ++			break;
    ++		default:
    ++			/* We don't support any other types on MacOS */
    ++			continue;
    ++		}
    ++
    ++		switch (ae_tag) {
    ++		case ARCHIVE_ENTRY_ACL_USER:
    ++			ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
    ++			if (mbr_uid_to_uuid(ae_uid, ae_uuid) != 0)
    ++				continue;
    ++			if (acl_set_qualifier(acl_entry, &ae_uuid) != 0)
    ++				continue;
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_GROUP:
    ++			ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
    ++			if (mbr_gid_to_uuid(ae_gid, ae_uuid) != 0)
    ++				continue;
    ++			if (acl_set_qualifier(acl_entry, &ae_uuid) != 0)
    ++				continue;
    ++			break;
    ++		default:
    ++			archive_set_error(a, ARCHIVE_ERRNO_MISC,
    ++			    "Unsupported ACL tag");
    ++			ret = ARCHIVE_FAILED;
    ++			goto exit_free;
    ++		}
    ++
    ++		if (acl_get_permset(acl_entry, &acl_permset) != 0) {
    ++			archive_set_error(a, errno,
    ++			    "Failed to get ACL permission set");
    ++			ret = ARCHIVE_FAILED;
    ++			goto exit_free;
    ++		}
    ++		if (acl_clear_perms(acl_permset) != 0) {
    ++			archive_set_error(a, errno,
    ++			    "Failed to clear ACL permissions");
    ++			ret = ARCHIVE_FAILED;
    ++			goto exit_free;
    ++		}
    ++
    ++		for (i = 0; i < acl_nfs4_perm_map_size; ++i) {
    ++			if (ae_permset & acl_nfs4_perm_map[i].a_perm) {
    ++				if (acl_add_perm(acl_permset,
    ++				    acl_nfs4_perm_map[i].p_perm) != 0) {
    ++					archive_set_error(a, errno,
    ++					    "Failed to add ACL permission");
    ++					ret = ARCHIVE_FAILED;
    ++					goto exit_free;
    ++				}
    ++			}
    ++		}
    ++
    ++		/*
    ++		 * acl_get_flagset_np() fails with non-NFSv4 ACLs
    ++		 */
    ++		if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
    ++			archive_set_error(a, errno,
    ++			    "Failed to get flagset from an NFSv4 ACL entry");
    ++			ret = ARCHIVE_FAILED;
    ++			goto exit_free;
    ++		}
    ++		if (acl_clear_flags_np(acl_flagset) != 0) {
    ++			archive_set_error(a, errno,
    ++			    "Failed to clear flags from an NFSv4 ACL flagset");
    ++			ret = ARCHIVE_FAILED;
    ++			goto exit_free;
    ++		}
    ++
    ++		for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
    ++			if (ae_permset & acl_nfs4_flag_map[i].a_perm) {
    ++				if (acl_add_flag_np(acl_flagset,
    ++				    acl_nfs4_flag_map[i].p_perm) != 0) {
    ++					archive_set_error(a, errno,
    ++					    "Failed to add flag to "
    ++					    "NFSv4 ACL flagset");
    ++					ret = ARCHIVE_FAILED;
    ++					goto exit_free;
    ++				}
    ++			}
    ++		}
    ++	}
    ++
    ++	if (fd >= 0) {
    ++		if (acl_set_fd_np(fd, acl, ACL_TYPE_EXTENDED) == 0)
    ++			ret = ARCHIVE_OK;
    ++		else {
    ++			if (errno == EOPNOTSUPP) {
    ++				/* Filesystem doesn't support ACLs */
    ++				ret = ARCHIVE_OK;
    ++			} else {
    ++				archive_set_error(a, errno,
    ++				    "Failed to set acl on fd: %s", tname);
    ++				ret = ARCHIVE_WARN;
    ++			}
    ++		}
    ++	} else if (acl_set_link_np(name, ACL_TYPE_EXTENDED, acl) != 0) {
    ++		if (errno == EOPNOTSUPP) {
    ++			/* Filesystem doesn't support ACLs */
    ++			ret = ARCHIVE_OK;
    ++		} else {
    ++			archive_set_error(a, errno, "Failed to set acl: %s",
    ++			    tname);
    ++			ret = ARCHIVE_WARN;
    ++		}
    ++	}
    ++exit_free:
    ++	acl_free(acl);
    ++	return (ret);
    ++}
    ++
    ++int
    ++archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
    ++    struct archive_acl *abstract_acl, __LA_MODE_T mode)
    ++{
    ++	int		ret = ARCHIVE_OK;
    ++
    ++	(void)mode;	/* UNUSED */
    ++
    ++	if ((archive_acl_types(abstract_acl) &
    ++	    ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
    ++		ret = set_acl(a, fd, name, abstract_acl,
    ++		    ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
    ++	}
    ++	return (ret);
    ++}
    +--- /dev/null
    ++++ libarchive/archive_write_disk_acl_freebsd.c
    +@@ -0,0 +1,321 @@
    ++/*-
    ++ * Copyright (c) 2003-2010 Tim Kientzle
    ++ * All rights reserved.
    ++ *
    ++ * Redistribution and use in source and binary forms, with or without
    ++ * modification, are permitted provided that the following conditions
    ++ * are met:
    ++ * 1. Redistributions of source code must retain the above copyright
    ++ *    notice, this list of conditions and the following disclaimer
    ++ *    in this position and unchanged.
    ++ * 2. Redistributions in binary form must reproduce the above copyright
    ++ *    notice, this list of conditions and the following disclaimer in the
    ++ *    documentation and/or other materials provided with the distribution.
    ++ *
    ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
    ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    ++ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
    ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    ++ */
    ++
    ++#include "archive_platform.h"
    ++__FBSDID("$FreeBSD$");
    ++
    ++#ifdef HAVE_SYS_TYPES_H
    ++#include <sys/types.h>
    ++#endif
    ++#ifdef HAVE_ERRNO_H
    ++#include <errno.h>
    ++#endif
    ++#ifdef HAVE_SYS_ACL_H
    ++#define _ACL_PRIVATE /* For debugging */
    ++#include <sys/acl.h>
    ++#endif
    ++
    ++#include "archive.h"
    ++#include "archive_entry.h"
    ++#include "archive_write_disk_private.h"
    ++#include "archive_acl_maps.h"
    ++
    ++static int
    ++set_acl(struct archive *a, int fd, const char *name,
    ++    struct archive_acl *abstract_acl,
    ++    int ae_requested_type, const char *tname)
    ++{
    ++	int		 acl_type = 0;
    ++	acl_t		 acl;
    ++	acl_entry_t	 acl_entry;
    ++	acl_permset_t	 acl_permset;
    ++#if ARCHIVE_ACL_FREEBSD_NFS4
    ++	acl_flagset_t	 acl_flagset;
    ++	int		 r;
    ++#endif
    ++	int		 ret;
    ++	int		 ae_type, ae_permset, ae_tag, ae_id;
    ++	int		 perm_map_size;
    ++	const acl_perm_map_t	*perm_map;
    ++	uid_t		 ae_uid;
    ++	gid_t		 ae_gid;
    ++	const char	*ae_name;
    ++	int		 entries;
    ++	int		 i;
    ++
    ++	ret = ARCHIVE_OK;
    ++	entries = archive_acl_reset(abstract_acl, ae_requested_type);
    ++	if (entries == 0)
    ++		return (ARCHIVE_OK);
    ++
    ++
    ++	switch (ae_requested_type) {
    ++	case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
    ++		acl_type = ACL_TYPE_ACCESS;
    ++		break;
    ++	case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
    ++		acl_type = ACL_TYPE_DEFAULT;
    ++		break;
    ++#if ARCHIVE_ACL_FREEBSD_NFS4
    ++	case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
    ++		acl_type = ACL_TYPE_NFS4;
    ++		break;
    ++#endif
    ++	default:
    ++		errno = ENOENT;
    ++		archive_set_error(a, errno, "Unsupported ACL type");
    ++		return (ARCHIVE_FAILED);
    ++	}
    ++
    ++	acl = acl_init(entries);
    ++	if (acl == (acl_t)NULL) {
    ++		archive_set_error(a, errno,
    ++		    "Failed to initialize ACL working storage");
    ++		return (ARCHIVE_FAILED);
    ++	}
    ++
    ++	while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
    ++		   &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
    ++		if (acl_create_entry(&acl, &acl_entry) != 0) {
    ++			archive_set_error(a, errno,
    ++			    "Failed to create a new ACL entry");
    ++			ret = ARCHIVE_FAILED;
    ++			goto exit_free;
    ++		}
    ++		switch (ae_tag) {
    ++		case ARCHIVE_ENTRY_ACL_USER:
    ++			ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
    ++			acl_set_tag_type(acl_entry, ACL_USER);
    ++			acl_set_qualifier(acl_entry, &ae_uid);
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_GROUP:
    ++			ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
    ++			acl_set_tag_type(acl_entry, ACL_GROUP);
    ++			acl_set_qualifier(acl_entry, &ae_gid);
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_USER_OBJ:
    ++			acl_set_tag_type(acl_entry, ACL_USER_OBJ);
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
    ++			acl_set_tag_type(acl_entry, ACL_GROUP_OBJ);
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_MASK:
    ++			acl_set_tag_type(acl_entry, ACL_MASK);
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_OTHER:
    ++			acl_set_tag_type(acl_entry, ACL_OTHER);
    ++			break;
    ++#if ARCHIVE_ACL_FREEBSD_NFS4
    ++		case ARCHIVE_ENTRY_ACL_EVERYONE:
    ++			acl_set_tag_type(acl_entry, ACL_EVERYONE);
    ++			break;
    ++#endif
    ++		default:
    ++			archive_set_error(a, ARCHIVE_ERRNO_MISC,
    ++			    "Unsupported ACL tag");
    ++			ret = ARCHIVE_FAILED;
    ++			goto exit_free;
    ++		}
    ++
    ++#if ARCHIVE_ACL_FREEBSD_NFS4
    ++		r = 0;
    ++		switch (ae_type) {
    ++		case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
    ++			r = acl_set_entry_type_np(acl_entry,
    ++			    ACL_ENTRY_TYPE_ALLOW);
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_TYPE_DENY:
    ++			r = acl_set_entry_type_np(acl_entry,
    ++			    ACL_ENTRY_TYPE_DENY);
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
    ++			r = acl_set_entry_type_np(acl_entry,
    ++			    ACL_ENTRY_TYPE_AUDIT);
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
    ++			r = acl_set_entry_type_np(acl_entry,
    ++			    ACL_ENTRY_TYPE_ALARM);
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
    ++		case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
    ++			// These don't translate directly into the system ACL.
    ++			break;
    ++		default:
    ++			archive_set_error(a, ARCHIVE_ERRNO_MISC,
    ++			    "Unsupported ACL entry type");
    ++			ret = ARCHIVE_FAILED;
    ++			goto exit_free;
    ++		}
    ++
    ++		if (r != 0) {
    ++			archive_set_error(a, errno,
    ++			    "Failed to set ACL entry type");
    ++			ret = ARCHIVE_FAILED;
    ++			goto exit_free;
    ++		}
    ++#endif
    ++
    ++		if (acl_get_permset(acl_entry, &acl_permset) != 0) {
    ++			archive_set_error(a, errno,
    ++			    "Failed to get ACL permission set");
    ++			ret = ARCHIVE_FAILED;
    ++			goto exit_free;
    ++		}
    ++		if (acl_clear_perms(acl_permset) != 0) {
    ++			archive_set_error(a, errno,
    ++			    "Failed to clear ACL permissions");
    ++			ret = ARCHIVE_FAILED;
    ++			goto exit_free;
    ++		}
    ++#if ARCHIVE_ACL_FREEBSD_NFS4
    ++		if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
    ++			perm_map_size = acl_nfs4_perm_map_size;
    ++			perm_map = acl_nfs4_perm_map;
    ++		} else {
    ++#endif
    ++			perm_map_size = acl_posix_perm_map_size;
    ++			perm_map = acl_posix_perm_map;
    ++#if ARCHIVE_ACL_FREEBSD_NFS4
    ++		}
    ++#endif
    ++
    ++		for (i = 0; i < perm_map_size; ++i) {
    ++			if (ae_permset & perm_map[i].a_perm) {
    ++				if (acl_add_perm(acl_permset,
    ++				    perm_map[i].p_perm) != 0) {
    ++					archive_set_error(a, errno,
    ++					    "Failed to add ACL permission");
    ++					ret = ARCHIVE_FAILED;
    ++					goto exit_free;
    ++				}
    ++			}
    ++		}
    ++
    ++#if ARCHIVE_ACL_FREEBSD_NFS4
    ++		if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
    ++			/*
    ++			 * acl_get_flagset_np() fails with non-NFSv4 ACLs
    ++			 */
    ++			if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
    ++				archive_set_error(a, errno,
    ++				    "Failed to get flagset from an NFSv4 "
    ++				    "ACL entry");
    ++				ret = ARCHIVE_FAILED;
    ++				goto exit_free;
    ++			}
    ++			if (acl_clear_flags_np(acl_flagset) != 0) {
    ++				archive_set_error(a, errno,
    ++				    "Failed to clear flags from an NFSv4 "
    ++				    "ACL flagset");
    ++				ret = ARCHIVE_FAILED;
    ++				goto exit_free;
    ++			}
    ++			for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
    ++				if (ae_permset & acl_nfs4_flag_map[i].a_perm) {
    ++					if (acl_add_flag_np(acl_flagset,
    ++					    acl_nfs4_flag_map[i].p_perm) != 0) {
    ++						archive_set_error(a, errno,
    ++						    "Failed to add flag to "
    ++						    "NFSv4 ACL flagset");
    ++						ret = ARCHIVE_FAILED;
    ++						goto exit_free;
    ++					}
    ++				}
    ++			}
    ++		}
    ++#endif
    ++	}
    ++
    ++	/* Try restoring the ACL through 'fd' if we can. */
    ++	if (fd >= 0) {
    ++		if (acl_set_fd_np(fd, acl, acl_type) == 0)
    ++			ret = ARCHIVE_OK;
    ++		else {
    ++			if (errno == EOPNOTSUPP) {
    ++				/* Filesystem doesn't support ACLs */
    ++				ret = ARCHIVE_OK;
    ++			} else {
    ++				archive_set_error(a, errno,
    ++				    "Failed to set acl on fd: %s", tname);
    ++				ret = ARCHIVE_WARN;
    ++			}
    ++		}
    ++	}
    ++#if HAVE_ACL_SET_LINK_NP
    ++	else if (acl_set_link_np(name, acl_type, acl) != 0)
    ++#else
    ++	/* FreeBSD older than 8.0 */
    ++	else if (acl_set_file(name, acl_type, acl) != 0)
    ++#endif
    ++	{
    ++		if (errno == EOPNOTSUPP) {
    ++			/* Filesystem doesn't support ACLs */
    ++			ret = ARCHIVE_OK;
    ++		} else {
    ++			archive_set_error(a, errno, "Failed to set acl: %s",
    ++			    tname);
    ++			ret = ARCHIVE_WARN;
    ++		}
    ++	}
    ++exit_free:
    ++	acl_free(acl);
    ++	return (ret);
    ++}
    ++
    ++int
    ++archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
    ++    struct archive_acl *abstract_acl, __LA_MODE_T mode)
    ++{
    ++	int		ret = ARCHIVE_OK;
    ++
    ++	(void)mode;	/* UNUSED */
    ++
    ++	if ((archive_acl_types(abstract_acl)
    ++	    & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
    ++		if ((archive_acl_types(abstract_acl)
    ++		    & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
    ++			ret = set_acl(a, fd, name, abstract_acl,
    ++			    ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
    ++			if (ret != ARCHIVE_OK)
    ++				return (ret);
    ++		}
    ++		if ((archive_acl_types(abstract_acl)
    ++		    & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
    ++			ret = set_acl(a, fd, name, abstract_acl,
    ++			    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
    ++
    ++		/* Simultaneous POSIX.1e and NFSv4 is not supported */
    ++		return (ret);
    ++	}
    ++#if ARCHIVE_ACL_FREEBSD_NFS4
    ++	else if ((archive_acl_types(abstract_acl) &
    ++	    ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
    ++		ret = set_acl(a, fd, name, abstract_acl,
    ++		    ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
    ++	}
    ++#endif
    ++	return (ret);
    ++}
    +--- /dev/null
    ++++ libarchive/archive_write_disk_acl_linux.c
    +@@ -0,0 +1,388 @@
    ++/*-
    ++ * Copyright (c) 2003-2010 Tim Kientzle
    ++ * All rights reserved.
    ++ *
    ++ * Redistribution and use in source and binary forms, with or without
    ++ * modification, are permitted provided that the following conditions
    ++ * are met:
    ++ * 1. Redistributions of source code must retain the above copyright
    ++ *    notice, this list of conditions and the following disclaimer
    ++ *    in this position and unchanged.
    ++ * 2. Redistributions in binary form must reproduce the above copyright
    ++ *    notice, this list of conditions and the following disclaimer in the
    ++ *    documentation and/or other materials provided with the distribution.
    ++ *
    ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
    ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    ++ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
    ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    ++ */
    ++
    ++#include "archive_platform.h"
    ++
    ++#ifdef HAVE_ERRNO_H
    ++#include <errno.h>
    ++#endif
    ++#ifdef HAVE_FCNTL_H
    ++#include <fcntl.h>
    ++#endif
    ++#if HAVE_ACL_LIBACL_H
    ++#include <acl/libacl.h>
    ++#endif
    ++#ifdef HAVE_SYS_ACL_H
    ++#include <sys/acl.h>
    ++#endif
    ++#if HAVE_SYS_RICHACL_H
    ++#include <sys/richacl.h>
    ++#endif
    ++
    ++#include "archive.h"
    ++#include "archive_entry.h"
    ++#include "archive_write_disk_private.h"
    ++#include "archive_acl_maps.h"
    ++
    ++#if ARCHIVE_ACL_LIBRICHACL
    ++static int
    ++_richacl_mode_to_mask(short mode)
    ++{
    ++	int mask = 0;
    ++
    ++	if (mode & S_IROTH)
    ++		mask |= RICHACE_POSIX_MODE_READ;
    ++	if (mode & S_IWOTH)
    ++		mask |= RICHACE_POSIX_MODE_WRITE;
    ++	if (mode & S_IXOTH)
    ++		mask |= RICHACE_POSIX_MODE_EXEC;
    ++
    ++	return (mask);
    ++}
    ++
    ++static void
    ++_richacl_mode_to_masks(struct richacl *richacl, __LA_MODE_T mode)
    ++{
    ++	richacl->a_owner_mask = _richacl_mode_to_mask((mode & 0700) >> 6);
    ++	richacl->a_group_mask = _richacl_mode_to_mask((mode & 0070) >> 3);
    ++	richacl->a_other_mask = _richacl_mode_to_mask(mode & 0007);
    ++}
    ++#endif /* ARCHIVE_ACL_LIBRICHACL */
    ++
    ++#if ARCHIVE_ACL_LIBRICHACL
    ++static int
    ++set_richacl(struct archive *a, int fd, const char *name,
    ++    struct archive_acl *abstract_acl, __LA_MODE_T mode,
    ++    int ae_requested_type, const char *tname)
    ++{
    ++	int		 ae_type, ae_permset, ae_tag, ae_id;
    ++	uid_t		 ae_uid;
    ++	gid_t		 ae_gid;
    ++	const char	*ae_name;
    ++	int		 entries;
    ++	int		 i;
    ++	int		 ret;
    ++	int		 e = 0;
    ++	struct richacl  *richacl = NULL;
    ++	struct richace  *richace;
    ++
    ++	ret = ARCHIVE_OK;
    ++	entries = archive_acl_reset(abstract_acl, ae_requested_type);
    ++	if (entries == 0)
    ++		return (ARCHIVE_OK);
    ++
    ++	if (ae_requested_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
    ++		errno = ENOENT;
    ++		archive_set_error(a, errno, "Unsupported ACL type");
    ++		return (ARCHIVE_FAILED);
    ++	}
    ++
    ++	richacl = richacl_alloc(entries);
    ++	if (richacl == NULL) {
    ++		archive_set_error(a, errno,
    ++			"Failed to initialize RichACL working storage");
    ++		return (ARCHIVE_FAILED);
    ++	}
    ++
    ++	e = 0;
    ++
    ++	while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
    ++		   &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
    ++		richace = &(richacl->a_entries[e]);
    ++
    ++		richace->e_flags = 0;
    ++		richace->e_mask = 0;
    ++
    ++		switch (ae_tag) {
    ++		case ARCHIVE_ENTRY_ACL_USER:
    ++			ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
    ++			richace->e_id = ae_uid;
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_GROUP:
    ++			ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
    ++			richace->e_id = ae_gid;
    ++			richace->e_flags |= RICHACE_IDENTIFIER_GROUP;
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_USER_OBJ:
    ++			richace->e_flags |= RICHACE_SPECIAL_WHO;
    ++			richace->e_id = RICHACE_OWNER_SPECIAL_ID;
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
    ++			richace->e_flags |= RICHACE_SPECIAL_WHO;
    ++			richace->e_id = RICHACE_GROUP_SPECIAL_ID;
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_EVERYONE:
    ++			richace->e_flags |= RICHACE_SPECIAL_WHO;
    ++			richace->e_id = RICHACE_EVERYONE_SPECIAL_ID;
    ++			break;
    ++		default:
    ++			archive_set_error(a, ARCHIVE_ERRNO_MISC,
    ++			    "Unsupported ACL tag");
    ++			ret = ARCHIVE_FAILED;
    ++			goto exit_free;
    ++		}
    ++
    ++		switch (ae_type) {
    ++			case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
    ++				richace->e_type =
    ++				    RICHACE_ACCESS_ALLOWED_ACE_TYPE;
    ++				break;
    ++			case ARCHIVE_ENTRY_ACL_TYPE_DENY:
    ++				richace->e_type =
    ++				    RICHACE_ACCESS_DENIED_ACE_TYPE;
    ++				break;
    ++			case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
    ++			case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
    ++				break;
    ++		default:
    ++			archive_set_error(a, ARCHIVE_ERRNO_MISC,
    ++			    "Unsupported ACL entry type");
    ++			ret = ARCHIVE_FAILED;
    ++			goto exit_free;
    ++		}
    ++
    ++		for (i = 0; i < acl_nfs4_perm_map_size; ++i) {
    ++			if (ae_permset & acl_nfs4_perm_map[i].a_perm)
    ++				richace->e_mask |= acl_nfs4_perm_map[i].p_perm;
    ++		}
    ++
    ++		for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
    ++			if (ae_permset &
    ++			    acl_nfs4_flag_map[i].a_perm)
    ++				richace->e_flags |= acl_nfs4_flag_map[i].p_perm;
    ++		}
    ++	e++;
    ++	}
    ++
    ++	/* Fill RichACL masks */
    ++	_richacl_mode_to_masks(richacl, mode);
    ++
    ++	if (fd >= 0) {
    ++		if (richacl_set_fd(fd, richacl) == 0)
    ++			ret = ARCHIVE_OK;
    ++		else {
    ++			if (errno == EOPNOTSUPP) {
    ++				/* Filesystem doesn't support ACLs */
    ++				ret = ARCHIVE_OK;
    ++			} else {
    ++				archive_set_error(a, errno,
    ++				    "Failed to set richacl on fd: %s", tname);
    ++				ret = ARCHIVE_WARN;
    ++			}
    ++		}
    ++	} else if (richacl_set_file(name, richacl) != 0) {
    ++		if (errno == EOPNOTSUPP) {
    ++			/* Filesystem doesn't support ACLs */
    ++			ret = ARCHIVE_OK;
    ++		} else {
    ++			archive_set_error(a, errno, "Failed to set richacl: %s",
    ++			    tname);
    ++			ret = ARCHIVE_WARN;
    ++		}
    ++	}
    ++exit_free:
    ++	richacl_free(richacl);
    ++	return (ret);
    ++}
    ++#endif /* ARCHIVE_ACL_RICHACL */
    ++
    ++#if ARCHIVE_ACL_LIBACL
    ++static int
    ++set_acl(struct archive *a, int fd, const char *name,
    ++    struct archive_acl *abstract_acl,
    ++    int ae_requested_type, const char *tname)
    ++{
    ++	int		 acl_type = 0;
    ++	int		 ae_type, ae_permset, ae_tag, ae_id;
    ++	uid_t		 ae_uid;
    ++	gid_t		 ae_gid;
    ++	const char	*ae_name;
    ++	int		 entries;
    ++	int		 i;
    ++	int		 ret;
    ++	acl_t		 acl = NULL;
    ++	acl_entry_t	 acl_entry;
    ++	acl_permset_t	 acl_permset;
    ++
    ++	ret = ARCHIVE_OK;
    ++	entries = archive_acl_reset(abstract_acl, ae_requested_type);
    ++	if (entries == 0)
    ++		return (ARCHIVE_OK);
    ++
    ++	switch (ae_requested_type) {
    ++	case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
    ++		acl_type = ACL_TYPE_ACCESS;
    ++		break;
    ++	case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
    ++		acl_type = ACL_TYPE_DEFAULT;
    ++		break;
    ++	default:
    ++		errno = ENOENT;
    ++		archive_set_error(a, errno, "Unsupported ACL type");
    ++		return (ARCHIVE_FAILED);
    ++	}
    ++
    ++	acl = acl_init(entries);
    ++	if (acl == (acl_t)NULL) {
    ++		archive_set_error(a, errno,
    ++		    "Failed to initialize ACL working storage");
    ++		return (ARCHIVE_FAILED);
    ++	}
    ++
    ++	while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
    ++		   &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
    ++
    ++		if (acl_create_entry(&acl, &acl_entry) != 0) {
    ++			archive_set_error(a, errno,
    ++			    "Failed to create a new ACL entry");
    ++			ret = ARCHIVE_FAILED;
    ++			goto exit_free;
    ++		}
    ++
    ++		switch (ae_tag) {
    ++		case ARCHIVE_ENTRY_ACL_USER:
    ++			ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
    ++			acl_set_tag_type(acl_entry, ACL_USER);
    ++			acl_set_qualifier(acl_entry, &ae_uid);
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_GROUP:
    ++			ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
    ++			acl_set_tag_type(acl_entry, ACL_GROUP);
    ++			acl_set_qualifier(acl_entry, &ae_gid);
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_USER_OBJ:
    ++			acl_set_tag_type(acl_entry, ACL_USER_OBJ);
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
    ++			acl_set_tag_type(acl_entry, ACL_GROUP_OBJ);
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_MASK:
    ++			acl_set_tag_type(acl_entry, ACL_MASK);
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_OTHER:
    ++			acl_set_tag_type(acl_entry, ACL_OTHER);
    ++			break;
    ++		default:
    ++			archive_set_error(a, ARCHIVE_ERRNO_MISC,
    ++			    "Unsupported ACL tag");
    ++			ret = ARCHIVE_FAILED;
    ++			goto exit_free;
    ++		}
    ++
    ++		if (acl_get_permset(acl_entry, &acl_permset) != 0) {
    ++			archive_set_error(a, errno,
    ++			    "Failed to get ACL permission set");
    ++			ret = ARCHIVE_FAILED;
    ++			goto exit_free;
    ++		}
    ++		if (acl_clear_perms(acl_permset) != 0) {
    ++			archive_set_error(a, errno,
    ++			    "Failed to clear ACL permissions");
    ++			ret = ARCHIVE_FAILED;
    ++			goto exit_free;
    ++		}
    ++
    ++		for (i = 0; i < acl_posix_perm_map_size; ++i) {
    ++			if (ae_permset & acl_posix_perm_map[i].a_perm) {
    ++				if (acl_add_perm(acl_permset,
    ++				    acl_posix_perm_map[i].p_perm) != 0) {
    ++					archive_set_error(a, errno,
    ++					    "Failed to add ACL permission");
    ++					ret = ARCHIVE_FAILED;
    ++					goto exit_free;
    ++				}
    ++			}
    ++		}
    ++
    ++	}
    ++
    ++	if (fd >= 0 && ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {
    ++		if (acl_set_fd(fd, acl) == 0)
    ++			ret = ARCHIVE_OK;
    ++		else {
    ++			if (errno == EOPNOTSUPP) {
    ++				/* Filesystem doesn't support ACLs */
    ++				ret = ARCHIVE_OK;
    ++			} else {
    ++				archive_set_error(a, errno,
    ++				    "Failed to set acl on fd: %s", tname);
    ++				ret = ARCHIVE_WARN;
    ++			}
    ++		}
    ++	} else if (acl_set_file(name, acl_type, acl) != 0) {
    ++		if (errno == EOPNOTSUPP) {
    ++			/* Filesystem doesn't support ACLs */
    ++			ret = ARCHIVE_OK;
    ++		} else {
    ++			archive_set_error(a, errno, "Failed to set acl: %s",
    ++			    tname);
    ++			ret = ARCHIVE_WARN;
    ++		}
    ++	}
    ++exit_free:
    ++	acl_free(acl);
    ++	return (ret);
    ++}
    ++#endif /* ARCHIVE_ACL_LIBACL */
    ++
    ++int
    ++archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
    ++    struct archive_acl *abstract_acl, __LA_MODE_T mode)
    ++{
    ++	int		ret = ARCHIVE_OK;
    ++
    ++#if !ARCHIVE_ACL_LIBRICHACL
    ++	(void)mode;	/* UNUSED */
    ++#endif
    ++
    ++#if ARCHIVE_ACL_LIBRICHACL
    ++	if ((archive_acl_types(abstract_acl)
    ++	    & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
    ++		ret = set_richacl(a, fd, name, abstract_acl, mode,
    ++		    ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
    ++	}
    ++#if ARCHIVE_ACL_LIBACL
    ++	else
    ++#endif
    ++#endif	/* ARCHIVE_ACL_LIBRICHACL */
    ++#if ARCHIVE_ACL_LIBACL
    ++	if ((archive_acl_types(abstract_acl)
    ++	    & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
    ++		if ((archive_acl_types(abstract_acl)
    ++		    & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
    ++			ret = set_acl(a, fd, name, abstract_acl,
    ++			    ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
    ++			if (ret != ARCHIVE_OK)
    ++				return (ret);
    ++		}
    ++		if ((archive_acl_types(abstract_acl)
    ++		    & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
    ++			ret = set_acl(a, fd, name, abstract_acl,
    ++			    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
    ++	}
    ++#endif	/* ARCHIVE_ACL_LIBACL */
    ++	return (ret);
    ++}
    +--- /dev/null
    ++++ libarchive/archive_write_disk_acl_sunos.c
    +@@ -0,0 +1,329 @@
    ++/*-
    ++ * Copyright (c) 2017 Martin Matuska
    ++ * All rights reserved.
    ++ *
    ++ * Redistribution and use in source and binary forms, with or without
    ++ * modification, are permitted provided that the following conditions
    ++ * are met:
    ++ * 1. Redistributions of source code must retain the above copyright
    ++ *    notice, this list of conditions and the following disclaimer
    ++ *    in this position and unchanged.
    ++ * 2. Redistributions in binary form must reproduce the above copyright
    ++ *    notice, this list of conditions and the following disclaimer in the
    ++ *    documentation and/or other materials provided with the distribution.
    ++ *
    ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
    ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    ++ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
    ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    ++ */
    ++
    ++#include "archive_platform.h"
    ++
    ++#ifdef HAVE_SYS_TYPES_H
    ++#include <sys/types.h>
    ++#endif
    ++#ifdef HAVE_ERRNO_H
    ++#include <errno.h>
    ++#endif
    ++#ifdef HAVE_SYS_ACL_H
    ++#define _ACL_PRIVATE /* For debugging */
    ++#include <sys/acl.h>
    ++#endif
    ++
    ++#include "archive.h"
    ++#include "archive_entry.h"
    ++#include "archive_write_disk_private.h"
    ++#include "archive_acl_maps.h"
    ++
    ++static int
    ++set_acl(struct archive *a, int fd, const char *name,
    ++    struct archive_acl *abstract_acl,
    ++    int ae_requested_type, const char *tname)
    ++{
    ++	aclent_t	 *aclent;
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++	ace_t		 *ace;
    ++#endif
    ++	int		 cmd, e, r;
    ++	void		 *aclp;
    ++	int		 ret;
    ++	int		 ae_type, ae_permset, ae_tag, ae_id;
    ++	int		 perm_map_size;
    ++	const acl_perm_map_t	*perm_map;
    ++	uid_t		 ae_uid;
    ++	gid_t		 ae_gid;
    ++	const char	*ae_name;
    ++	int		 entries;
    ++	int		 i;
    ++
    ++	ret = ARCHIVE_OK;
    ++	entries = archive_acl_reset(abstract_acl, ae_requested_type);
    ++	if (entries == 0)
    ++		return (ARCHIVE_OK);
    ++
    ++
    ++	switch (ae_requested_type) {
    ++	case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
    ++		cmd = SETACL;
    ++		aclp = malloc(entries * sizeof(aclent_t));
    ++		break;
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++	case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
    ++		cmd = ACE_SETACL;
    ++		aclp = malloc(entries * sizeof(ace_t));
    ++
    ++		break;
    ++#endif
    ++	default:
    ++		errno = ENOENT;
    ++		archive_set_error(a, errno, "Unsupported ACL type");
    ++		return (ARCHIVE_FAILED);
    ++	}
    ++
    ++	if (aclp == NULL) {
    ++		archive_set_error(a, errno,
    ++		    "Can't allocate memory for acl buffer");
    ++		return (ARCHIVE_FAILED);
    ++	}
    ++
    ++	e = 0;
    ++
    ++	while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
    ++		   &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
    ++		aclent = NULL;
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++		ace = NULL;
    ++#endif
    ++		if (cmd == SETACL) {
    ++			aclent = &((aclent_t *)aclp)[e];
    ++			aclent->a_id = -1;
    ++			aclent->a_type = 0;
    ++			aclent->a_perm = 0;
    ++		}
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++		else {	/* cmd == ACE_SETACL */
    ++			ace = &((ace_t *)aclp)[e];
    ++			ace->a_who = -1;
    ++			ace->a_access_mask = 0;
    ++			ace->a_flags = 0;
    ++		}
    ++#endif	/* ARCHIVE_ACL_SUNOS_NFS4 */
    ++
    ++		switch (ae_tag) {
    ++		case ARCHIVE_ENTRY_ACL_USER:
    ++			ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
    ++			if (aclent != NULL) {
    ++				aclent->a_id = ae_uid;
    ++				aclent->a_type |= USER;
    ++			}
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++			else {
    ++				ace->a_who = ae_uid;
    ++			}
    ++#endif
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_GROUP:
    ++			ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
    ++			if (aclent != NULL) {
    ++				aclent->a_id = ae_gid;
    ++				aclent->a_type |= GROUP;
    ++			}
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++			else {
    ++				ace->a_who = ae_gid;
    ++				ace->a_flags |= ACE_IDENTIFIER_GROUP;
    ++			}
    ++#endif
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_USER_OBJ:
    ++			if (aclent != NULL)
    ++				aclent->a_type |= USER_OBJ;
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++			else {
    ++				ace->a_flags |= ACE_OWNER;
    ++			}
    ++#endif
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
    ++			if (aclent != NULL)
    ++				aclent->a_type |= GROUP_OBJ;
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++			else {
    ++				ace->a_flags |= ACE_GROUP;
    ++				ace->a_flags |= ACE_IDENTIFIER_GROUP;
    ++			}
    ++#endif
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_MASK:
    ++			if (aclent != NULL)
    ++				aclent->a_type |= CLASS_OBJ;
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_OTHER:
    ++			if (aclent != NULL)
    ++				aclent->a_type |= OTHER_OBJ;
    ++			break;
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++		case ARCHIVE_ENTRY_ACL_EVERYONE:
    ++			if (ace != NULL)
    ++				ace->a_flags |= ACE_EVERYONE;
    ++			break;
    ++#endif
    ++		default:
    ++			archive_set_error(a, ARCHIVE_ERRNO_MISC,
    ++			    "Unsupported ACL tag");
    ++			ret = ARCHIVE_FAILED;
    ++			goto exit_free;
    ++		}
    ++
    ++		r = 0;
    ++		switch (ae_type) {
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++		case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
    ++			if (ace != NULL)
    ++				ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
    ++			else
    ++				r = -1;
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_TYPE_DENY:
    ++			if (ace != NULL)
    ++				ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
    ++			else
    ++				r = -1;
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
    ++			if (ace != NULL)
    ++				ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE;
    ++			else
    ++				r = -1;
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
    ++			if (ace != NULL)
    ++				ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE;
    ++			else
    ++				r = -1;
    ++			break;
    ++#endif
    ++		case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
    ++			if (aclent == NULL)
    ++				r = -1;
    ++			break;
    ++		case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
    ++			if (aclent != NULL)
    ++				aclent->a_type |= ACL_DEFAULT;
    ++			else
    ++				r = -1;
    ++			break;
    ++		default:
    ++			archive_set_error(a, ARCHIVE_ERRNO_MISC,
    ++			    "Unsupported ACL entry type");
    ++			ret = ARCHIVE_FAILED;
    ++			goto exit_free;
    ++		}
    ++
    ++		if (r != 0) {
    ++			errno = EINVAL;
    ++			archive_set_error(a, errno,
    ++			    "Failed to set ACL entry type");
    ++			ret = ARCHIVE_FAILED;
    ++			goto exit_free;
    ++		}
    ++
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++		if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
    ++			perm_map_size = acl_nfs4_perm_map_size;
    ++			perm_map = acl_nfs4_perm_map;
    ++		} else {
    ++#endif
    ++			perm_map_size = acl_posix_perm_map_size;
    ++			perm_map = acl_posix_perm_map;
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++		}
    ++#endif
    ++		for (i = 0; i < perm_map_size; ++i) {
    ++			if (ae_permset & perm_map[i].a_perm) {
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++				if (ae_requested_type ==
    ++				    ARCHIVE_ENTRY_ACL_TYPE_NFS4)
    ++					ace->a_access_mask |=
    ++					    perm_map[i].p_perm;
    ++				else
    ++#endif
    ++					aclent->a_perm |= perm_map[i].p_perm;
    ++			}
    ++		}
    ++
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++		if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
    ++			for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
    ++				if (ae_permset & acl_nfs4_flag_map[i].a_perm) {
    ++					ace->a_flags |=
    ++					    acl_nfs4_flag_map[i].p_perm;
    ++				}
    ++			}
    ++		}
    ++#endif
    ++	e++;
    ++	}
    ++
    ++	/* Try restoring the ACL through 'fd' if we can. */
    ++	if (fd >= 0) {
    ++		if (facl(fd, cmd, entries, aclp) == 0)
    ++			ret = ARCHIVE_OK;
    ++		else {
    ++			if (errno == EOPNOTSUPP) {
    ++				/* Filesystem doesn't support ACLs */
    ++				ret = ARCHIVE_OK;
    ++			} else {
    ++				archive_set_error(a, errno,
    ++				    "Failed to set acl on fd: %s", tname);
    ++				ret = ARCHIVE_WARN;
    ++			}
    ++		}
    ++	} else if (acl(name, cmd, entries, aclp) != 0) {
    ++		if (errno == EOPNOTSUPP) {
    ++			/* Filesystem doesn't support ACLs */
    ++			ret = ARCHIVE_OK;
    ++		} else {
    ++			archive_set_error(a, errno, "Failed to set acl: %s",
    ++			    tname);
    ++			ret = ARCHIVE_WARN;
    ++		}
    ++	}
    ++exit_free:
    ++	free(aclp);
    ++	return (ret);
    ++}
    ++
    ++int
    ++archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
    ++    struct archive_acl *abstract_acl, __LA_MODE_T mode)
    ++{
    ++	int		ret = ARCHIVE_OK;
    ++
    ++	(void)mode;	/* UNUSED */
    ++
    ++	if ((archive_acl_types(abstract_acl)
    ++	    & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
    ++		/* Solaris writes POSIX.1e access and default ACLs together */
    ++		ret = set_acl(a, fd, name, abstract_acl,
    ++		    ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, "posix1e");
    ++
    ++		/* Simultaneous POSIX.1e and NFSv4 is not supported */
    ++		return (ret);
    ++	}
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++	else if ((archive_acl_types(abstract_acl) &
    ++	    ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
    ++		ret = set_acl(a, fd, name, abstract_acl,
    ++		    ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
    ++	}
    ++#endif
    ++	return (ret);
    ++}
    +--- libarchive/archive_write_disk_posix.c.orig
    ++++ libarchive/archive_write_disk_posix.c
    +@@ -575,10 +575,55 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
    + 	if (a->flags & ARCHIVE_EXTRACT_TIME)
    + 		a->todo |= TODO_TIMES;
    + 	if (a->flags & ARCHIVE_EXTRACT_ACL) {
    ++#if ARCHIVE_ACL_DARWIN
    ++		/*
    ++		 * On MacOS, platform ACLs get stored in mac_metadata, too.
    ++		 * If we intend to extract mac_metadata and it is present
    ++		 * we skip extracting libarchive NFSv4 ACLs.
    ++		 */
    ++		size_t metadata_size;
    ++
    ++		if ((a->flags & ARCHIVE_EXTRACT_MAC_METADATA) == 0 ||
    ++		    archive_entry_mac_metadata(a->entry,
    ++		    &metadata_size) == NULL || metadata_size == 0)
    ++#endif
    ++#if ARCHIVE_ACL_LIBRICHACL
    ++		/*
    ++		 * RichACLs are stored in an extended attribute.
    ++		 * If we intend to extract extended attributes and have this
    ++		 * attribute we skip extracting libarchive NFSv4 ACLs.
    ++		 */
    ++		short extract_acls = 1;
    ++		if (a->flags & ARCHIVE_EXTRACT_XATTR && (
    ++		    archive_entry_acl_types(a->entry) &
    ++		    ARCHIVE_ENTRY_ACL_TYPE_NFS4)) {
    ++			const char *attr_name;
    ++			const void *attr_value;
    ++			size_t attr_size;
    ++			int i = archive_entry_xattr_reset(a->entry);
    ++			while (i--) {
    ++				archive_entry_xattr_next(a->entry, &attr_name,
    ++				    &attr_value, &attr_size);
    ++				if (attr_name != NULL && attr_value != NULL &&
    ++				    attr_size > 0 && strcmp(attr_name,
    ++				    "trusted.richacl") == 0) {
    ++					extract_acls = 0;
    ++					break;
    ++				}
    ++			}
    ++		}
    ++		if (extract_acls)
    ++#endif
    ++#if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBRICHACL
    ++		{
    ++#endif
    + 		if (archive_entry_filetype(a->entry) == AE_IFDIR)
    + 			a->deferred |= TODO_ACLS;
    + 		else
    + 			a->todo |= TODO_ACLS;
    ++#if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBRICHACL
    ++		}
    ++#endif
    + 	}
    + 	if (a->flags & ARCHIVE_EXTRACT_MAC_METADATA) {
    + 		if (archive_entry_filetype(a->entry) == AE_IFDIR)
    +@@ -1703,25 +1748,11 @@ _archive_write_disk_finish_entry(struct archive *_a)
    + 	 */
    + 	if (a->todo & TODO_ACLS) {
    + 		int r2;
    +-#ifdef HAVE_DARWIN_ACL
    +-		/*
    +-		 * On Mac OS, platform ACLs are stored also in mac_metadata by
    +-		 * the operating system. If mac_metadata is present it takes
    +-		 * precedence and we skip extracting libarchive NFSv4 ACLs
    +-		 */
    +-		const void *metadata;
    +-		size_t metadata_size;
    +-		metadata = archive_entry_mac_metadata(a->entry, &metadata_size);
    +-		if ((a->todo & TODO_MAC_METADATA) == 0 ||
    +-		    metadata == NULL || metadata_size == 0) {
    +-#endif
    + 		r2 = archive_write_disk_set_acls(&a->archive, a->fd,
    + 		    archive_entry_pathname(a->entry),
    +-		    archive_entry_acl(a->entry));
    ++		    archive_entry_acl(a->entry),
    ++		    archive_entry_mode(a->entry));
    + 		if (r2 < ret) ret = r2;
    +-#ifdef HAVE_DARWIN_ACL
    +-		}
    +-#endif
    + 	}
    + 
    + finish_metadata:
    +@@ -2293,13 +2324,8 @@ _archive_write_disk_close(struct archive *_a)
    + 		if (p->fixup & TODO_MODE_BASE)
    + 			chmod(p->name, p->mode);
    + 		if (p->fixup & TODO_ACLS)
    +-#ifdef HAVE_DARWIN_ACL
    +-			if ((p->fixup & TODO_MAC_METADATA) == 0 ||
    +-			    p->mac_metadata == NULL ||
    +-			    p->mac_metadata_size == 0)
    +-#endif
    +-				archive_write_disk_set_acls(&a->archive,
    +-				    -1, p->name, &p->acl);
    ++			archive_write_disk_set_acls(&a->archive, -1, p->name,
    ++			    &p->acl, p->mode);
    + 		if (p->fixup & TODO_FFLAGS)
    + 			set_fflags_platform(a, -1, p->name,
    + 			    p->mode, p->fflags_set, 0);
    +@@ -2467,7 +2493,7 @@ fsobj_error(int *a_eno, struct archive_string *a_estr,
    + 	if (a_eno)
    + 		*a_eno = err;
    + 	if (a_estr)
    +-		archive_string_sprintf(a_estr, errstr, path);
    ++		archive_string_sprintf(a_estr, "%s%s", errstr, path);
    + }
    + 
    + /*
    +@@ -2573,7 +2599,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
    + 				 * with the deep-directory editing.
    + 				 */
    + 				fsobj_error(a_eno, a_estr, errno,
    +-				    "Could not stat %s", path);
    ++				    "Could not stat ", path);
    + 				res = ARCHIVE_FAILED;
    + 				break;
    + 			}
    +@@ -2582,7 +2608,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
    + 				if (chdir(head) != 0) {
    + 					tail[0] = c;
    + 					fsobj_error(a_eno, a_estr, errno,
    +-					    "Could not chdir %s", path);
    ++					    "Could not chdir ", path);
    + 					res = (ARCHIVE_FATAL);
    + 					break;
    + 				}
    +@@ -2599,7 +2625,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
    + 				if (unlink(head)) {
    + 					tail[0] = c;
    + 					fsobj_error(a_eno, a_estr, errno,
    +-					    "Could not remove symlink %s",
    ++					    "Could not remove symlink ",
    + 					    path);
    + 					res = ARCHIVE_FAILED;
    + 					break;
    +@@ -2618,7 +2644,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
    + 				/*
    + 				if (!S_ISLNK(path)) {
    + 					fsobj_error(a_eno, a_estr, 0,
    +-					    "Removing symlink %s", path);
    ++					    "Removing symlink ", path);
    + 				}
    + 				*/
    + 				/* Symlink gone.  No more problem! */
    +@@ -2630,7 +2656,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
    + 					tail[0] = c;
    + 					fsobj_error(a_eno, a_estr, 0,
    + 					    "Cannot remove intervening "
    +-					    "symlink %s", path);
    ++					    "symlink ", path);
    + 					res = ARCHIVE_FAILED;
    + 					break;
    + 				}
    +@@ -2652,7 +2678,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
    + 					} else {
    + 						fsobj_error(a_eno, a_estr,
    + 						    errno,
    +-						    "Could not stat %s", path);
    ++						    "Could not stat ", path);
    + 						res = (ARCHIVE_FAILED);
    + 						break;
    + 					}
    +@@ -2661,7 +2687,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
    + 						tail[0] = c;
    + 						fsobj_error(a_eno, a_estr,
    + 						    errno,
    +-						    "Could not chdir %s", path);
    ++						    "Could not chdir ", path);
    + 						res = (ARCHIVE_FATAL);
    + 						break;
    + 					}
    +@@ -2674,14 +2700,14 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
    + 					tail[0] = c;
    + 					fsobj_error(a_eno, a_estr, 0,
    + 					    "Cannot extract through "
    +-					    "symlink %s", path);
    ++					    "symlink ", path);
    + 					res = ARCHIVE_FAILED;
    + 					break;
    + 				}
    + 			} else {
    + 				tail[0] = c;
    + 				fsobj_error(a_eno, a_estr, 0,
    +-				    "Cannot extract through symlink %s", path);
    ++				    "Cannot extract through symlink ", path);
    + 				res = ARCHIVE_FAILED;
    + 				break;
    + 			}
    +@@ -4239,5 +4265,19 @@ older(struct stat *st, struct archive_entry *entry)
    + 	return (0);
    + }
    + 
    ++#ifndef ARCHIVE_ACL_SUPPORT
    ++int
    ++archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
    ++    struct archive_acl *abstract_acl, __LA_MODE_T mode)
    ++{
    ++	(void)a; /* UNUSED */
    ++	(void)fd; /* UNUSED */
    ++	(void)name; /* UNUSED */
    ++	(void)abstract_acl; /* UNUSED */
    ++	(void)mode; /* UNUSED */
    ++	return (ARCHIVE_OK);
    ++}
    ++#endif
    ++
    + #endif /* !_WIN32 || __CYGWIN__ */
    + 
    +--- libarchive/archive_write_disk_private.h.orig
    ++++ libarchive/archive_write_disk_private.h
    +@@ -33,11 +33,13 @@
    + #ifndef ARCHIVE_WRITE_DISK_PRIVATE_H_INCLUDED
    + #define ARCHIVE_WRITE_DISK_PRIVATE_H_INCLUDED
    + 
    ++#include "archive_platform_acl.h"
    + #include "archive_acl_private.h"
    ++#include "archive_entry.h"
    + 
    + struct archive_write_disk;
    + 
    +-int
    +-archive_write_disk_set_acls(struct archive *, int /* fd */, const char * /* pathname */, struct archive_acl *);
    ++int archive_write_disk_set_acls(struct archive *, int, const char *,
    ++    struct archive_acl *, __LA_MODE_T);
    + 
    + #endif
    +--- libarchive/archive_write_finish_entry.3.orig
    ++++ libarchive/archive_write_finish_entry.3
    +@@ -24,7 +24,7 @@
    + .\"
    + .\" $FreeBSD$
    + .\"
    +-.Dd February 2, 2012
    ++.Dd February 28, 2017
    + .Dt ARCHIVE_WRITE_FINISH_ENTRY 3
    + .Os
    + .Sh NAME
    +@@ -45,6 +45,9 @@ is called automatically by
    + and
    + .Fn archive_write_close
    + as needed.
    ++For
    ++.Tn archive_write_disk
    ++handles, this flushes pending file attribute changes like modification time.
    + .\" .Sh EXAMPLE
    + .Sh RETURN VALUES
    + This function returns
    +--- libarchive/archive_write_format.3.orig
    ++++ libarchive/archive_write_format.3
    +@@ -108,7 +108,6 @@ Streaming Archive Library (libarchive, -larchive)
    + These functions set the format that will be used for the archive.
    + .Pp
    + The library can write a variety of common archive formats.
    +-
    + .Bl -tag -width indent
    + .It Fn archive_write_set_format
    + Sets the format based on the format code (see
    +--- libarchive/mtree.5.orig
    ++++ libarchive/mtree.5
    +@@ -48,7 +48,7 @@ Leading whitespace is always ignored.
    + .Pp
    + When encoding file or pathnames, any backslash character or
    + character outside of the 95 printable ASCII characters must be
    +-encoded as a a backslash followed by three
    ++encoded as a backslash followed by three
    + octal digits.
    + When reading mtree files, any appearance of a backslash
    + followed by three octal digits should be converted into the
    +--- libarchive/test/test_acl_platform_nfs4.c.orig
    ++++ libarchive/test/test_acl_platform_nfs4.c
    +@@ -26,15 +26,18 @@
    + #include "test.h"
    + __FBSDID("$FreeBSD$");
    + 
    +-#if HAVE_POSIX_ACL || HAVE_NFS4_ACL
    ++#if ARCHIVE_ACL_NFS4
    ++#if HAVE_SYS_ACL_H
    + #define _ACL_PRIVATE
    + #include <sys/acl.h>
    +-#if HAVE_DARWIN_ACL
    +-#include <membership.h>
    + #endif
    ++#if HAVE_SYS_RICHACL_H
    ++#include <sys/richacl.h>
    ++#endif
    ++#if HAVE_MEMBERSHIP_H
    ++#include <membership.h>
    + #endif
    + 
    +-#if HAVE_NFS4_ACL
    + struct myacl_t {
    + 	int type;
    + 	int permset;
    +@@ -44,7 +47,7 @@ struct myacl_t {
    + };
    + 
    + static struct myacl_t acls_reg[] = {
    +-#if !HAVE_DARWIN_ACL
    ++#if !ARCHIVE_ACL_DARWIN
    + 	/* For this test, we need the file owner to be able to read and write the ACL. */
    + 	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
    + 	  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,
    +@@ -91,7 +94,7 @@ static struct myacl_t acls_reg[] = {
    + //	  ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
    + 	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
    + 	  ARCHIVE_ENTRY_ACL_GROUP, 136, "group136" },
    +-#if !HAVE_DARWIN_ACL
    ++#if !ARCHIVE_ACL_DARWIN
    + 	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
    + 	  ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
    + 	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
    +@@ -134,7 +137,7 @@ static const int acls_reg_cnt = (int)(sizeof(acls_reg)/sizeof(acls_reg[0]));
    + 
    + static struct myacl_t acls_dir[] = {
    + 	/* For this test, we need to be able to read and write the ACL. */
    +-#if !HAVE_DARWIN_ACL
    ++#if !ARCHIVE_ACL_DARWIN
    + 	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_READ_ACL,
    + 	  ARCHIVE_ENTRY_ACL_USER_OBJ, -1, ""},
    + #endif
    +@@ -180,13 +183,17 @@ static struct myacl_t acls_dir[] = {
    + 	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
    + 	  ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT,
    + 	  ARCHIVE_ENTRY_ACL_USER, 302, "user302" },
    +-#if 0
    + 	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
    +-	  ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT,
    ++	  ARCHIVE_ENTRY_ACL_READ_DATA |
    ++	  ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT |
    ++	  ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT,
    + 	  ARCHIVE_ENTRY_ACL_USER, 303, "user303" },
    + 	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
    +-	  ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY,
    ++	  ARCHIVE_ENTRY_ACL_READ_DATA |
    ++	  ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT |
    ++	  ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY,
    + 	  ARCHIVE_ENTRY_ACL_USER, 304, "user304" },
    ++#if !defined(ARCHIVE_ACL_SUNOS_NFS4) || defined(ACE_INHERITED_ACE)
    + 	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
    + 	  ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_INHERITED,
    + 	  ARCHIVE_ENTRY_ACL_USER, 305, "user305" },
    +@@ -207,7 +214,7 @@ static struct myacl_t acls_dir[] = {
    + 	  ARCHIVE_ENTRY_ACL_USER, 501, "user501" },
    + 	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
    + 	  ARCHIVE_ENTRY_ACL_GROUP, 502, "group502" },
    +-#if !HAVE_DARWIN_ACL
    ++#if !ARCHIVE_ACL_DARWIN
    + 	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
    + 	  ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
    + 	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
    +@@ -254,12 +261,14 @@ set_acls(struct archive_entry *ae, struct myacl_t *acls, int start, int end)
    + 	int i;
    + 
    + 	archive_entry_acl_clear(ae);
    ++#if !ARCHIVE_ACL_DARWIN
    + 	if (start > 0) {
    + 		assertEqualInt(ARCHIVE_OK,
    + 			archive_entry_acl_add_entry(ae,
    + 			    acls[0].type, acls[0].permset, acls[0].tag,
    + 			    acls[0].qual, acls[0].name));
    + 	}
    ++#endif
    + 	for (i = start; i < end; i++) {
    + 		assertEqualInt(ARCHIVE_OK,
    + 		    archive_entry_acl_add_entry(ae,
    +@@ -269,76 +278,96 @@ set_acls(struct archive_entry *ae, struct myacl_t *acls, int start, int end)
    + }
    + 
    + static int
    +-#ifdef HAVE_SUN_ACL
    +-acl_permset_to_bitmap(uint32_t a_access_mask)
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++acl_permset_to_bitmap(uint32_t mask)
    ++#elif ARCHIVE_ACL_LIBRICHACL
    ++acl_permset_to_bitmap(unsigned int mask)
    + #else
    + acl_permset_to_bitmap(acl_permset_t opaque_ps)
    + #endif
    + {
    +-	static struct { int machine; int portable; } perms[] = {
    +-#ifdef HAVE_SUN_ACL	/* Solaris NFSv4 ACL permissions */
    +-		{ACE_EXECUTE, ARCHIVE_ENTRY_ACL_EXECUTE},
    +-		{ACE_READ_DATA, ARCHIVE_ENTRY_ACL_READ_DATA},
    +-		{ACE_LIST_DIRECTORY, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY},
    +-		{ACE_WRITE_DATA, ARCHIVE_ENTRY_ACL_WRITE_DATA},
    +-		{ACE_ADD_FILE, ARCHIVE_ENTRY_ACL_ADD_FILE},
    +-		{ACE_APPEND_DATA, ARCHIVE_ENTRY_ACL_APPEND_DATA},
    +-		{ACE_ADD_SUBDIRECTORY, ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY},
    +-		{ACE_READ_NAMED_ATTRS, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS},
    +-		{ACE_WRITE_NAMED_ATTRS, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS},
    +-		{ACE_DELETE_CHILD, ARCHIVE_ENTRY_ACL_DELETE_CHILD},
    +-		{ACE_READ_ATTRIBUTES, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES},
    +-		{ACE_WRITE_ATTRIBUTES, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES},
    +-		{ACE_DELETE, ARCHIVE_ENTRY_ACL_DELETE},
    +-		{ACE_READ_ACL, ARCHIVE_ENTRY_ACL_READ_ACL},
    +-		{ACE_WRITE_ACL, ARCHIVE_ENTRY_ACL_WRITE_ACL},
    +-		{ACE_WRITE_OWNER, ARCHIVE_ENTRY_ACL_WRITE_OWNER},
    +-		{ACE_SYNCHRONIZE, ARCHIVE_ENTRY_ACL_SYNCHRONIZE}
    +-#elif HAVE_DARWIN_ACL	/* MacOS NFSv4 ACL permissions */
    +-		{ACL_READ_DATA, ARCHIVE_ENTRY_ACL_READ_DATA},
    +-		{ACL_LIST_DIRECTORY, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY},
    +-		{ACL_WRITE_DATA, ARCHIVE_ENTRY_ACL_WRITE_DATA},
    +-		{ACL_ADD_FILE, ARCHIVE_ENTRY_ACL_ADD_FILE},
    +-		{ACL_EXECUTE, ARCHIVE_ENTRY_ACL_EXECUTE},
    +-		{ACL_DELETE, ARCHIVE_ENTRY_ACL_DELETE},
    +-		{ACL_APPEND_DATA, ARCHIVE_ENTRY_ACL_APPEND_DATA},
    +-		{ACL_ADD_SUBDIRECTORY, ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY},
    +-		{ACL_DELETE_CHILD, ARCHIVE_ENTRY_ACL_DELETE_CHILD},
    +-		{ACL_READ_ATTRIBUTES, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES},
    +-		{ACL_WRITE_ATTRIBUTES, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES},
    +-		{ACL_READ_EXTATTRIBUTES, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS},
    +-		{ACL_WRITE_EXTATTRIBUTES, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS},
    +-		{ACL_READ_SECURITY, ARCHIVE_ENTRY_ACL_READ_ACL},
    +-		{ACL_WRITE_SECURITY, ARCHIVE_ENTRY_ACL_WRITE_ACL},
    +-		{ACL_CHANGE_OWNER, ARCHIVE_ENTRY_ACL_WRITE_OWNER},
    +-		{ACL_SYNCHRONIZE, ARCHIVE_ENTRY_ACL_SYNCHRONIZE},
    ++	static struct { int portable; int machine; } perms[] = {
    ++#ifdef ARCHIVE_ACL_SUNOS_NFS4	/* Solaris NFSv4 ACL permissions */
    ++		{ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE},
    ++		{ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA},
    ++		{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY},
    ++		{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA},
    ++		{ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE},
    ++		{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA},
    ++		{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY},
    ++		{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS},
    ++		{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS},
    ++		{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD},
    ++		{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES},
    ++		{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES},
    ++		{ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE},
    ++		{ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL},
    ++		{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL},
    ++		{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER},
    ++		{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE}
    ++#elif ARCHIVE_ACL_DARWIN	/* MacOS NFSv4 ACL permissions */
    ++		{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
    ++		{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
    ++		{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
    ++		{ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
    ++		{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
    ++		{ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
    ++		{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
    ++		{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
    ++		{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
    ++		{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
    ++		{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
    ++		{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES},
    ++		{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES},
    ++		{ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY},
    ++		{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY},
    ++		{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER},
    ++#if HAVE_DECL_ACL_SYNCHRONIZE
    ++		{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
    ++#endif
    ++#elif ARCHIVE_ACL_LIBRICHACL
    ++		{ARCHIVE_ENTRY_ACL_EXECUTE, RICHACE_EXECUTE},
    ++		{ARCHIVE_ENTRY_ACL_READ_DATA, RICHACE_READ_DATA},
    ++		{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, RICHACE_LIST_DIRECTORY},
    ++		{ARCHIVE_ENTRY_ACL_WRITE_DATA, RICHACE_WRITE_DATA},
    ++		{ARCHIVE_ENTRY_ACL_ADD_FILE, RICHACE_ADD_FILE},
    ++		{ARCHIVE_ENTRY_ACL_APPEND_DATA, RICHACE_APPEND_DATA},
    ++		{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, RICHACE_ADD_SUBDIRECTORY},
    ++		{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, RICHACE_READ_NAMED_ATTRS},
    ++		{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, RICHACE_WRITE_NAMED_ATTRS},
    ++		{ARCHIVE_ENTRY_ACL_DELETE_CHILD, RICHACE_DELETE_CHILD},
    ++		{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, RICHACE_READ_ATTRIBUTES},
    ++		{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, RICHACE_WRITE_ATTRIBUTES},
    ++		{ARCHIVE_ENTRY_ACL_DELETE, RICHACE_DELETE},
    ++		{ARCHIVE_ENTRY_ACL_READ_ACL, RICHACE_READ_ACL},
    ++		{ARCHIVE_ENTRY_ACL_WRITE_ACL, RICHACE_WRITE_ACL},
    ++		{ARCHIVE_ENTRY_ACL_WRITE_OWNER, RICHACE_WRITE_OWNER},
    ++		{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, RICHACE_SYNCHRONIZE}
    + #else	/* FreeBSD NFSv4 ACL permissions */
    +-		{ACL_EXECUTE, ARCHIVE_ENTRY_ACL_EXECUTE},
    +-		{ACL_WRITE, ARCHIVE_ENTRY_ACL_WRITE},
    +-		{ACL_READ, ARCHIVE_ENTRY_ACL_READ},
    +-		{ACL_READ_DATA, ARCHIVE_ENTRY_ACL_READ_DATA},
    +-		{ACL_LIST_DIRECTORY, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY},
    +-		{ACL_WRITE_DATA, ARCHIVE_ENTRY_ACL_WRITE_DATA},
    +-		{ACL_ADD_FILE, ARCHIVE_ENTRY_ACL_ADD_FILE},
    +-		{ACL_APPEND_DATA, ARCHIVE_ENTRY_ACL_APPEND_DATA},
    +-		{ACL_ADD_SUBDIRECTORY, ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY},
    +-		{ACL_READ_NAMED_ATTRS, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS},
    +-		{ACL_WRITE_NAMED_ATTRS, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS},
    +-		{ACL_DELETE_CHILD, ARCHIVE_ENTRY_ACL_DELETE_CHILD},
    +-		{ACL_READ_ATTRIBUTES, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES},
    +-		{ACL_WRITE_ATTRIBUTES, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES},
    +-		{ACL_DELETE, ARCHIVE_ENTRY_ACL_DELETE},
    +-		{ACL_READ_ACL, ARCHIVE_ENTRY_ACL_READ_ACL},
    +-		{ACL_WRITE_ACL, ARCHIVE_ENTRY_ACL_WRITE_ACL},
    +-		{ACL_WRITE_OWNER, ARCHIVE_ENTRY_ACL_WRITE_OWNER},
    +-		{ACL_SYNCHRONIZE, ARCHIVE_ENTRY_ACL_SYNCHRONIZE}
    ++		{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
    ++		{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
    ++		{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
    ++		{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
    ++		{ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
    ++		{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
    ++		{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
    ++		{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
    ++		{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
    ++		{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
    ++		{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
    ++		{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
    ++		{ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
    ++		{ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
    ++		{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
    ++		{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
    ++		{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
    + #endif
    + 	};
    + 	int i, permset = 0;
    + 
    + 	for (i = 0; i < (int)(sizeof(perms)/sizeof(perms[0])); ++i)
    +-#if HAVE_SUN_ACL
    +-		if (a_access_mask & perms[i].machine)
    ++#if ARCHIVE_ACL_SUNOS_NFS4 || ARCHIVE_ACL_LIBRICHACL
    ++		if (mask & perms[i].machine)
    + #else
    + 		if (acl_get_perm_np(opaque_ps, perms[i].machine))
    + #endif
    +@@ -347,88 +376,70 @@ acl_permset_to_bitmap(acl_permset_t opaque_ps)
    + }
    + 
    + static int
    +-#if HAVE_SUN_ACL
    +-acl_flagset_to_bitmap(uint16_t a_flags)
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++acl_flagset_to_bitmap(uint16_t flags)
    ++#elif ARCHIVE_ACL_LIBRICHACL
    ++acl_flagset_to_bitmap(int flags)
    + #else
    + acl_flagset_to_bitmap(acl_flagset_t opaque_fs)
    + #endif
    + {
    +-	static struct { int machine; int portable; } flags[] = {
    +-#if HAVE_SUN_ACL	/* Solaris NFSv4 ACL inheritance flags */
    +-		{ACE_FILE_INHERIT_ACE, ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT},
    +-		{ACE_DIRECTORY_INHERIT_ACE, ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT},
    +-		{ACE_NO_PROPAGATE_INHERIT_ACE, ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT},
    +-		{ACE_INHERIT_ONLY_ACE, ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY},
    +-		{ACE_SUCCESSFUL_ACCESS_ACE_FLAG, ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS},
    +-		{ACE_FAILED_ACCESS_ACE_FLAG, ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS},
    +-		{ACE_INHERITED_ACE, ARCHIVE_ENTRY_ACL_ENTRY_INHERITED}
    +-#elif HAVE_DARWIN_ACL	/* MacOS NFSv4 ACL inheritance flags */
    +-		{ACL_ENTRY_INHERITED, ARCHIVE_ENTRY_ACL_ENTRY_INHERITED},
    +-		{ACL_ENTRY_FILE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT},
    +-		{ACL_ENTRY_DIRECTORY_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT},
    +-		{ACL_ENTRY_LIMIT_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT},
    +-		{ACL_ENTRY_ONLY_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY}
    ++	static struct { int portable; int machine; } perms[] = {
    ++#if ARCHIVE_ACL_SUNOS_NFS4	/* Solaris NFSv4 ACL inheritance flags */
    ++		{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE},
    ++		{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE},
    ++		{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE},
    ++		{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE},
    ++		{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
    ++		{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG},
    ++#ifdef ACE_INHERITED_ACE
    ++		{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}
    ++#endif
    ++#elif ARCHIVE_ACL_DARWIN	/* MacOS NFSv4 ACL inheritance flags */
    ++		{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED},
    ++		{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
    ++		{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
    ++		{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_LIMIT_INHERIT},
    ++		{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT}
    ++#elif ARCHIVE_ACL_LIBRICHACL
    ++		{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, RICHACE_FILE_INHERIT_ACE},
    ++		{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, RICHACE_DIRECTORY_INHERIT_ACE},
    ++		{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, RICHACE_NO_PROPAGATE_INHERIT_ACE},
    ++		{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, RICHACE_INHERIT_ONLY_ACE},
    ++		{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, RICHACE_INHERITED_ACE}
    + #else	/* FreeBSD NFSv4 ACL inheritance flags */
    +-		{ACL_ENTRY_FILE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT},
    +-		{ACL_ENTRY_DIRECTORY_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT},
    +-		{ACL_ENTRY_NO_PROPAGATE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT},
    +-		{ACL_ENTRY_SUCCESSFUL_ACCESS, ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS},
    +-		{ACL_ENTRY_NO_PROPAGATE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS},
    +-		{ACL_ENTRY_INHERIT_ONLY, ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY},
    ++		{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED},
    ++		{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
    ++		{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
    ++		{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
    ++		{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
    ++		{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
    ++		{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}
    + #endif
    + 	};
    + 	int i, flagset = 0;
    + 
    +-	for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); ++i)
    +-#if HAVE_SUN_ACL
    +-		if (a_flags & flags[i].machine)
    ++	for (i = 0; i < (int)(sizeof(perms)/sizeof(perms[0])); ++i)
    ++#if ARCHIVE_ACL_SUNOS_NFS4 || ARCHIVE_ACL_LIBRICHACL
    ++		if (flags & perms[i].machine)
    + #else
    +-		if (acl_get_flag_np(opaque_fs, flags[i].machine))
    ++		if (acl_get_flag_np(opaque_fs, perms[i].machine))
    + #endif
    +-			flagset |= flags[i].portable;
    ++			flagset |= perms[i].portable;
    + 	return flagset;
    + }
    + 
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    + static int
    +-#if HAVE_SUN_ACL
    + acl_match(ace_t *ace, struct myacl_t *myacl)
    +-#else
    +-acl_match(acl_entry_t aclent, struct myacl_t *myacl)
    +-#endif
    + {
    +-#if !HAVE_SUN_ACL
    +-#if HAVE_DARWIN_ACL
    +-	void *q;
    +-	uid_t ugid;
    +-	int r, idtype;
    +-#else
    +-	gid_t g, *gp;
    +-	uid_t u, *up;
    +-	acl_entry_type_t entry_type;
    +-#endif	/* !HAVE_DARWIN_ACL */
    +-	acl_tag_t tag_type;
    +-	acl_permset_t opaque_ps;
    +-	acl_flagset_t opaque_fs;
    +-#endif	/* !HAVE_SUN_ACL */
    + 	int perms;
    + 
    +-#if HAVE_SUN_ACL
    + 	perms = acl_permset_to_bitmap(ace->a_access_mask) | acl_flagset_to_bitmap(ace->a_flags);
    +-#else
    +-	acl_get_tag_type(aclent, &tag_type);
    +-#if !HAVE_DARWIN_ACL
    +-	acl_get_entry_type_np(aclent, &entry_type);
    +-#endif
    + 
    +-	/* translate the silly opaque permset to a bitmap */
    +-	acl_get_permset(aclent, &opaque_ps);
    +-	acl_get_flagset_np(aclent, &opaque_fs);
    +-	perms = acl_permset_to_bitmap(opaque_ps) | acl_flagset_to_bitmap(opaque_fs);
    +-#endif
    + 	if (perms != myacl->permset)
    + 		return (0);
    + 
    +-#if HAVE_SUN_ACL
    + 	switch (ace->a_type) {
    + 	case ACE_ACCESS_ALLOWED_ACE_TYPE:
    + 		if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW)
    +@@ -470,7 +481,85 @@ acl_match(acl_entry_t aclent, struct myacl_t *myacl)
    + 		if ((uid_t)myacl->qual != ace->a_who)
    + 			return (0);
    + 	}
    +-#elif HAVE_DARWIN_ACL
    ++	return (1);
    ++}
    ++#elif ARCHIVE_ACL_LIBRICHACL
    ++static int
    ++acl_match(struct richace *richace, struct myacl_t *myacl)
    ++{
    ++	int perms;
    ++
    ++	perms = acl_permset_to_bitmap(richace->e_mask) |
    ++	    acl_flagset_to_bitmap(richace->e_flags);
    ++
    ++	if (perms != myacl->permset)
    ++		return (0);
    ++
    ++	switch (richace->e_type) {
    ++	case RICHACE_ACCESS_ALLOWED_ACE_TYPE:
    ++		if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW)
    ++			return (0);
    ++		break;
    ++	case RICHACE_ACCESS_DENIED_ACE_TYPE:
    ++		if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_DENY)
    ++			return (0);
    ++		break;
    ++	default:
    ++		return (0);
    ++	}
    ++
    ++	if (richace->e_flags & RICHACE_SPECIAL_WHO) {
    ++		switch (richace->e_id) {
    ++		case RICHACE_OWNER_SPECIAL_ID:
    ++			if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ)
    ++				return (0);
    ++			break;
    ++		case RICHACE_GROUP_SPECIAL_ID:
    ++			if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ)
    ++				return (0);
    ++			break;
    ++		case RICHACE_EVERYONE_SPECIAL_ID:
    ++			if (myacl->tag != ARCHIVE_ENTRY_ACL_EVERYONE)
    ++				return (0);
    ++			break;
    ++		default:
    ++			/* Invalid e_id */
    ++			return (0);
    ++		}
    ++	} else if (richace->e_flags & RICHACE_IDENTIFIER_GROUP) {
    ++		if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
    ++			return (0);
    ++		if ((gid_t)myacl->qual != richace->e_id)
    ++			return (0);
    ++	} else {
    ++		if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
    ++			return (0);
    ++		if ((uid_t)myacl->qual != richace->e_id)
    ++			return (0);
    ++	}
    ++	return (1);
    ++}
    ++#elif ARCHIVE_ACL_DARWIN
    ++static int
    ++acl_match(acl_entry_t aclent, struct myacl_t *myacl)
    ++{
    ++	void *q;
    ++	uid_t ugid;
    ++	int r, idtype;
    ++	acl_tag_t tag_type;
    ++	acl_permset_t opaque_ps;
    ++	acl_flagset_t opaque_fs;
    ++	int perms;
    ++
    ++	acl_get_tag_type(aclent, &tag_type);
    ++
    ++	/* translate the silly opaque permset to a bitmap */
    ++	acl_get_permset(aclent, &opaque_ps);
    ++	acl_get_flagset_np(aclent, &opaque_fs);
    ++	perms = acl_permset_to_bitmap(opaque_ps) | acl_flagset_to_bitmap(opaque_fs);
    ++	if (perms != myacl->permset)
    ++		return (0);
    ++
    + 	r = 0;
    + 	switch (tag_type) {
    + 	case ACL_EXTENDED_ALLOW:
    +@@ -507,7 +596,30 @@ acl_match(acl_entry_t aclent, struct myacl_t *myacl)
    + 		default:
    + 			return (0);
    + 	}
    +-#else	/* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
    ++	return (1);
    ++}
    ++#else /* ARCHIVE_ACL_FREEBSD_NFS4 */
    ++static int
    ++acl_match(acl_entry_t aclent, struct myacl_t *myacl)
    ++{
    ++	gid_t g, *gp;
    ++	uid_t u, *up;
    ++	acl_entry_type_t entry_type;
    ++	acl_tag_t tag_type;
    ++	acl_permset_t opaque_ps;
    ++	acl_flagset_t opaque_fs;
    ++	int perms;
    ++
    ++	acl_get_tag_type(aclent, &tag_type);
    ++	acl_get_entry_type_np(aclent, &entry_type);
    ++
    ++	/* translate the silly opaque permset to a bitmap */
    ++	acl_get_permset(aclent, &opaque_ps);
    ++	acl_get_flagset_np(aclent, &opaque_fs);
    ++	perms = acl_permset_to_bitmap(opaque_ps) | acl_flagset_to_bitmap(opaque_fs);
    ++	if (perms != myacl->permset)
    ++		return (0);
    ++
    + 	switch (entry_type) {
    + 	case ACL_ENTRY_TYPE_ALLOW:
    + 		if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW)
    +@@ -559,14 +671,17 @@ acl_match(acl_entry_t aclent, struct myacl_t *myacl)
    + 		if (myacl->tag != ARCHIVE_ENTRY_ACL_EVERYONE) return (0);
    + 		break;
    + 	}
    +-#endif	/* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
    + 	return (1);
    + }
    ++#endif	/* various ARCHIVE_ACL_NFS4 implementations */
    + 
    + static void
    + compare_acls(
    +-#if HAVE_SUN_ACL
    +-    acl_t *acl,
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++    void *aclp,
    ++    int aclcnt,
    ++#elif ARCHIVE_ACL_LIBRICHACL
    ++    struct richacl *richacl,
    + #else
    +     acl_t acl,
    + #endif
    +@@ -575,38 +690,61 @@ compare_acls(
    + 	int *marker;
    + 	int matched;
    + 	int i, n;
    +-#if HAVE_SUN_ACL
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    + 	int e;
    + 	ace_t *acl_entry;
    ++#elif ARCHIVE_ACL_LIBRICHACL
    ++	int e;
    ++	struct richace *acl_entry;
    ++	int aclcnt;
    + #else
    + 	int entry_id = ACL_FIRST_ENTRY;
    + 	acl_entry_t acl_entry;
    ++#if ARCHIVE_ACL_DARWIN
    ++	const int acl_get_entry_ret = 0;
    ++#else
    ++	const int acl_get_entry_ret = 1;
    ++#endif
    ++#endif
    ++
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++	if (aclp == NULL)
    ++		return;
    ++#elif ARCHIVE_ACL_LIBRICHACL
    ++	if (richacl == NULL)
    ++		return;
    ++	aclcnt = richacl->a_count;
    ++#else
    ++	if (acl == NULL)
    ++		return;
    + #endif
    + 
    + 	n = end - start;
    + 	marker = malloc(sizeof(marker[0]) * (n + 1));
    + 	for (i = 0; i < n; i++)
    + 		marker[i] = i + start;
    ++#if !ARCHIVE_ACL_DARWIN
    + 	/* Always include the first ACE. */
    + 	if (start > 0) {
    + 	  marker[n] = 0;
    + 	  ++n;
    + 	}
    ++#endif
    + 
    + 	/*
    + 	 * Iterate over acls in system acl object, try to match each
    + 	 * one with an item in the myacls array.
    + 	 */
    +-#if HAVE_SUN_ACL
    +-	for (e = 0; e < acl->acl_cnt; e++)
    +-#elif HAVE_DARWIN_ACL
    +-	while (0 == acl_get_entry(acl, entry_id, &acl_entry))
    ++#if ARCHIVE_ACL_SUNOS_NFS4 || ARCHIVE_ACL_LIBRICHACL
    ++	for (e = 0; e < aclcnt; e++)
    + #else
    +-	while (1 == acl_get_entry(acl, entry_id, &acl_entry))
    ++	while (acl_get_entry_ret == acl_get_entry(acl, entry_id, &acl_entry))
    + #endif
    + 	{
    +-#if HAVE_SUN_ACL
    +-		acl_entry = &((ace_t *)acl->acl_aclp)[e];
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++		acl_entry = &((ace_t *)aclp)[e];
    ++#elif ARCHIVE_ACL_LIBRICHACL
    ++		acl_entry = &(richacl->a_entries[e]);
    + #else
    + 		/* After the first time... */
    + 		entry_id = ACL_NEXT_ENTRY;
    +@@ -699,7 +837,7 @@ compare_entry_acls(struct archive_entry *ae, struct myacl_t *myacls, const char
    + 	}
    + 	free(marker);
    + }
    +-#endif	/* HAVE_NFS4_ACL */
    ++#endif	/* ARCHIVE_ACL_NFS4 */
    + 
    + /*
    +  * Verify ACL restore-to-disk.  This test is Platform-specific.
    +@@ -707,101 +845,36 @@ compare_entry_acls(struct archive_entry *ae, struct myacl_t *myacls, const char
    + 
    + DEFINE_TEST(test_acl_platform_nfs4)
    + {
    +-#if !HAVE_NFS4_ACL
    ++#if !ARCHIVE_ACL_NFS4
    + 	skipping("NFS4 ACLs are not supported on this platform");
    +-#else
    ++#else /* ARCHIVE_ACL_NFS4 */
    + 	char buff[64];
    ++	int i;
    + 	struct stat st;
    + 	struct archive *a;
    + 	struct archive_entry *ae;
    +-	int i, n;
    +-	char *func;
    +-#if HAVE_DARWIN_ACL /* On MacOS we skip trivial ACLs in some tests */
    ++#if ARCHIVE_ACL_DARWIN /* On MacOS we skip trivial ACLs in some tests */
    + 	const int regcnt = acls_reg_cnt - 4;
    + 	const int dircnt = acls_dir_cnt - 4;
    + #else
    + 	const int regcnt = acls_reg_cnt;
    + 	const int dircnt = acls_dir_cnt;
    + #endif
    +-#if HAVE_SUN_ACL
    +-	acl_t *acl;
    +-#else	/* !HAVE_SUN_ACL */
    +-#if HAVE_DARWIN_ACL
    +-	acl_entry_t aclent;
    +-	acl_permset_t permset;
    +-	const uid_t uid = 1000;
    +-	uuid_t uuid;
    +-#endif	/* HAVE_DARWIN_ACL */
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++	void *aclp;
    ++	int aclcnt;
    ++#elif ARCHIVE_ACL_LIBRICHACL
    ++	struct richacl *richacl;
    ++#else	/* !ARCHIVE_ACL_SUNOS_NFS4 */
    + 	acl_t acl;
    +-#endif	/* !HAVE_SUN_ACL */
    +-
    +-	/*
    +-	 * First, do a quick manual set/read of ACL data to
    +-	 * verify that the local filesystem does support ACLs.
    +-	 * If it doesn't, we'll simply skip the remaining tests.
    +-	 */
    +-#if HAVE_POSIX_ACL && HAVE_ACL_TYPE_NFS4
    +-	acl = acl_from_text("owner@:rwxp::allow,group@:rwp:f:allow");
    +-	failure("acl_from_text(): errno = %d (%s)", errno, strerror(errno));
    +-	assert((void *)acl != NULL);
    +-#elif HAVE_DARWIN_ACL
    +-	acl = acl_init(1);
    +-	assert((void *)acl != NULL);
    +-	assertEqualInt(0, acl_create_entry(&acl, &aclent));
    +-	assertEqualInt(0, acl_set_tag_type(aclent, ACL_EXTENDED_ALLOW));
    +-	assertEqualInt(0, acl_get_permset(aclent, &permset));
    +-	assertEqualInt(0, acl_add_perm(permset, ACL_READ_DATA));
    +-	assertEqualInt(0, acl_add_perm(permset, ACL_WRITE_DATA));
    +-	assertEqualInt(0, acl_add_perm(permset, ACL_APPEND_DATA));
    +-	assertEqualInt(0, acl_add_perm(permset, ACL_EXECUTE));
    +-	assertEqualInt(0, acl_set_permset(aclent, permset));
    +-	assertEqualInt(0, mbr_identifier_to_uuid(ID_TYPE_UID, &uid,
    +-	    sizeof(uid_t), uuid));
    +-	assertEqualInt(0, acl_set_qualifier(aclent, uuid));
    +-#endif
    +-
    +-	/* Create a test dir and try to set an ACL on it. */
    +-	if (!assertMakeDir("pretest", 0755)) {
    +-#if !HAVE_SUN_ACL
    +-		acl_free(acl);
    + #endif
    +-		return;
    +-	}
    + 
    +-#if HAVE_SUN_ACL
    +-	func = "acl_get()";
    +-	n = acl_get("pretest", 0, &acl);
    +-#else
    +-	func = "acl_set_file()";
    +-#if HAVE_DARWIN_ACL
    +-	n = acl_set_file("pretest", ACL_TYPE_EXTENDED, acl);
    +-#else
    +-	n = acl_set_file("pretest", ACL_TYPE_NFS4, acl);
    +-#endif
    +-	acl_free(acl);
    +-#endif
    +-	if (n != 0) {
    +-#if HAVE_SUN_ACL
    +-		if (errno == ENOSYS)
    +-#else
    +-		if (errno == EOPNOTSUPP || errno == EINVAL)
    +-#endif
    +-		{
    +-			skipping("NFS4 ACL is not supported on this filesystem");
    +-			return;
    +-		}
    +-	}
    +-	failure("%s: errno = %d (%s)", func, errno, strerror(errno));
    +-	assertEqualInt(0, n);
    ++	assertMakeFile("pretest", 0644, "a");
    + 
    +-#if HAVE_SUN_ACL
    +-	if (acl->acl_type != ACE_T) {
    +-		acl_free(acl);
    +-		skipping("NFS4 ACL is not supported on this filesystem");
    ++	if (setTestAcl("pretest") != ARCHIVE_TEST_ACL_TYPE_NFS4) {
    ++		skipping("NFS4 ACLs are not writable on this filesystem");
    + 		return;
    + 	}
    +-	acl_free(acl);
    +-#endif
    + 
    + 	/* Create a write-to-disk object. */
    + 	assert(NULL != (a = archive_write_disk_new()));
    +@@ -848,63 +921,115 @@ DEFINE_TEST(test_acl_platform_nfs4)
    + 	/* Verify the data on disk. */
    + 	assertEqualInt(0, stat("testall", &st));
    + 	assertEqualInt(st.st_mtime, 123456);
    +-#if HAVE_SUN_ACL
    +-	n = acl_get("testall", 0, &acl);
    +-	failure("acl_get(): errno = %d (%s)", errno, strerror(errno));
    +-	assertEqualInt(0, n);
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++	aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, "testall");
    ++	failure("acl(\"%s\"): errno = %d (%s)", "testall", errno,
    ++	    strerror(errno));
    ++	assert(aclp != NULL);
    ++#elif ARCHIVE_ACL_LIBRICHACL
    ++	richacl = richacl_get_file("testall");
    ++	failure("richacl_get_file(\"%s\"): errno = %d (%s)", "testall", errno,
    ++	    strerror(errno));
    ++	assert(richacl != NULL);
    + #else
    +-#if HAVE_DARWIN_ACL
    ++#if ARCHIVE_ACL_DARWIN
    + 	acl = acl_get_file("testall", ACL_TYPE_EXTENDED);
    + #else
    + 	acl = acl_get_file("testall", ACL_TYPE_NFS4);
    + #endif
    +-	failure("acl_get_file(): errno = %d (%s)", errno, strerror(errno));
    ++	failure("acl_get_file(\"%s\"): errno = %d (%s)", "testall", errno,
    ++	    strerror(errno));
    + 	assert(acl != (acl_t)NULL);
    + #endif
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++	compare_acls(aclp, aclcnt, acls_reg, "testall", 0, regcnt);
    ++	free(aclp);
    ++	aclp = NULL;
    ++#elif ARCHIVE_ACL_LIBRICHACL
    ++	compare_acls(richacl, acls_reg, "testall", 0, regcnt);
    ++	richacl_free(richacl);
    ++#else
    + 	compare_acls(acl, acls_reg, "testall", 0, regcnt);
    + 	acl_free(acl);
    ++#endif
    ++
    + 
    + 	/* Verify single-permission dirs on disk. */
    + 	for (i = 0; i < dircnt; ++i) {
    + 		sprintf(buff, "dir%d", i);
    + 		assertEqualInt(0, stat(buff, &st));
    + 		assertEqualInt(st.st_mtime, 123456 + i);
    +-#if HAVE_SUN_ACL
    +-		n = acl_get(buff, 0, &acl);
    +-		failure("acl_get(): errno = %d (%s)", errno, strerror(errno));
    +-		assertEqualInt(0, n);
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++		aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, buff);
    ++		failure("acl(\"%s\"): errno = %d (%s)", buff, errno,
    ++		    strerror(errno));
    ++		assert(aclp != NULL);
    ++#elif ARCHIVE_ACL_LIBRICHACL
    ++		richacl = richacl_get_file(buff);
    ++		/* First and last two dir do not return a richacl */
    ++		if ((i == 0 || i >= dircnt - 2) && richacl == NULL &&
    ++		    errno == ENODATA)
    ++			continue;
    ++		failure("richacl_get_file(\"%s\"): errno = %d (%s)", buff,
    ++		    errno, strerror(errno));
    ++		assert(richacl != NULL);
    + #else
    +-#if HAVE_DARWIN_ACL
    ++#if ARCHIVE_ACL_DARWIN
    + 		acl = acl_get_file(buff, ACL_TYPE_EXTENDED);
    + #else
    + 		acl = acl_get_file(buff, ACL_TYPE_NFS4);
    + #endif
    +-		failure("acl_get_file(): errno = %d (%s)", errno,
    ++		failure("acl_get_file(\"%s\"): errno = %d (%s)", buff, errno,
    + 		    strerror(errno));
    + 		assert(acl != (acl_t)NULL);
    + #endif
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++		compare_acls(aclp, aclcnt, acls_dir, buff, i, i + 1);
    ++		free(aclp);
    ++		aclp = NULL;
    ++#elif ARCHIVE_ACL_LIBRICHACL
    ++		compare_acls(richacl, acls_dir, buff, i, i + 1);
    ++		richacl_free(richacl);
    ++#else
    + 		compare_acls(acl, acls_dir, buff, i, i + 1);
    + 		acl_free(acl);
    ++#endif
    + 	}
    + 
    + 	/* Verify "dirall" on disk. */
    + 	assertEqualInt(0, stat("dirall", &st));
    + 	assertEqualInt(st.st_mtime, 123456);
    +-#if HAVE_SUN_ACL
    +-	n = acl_get("dirall", 0, &acl);
    +-	failure("acl_get(): errno = %d (%s)", errno, strerror(errno));
    +-	assertEqualInt(0, n);
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++	aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, "dirall");
    ++	failure("acl(\"%s\"): errno = %d (%s)", "dirall", errno,
    ++	    strerror(errno));
    ++	assert(aclp != NULL);
    ++#elif ARCHIVE_ACL_LIBRICHACL
    ++	richacl = richacl_get_file("dirall");
    ++	failure("richacl_get_file(\"%s\"): errno = %d (%s)", "dirall",
    ++	    errno, strerror(errno));
    ++	assert(richacl != NULL);
    + #else
    +-#if HAVE_DARWIN_ACL
    ++#if ARCHIVE_ACL_DARWIN
    + 	acl = acl_get_file("dirall", ACL_TYPE_EXTENDED);
    + #else
    + 	acl = acl_get_file("dirall", ACL_TYPE_NFS4);
    + #endif
    +-	failure("acl_get_file(): errno = %d (%s)", errno, strerror(errno));
    ++	failure("acl_get_file(\"%s\"): errno = %d (%s)", "dirall", errno,
    ++	    strerror(errno));
    + 	assert(acl != (acl_t)NULL);
    + #endif
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++	compare_acls(aclp, aclcnt, acls_dir, "dirall", 0, dircnt);
    ++	free(aclp);
    ++	aclp = NULL;
    ++#elif ARCHIVE_ACL_LIBRICHACL
    ++	compare_acls(richacl, acls_dir, "dirall", 0, dircnt);
    ++	richacl_free(richacl);
    ++#else
    + 	compare_acls(acl, acls_dir, "dirall", 0, dircnt);
    + 	acl_free(acl);
    ++#endif
    + 
    + 	/* Read and compare ACL via archive_read_disk */
    + 	a = archive_read_disk_new();
    +@@ -929,5 +1054,5 @@ DEFINE_TEST(test_acl_platform_nfs4)
    + 	compare_entry_acls(ae, acls_dir, "dirall", 0, acls_dir_cnt);
    + 	archive_entry_free(ae);
    + 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
    +-#endif /* HAVE_NFS4_ACL */
    ++#endif /* ARCHIVE_ACL_NFS4 */
    + }
    +--- libarchive/test/test_acl_platform_posix1e.c.orig
    ++++ libarchive/test/test_acl_platform_posix1e.c
    +@@ -26,7 +26,7 @@
    + #include "test.h"
    + __FBSDID("$FreeBSD: head/lib/libarchive/test/test_acl_freebsd.c 189427 2009-03-06 04:21:23Z kientzle $");
    + 
    +-#if HAVE_POSIX_ACL || HAVE_SUN_ACL
    ++#if ARCHIVE_ACL_POSIX1E
    + #include <sys/acl.h>
    + #if HAVE_ACL_GET_PERM
    + #include <acl/libacl.h>
    +@@ -55,18 +55,18 @@ static struct archive_test_acl_t acls2[] = {
    + };
    + 
    + static int
    +-#if HAVE_SUN_ACL
    ++#if ARCHIVE_ACL_SUNOS
    + acl_entry_get_perm(aclent_t *aclent)
    + #else
    + acl_entry_get_perm(acl_entry_t aclent)
    + #endif
    + {
    + 	int permset = 0;
    +-#if HAVE_POSIX_ACL
    ++#if ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL
    + 	acl_permset_t opaque_ps;
    + #endif
    + 
    +-#if HAVE_SUN_ACL
    ++#if ARCHIVE_ACL_SUNOS
    + 	if (aclent->a_perm & 1)
    + 		permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
    + 	if (aclent->a_perm & 2)
    +@@ -127,114 +127,108 @@ acl_get_specific_entry(acl_t acl, acl_tag_t requested_tag_type, int requested_ta
    + }
    + #endif
    + 
    ++#if ARCHIVE_ACL_SUNOS
    + static int
    +-#if HAVE_SUN_ACL
    + acl_match(aclent_t *aclent, struct archive_test_acl_t *myacl)
    +-#else
    ++{
    ++
    ++	if (myacl->permset != acl_entry_get_perm(aclent))
    ++		return (0);
    ++
    ++	switch (aclent->a_type) {
    ++	case DEF_USER_OBJ:
    ++	case USER_OBJ:
    ++		if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) return (0);
    ++		break;
    ++		if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
    ++			return (0);
    ++		if ((uid_t)myacl->qual != aclent->a_id)
    ++			return (0);
    ++		break;
    ++	case DEF_GROUP_OBJ:
    ++	case GROUP_OBJ:
    ++		if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ) return (0);
    ++		break;
    ++	case DEF_GROUP:
    ++	case GROUP:
    ++		if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
    ++			return (0);
    ++		if ((gid_t)myacl->qual != aclent->a_id)
    ++			return (0);
    ++		break;
    ++	case DEF_CLASS_OBJ:
    ++	case CLASS_OBJ:
    ++		if (myacl->tag != ARCHIVE_ENTRY_ACL_MASK) return (0);
    ++		break;
    ++	case DEF_OTHER_OBJ:
    ++	case OTHER_OBJ:
    ++		if (myacl->tag != ARCHIVE_ENTRY_ACL_OTHER) return (0);
    ++		break;
    ++	}
    ++	return (1);
    ++}
    ++
    ++#else	/* ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL */
    ++static int
    + acl_match(acl_entry_t aclent, struct archive_test_acl_t *myacl)
    +-#endif
    + {
    +-#if HAVE_POSIX_ACL
    + 	gid_t g, *gp;
    + 	uid_t u, *up;
    + 	acl_tag_t tag_type;
    +-#endif
    + 
    + 	if (myacl->permset != acl_entry_get_perm(aclent))
    + 		return (0);
    + 
    +-#if HAVE_SUN_ACL
    +-	switch (aclent->a_type)
    +-#else
    + 	acl_get_tag_type(aclent, &tag_type);
    +-	switch (tag_type)
    +-#endif
    +-	{
    +-#if HAVE_SUN_ACL
    +-	case DEF_USER_OBJ:
    +-	case USER_OBJ:
    +-#else
    ++	switch (tag_type) {
    + 	case ACL_USER_OBJ:
    +-#endif
    + 		if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) return (0);
    + 		break;
    +-#if HAVE_SUN_ACL
    +-	case DEF_USER:
    +-	case USER:
    +-#else
    + 	case ACL_USER:
    +-#endif
    + 		if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
    + 			return (0);
    +-#if HAVE_SUN_ACL
    +-		if ((uid_t)myacl->qual != aclent->a_id)
    +-			return (0);
    +-#else
    + 		up = acl_get_qualifier(aclent);
    + 		u = *up;
    + 		acl_free(up);
    + 		if ((uid_t)myacl->qual != u)
    + 			return (0);
    +-#endif
    + 		break;
    +-#if HAVE_SUN_ACL
    +-	case DEF_GROUP_OBJ:
    +-	case GROUP_OBJ:
    +-#else
    + 	case ACL_GROUP_OBJ:
    +-#endif
    + 		if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ) return (0);
    + 		break;
    +-#if HAVE_SUN_ACL
    +-	case DEF_GROUP:
    +-	case GROUP:
    +-#else
    + 	case ACL_GROUP:
    +-#endif
    + 		if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
    + 			return (0);
    +-#if HAVE_SUN_ACL
    +-		if ((gid_t)myacl->qual != aclent->a_id)
    +-			return (0);
    +-#else
    + 		gp = acl_get_qualifier(aclent);
    + 		g = *gp;
    + 		acl_free(gp);
    + 		if ((gid_t)myacl->qual != g)
    + 			return (0);
    +-#endif
    + 		break;
    +-#if HAVE_SUN_ACL
    +-	case DEF_CLASS_OBJ:
    +-	case CLASS_OBJ:
    +-#else
    + 	case ACL_MASK:
    +-#endif
    + 		if (myacl->tag != ARCHIVE_ENTRY_ACL_MASK) return (0);
    + 		break;
    +-#if HAVE_SUN_ACL
    +-	case DEF_OTHER_OBJ:
    +-	case OTHER_OBJ:
    +-#else
    + 	case ACL_OTHER:
    +-#endif
    + 		if (myacl->tag != ARCHIVE_ENTRY_ACL_OTHER) return (0);
    + 		break;
    + 	}
    + 	return (1);
    + }
    ++#endif
    + 
    + static void
    +-#if HAVE_SUN_ACL
    +-compare_acls(acl_t *acl, struct archive_test_acl_t *myacls, int n)
    ++compare_acls(
    ++#if ARCHIVE_ACL_SUNOS
    ++    void *aclp, int aclcnt,
    + #else
    +-compare_acls(acl_t acl, struct archive_test_acl_t *myacls, int n)
    ++    acl_t acl,
    + #endif
    ++    struct archive_test_acl_t *myacls, int n)
    + {
    + 	int *marker;
    + 	int matched;
    + 	int i;
    +-#if HAVE_SUN_ACL
    ++#if ARCHIVE_ACL_SUNOS
    + 	int e;
    + 	aclent_t *acl_entry;
    + #else
    +@@ -253,9 +247,9 @@ compare_acls(acl_t acl, struct archive_test_acl_t *myacls, int n)
    + 	 * Iterate over acls in system acl object, try to match each
    + 	 * one with an item in the myacls array.
    + 	 */
    +-#if HAVE_SUN_ACL
    +-	for(e = 0; e < acl->acl_cnt; e++) {
    +-		acl_entry = &((aclent_t *)acl->acl_aclp)[e];
    ++#if ARCHIVE_ACL_SUNOS
    ++	for(e = 0; e < aclcnt; e++) {
    ++		acl_entry = &((aclent_t *)aclp)[e];
    + #else
    + 	while (1 == acl_get_entry(acl, entry_id, &acl_entry)) {
    + 		/* After the first time... */
    +@@ -288,99 +282,33 @@ compare_acls(acl_t acl, struct archive_test_acl_t *myacls, int n)
    + 	}
    + 	free(marker);
    + }
    +-
    + #endif
    + 
    +-
    + /*
    +  * Verify ACL restore-to-disk.  This test is Platform-specific.
    +  */
    + 
    + DEFINE_TEST(test_acl_platform_posix1e_restore)
    + {
    +-#if !HAVE_SUN_ACL && !HAVE_POSIX_ACL
    ++#if !ARCHIVE_ACL_POSIX1E
    + 	skipping("POSIX.1e ACLs are not supported on this platform");
    +-#else	/* HAVE_SUN_ACL || HAVE_POSIX_ACL */
    ++#else	/* ARCHIVE_ACL_POSIX1E */
    + 	struct stat st;
    + 	struct archive *a;
    + 	struct archive_entry *ae;
    +-	int n, fd;
    +-	char *func;
    +-#if HAVE_SUN_ACL
    +-	acl_t *acl, *acl2;
    ++#if ARCHIVE_ACL_SUNOS
    ++	void *aclp;
    ++	int aclcnt;
    + #else
    + 	acl_t acl;
    + #endif
    + 
    +-	/*
    +-	 * First, do a quick manual set/read of ACL data to
    +-	 * verify that the local filesystem does support ACLs.
    +-	 * If it doesn't, we'll simply skip the remaining tests.
    +-	 */
    +-#if HAVE_SUN_ACL
    +-	n = acl_fromtext("user::rwx,user:1:rw-,group::rwx,group:15:r-x,other:rwx,mask:rwx", &acl);
    +-	failure("acl_fromtext(): errno = %d (%s)", errno, strerror(errno));
    +-	assertEqualInt(0, n);
    +-#else
    +-	acl = acl_from_text("u::rwx,u:1:rw,g::rwx,g:15:rx,o::rwx,m::rwx");
    +-	failure("acl_from_text(): errno = %d (%s)", errno, strerror(errno));
    +-	assert((void *)acl != NULL);
    +-#endif
    +-
    +-	/* Create a test file and try ACL on it. */
    +-	fd = open("pretest", O_WRONLY | O_CREAT | O_EXCL, 0777);
    +-	failure("Could not create test file?!");
    +-	if (!assert(fd >= 0)) {
    +-		acl_free(acl);
    +-		return;
    +-	}
    +-
    +-#if HAVE_SUN_ACL
    +-	n = facl_get(fd, 0, &acl2);
    +-	if (n != 0) {
    +-		close(fd);
    +-		acl_free(acl);
    +-	}
    +-	if (errno == ENOSYS) {
    +-		skipping("POSIX.1e ACLs are not supported on this filesystem");
    +-		return;
    +-	}
    +-	failure("facl_get(): errno = %d (%s)", errno, strerror(errno));
    +-	assertEqualInt(0, n);
    ++	assertMakeFile("pretest", 0644, "a");
    + 
    +-	if (acl2->acl_type != ACLENT_T) {
    +-		acl_free(acl2);
    +-		skipping("POSIX.1e ACLs are not supported on this filesystem");
    ++	if (setTestAcl("pretest") != ARCHIVE_TEST_ACL_TYPE_POSIX1E) {
    ++		skipping("POSIX.1e ACLs are not writable on this filesystem");
    + 		return;
    + 	}
    +-	acl_free(acl2);
    +-
    +-	func = "facl_set()";
    +-	n = facl_set(fd, acl);
    +-#else
    +-	func = "acl_set_fd()";
    +-	n = acl_set_fd(fd, acl);
    +-#endif
    +-	acl_free(acl);
    +-	if (n != 0) {
    +-#if HAVE_SUN_ACL
    +-		if (errno == ENOSYS)
    +-#else
    +-		if (errno == EOPNOTSUPP || errno == EINVAL)
    +-#endif
    +-		{
    +-			close(fd);
    +-			skipping("POSIX.1e ACLs are not supported on this filesystem");
    +-			return;
    +-		}
    +-	}
    +-	failure("%s: errno = %d (%s)", func, errno, strerror(errno));
    +-	assertEqualInt(0, n);
    +-
    +-#if HAVE_SUN_ACL
    +-
    +-#endif
    +-	close(fd);
    + 
    + 	/* Create a write-to-disk object. */
    + 	assert(NULL != (a = archive_write_disk_new()));
    +@@ -404,18 +332,25 @@ DEFINE_TEST(test_acl_platform_posix1e_restore)
    + 	/* Verify the data on disk. */
    + 	assertEqualInt(0, stat("test0", &st));
    + 	assertEqualInt(st.st_mtime, 123456);
    +-#if HAVE_SUN_ACL
    +-	n = acl_get("test0", 0, &acl);
    +-	failure("acl_get(): errno = %d (%s)", errno, strerror(errno));
    +-	assertEqualInt(0, n);
    ++#if ARCHIVE_ACL_SUNOS
    ++	aclp = sunacl_get(GETACL, &aclcnt, 0, "test0");
    ++	failure("acl(): errno = %d (%s)", errno, strerror(errno));
    ++	assert(aclp != NULL);
    + #else
    + 	acl = acl_get_file("test0", ACL_TYPE_ACCESS);
    + 	failure("acl_get_file(): errno = %d (%s)", errno, strerror(errno));
    + 	assert(acl != (acl_t)NULL);
    + #endif
    ++#if ARCHIVE_ACL_SUNOS
    ++	compare_acls(aclp, aclcnt, acls2, sizeof(acls2)/sizeof(acls2[0]));
    ++	free(aclp);
    ++	aclp = NULL;
    ++#else
    + 	compare_acls(acl, acls2, sizeof(acls2)/sizeof(acls2[0]));
    + 	acl_free(acl);
    +-#endif	/* HAVE_SUN_ACL || HAVE_POSIX_ACL */
    ++#endif
    ++
    ++#endif	/* ARCHIVE_ACL_POSIX1E */
    + }
    + 
    + /*
    +@@ -423,16 +358,17 @@ DEFINE_TEST(test_acl_platform_posix1e_restore)
    +  */
    + DEFINE_TEST(test_acl_platform_posix1e_read)
    + {
    +-#if !HAVE_SUN_ACL && !HAVE_POSIX_ACL
    ++#if !ARCHIVE_ACL_POSIX1E
    + 	skipping("POSIX.1e ACLs are not supported on this platform");
    +-#else
    ++#else /* ARCHIVE_ACL_POSIX1E */
    + 	struct archive *a;
    + 	struct archive_entry *ae;
    + 	int n, fd, flags, dflags;
    + 	char *func, *acl_text;
    + 	const char *acl1_text, *acl2_text, *acl3_text;
    +-#if HAVE_SUN_ACL
    +-	acl_t *acl, *acl1, *acl2, *acl3;
    ++#if ARCHIVE_ACL_SUNOS
    ++	void *aclp;
    ++	int aclcnt;
    + #else
    + 	acl_t acl1, acl2, acl3;
    + #endif
    +@@ -444,16 +380,21 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
    + 	 */
    + 
    + 	/* Create a test file f1 with acl1 */
    +-#if HAVE_SUN_ACL
    ++#if ARCHIVE_ACL_SUNOS
    + 	acl1_text = "user::rwx,"
    + 	    "group::rwx,"
    + 	    "other:rwx,"
    + 	    "user:1:rw-,"
    + 	    "group:15:r-x,"
    + 	    "mask:rwx";
    +-	n = acl_fromtext(acl1_text, &acl1);
    +-	failure("acl_fromtext(): errno = %d (%s)", errno, strerror(errno));
    +-	assertEqualInt(0, n);
    ++	aclent_t aclp1[] = {
    ++	    { USER_OBJ, -1, 4 | 2 | 1 },
    ++	    { USER, 1, 4 | 2 },
    ++	    { GROUP_OBJ, -1, 4 | 2 | 1 },
    ++	    { GROUP, 15, 4 | 1 },
    ++	    { CLASS_OBJ, -1, 4 | 2 | 1 },
    ++	    { OTHER_OBJ, -1, 4 | 2 | 1 }
    ++	};
    + #else
    + 	acl1_text = "user::rwx\n"
    + 	    "group::rwx\n"
    +@@ -468,41 +409,36 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
    + 	fd = open("f1", O_WRONLY | O_CREAT | O_EXCL, 0777);
    + 	failure("Could not create test file?!");
    + 	if (!assert(fd >= 0)) {
    ++#if !ARCHIVE_ACL_SUNOS
    + 		acl_free(acl1);
    ++#endif
    + 		return;
    + 	}
    +-#if HAVE_SUN_ACL
    ++#if ARCHIVE_ACL_SUNOS
    + 	/* Check if Solaris filesystem supports POSIX.1e ACLs */
    +-	n = facl_get(fd, 0, &acl);
    +-	if (n != 0)
    ++	aclp = sunacl_get(GETACL, &aclcnt, fd, NULL);
    ++	if (aclp == 0)
    + 		close(fd);
    +-	if (n != 0 && errno == ENOSYS) {
    +-		acl_free(acl1);
    ++	if (errno == ENOSYS || errno == ENOTSUP) {
    + 		skipping("POSIX.1e ACLs are not supported on this filesystem");
    + 		return;
    + 	}
    +-	failure("facl_get(): errno = %d (%s)", errno, strerror(errno));
    +-	assertEqualInt(0, n);
    ++	failure("facl(): errno = %d (%s)", errno, strerror(errno));
    ++	assert(aclp != NULL);
    + 
    +-	if (acl->acl_type != ACLENT_T) {
    +-		acl_free(acl);
    +-		acl_free(acl1);
    +-		close(fd);
    +-		skipping("POSIX.1e ACLs are not supported on this filesystem");
    +-		return;
    +-	}
    +-
    +-	func = "facl_set()";
    +-	n = facl_set(fd, acl1);
    ++	func = "facl()";
    ++	n = facl(fd, SETACL, (int)(sizeof(aclp1)/sizeof(aclp1[0])), aclp1);
    + #else
    + 	func = "acl_set_fd()";
    + 	n = acl_set_fd(fd, acl1);
    + #endif
    ++#if !ARCHIVE_ACL_SUNOS
    + 	acl_free(acl1);
    ++#endif
    + 
    + 	if (n != 0) {
    +-#if HAVE_SUN_ACL
    +-		if (errno == ENOSYS)
    ++#if ARCHIVE_ACL_SUNOS
    ++		if (errno == ENOSYS || errno == ENOTSUP)
    + #else
    + 		if (errno == EOPNOTSUPP || errno == EINVAL)
    + #endif
    +@@ -530,16 +466,21 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
    + 	 * to read ACLs, resulting in reading the ACL from a like-named
    + 	 * file in the wrong directory.
    + 	 */
    +-#if HAVE_SUN_ACL
    ++#if ARCHIVE_ACL_SUNOS
    + 	acl2_text = "user::rwx,"
    + 	    "group::rwx,"
    + 	    "other:---,"
    + 	    "user:1:r--,"
    + 	    "group:15:r--,"
    + 	    "mask:rwx";
    +-	n = acl_fromtext(acl2_text, &acl2);
    +-	failure("acl_fromtext(): errno = %d (%s)", errno, strerror(errno));
    +-	assertEqualInt(0, n);
    ++	aclent_t aclp2[] = {
    ++	    { USER_OBJ, -1, 4 | 2 | 1 },
    ++	    { USER, 1, 4 },
    ++	    { GROUP_OBJ, -1, 4 | 2 | 1},
    ++	    { GROUP, 15, 4 },
    ++	    { CLASS_OBJ, -1, 4 | 2 | 1},
    ++	    { OTHER_OBJ, -1, 0 }
    ++	};
    + #else
    + 	acl2_text = "user::rwx\n"
    + 	    "group::rwx\n"
    +@@ -554,17 +495,19 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
    + 	fd = open("d/f1", O_WRONLY | O_CREAT | O_EXCL, 0777);
    + 	failure("Could not create test file?!");
    + 	if (!assert(fd >= 0)) {
    ++#if !ARCHIVE_ACL_SUNOS
    + 		acl_free(acl2);
    ++#endif
    + 		return;
    + 	}
    +-#if HAVE_SUN_ACL
    +-	func = "facl_set()";
    +-	n = facl_set(fd, acl2);
    ++#if ARCHIVE_ACL_SUNOS
    ++	func = "facl()";
    ++	n = facl(fd, SETACL, (int)(sizeof(aclp2) / sizeof(aclp2[0])), aclp2);
    + #else
    + 	func = "acl_set_fd()";
    + 	n = acl_set_fd(fd, acl2);
    +-#endif
    + 	acl_free(acl2);
    ++#endif
    + 	if (n != 0)
    + 		close(fd);
    + 	failure("%s: errno = %d (%s)", func, errno, strerror(errno));
    +@@ -574,7 +517,7 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
    + 	/* Create nested directory d2 with default ACLs */
    + 	assertMakeDir("d/d2", 0755);
    + 
    +-#if HAVE_SUN_ACL
    ++#if ARCHIVE_ACL_SUNOS
    + 	acl3_text = "user::rwx,"
    + 	    "group::r-x,"
    + 	    "other:r-x,"
    +@@ -587,9 +530,20 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
    + 	    "default:group:15:r--,"
    + 	    "default:mask:rwx,"
    + 	    "default:other:r-x";
    +-	n = acl_fromtext(acl3_text, &acl3);
    +-	failure("acl_fromtext(): errno = %d (%s)", errno, strerror(errno));
    +-	assertEqualInt(0, n);
    ++	aclent_t aclp3[] = {
    ++	    { USER_OBJ, -1, 4 | 2 | 1 },
    ++	    { USER, 2, 4 },
    ++	    { GROUP_OBJ, -1, 4 | 1 },
    ++	    { GROUP, 16, 2 },
    ++	    { CLASS_OBJ, -1, 4 | 2 | 1 },
    ++	    { OTHER_OBJ, -1, 4 | 1 },
    ++	    { USER_OBJ | ACL_DEFAULT, -1, 4 | 2 | 1 },
    ++	    { USER | ACL_DEFAULT, 1, 4 },
    ++	    { GROUP_OBJ | ACL_DEFAULT, -1, 4 | 1 },
    ++	    { GROUP | ACL_DEFAULT, 15, 4 },
    ++	    { CLASS_OBJ | ACL_DEFAULT, -1, 4 | 2 | 1},
    ++	    { OTHER_OBJ | ACL_DEFAULT, -1, 4 | 1 }
    ++	};
    + #else
    + 	acl3_text = "user::rwx\n"
    + 	    "user:1:r--\n"
    +@@ -602,15 +556,14 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
    + 	assert((void *)acl3 != NULL);
    + #endif
    + 
    +-#if HAVE_SUN_ACL
    +-	func = "acl_set()";
    +-	n = acl_set("d/d2", acl3);
    ++#if ARCHIVE_ACL_SUNOS
    ++	func = "acl()";
    ++	n = acl("d/d2", SETACL, (int)(sizeof(aclp3) / sizeof(aclp3[0])), aclp3);
    + #else
    + 	func = "acl_set_file()";
    + 	n = acl_set_file("d/d2", ACL_TYPE_DEFAULT, acl3);
    +-#endif
    + 	acl_free(acl3);
    +-
    ++#endif
    + 	failure("%s: errno = %d (%s)", func, errno, strerror(errno));
    + 	assertEqualInt(0, n);
    + 
    +@@ -619,7 +572,7 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
    + 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "."));
    + 	assert(NULL != (ae = archive_entry_new()));
    + 
    +-#if HAVE_SUN_ACL
    ++#if ARCHIVE_ACL_SUNOS
    + 	flags = ARCHIVE_ENTRY_ACL_TYPE_POSIX1E
    + 	    | ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA
    + 	    | ARCHIVE_ENTRY_ACL_STYLE_SOLARIS;
    +@@ -649,5 +602,5 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
    + 
    + 	archive_entry_free(ae);
    + 	assertEqualInt(ARCHIVE_OK, archive_free(a));
    +-#endif
    ++#endif /* ARCHIVE_ACL_POSIX1E */
    + }
    +--- libarchive/test/test_read_disk_directory_traversals.c.orig
    ++++ libarchive/test/test_read_disk_directory_traversals.c
    +@@ -1231,8 +1231,8 @@ test_restore_atime(void)
    + 	 * Test4: Traversals with ARCHIVE_READDISK_RESTORE_ATIME and
    + 	 * ARCHIVE_READDISK_HONOR_NODUMP
    + 	 */
    +-	assertNodump("at/f1");
    +-	assertNodump("at/f2");
    ++	assertSetNodump("at/f1");
    ++	assertSetNodump("at/f2");
    + 	assertUtimes("at/f1", 886600, 0, 886600, 0);
    + 	assertUtimes("at/f2", 886611, 0, 886611, 0);
    + 	assertUtimes("at/fe", 886611, 0, 886611, 0);
    +@@ -1450,7 +1450,7 @@ test_nodump(void)
    + 	assertMakeFile("nd/f1", 0644, "0123456789");
    + 	assertMakeFile("nd/f2", 0644, "hello world");
    + 	assertMakeFile("nd/fe", 0644, NULL);
    +-	assertNodump("nd/f2");
    ++	assertSetNodump("nd/f2");
    + 	assertUtimes("nd/f1", 886600, 0, 886600, 0);
    + 	assertUtimes("nd/f2", 886611, 0, 886611, 0);
    + 	assertUtimes("nd/fe", 886611, 0, 886611, 0);
    +--- tar/bsdtar.1.orig
    ++++ tar/bsdtar.1
    +@@ -25,7 +25,7 @@
    + .\"
    + .\" $FreeBSD$
    + .\"
    +-.Dd February 24, 2017
    ++.Dd February 25, 2017
    + .Dt TAR 1
    + .Os
    + .Sh NAME
    +@@ -450,14 +450,7 @@ This is the reverse of
    + .Fl p
    + and the default behavior if
    + .Nm
    +-is run as non-root and can be overridden by also specifying
    +-.Fl Fl acls ,
    +-.Fl Fl fflags ,
    +-.Fl Fl mac-metadata,
    +-.Fl Fl same-owner ,
    +-.Fl Fl same-permissions
    +-and
    +-.Fl Fl xattrs .
    ++is run as non-root.
    + .It Fl Fl no-xattrs
    + (c, r, u, x modes only)
    + Do not archive or extract extended attributes. This is the reverse of
    +@@ -647,16 +640,16 @@ This option suppresses these behaviors.
    + (x mode only)
    + Preserve file permissions.
    + Attempt to restore the full permissions, including owner, file modes, ACLs,
    +-extended atributes and extended file flags, if available, for each item
    +-extracted from the archive. This is the default, if
    ++extended attributes and extended file flags, if available, for each item
    ++extracted from the archive. This is te reverse of
    ++.Fl Fl no-same-permissions
    ++and the default if
    + .Nm
    +-is being run by root and can be overridden by also specifying
    ++is being run by root and can be partially overridden by also specifying
    + .Fl Fl no-acls ,
    + .Fl Fl no-fflags ,
    +-.Fl Fl no-mac-metadata,
    +-.Fl Fl no-same-owner ,
    +-.Fl Fl no-same-permissions
    +-and
    ++.Fl Fl no-mac-metadata
    ++or
    + .Fl Fl no-xattrs .
    + .It Fl Fl passphrase Ar passphrase
    + The
    +--- tar/bsdtar.c.orig
    ++++ tar/bsdtar.c
    +@@ -118,11 +118,11 @@ need_report(void)
    + }
    + #endif
    + 
    +-static void		 long_help(void);
    ++static void		 long_help(void) __LA_DEAD;
    + static void		 only_mode(struct bsdtar *, const char *opt,
    + 			     const char *valid);
    + static void		 set_mode(struct bsdtar *, char opt);
    +-static void		 version(void);
    ++static void		 version(void) __LA_DEAD;
    + 
    + /* A basic set of security flags to request from libarchive. */
    + #define	SECURITY					\
    +--- tar/bsdtar.h.orig
    ++++ tar/bsdtar.h
    +@@ -189,7 +189,7 @@ void	do_chdir(struct bsdtar *);
    + int	edit_pathname(struct bsdtar *, struct archive_entry *);
    + int	need_report(void);
    + int	pathcmp(const char *a, const char *b);
    +-void	safe_fprintf(FILE *, const char *fmt, ...);
    ++void	safe_fprintf(FILE *, const char *fmt, ...) __LA_PRINTF(2, 3);
    + void	set_chdir(struct bsdtar *, const char *newdir);
    + const char *tar_i64toa(int64_t);
    + void	tar_mode_c(struct bsdtar *bsdtar);
    +@@ -197,8 +197,8 @@ void	tar_mode_r(struct bsdtar *bsdtar);
    + void	tar_mode_t(struct bsdtar *bsdtar);
    + void	tar_mode_u(struct bsdtar *bsdtar);
    + void	tar_mode_x(struct bsdtar *bsdtar);
    +-void	usage(void);
    +-int	yes(const char *fmt, ...);
    ++void	usage(void) __LA_DEAD;
    ++int	yes(const char *fmt, ...) __LA_PRINTF(1, 2);
    + 
    + #if defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H)
    + void	add_substitution(struct bsdtar *, const char *);
    +--- tar/test/CMakeLists.txt.orig
    ++++ tar/test/CMakeLists.txt
    +@@ -34,9 +34,11 @@ IF(ENABLE_TAR AND ENABLE_TEST)
    +     test_option_U_upper.c
    +     test_option_X_upper.c
    +     test_option_a.c
    ++    test_option_acls.c
    +     test_option_b.c
    +     test_option_b64encode.c
    +     test_option_exclude.c
    ++    test_option_fflags.c
    +     test_option_gid_gname.c
    +     test_option_grzip.c
    +     test_option_j.c
    +@@ -71,6 +73,16 @@ IF(ENABLE_TAR AND ENABLE_TEST)
    +   # Register target
    +   #
    +   ADD_EXECUTABLE(bsdtar_test ${bsdtar_test_SOURCES})
    ++  IF(ENABLE_ACL)
    ++    SET(TEST_ACL_LIBS "")
    ++    IF(HAVE_LIBACL)
    ++      LIST(APPEND TEST_ACL_LIBS ${ACL_LIBRARY})
    ++    ENDIF(HAVE_LIBACL)
    ++    IF(HAVE_LIBRICHACL)
    ++      LIST(APPEND TEST_ACL_LIBS ${RICHACL_LIBRARY})
    ++    ENDIF(HAVE_LIBRICHACL)
    ++    TARGET_LINK_LIBRARIES(bsdtar_test ${TEST_ACL_LIBS})
    ++  ENDIF(ENABLE_ACL)
    +   SET_PROPERTY(TARGET bsdtar_test PROPERTY COMPILE_DEFINITIONS LIST_H)
    + 
    +   #
    +--- /dev/null
    ++++ tar/test/test_option_acls.c
    +@@ -0,0 +1,469 @@
    ++/*-
    ++ * Copyright (c) 2017 Martin Matuska
    ++ * All rights reserved.
    ++ *
    ++ * Redistribution and use in source and binary forms, with or without
    ++ * modification, are permitted provided that the following conditions
    ++ * are met:
    ++ * 1. Redistributions of source code must retain the above copyright
    ++ *    notice, this list of conditions and the following disclaimer.
    ++ * 2. Redistributions in binary form must reproduce the above copyright
    ++ *    notice, this list of conditions and the following disclaimer in the
    ++ *    documentation and/or other materials provided with the distribution.
    ++ *
    ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
    ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    ++ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
    ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    ++ */
    ++#include "test.h"
    ++__FBSDID("$FreeBSD$");
    ++
    ++#if HAVE_POSIX_ACL || HAVE_DARWIN_ACL
    ++static const acl_perm_t acl_perms[] = {
    ++#if HAVE_DARWIN_ACL
    ++    ACL_READ_DATA,
    ++    ACL_LIST_DIRECTORY,
    ++    ACL_WRITE_DATA,
    ++    ACL_ADD_FILE,
    ++    ACL_EXECUTE,
    ++    ACL_SEARCH,
    ++    ACL_DELETE,
    ++    ACL_APPEND_DATA,
    ++    ACL_ADD_SUBDIRECTORY,
    ++    ACL_DELETE_CHILD,
    ++    ACL_READ_ATTRIBUTES,
    ++    ACL_WRITE_ATTRIBUTES,
    ++    ACL_READ_EXTATTRIBUTES,
    ++    ACL_WRITE_EXTATTRIBUTES,
    ++    ACL_READ_SECURITY,
    ++    ACL_WRITE_SECURITY,
    ++    ACL_CHANGE_OWNER,
    ++    ACL_SYNCHRONIZE
    ++#else /* !HAVE_DARWIN_ACL */
    ++    ACL_EXECUTE,
    ++    ACL_WRITE,
    ++    ACL_READ,
    ++#if HAVE_FREEBSD_NFS4_ACL
    ++    ACL_READ_DATA,
    ++    ACL_LIST_DIRECTORY,
    ++    ACL_WRITE_DATA,
    ++    ACL_ADD_FILE,
    ++    ACL_APPEND_DATA,
    ++    ACL_ADD_SUBDIRECTORY,
    ++    ACL_READ_NAMED_ATTRS,
    ++    ACL_WRITE_NAMED_ATTRS,
    ++    ACL_DELETE_CHILD,
    ++    ACL_READ_ATTRIBUTES,
    ++    ACL_WRITE_ATTRIBUTES,
    ++    ACL_DELETE,
    ++    ACL_READ_ACL,
    ++    ACL_WRITE_ACL,
    ++    ACL_WRITE_OWNER,
    ++    ACL_SYNCHRONIZE
    ++#endif	/* HAVE_FREEBSD_NFS4_ACL */
    ++#endif /* !HAVE_DARWIN_ACL */
    ++};
    ++#if HAVE_DARWIN_ACL || HAVE_FREEBSD_NFS4_ACL
    ++static const acl_flag_t acl_flags[] = {
    ++#if HAVE_DARWIN_ACL
    ++    ACL_ENTRY_INHERITED,
    ++    ACL_ENTRY_FILE_INHERIT,
    ++    ACL_ENTRY_DIRECTORY_INHERIT,
    ++    ACL_ENTRY_LIMIT_INHERIT,
    ++    ACL_ENTRY_ONLY_INHERIT
    ++#else	/* HAVE_FREEBSD_NFS4_ACL */
    ++    ACL_ENTRY_FILE_INHERIT,
    ++    ACL_ENTRY_DIRECTORY_INHERIT,
    ++    ACL_ENTRY_NO_PROPAGATE_INHERIT,
    ++    ACL_ENTRY_INHERIT_ONLY,
    ++    ACL_ENTRY_SUCCESSFUL_ACCESS,
    ++    ACL_ENTRY_FAILED_ACCESS,
    ++    ACL_ENTRY_INHERITED
    ++#endif	/* HAVE_FREEBSD_NFS4_ACL */
    ++};
    ++#endif /* HAVE_DARWIN_ACL || HAVE_FREEBSD_NFS4_ACL */
    ++
    ++/*
    ++ * Compare two ACL entries on FreeBSD or on Mac OS X
    ++ */
    ++static int
    ++compare_acl_entry(acl_entry_t ae_a, acl_entry_t ae_b, int is_nfs4)
    ++{
    ++	acl_tag_t tag_a, tag_b;
    ++	acl_permset_t permset_a, permset_b;
    ++	int perm_a, perm_b, perm_start, perm_end;
    ++	void *qual_a, *qual_b;
    ++#if HAVE_FREEBSD_NFS4_ACL
    ++	acl_entry_type_t type_a, type_b;
    ++#endif
    ++#if HAVE_FREEBSD_NFS4_ACL || HAVE_DARWIN_ACL
    ++	acl_flagset_t flagset_a, flagset_b;
    ++	int flag_a, flag_b;
    ++#endif
    ++	int i, r;
    ++
    ++
    ++	/* Compare ACL tag */
    ++	r = acl_get_tag_type(ae_a, &tag_a);
    ++	failure("acl_get_tag_type() error: %s", strerror(errno));
    ++	if (assertEqualInt(r, 0) == 0)
    ++		return (-1);
    ++	r = acl_get_tag_type(ae_b, &tag_b);
    ++	failure("acl_get_tag_type() error: %s", strerror(errno));
    ++	if (assertEqualInt(r, 0) == 0)
    ++		return (-1);
    ++	if (tag_a != tag_b)
    ++		return (0);
    ++
    ++	/* Compare ACL qualifier */
    ++#if HAVE_DARWIN_ACL
    ++	if (tag_a == ACL_EXTENDED_ALLOW || tag_b == ACL_EXTENDED_DENY)
    ++#else
    ++	if (tag_a == ACL_USER || tag_a == ACL_GROUP)
    ++#endif
    ++	{
    ++		qual_a = acl_get_qualifier(ae_a);
    ++		failure("acl_get_qualifier() error: %s", strerror(errno));
    ++		if (assert(qual_a != NULL) == 0)
    ++			return (-1);
    ++		qual_b = acl_get_qualifier(ae_b);
    ++		failure("acl_get_qualifier() error: %s", strerror(errno));
    ++		if (assert(qual_b != NULL) == 0) {
    ++			acl_free(qual_a);
    ++			return (-1);
    ++		}
    ++#if HAVE_DARWIN_ACL
    ++		if (memcmp(((guid_t *)qual_a)->g_guid,
    ++		    ((guid_t *)qual_b)->g_guid, KAUTH_GUID_SIZE) != 0)
    ++#else
    ++		if ((tag_a == ACL_USER &&
    ++		    (*(uid_t *)qual_a != *(uid_t *)qual_b)) ||
    ++		    (tag_a == ACL_GROUP &&
    ++		    (*(gid_t *)qual_a != *(gid_t *)qual_b)))
    ++#endif
    ++		{
    ++			acl_free(qual_a);
    ++			acl_free(qual_b);
    ++			return (0);
    ++		}
    ++		acl_free(qual_a);
    ++		acl_free(qual_b);
    ++	}
    ++
    ++#if HAVE_FREEBSD_NFS4_ACL
    ++	if (is_nfs4) {
    ++		/* Compare NFS4 ACL type */
    ++		r = acl_get_entry_type_np(ae_a, &type_a);
    ++		failure("acl_get_entry_type_np() error: %s", strerror(errno));
    ++		if (assertEqualInt(r, 0) == 0)
    ++			return (-1);
    ++		r = acl_get_entry_type_np(ae_b, &type_b);
    ++		failure("acl_get_entry_type_np() error: %s", strerror(errno));
    ++		if (assertEqualInt(r, 0) == 0)
    ++			return (-1);
    ++		if (type_a != type_b)
    ++			return (0);
    ++	}
    ++#endif
    ++
    ++	/* Compare ACL perms */
    ++	r = acl_get_permset(ae_a, &permset_a);
    ++	failure("acl_get_permset() error: %s", strerror(errno));
    ++	if (assertEqualInt(r, 0) == 0)
    ++		return (-1);
    ++	r = acl_get_permset(ae_b, &permset_b);
    ++	failure("acl_get_permset() error: %s", strerror(errno));
    ++	if (assertEqualInt(r, 0) == 0)
    ++		return (-1);
    ++
    ++	perm_start = 0;
    ++	perm_end = (int)(sizeof(acl_perms) / sizeof(acl_perms[0]));
    ++#if HAVE_FREEBSD_NFS4_ACL
    ++	if (is_nfs4)
    ++		perm_start = 3;
    ++	else
    ++		perm_end = 3;
    ++#endif
    ++	/* Cycle through all perms and compare their value */
    ++	for (i = perm_start; i < perm_end; i++) {
    ++#if HAVE_LIBACL
    ++		perm_a = acl_get_perm(permset_a, acl_perms[i]);
    ++		perm_b = acl_get_perm(permset_b, acl_perms[i]);
    ++#else
    ++		perm_a = acl_get_perm_np(permset_a, acl_perms[i]);
    ++		perm_b = acl_get_perm_np(permset_b, acl_perms[i]);
    ++#endif
    ++		if (perm_a == -1 || perm_b == -1)
    ++			return (-1);
    ++		if (perm_a != perm_b)
    ++			return (0);
    ++	}
    ++
    ++#if HAVE_FREEBSD_NFS4_ACL || HAVE_DARWIN_ACL
    ++	if (is_nfs4) {
    ++		r = acl_get_flagset_np(ae_a, &flagset_a);
    ++		failure("acl_get_flagset_np() error: %s", strerror(errno));
    ++		if (assertEqualInt(r, 0) == 0)
    ++			return (-1);
    ++		r = acl_get_flagset_np(ae_b, &flagset_b);
    ++		failure("acl_get_flagset_np() error: %s", strerror(errno));
    ++		if (assertEqualInt(r, 0) == 0)
    ++			return (-1);
    ++		/* Cycle through all flags and compare their status */
    ++		for (i = 0; i < (int)(sizeof(acl_flags) / sizeof(acl_flags[0]));
    ++		    i++) {
    ++			flag_a = acl_get_flag_np(flagset_a, acl_flags[i]);
    ++			flag_b = acl_get_flag_np(flagset_b, acl_flags[i]);
    ++			if (flag_a == -1 || flag_b == -1)
    ++				return (-1);
    ++			if (flag_a != flag_b)
    ++				return (0);
    ++		}
    ++	}
    ++#else	/* HAVE_FREEBSD_NFS4_ACL || HAVE_DARWIN_ACL*/
    ++	(void)is_nfs4;	/* UNUSED */
    ++#endif
    ++	return (1);
    ++}
    ++#endif	/* HAVE_POSIX_ACL || HAVE_DARWIN_ACL */
    ++
    ++#if HAVE_SUN_ACL || HAVE_DARWIN_ACL || HAVE_POSIX_ACL
    ++/*
    ++ * Clear default ACLs or inheritance flags
    ++ */
    ++static void
    ++clear_inheritance_flags(const char *path, int type)
    ++{
    ++	switch (type) {
    ++	case ARCHIVE_TEST_ACL_TYPE_POSIX1E:
    ++#if HAVE_POSIX_ACL
    ++		acl_delete_def_file(path);
    ++#else
    ++		/* Solaris */
    ++		setTestAcl(path);
    ++#endif
    ++		break;
    ++	case ARCHIVE_TEST_ACL_TYPE_NFS4:
    ++#if HAVE_NFS4_ACL
    ++		setTestAcl(path);
    ++#endif
    ++		break;
    ++	default:
    ++		(void)path;	/* UNUSED */
    ++		break;
    ++	}
    ++}
    ++
    ++static int
    ++compare_acls(const char *path_a, const char *path_b)
    ++{
    ++	int ret = 1;
    ++	int is_nfs4 = 0;
    ++#if HAVE_SUN_ACL
    ++	void *acl_a, *acl_b;
    ++	int aclcnt_a, aclcnt_b;
    ++        aclent_t *aclent_a, *aclent_b;
    ++        ace_t *ace_a, *ace_b;
    ++	int e;
    ++#else
    ++	acl_t acl_a, acl_b;
    ++	acl_entry_t aclent_a, aclent_b;
    ++	int a, b, r;
    ++#endif
    ++
    ++	acl_a = NULL;
    ++	acl_b = NULL;
    ++#if HAVE_SUN_ACL
    ++	acl_a = sunacl_get(GETACL, &aclcnt_a, 0, path_a);
    ++	if (acl_a == NULL) {
    ++#if HAVE_SUN_NFS4_ACL
    ++		is_nfs4 = 1;
    ++		acl_a = sunacl_get(ACE_GETACL, &aclcnt_a, 0, path_a);
    ++#endif
    ++		failure("acl_get() error: %s", strerror(errno));
    ++		if (assert(acl_a != NULL) == 0)
    ++			return (-1);
    ++#if HAVE_SUN_NFS4_ACL
    ++		acl_b = sunacl_get(ACE_GETACL, &aclcnt_b, 0, path_b);
    ++#endif
    ++	} else
    ++		acl_b = sunacl_get(GETACL, &aclcnt_b, 0, path_b);
    ++	if (acl_b == NULL && (errno == ENOSYS || errno == ENOTSUP)) {
    ++		free(acl_a);
    ++		return (0);
    ++	}
    ++	failure("acl_get() error: %s", strerror(errno));
    ++	if (assert(acl_b != NULL) == 0) {
    ++		free(acl_a);
    ++		return (-1);
    ++	}
    ++
    ++	if (aclcnt_a != aclcnt_b) {
    ++		ret = 0;
    ++		goto exit_free;
    ++	}
    ++
    ++	for (e = 0; e < aclcnt_a; e++) {
    ++		if (!is_nfs4) {
    ++			aclent_a = &((aclent_t *)acl_a)[e];
    ++			aclent_b = &((aclent_t *)acl_b)[e];
    ++			if (aclent_a->a_type != aclent_b->a_type ||
    ++			    aclent_a->a_id != aclent_b->a_id ||
    ++			    aclent_a->a_perm != aclent_b->a_perm) {
    ++				ret = 0;
    ++				goto exit_free;
    ++			}
    ++		}
    ++#if HAVE_SUN_NFS4_ACL
    ++		else {
    ++			ace_a = &((ace_t *)acl_a)[e];
    ++			ace_b = &((ace_t *)acl_b)[e];
    ++			if (ace_a->a_who != ace_b->a_who ||
    ++			    ace_a->a_access_mask != ace_b->a_access_mask ||
    ++			    ace_a->a_flags != ace_b->a_flags ||
    ++			    ace_a->a_type != ace_b->a_type) {
    ++				ret = 0;
    ++				goto exit_free;
    ++			}
    ++		}
    ++#endif
    ++	}
    ++#else	/* !HAVE_SUN_ACL */
    ++#if HAVE_DARWIN_ACL
    ++	is_nfs4 = 1;
    ++	acl_a = acl_get_file(path_a, ACL_TYPE_EXTENDED);
    ++#elif HAVE_FREEBSD_NFS4_ACL
    ++	acl_a = acl_get_file(path_a, ACL_TYPE_NFS4);
    ++	if (acl_a != NULL)
    ++		is_nfs4 = 1;
    ++#endif
    ++#if !HAVE_DARWIN_ACL
    ++	if (acl_a == NULL)
    ++		acl_a = acl_get_file(path_a, ACL_TYPE_ACCESS);
    ++#endif
    ++	failure("acl_get_file() error: %s (%s)", path_a, strerror(errno));
    ++	if (assert(acl_a != NULL) == 0)
    ++		return (-1);
    ++#if HAVE_DARWIN_ACL
    ++	acl_b = acl_get_file(path_b, ACL_TYPE_EXTENDED);
    ++#elif HAVE_FREEBSD_NFS4_ACL
    ++	acl_b = acl_get_file(path_b, ACL_TYPE_NFS4);
    ++#endif
    ++#if !HAVE_DARWIN_ACL
    ++	if (acl_b == NULL) {
    ++#if HAVE_FREEBSD_NFS4_ACL
    ++		if (is_nfs4) {
    ++			acl_free(acl_a);
    ++			return (0);
    ++		}
    ++#endif
    ++		acl_b = acl_get_file(path_b, ACL_TYPE_ACCESS);
    ++	}
    ++	failure("acl_get_file() error: %s (%s)", path_b, strerror(errno));
    ++	if (assert(acl_b != NULL) == 0) {
    ++		acl_free(acl_a);
    ++		return (-1);
    ++	}
    ++#endif
    ++	a = acl_get_entry(acl_a, ACL_FIRST_ENTRY, &aclent_a);
    ++	if (a == -1) {
    ++		ret = 0;
    ++		goto exit_free;
    ++	}
    ++	b = acl_get_entry(acl_b, ACL_FIRST_ENTRY, &aclent_b);
    ++	if (b == -1) {
    ++		ret = 0;
    ++		goto exit_free;
    ++	}
    ++#if HAVE_DARWIN_ACL
    ++	while (a == 0 && b == 0)
    ++#else	/* FreeBSD, Linux */
    ++	while (a == 1 && b == 1)
    ++#endif
    ++	{
    ++		r = compare_acl_entry(aclent_a, aclent_b, is_nfs4);
    ++		if (r != 1) {
    ++			ret = r;
    ++			goto exit_free;
    ++		}
    ++		a = acl_get_entry(acl_a, ACL_NEXT_ENTRY, &aclent_a);
    ++		b = acl_get_entry(acl_b, ACL_NEXT_ENTRY, &aclent_b);
    ++	}
    ++	/* Entry count must match */
    ++	if (a != b)
    ++		ret = 0;
    ++#endif	/* !HAVE_SUN_ACL */
    ++exit_free:
    ++#if HAVE_SUN_ACL
    ++	free(acl_a);
    ++	free(acl_b);
    ++#else
    ++	acl_free(acl_a);
    ++	acl_free(acl_b);
    ++#endif
    ++	return (ret);
    ++}
    ++#endif	/* HAVE_SUN_ACL || HAVE_DARWIN_ACL || HAVE_POSIX_ACL */
    ++
    ++DEFINE_TEST(test_option_acls)
    ++{
    ++#if !HAVE_SUN_ACL && !HAVE_DARWIN_ACL && !HAVE_POSIX_ACL
    ++        skipping("ACLs are not supported on this platform");
    ++#else   /* HAVE_SUN_ACL || HAVE_DARWIN_ACL || HAVE_POSIX_ACL */
    ++	int acltype, r;
    ++
    ++	assertMakeFile("f", 0644, "a");
    ++	acltype = setTestAcl("f");
    ++	if (acltype == 0) {
    ++		skipping("Can't write ACLs on the filesystem");
    ++		return;
    ++	}
    ++
    ++	/* Archive it with acls */
    ++        r = systemf("%s -c --no-mac-metadata --acls -f acls.tar f >acls.out 2>acls.err", testprog);
    ++        assertEqualInt(r, 0);
    ++
    ++	/* Archive it without acls */
    ++	r = systemf("%s -c --no-mac-metadata --no-acls -f noacls.tar f >noacls.out 2>noacls.err", testprog);
    ++	assertEqualInt(r, 0);
    ++
    ++	/* Extract acls with acls */
    ++	assertMakeDir("acls_acls", 0755);
    ++	clear_inheritance_flags("acls_acls", acltype);
    ++	r = systemf("%s -x -C acls_acls --no-same-permissions --acls -f acls.tar >acls_acls.out 2>acls_acls.err", testprog);
    ++	assertEqualInt(r, 0);
    ++	r = compare_acls("f", "acls_acls/f");
    ++	assertEqualInt(r, 1);
    ++
    ++	/* Extractl acls without acls */
    ++	assertMakeDir("acls_noacls", 0755);
    ++	clear_inheritance_flags("acls_noacls", acltype);
    ++	r = systemf("%s -x -C acls_noacls -p --no-acls -f acls.tar >acls_noacls.out 2>acls_noacls.err", testprog);
    ++	assertEqualInt(r, 0);
    ++	r = compare_acls("f", "acls_noacls/f");
    ++	assertEqualInt(r, 0);
    ++
    ++	/* Extract noacls with acls flag */
    ++	assertMakeDir("noacls_acls", 0755);
    ++	clear_inheritance_flags("noacls_acls", acltype);
    ++	r = systemf("%s -x -C noacls_acls --no-same-permissions --acls -f noacls.tar >noacls_acls.out 2>noacls_acls.err", testprog);
    ++	assertEqualInt(r, 0);
    ++	r = compare_acls("f", "noacls_acls/f");
    ++	assertEqualInt(r, 0);
    ++
    ++	/* Extract noacls with noacls */
    ++	assertMakeDir("noacls_noacls", 0755);
    ++	clear_inheritance_flags("noacls_noacls", acltype);
    ++	r = systemf("%s -x -C noacls_noacls -p --no-acls -f noacls.tar >noacls_noacls.out 2>noacls_noacls.err", testprog);
    ++	assertEqualInt(r, 0);
    ++	r = compare_acls("f", "noacls_noacls/f");
    ++	assertEqualInt(r, 0);
    ++#endif	/* HAVE_SUN_ACL || HAVE_DARWIN_ACL || HAVE_POSIX_ACL */
    ++}
    +--- /dev/null
    ++++ tar/test/test_option_fflags.c
    +@@ -0,0 +1,106 @@
    ++/*-
    ++ * Copyright (c) 2017 Martin Matuska
    ++ * All rights reserved.
    ++ *
    ++ * Redistribution and use in source and binary forms, with or without
    ++ * modification, are permitted provided that the following conditions
    ++ * are met:
    ++ * 1. Redistributions of source code must retain the above copyright
    ++ *    notice, this list of conditions and the following disclaimer.
    ++ * 2. Redistributions in binary form must reproduce the above copyright
    ++ *    notice, this list of conditions and the following disclaimer in the
    ++ *    documentation and/or other materials provided with the distribution.
    ++ *
    ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
    ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    ++ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
    ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    ++ */
    ++#include "test.h"
    ++__FBSDID("$FreeBSD$");
    ++
    ++static void
    ++clear_fflags(const char *pathname)
    ++{
    ++#if defined(HAVE_STRUCT_STAT_ST_FLAGS)
    ++	chflags(pathname, 0);
    ++#elif (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \
    ++      (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS))
    ++	int fd;
    ++
    ++	fd = open(pathname, O_RDONLY | O_NONBLOCK);
    ++	if (fd < 0)
    ++		return;
    ++	ioctl(fd,
    ++#ifdef FS_IOC_GETFLAGS
    ++	    FS_IOC_GETFLAGS,
    ++#else
    ++	    EXT2_IOC_GETFLAGS,
    ++#endif
    ++	    0);
    ++#else
    ++	(void)pathname; /* UNUSED */
    ++#endif
    ++	return;
    ++}
    ++
    ++DEFINE_TEST(test_option_fflags)
    ++{
    ++	int r;
    ++
    ++	if (!canNodump()) {
    ++		skipping("Can't test nodump flag on this filesystem");
    ++		return;
    ++	}
    ++
    ++	/* Create a file. */
    ++	assertMakeFile("f", 0644, "a");
    ++
    ++	/* Set nodump flag on the file */
    ++	assertSetNodump("f");
    ++
    ++	/* FreeBSD ZFS workaround: ZFS sets uarch on all touched files and dirs */
    ++	chmod("f", 0644);
    ++
    ++	/* Archive it with fflags */
    ++	r = systemf("%s -c --fflags -f fflags.tar f >fflags.out 2>fflags.err", testprog);
    ++	assertEqualInt(r, 0);
    ++
    ++	/* Archive it without fflags */
    ++	r = systemf("%s -c --no-fflags -f nofflags.tar f >nofflags.out 2>nofflags.err", testprog);
    ++	assertEqualInt(r, 0);
    ++
    ++	/* Extract fflags with fflags */
    ++	assertMakeDir("fflags_fflags", 0755);
    ++	clear_fflags("fflags_fflags");
    ++	r = systemf("%s -x -C fflags_fflags --no-same-permissions --fflags -f fflags.tar >fflags_fflags.out 2>fflags_fflags.err", testprog);
    ++	assertEqualInt(r, 0);
    ++	assertEqualFflags("f", "fflags_fflags/f");
    ++
    ++	/* Extract fflags without fflags */
    ++	assertMakeDir("fflags_nofflags", 0755);
    ++	clear_fflags("fflags_nofflags");
    ++	r = systemf("%s -x -C fflags_nofflags -p --no-fflags -f fflags.tar >fflags_nofflags.out 2>fflags_nofflags.err", testprog);
    ++	assertEqualInt(r, 0);
    ++	assertUnequalFflags("f", "fflags_nofflags/f");
    ++
    ++	/* Extract nofflags with fflags */
    ++	assertMakeDir("nofflags_fflags", 0755);
    ++	clear_fflags("nofflags_fflags");
    ++	r = systemf("%s -x -C nofflags_fflags --no-same-permissions --fflags -f nofflags.tar >nofflags_fflags.out 2>nofflags_fflags.err", testprog);
    ++	assertEqualInt(r, 0);	
    ++	assertUnequalFflags("f", "nofflags_fflags/f");
    ++
    ++	/* Extract nofflags with nofflags */
    ++	assertMakeDir("nofflags_nofflags", 0755);
    ++	clear_fflags("nofflags_nofflags");
    ++	r = systemf("%s -x -C nofflags_nofflags -p --no-fflags -f nofflags.tar >nofflags_nofflags.out 2>nofflags_nofflags.err", testprog);
    ++	assertEqualInt(r, 0);
    ++	assertUnequalFflags("f", "nofflags_nofflags/f");
    ++}
    +--- tar/test/test_option_nodump.c.orig
    ++++ tar/test/test_option_nodump.c
    +@@ -36,7 +36,7 @@ DEFINE_TEST(test_option_nodump)
    + 	assertMakeFile("file1", 0644, "file1");
    + 	assertMakeFile("file2", 0644, "file2");
    + 	assertMakeFile("file3", 0644, "file3");
    +-	assertNodump("file2");
    ++	assertSetNodump("file2");
    + 
    + 	/* Test 1: Without --nodump */
    + 	assertEqualInt(0, systemf("%s -cf test1.tar file1 file2 file3",
    +--- test_utils/test_common.h.orig
    ++++ test_utils/test_common.h
    +@@ -73,6 +73,12 @@
    + #include <unistd.h>
    + #endif
    + #include <wchar.h>
    ++#ifdef HAVE_ACL_LIBACL_H
    ++#include <acl/libacl.h>
    ++#endif
    ++#ifdef HAVE_SYS_ACL_H
    ++#include <sys/acl.h>
    ++#endif
    + #ifdef HAVE_WINDOWS_H
    + #include <windows.h>
    + #endif
    +@@ -121,31 +127,10 @@
    + #define	O_BINARY 0
    + #endif
    + 
    +-/*
    +- * If this platform has <sys/acl.h>, acl_create(), acl_init(),
    +- * acl_set_file(), and ACL_USER, we assume it has the rest of the
    +- * POSIX.1e draft functions used in archive_read_extract.c.
    +- */
    +-#if HAVE_SYS_ACL_H && HAVE_ACL_CREATE_ENTRY && HAVE_ACL_INIT && HAVE_ACL_SET_FILE
    +-#if HAVE_ACL_USER
    +-#define	HAVE_POSIX_ACL	1
    +-#elif HAVE_ACL_TYPE_EXTENDED
    +-#define	HAVE_DARWIN_ACL	1
    +-#endif
    +-#endif
    +-
    +-/*
    +- * If this platform has <sys/acl.h>, acl_get(), facl_get(), acl_set(),
    +- * facl_set() and types aclent_t and ace_t it uses Solaris-style ACL functions
    +- */
    +-#if HAVE_SYS_ACL_H && HAVE_ACL_GET && HAVE_FACL_GET && HAVE_ACL_SET && HAVE_FACL_SET && HAVE_ACLENT_T && HAVE_ACE_T
    +-#define	HAVE_SUN_ACL	1
    +-#endif
    ++#include "archive_platform_acl.h"
    ++#define	ARCHIVE_TEST_ACL_TYPE_POSIX1E	1
    ++#define	ARCHIVE_TEST_ACL_TYPE_NFS4	2
    + 
    +-/* Define if platform supports NFSv4 ACLs */
    +-#if (HAVE_POSIX_ACL && HAVE_ACL_TYPE_NFS4) || HAVE_SUN_ACL || HAVE_DARWIN_ACL
    +-#define	HAVE_NFS4_ACL	1
    +-#endif
    + 
    + /*
    +  * Redefine DEFINE_TEST for use in defining the test functions.
    +@@ -158,6 +143,9 @@
    + /* chdir() and error if it fails */
    + #define assertChdir(path)  \
    +   assertion_chdir(__FILE__, __LINE__, path)
    ++/* Assert two files have the same file flags */
    ++#define assertEqualFflags(patha, pathb)	\
    ++  assertion_compare_fflags(__FILE__, __LINE__, patha, pathb, 0)
    + /* Assert two integers are the same.  Reports value of each one if not. */
    + #define assertEqualInt(v1,v2) \
    +   assertion_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
    +@@ -239,10 +227,13 @@
    +   assertion_make_hardlink(__FILE__, __LINE__, newfile, oldfile)
    + #define assertMakeSymlink(newfile, linkto)	\
    +   assertion_make_symlink(__FILE__, __LINE__, newfile, linkto)
    +-#define assertNodump(path)      \
    +-  assertion_nodump(__FILE__, __LINE__, path)
    ++#define assertSetNodump(path)	\
    ++  assertion_set_nodump(__FILE__, __LINE__, path)
    + #define assertUmask(mask)	\
    +   assertion_umask(__FILE__, __LINE__, mask)
    ++/* Assert that two files have unequal file flags */
    ++#define assertUnequalFflags(patha, pathb)	\
    ++  assertion_compare_fflags(__FILE__, __LINE__, patha, pathb, 1)
    + #define assertUtimes(pathname, atime, atime_nsec, mtime, mtime_nsec)	\
    +   assertion_utimes(__FILE__, __LINE__, pathname, atime, atime_nsec, mtime, mtime_nsec)
    + #ifndef PROGRAM
    +@@ -265,6 +256,8 @@
    + void failure(const char *fmt, ...);
    + int assertion_assert(const char *, int, int, const char *, void *);
    + int assertion_chdir(const char *, int, const char *);
    ++int assertion_compare_fflags(const char *, int, const char *, const char *,
    ++    int);
    + int assertion_empty_file(const char *, int, const char *);
    + int assertion_equal_file(const char *, int, const char *, const char *);
    + int assertion_equal_int(const char *, int, long long, const char *, long long, const char *, void *);
    +@@ -295,8 +288,8 @@ int assertion_make_dir(const char *, int, const char *, int);
    + int assertion_make_file(const char *, int, const char *, int, int, const void *);
    + int assertion_make_hardlink(const char *, int, const char *newpath, const char *);
    + int assertion_make_symlink(const char *, int, const char *newpath, const char *);
    +-int assertion_nodump(const char *, int, const char *);
    + int assertion_non_empty_file(const char *, int, const char *);
    ++int assertion_set_nodump(const char *, int, const char *);
    + int assertion_text_file_contents(const char *, int, const char *buff, const char *f);
    + int assertion_umask(const char *, int, int);
    + int assertion_utimes(const char *, int, const char *, long, long, long, long );
    +@@ -347,9 +340,17 @@ int canXz(void);
    + /* Return true if this filesystem can handle nodump flags. */
    + int canNodump(void);
    + 
    ++/* Set test ACLs */
    ++int setTestAcl(const char *path);
    ++
    + /* Return true if the file has large i-node number(>0xffffffff). */
    + int is_LargeInode(const char *);
    + 
    ++#if ARCHIVE_ACL_SUNOS
    ++/* Fetch ACLs on Solaris using acl() or facl() */
    ++void *sunacl_get(int cmd, int *aclcnt, int fd, const char *path);
    ++#endif
    ++
    + /* Suck file into string allocated via malloc(). Call free() when done. */
    + /* Supports printf-style args: slurpfile(NULL, "%s/myfile", refdir); */
    + char *slurpfile(size_t *, const char *fmt, ...);
    +--- test_utils/test_main.c.orig
    ++++ test_utils/test_main.c
    +@@ -56,6 +56,24 @@
    + #include <stdarg.h>
    + #include <time.h>
    + 
    ++#ifdef HAVE_SIGNAL_H
    ++#endif
    ++#ifdef HAVE_ACL_LIBACL_H
    ++#include <acl/libacl.h>
    ++#endif
    ++#ifdef HAVE_SYS_TYPES_H
    ++#include <sys/types.h>
    ++#endif
    ++#ifdef HAVE_SYS_ACL_H
    ++#include <sys/acl.h>
    ++#endif
    ++#ifdef HAVE_SYS_RICHACL_H
    ++#include <sys/richacl.h>
    ++#endif
    ++#if HAVE_MEMBERSHIP_H
    ++#include <membership.h>
    ++#endif
    ++
    + /*
    +  *
    +  * Windows support routines
    +@@ -1883,9 +1901,103 @@ assertion_utimes(const char *file, int line,
    + #endif /* defined(_WIN32) && !defined(__CYGWIN__) */
    + }
    + 
    ++/* Compare file flags */
    ++int
    ++assertion_compare_fflags(const char *file, int line, const char *patha,
    ++    const char *pathb, int nomatch)
    ++{
    ++#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
    ++	struct stat sa, sb;
    ++
    ++	assertion_count(file, line);
    ++
    ++	if (stat(patha, &sa) < 0)
    ++		return (0);
    ++	if (stat(pathb, &sb) < 0)
    ++		return (0);
    ++	if (!nomatch && sa.st_flags != sb.st_flags) {
    ++		failure_start(file, line, "File flags should be identical: "
    ++		    "%s=%#010x %s=%#010x", patha, sa.st_flags, pathb,
    ++		    sb.st_flags);
    ++		failure_finish(NULL);
    ++		return (0);
    ++	}
    ++	if (nomatch && sa.st_flags == sb.st_flags) {
    ++		failure_start(file, line, "File flags should be different: "
    ++		    "%s=%#010x %s=%#010x", patha, sa.st_flags, pathb,
    ++		    sb.st_flags);
    ++		failure_finish(NULL);
    ++		return (0);
    ++	}
    ++#elif (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS) && \
    ++       defined(FS_NODUMP_FL)) || \
    ++      (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS) \
    ++         && defined(EXT2_NODUMP_FL))
    ++	int fd, r, flagsa, flagsb;
    ++
    ++	assertion_count(file, line);
    ++	fd = open(patha, O_RDONLY | O_NONBLOCK);
    ++	if (fd < 0) {
    ++		failure_start(file, line, "Can't open %s\n", patha);
    ++		failure_finish(NULL);
    ++		return (0);
    ++	}
    ++	r = ioctl(fd,
    ++#ifdef FS_IOC_GETFLAGS
    ++	    FS_IOC_GETFLAGS,
    ++#else
    ++	    EXT2_IOC_GETFLAGS,
    ++#endif
    ++	    &flagsa);
    ++	close(fd);
    ++	if (r < 0) {
    ++		failure_start(file, line, "Can't get flags %s\n", patha);
    ++		failure_finish(NULL);
    ++		return (0);
    ++	}
    ++	fd = open(pathb, O_RDONLY | O_NONBLOCK);
    ++	if (fd < 0) {
    ++		failure_start(file, line, "Can't open %s\n", pathb);
    ++		failure_finish(NULL);
    ++		return (0);
    ++	}
    ++	r = ioctl(fd,
    ++#ifdef FS_IOC_GETFLAGS
    ++	    FS_IOC_GETFLAGS,
    ++#else
    ++	    EXT2_IOC_GETFLAGS,
    ++#endif
    ++	    &flagsb);
    ++	close(fd);
    ++	if (r < 0) {
    ++		failure_start(file, line, "Can't get flags %s\n", pathb);
    ++		failure_finish(NULL);
    ++		return (0);
    ++	}
    ++	if (!nomatch && flagsa != flagsb) {
    ++		failure_start(file, line, "File flags should be identical: "
    ++		    "%s=%#010x %s=%#010x", patha, flagsa, pathb, flagsb);
    ++		failure_finish(NULL);
    ++		return (0);
    ++	}
    ++	if (nomatch && flagsa == flagsb) {
    ++		failure_start(file, line, "File flags should be different: "
    ++		    "%s=%#010x %s=%#010x", patha, flagsa, pathb, flagsb);
    ++		failure_finish(NULL);
    ++		return (0);
    ++	}
    ++#else
    ++	(void)patha; /* UNUSED */
    ++	(void)pathb; /* UNUSED */
    ++	(void)nomatch; /* UNUSED */
    ++	assertion_count(file, line);
    ++#endif
    ++	return (1);
    ++}
    ++
    + /* Set nodump, report failures. */
    + int
    +-assertion_nodump(const char *file, int line, const char *pathname)
    ++assertion_set_nodump(const char *file, int line, const char *pathname)
    + {
    + #if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
    + 	int r;
    +@@ -2256,11 +2368,10 @@ canXz(void)
    + /*
    +  * Can this filesystem handle nodump flags.
    +  */
    +-#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
    +-
    + int
    + canNodump(void)
    + {
    ++#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
    + 	const char *path = "cannodumptest";
    + 	struct stat sb;
    + 
    +@@ -2271,16 +2382,10 @@ canNodump(void)
    + 		return (0);
    + 	if (sb.st_flags & UF_NODUMP)
    + 		return (1);
    +-	return (0);
    +-}
    +-
    + #elif (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS) \
    + 	 && defined(FS_NODUMP_FL)) || \
    +       (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS) \
    + 	 && defined(EXT2_NODUMP_FL))
    +-int
    +-canNodump(void)
    +-{
    + 	const char *path = "cannodumptest";
    + 	int fd, r, flags;
    + 
    +@@ -2331,18 +2436,250 @@ canNodump(void)
    + 	if (flags & EXT2_NODUMP_FL)
    + #endif
    + 		return (1);
    ++#endif
    + 	return (0);
    + }
    + 
    +-#else
    +-
    +-int
    +-canNodump()
    ++#if ARCHIVE_ACL_SUNOS
    ++/* Fetch ACLs on Solaris using acl() or facl() */
    ++void *
    ++sunacl_get(int cmd, int *aclcnt, int fd, const char *path)
    + {
    +-	return (0);
    ++	int cnt, cntcmd;
    ++	size_t size;
    ++	void *aclp;
    ++
    ++	if (cmd == GETACL) {
    ++		cntcmd = GETACLCNT;
    ++		size = sizeof(aclent_t);
    ++	}
    ++#if ARCHIVE_ACL_SUNOS_NFS4
    ++	else if (cmd == ACE_GETACL) {
    ++		cntcmd = ACE_GETACLCNT;
    ++		size = sizeof(ace_t);
    ++	}
    ++#endif
    ++	else {
    ++		errno = EINVAL;
    ++		*aclcnt = -1;
    ++		return (NULL);
    ++	}
    ++
    ++	aclp = NULL;
    ++	cnt = -2;
    ++	while (cnt == -2 || (cnt == -1 && errno == ENOSPC)) {
    ++		if (path != NULL)
    ++			cnt = acl(path, cntcmd, 0, NULL);
    ++		else
    ++			cnt = facl(fd, cntcmd, 0, NULL);
    ++
    ++		if (cnt > 0) {
    ++			if (aclp == NULL)
    ++				aclp = malloc(cnt * size);
    ++			else
    ++				aclp = realloc(NULL, cnt * size);
    ++			if (aclp != NULL) {
    ++				if (path != NULL)
    ++					cnt = acl(path, cmd, cnt, aclp);
    ++				else
    ++					cnt = facl(fd, cmd, cnt, aclp);
    ++			}
    ++		} else {
    ++			if (aclp != NULL) {
    ++				free(aclp);
    ++				aclp = NULL;
    ++			}
    ++			break;
    ++		}
    ++	}
    ++
    ++	*aclcnt = cnt;
    ++	return (aclp);
    + }
    ++#endif /* ARCHIVE_ACL_SUNOS */
    ++
    ++/*
    ++ * Set test ACLs on a path
    ++ * Return values:
    ++ * 0: error setting ACLs
    ++ * ARCHIVE_TEST_ACL_TYPE_POSIX1E: POSIX.1E ACLs have been set
    ++ * ARCHIVE_TEST_ACL_TYPE_NFS4: NFSv4 or extended ACLs have been set
    ++ */
    ++int
    ++setTestAcl(const char *path)
    ++{
    ++#if ARCHIVE_ACL_SUPPORT
    ++	int r = 1;
    ++#if ARCHIVE_ACL_LIBACL || ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_DARWIN
    ++	acl_t acl;
    ++#endif
    ++#if ARCHIVE_ACL_LIBRICHACL
    ++	struct richacl *richacl;
    ++#endif
    ++#if ARCHIVE_ACL_LIBACL || ARCHIVE_ACL_FREEBSD
    ++	const char *acltext_posix1e = "user:1:rw-,"
    ++	    "group:15:r-x,"
    ++	    "user::rwx,"
    ++	    "group::rwx,"
    ++	    "other::r-x,"
    ++	    "mask::rwx";
    ++#elif ARCHIVE_ACL_SUNOS /* Solaris POSIX.1e */
    ++	aclent_t aclp_posix1e[] = {
    ++	    { USER_OBJ, -1, 4 | 2 | 1 },
    ++	    { USER, 1, 4 | 2 },
    ++	    { GROUP_OBJ, -1, 4 | 2 | 1 },
    ++	    { GROUP, 15, 4 | 1 },
    ++	    { CLASS_OBJ, -1, 4 | 2 | 1 },
    ++	    { OTHER_OBJ, -1, 4 | 2 | 1 }
    ++	};
    ++#endif
    ++#if ARCHIVE_ACL_FREEBSD /* FreeBSD NFS4 */
    ++	const char *acltext_nfs4 = "user:1:rwpaRcs::allow:1,"
    ++	    "group:15:rxaRcs::allow:15,"
    ++	    "owner@:rwpxaARWcCos::allow,"
    ++	    "group@:rwpxaRcs::allow,"
    ++	    "everyone@:rxaRcs::allow";
    ++#elif ARCHIVE_ACL_LIBRICHACL
    ++	const char *acltext_nfs4 = "owner:rwpxaARWcCoS::mask,"
    ++	    "group:rwpxaRcS::mask,"
    ++	    "other:rxaRcS::mask,"
    ++	    "user:1:rwpaRcS::allow,"
    ++	    "group:15:rxaRcS::allow,"
    ++	    "owner@:rwpxaARWcCoS::allow,"
    ++	    "group@:rwpxaRcS::allow,"
    ++	    "everyone@:rxaRcS::allow";
    ++#elif ARCHIVE_ACL_SUNOS_NFS4 /* Solaris NFS4 */
    ++	ace_t aclp_nfs4[] = {
    ++	    { 1, ACE_READ_DATA | ACE_WRITE_DATA | ACE_APPEND_DATA |
    ++	      ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS | ACE_READ_ACL |
    ++	      ACE_SYNCHRONIZE, 0, ACE_ACCESS_ALLOWED_ACE_TYPE },
    ++	    { 15, ACE_READ_DATA | ACE_EXECUTE | ACE_READ_ATTRIBUTES |
    ++	      ACE_READ_NAMED_ATTRS | ACE_READ_ACL | ACE_SYNCHRONIZE,
    ++	      ACE_IDENTIFIER_GROUP, ACE_ACCESS_ALLOWED_ACE_TYPE },
    ++	    { -1, ACE_READ_DATA | ACE_WRITE_DATA | ACE_APPEND_DATA |
    ++	      ACE_EXECUTE | ACE_READ_ATTRIBUTES | ACE_WRITE_ATTRIBUTES |
    ++	      ACE_READ_NAMED_ATTRS | ACE_WRITE_NAMED_ATTRS |
    ++	      ACE_READ_ACL | ACE_WRITE_ACL | ACE_WRITE_OWNER | ACE_SYNCHRONIZE,
    ++	      ACE_OWNER, ACE_ACCESS_ALLOWED_ACE_TYPE },
    ++	    { -1, ACE_READ_DATA | ACE_WRITE_DATA | ACE_APPEND_DATA |
    ++	      ACE_EXECUTE | ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS |
    ++	      ACE_READ_ACL | ACE_SYNCHRONIZE, ACE_GROUP | ACE_IDENTIFIER_GROUP,
    ++	      ACE_ACCESS_ALLOWED_ACE_TYPE },
    ++	    { -1, ACE_READ_DATA | ACE_EXECUTE | ACE_READ_ATTRIBUTES |
    ++	      ACE_READ_NAMED_ATTRS | ACE_READ_ACL | ACE_SYNCHRONIZE,
    ++	      ACE_EVERYONE, ACE_ACCESS_ALLOWED_ACE_TYPE }
    ++	};
    ++#elif ARCHIVE_ACL_DARWIN /* Mac OS X */
    ++	acl_entry_t aclent;
    ++	acl_permset_t permset;
    ++	const uid_t uid = 1;
    ++	uuid_t uuid;
    ++	int i;
    ++	const acl_perm_t acl_perms[] = {
    ++		ACL_READ_DATA,
    ++		ACL_WRITE_DATA,
    ++		ACL_APPEND_DATA,
    ++		ACL_EXECUTE,
    ++		ACL_READ_ATTRIBUTES,
    ++		ACL_READ_EXTATTRIBUTES,
    ++		ACL_READ_SECURITY,
    ++#if HAVE_DECL_ACL_SYNCHRONIZE
    ++		ACL_SYNCHRONIZE
    ++#endif
    ++	};
    ++#endif /* ARCHIVE_ACL_DARWIN */
    + 
    ++#if ARCHIVE_ACL_FREEBSD
    ++	acl = acl_from_text(acltext_nfs4);
    ++	failure("acl_from_text() error: %s", strerror(errno));
    ++	if (assert(acl != NULL) == 0)
    ++		return (0);
    ++#elif ARCHIVE_ACL_LIBRICHACL
    ++	richacl = richacl_from_text(acltext_nfs4, NULL, NULL);
    ++	failure("richacl_from_text() error: %s", strerror(errno));
    ++	if (assert(richacl != NULL) == 0)
    ++		return (0);
    ++#elif ARCHIVE_ACL_DARWIN
    ++	acl = acl_init(1);
    ++	failure("acl_init() error: %s", strerror(errno));
    ++	if (assert(acl != NULL) == 0)
    ++		return (0);
    ++	r = acl_create_entry(&acl, &aclent);
    ++	failure("acl_create_entry() error: %s", strerror(errno));
    ++	if (assertEqualInt(r, 0) == 0)
    ++		goto testacl_free;
    ++	r = acl_set_tag_type(aclent, ACL_EXTENDED_ALLOW);
    ++	failure("acl_set_tag_type() error: %s", strerror(errno));
    ++	if (assertEqualInt(r, 0) == 0)
    ++		goto testacl_free;
    ++	r = acl_get_permset(aclent, &permset);
    ++	failure("acl_get_permset() error: %s", strerror(errno));
    ++	if (assertEqualInt(r, 0) == 0)
    ++		goto testacl_free;
    ++	for (i = 0; i < (int)(sizeof(acl_perms) / sizeof(acl_perms[0])); i++) {
    ++		r = acl_add_perm(permset, acl_perms[i]);
    ++		failure("acl_add_perm() error: %s", strerror(errno));
    ++		if (assertEqualInt(r, 0) == 0)
    ++			goto testacl_free;
    ++	}
    ++	r = acl_set_permset(aclent, permset);
    ++	failure("acl_set_permset() error: %s", strerror(errno));
    ++	if (assertEqualInt(r, 0) == 0)
    ++		goto testacl_free;
    ++	r = mbr_uid_to_uuid(uid, uuid);
    ++	failure("mbr_uid_to_uuid() error: %s", strerror(errno));
    ++	if (assertEqualInt(r, 0) == 0)
    ++		goto testacl_free;
    ++	r = acl_set_qualifier(aclent, uuid);
    ++	failure("acl_set_qualifier() error: %s", strerror(errno));
    ++	if (assertEqualInt(r, 0) == 0)
    ++		goto testacl_free;
    ++#endif /* ARCHIVE_ACL_DARWIN */
    ++
    ++#if ARCHIVE_ACL_NFS4
    ++#if ARCHIVE_ACL_FREEBSD
    ++	r = acl_set_file(path, ACL_TYPE_NFS4, acl);
    ++	acl_free(acl);
    ++#elif ARCHIVE_ACL_LIBRICHACL
    ++	r = richacl_set_file(path, richacl);
    ++	richacl_free(richacl);
    ++#elif ARCHIVE_ACL_SUNOS_NFS4
    ++	r = acl(path, ACE_SETACL,
    ++	    (int)(sizeof(aclp_nfs4)/sizeof(aclp_nfs4[0])), aclp_nfs4);
    ++#elif ARCHIVE_ACL_DARWIN
    ++	r = acl_set_file(path, ACL_TYPE_EXTENDED, acl);
    ++	acl_free(acl);
    ++#endif
    ++	if (r == 0)
    ++		return (ARCHIVE_TEST_ACL_TYPE_NFS4);
    ++#endif	/* ARCHIVE_ACL_NFS4 */
    ++
    ++#if ARCHIVE_ACL_POSIX1E
    ++#if ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL
    ++	acl = acl_from_text(acltext_posix1e);
    ++	failure("acl_from_text() error: %s", strerror(errno));
    ++	if (assert(acl != NULL) == 0)
    ++		return (0);
    ++
    ++	r = acl_set_file(path, ACL_TYPE_ACCESS, acl);
    ++	acl_free(acl);
    ++#elif ARCHIVE_ACL_SUNOS
    ++	r = acl(path, SETACL,
    ++	    (int)(sizeof(aclp_posix1e)/sizeof(aclp_posix1e[0])), aclp_posix1e);
    + #endif
    ++	if (r == 0)
    ++		return (ARCHIVE_TEST_ACL_TYPE_POSIX1E);
    ++	else
    ++		return (0);
    ++#endif /* ARCHIVE_ACL_POSIX1E */
    ++#if ARCHIVE_ACL_DARWIN
    ++testacl_free:
    ++	acl_free(acl);
    ++#endif
    ++#endif /* ARCHIVE_ACL_SUPPORT */
    ++	(void)path;	/* UNUSED */
    ++	return (0);
    ++}
    + 
    + /*
    +  * Sleep as needed; useful for verifying disk timestamp changes by
    diff --git libarchive/files/patch-Makefile.am.diff libarchive/files/patch-Makefile.am.diff
    new file mode 100644
    index 0000000000..05e51c0eb0
    - +  
     1--- Makefile.am.orig
     2+++ Makefile.am
     3@@ -23,7 +23,7 @@
     4 DISTCHECK_CONFIGURE_FLAGS = --enable-bsdtar --enable-bsdcpio
     5 # The next line is commented out by default in shipping libarchive releases.
     6 # It is uncommented by default in trunk.
     7-DEV_CFLAGS=-Werror -Wextra -Wunused -Wshadow -Wmissing-prototypes -Wcast-qual -g
     8+# DEV_CFLAGS=-Werror -Wextra -Wunused -Wshadow -Wmissing-prototypes -Wcast-qual -g
     9 AM_CFLAGS=$(DEV_CFLAGS)
     10 PLATFORMCPPFLAGS = @PLATFORMCPPFLAGS@
     11 AM_CPPFLAGS=$(PLATFORMCPPFLAGS)