New tar test: test_option_acls
Add sunacl_get() and setTestAcl() to common test code
Test for membership.h on Mac OS X and make it a requirement for ACLs
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5bcff48..bddf30c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -579,6 +579,7 @@
 
 LA_CHECK_INCLUDE_FILE("linux/magic.h" HAVE_LINUX_MAGIC_H)
 LA_CHECK_INCLUDE_FILE("locale.h" HAVE_LOCALE_H)
+LA_CHECK_INCLUDE_FILE("membership.h" HAVE_MEMBERSHIP_H)
 LA_CHECK_INCLUDE_FILE("memory.h" HAVE_MEMORY_H)
 LA_CHECK_INCLUDE_FILE("paths.h" HAVE_PATHS_H)
 LA_CHECK_INCLUDE_FILE("poll.h" HAVE_POLL_H)
diff --git a/Makefile.am b/Makefile.am
index 600e1ff..b5a41f9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -951,6 +951,7 @@
 	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 \
diff --git a/build/cmake/config.h.in b/build/cmake/config.h.in
index fd4fbdc..8c18edf 100644
--- a/build/cmake/config.h.in
+++ b/build/cmake/config.h.in
@@ -773,6 +773,9 @@
 /* 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
 
diff --git a/cat/test/CMakeLists.txt b/cat/test/CMakeLists.txt
index 7f1ce5e..0623cc3 100644
--- a/cat/test/CMakeLists.txt
+++ b/cat/test/CMakeLists.txt
@@ -29,6 +29,11 @@
   # Register target
   #
   ADD_EXECUTABLE(bsdcat_test ${bsdcat_test_SOURCES})
+  IF(ENABLE_ACL)
+    IF(HAVE_LIBACL)
+      TARGET_LINK_LIBRARIES(bsdcat_test ${ACL_LIBRARY})
+    ENDIF(HAVE_LIBACL)
+  ENDIF(ENABLE_ACL)
   SET_PROPERTY(TARGET bsdcat_test PROPERTY COMPILE_DEFINITIONS LIST_H)
 
   #
diff --git a/configure.ac b/configure.ac
index b9f7f53..0592279 100644
--- a/configure.ac
+++ b/configure.ac
@@ -699,6 +699,7 @@
 if test "x$enable_acl" != "xno"; then
    AC_CHECK_HEADERS([acl/libacl.h])
    AC_CHECK_HEADERS([sys/acl.h])
+   AC_CHECK_HEADERS([membership.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])
diff --git a/cpio/test/CMakeLists.txt b/cpio/test/CMakeLists.txt
index ec9509b..cc5fe01 100644
--- a/cpio/test/CMakeLists.txt
+++ b/cpio/test/CMakeLists.txt
@@ -62,6 +62,11 @@
   # Register target
   #
   ADD_EXECUTABLE(bsdcpio_test ${bsdcpio_test_SOURCES})
+  IF(ENABLE_ACL)
+    IF(HAVE_LIBACL)
+      TARGET_LINK_LIBRARIES(bsdcpio_test ${ACL_LIBRARY})
+    ENDIF(HAVE_LIBACL)
+  ENDIF(ENABLE_ACL)
   SET_PROPERTY(TARGET bsdcpio_test PROPERTY COMPILE_DEFINITIONS LIST_H)
 
   #
diff --git a/libarchive/archive_platform.h b/libarchive/archive_platform.h
index 128f0e0..01d6a70 100644
--- a/libarchive/archive_platform.h
+++ b/libarchive/archive_platform.h
@@ -150,7 +150,7 @@
 #if HAVE_SYS_ACL_H && HAVE_ACL_CREATE_ENTRY && HAVE_ACL_INIT && HAVE_ACL_SET_FILE
 #if HAVE_DECL_ACL_USER
 #define	HAVE_POSIX_ACL	1
-#elif HAVE_DECL_ACL_TYPE_EXTENDED
+#elif HAVE_DECL_ACL_TYPE_EXTENDED && HAVE_MEMBERSHIP_H
 #define HAVE_DARWIN_ACL 1
 #endif
 #if HAVE_DECL_ACL_TYPE_NFS4
diff --git a/libarchive/test/test_acl_platform_nfs4.c b/libarchive/test/test_acl_platform_nfs4.c
index 5783e52..c885408 100644
--- a/libarchive/test/test_acl_platform_nfs4.c
+++ b/libarchive/test/test_acl_platform_nfs4.c
@@ -248,63 +248,6 @@
 
 static const int acls_dir_cnt = (int)(sizeof(acls_dir)/sizeof(acls_dir[0]));
 
-#if HAVE_SUN_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 HAVE_SUN_NFS4_ACL
-	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 /* HAVE_SUN_ACL */
-
 static void
 set_acls(struct archive_entry *ae, struct myacl_t *acls, int start, int end)
 {
@@ -777,11 +720,10 @@
 	skipping("NFS4 ACLs are not supported on this platform");
 #else
 	char buff[64];
+	int i;
 	struct stat st;
 	struct archive *a;
 	struct archive_entry *ae;
-	int i;
-	char *func;
 #if HAVE_DARWIN_ACL /* On MacOS we skip trivial ACLs in some tests */
 	const int regcnt = acls_reg_cnt - 4;
 	const int dircnt = acls_dir_cnt - 4;
@@ -793,93 +735,16 @@
 	void *aclp;
 	int aclcnt;
 #else	/* !HAVE_SUN_NFS4_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 */
-	int n;
 	acl_t acl;
-#endif	/* !HAVE_SUN_NFS4_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_FREEBSD_NFS4_ACL
-	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_NFS4_ACL
-		acl_free(acl);
-#endif
+	assertMakeFile("pretest", 0644, "a");
+
+	if (setTestAcl("pretest") != ARCHIVE_TEST_ACL_TYPE_NFS4) {
+		skipping("NFS4 ACLs are not writable on this filesystem");
 		return;
 	}
 
-#if HAVE_SUN_NFS4_ACL
-	func = "acl()";
-	aclp = sunacl_get(GETACL, &aclcnt, 0, "pretest");
-	if (aclp != NULL) {
-		skipping("NFS4 ACL is not supported on this filesystem");
-		free(aclp);
-		return;
-	}
-	free(aclp);
-	aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, "pretest");
-#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 HAVE_SUN_NFS4_ACL
-	if (aclp == NULL)
-#else
-	if (n != 0)
-#endif
-	{
-#if HAVE_SUN_NFS4_ACL
-		if (errno == ENOSYS || errno == ENOTSUP)
-#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));
-#if HAVE_SUN_NFS4_ACL
-	assert(aclp != NULL);
-	free(aclp);
-	aclp = NULL;
-#else
-	assertEqualInt(0, n);
-#endif
-
 	/* Create a write-to-disk object. */
 	assert(NULL != (a = archive_write_disk_new()));
 	archive_write_disk_set_options(a,
diff --git a/libarchive/test/test_acl_platform_posix1e.c b/libarchive/test/test_acl_platform_posix1e.c
index a0da227..0224a57 100644
--- a/libarchive/test/test_acl_platform_posix1e.c
+++ b/libarchive/test/test_acl_platform_posix1e.c
@@ -35,63 +35,6 @@
 #define ACL_GET_PERM acl_get_perm_np
 #endif
 
-#if HAVE_SUN_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 HAVE_SUN_NFS4_ACL
-	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  /* HAVE_SUN_ACL */
-
 static struct archive_test_acl_t acls2[] = {
 	{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE | ARCHIVE_ENTRY_ACL_READ,
 	  ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
@@ -361,8 +304,6 @@
 	struct stat st;
 	struct archive *a;
 	struct archive_entry *ae;
-	int n, fd;
-	char *func;
 #if HAVE_SUN_ACL
 	void *aclp;
 	int aclcnt;
@@ -370,78 +311,13 @@
 	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
-	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
-	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
+	assertMakeFile("pretest", 0644, "a");
 
-	/* 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)) {
-#if !HAVE_SUN_ACL
-		acl_free(acl);
-#endif
+	if (setTestAcl("pretest") != ARCHIVE_TEST_ACL_TYPE_POSIX1E) {
+		skipping("POSIX.1e ACLs are not writable on this filesystem");
 		return;
 	}
 
-#if HAVE_SUN_ACL
-	aclp = sunacl_get(GETACL, &aclcnt, fd, NULL);
-	if (aclp == NULL)
-		close(fd);
-	if (errno == ENOSYS || errno == ENOTSUP) {
-		skipping("POSIX.1e ACLs are not supported on this filesystem");
-		return;
-	}
-	failure("facl(): errno = %d (%s)", errno, strerror(errno));
-	if (assert(aclp != NULL) == 0) {
-		free(aclp);
-		return;
-	}
-	free(aclp);
-	aclp = NULL;
-
-	func = "facl()";
-	n = facl(fd, SETACL, (int)(sizeof(aclp1)/sizeof(aclp1[0])), &aclp1);
-#else
-	func = "acl_set_fd()";
-	n = acl_set_fd(fd, acl);
-#endif
-#if !HAVE_SUN_ACL
-	acl_free(acl);
-#endif
-	if (n != 0) {
-#if HAVE_SUN_ACL
-		if (errno == ENOSYS || errno == ENOTSUP)
-#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);
-
-	close(fd);
-
 	/* Create a write-to-disk object. */
 	assert(NULL != (a = archive_write_disk_new()));
 	archive_write_disk_set_options(a,
diff --git a/tar/test/CMakeLists.txt b/tar/test/CMakeLists.txt
index 9115d6f..e6054ba 100644
--- a/tar/test/CMakeLists.txt
+++ b/tar/test/CMakeLists.txt
@@ -34,6 +34,7 @@
     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
@@ -72,6 +73,11 @@
   # Register target
   #
   ADD_EXECUTABLE(bsdtar_test ${bsdtar_test_SOURCES})
+  IF(ENABLE_ACL)
+    IF(HAVE_LIBACL)
+      TARGET_LINK_LIBRARIES(bsdtar_test ${ACL_LIBRARY})
+    ENDIF(HAVE_LIBACL)
+  ENDIF(ENABLE_ACL)
   SET_PROPERTY(TARGET bsdtar_test PROPERTY COMPILE_DEFINITIONS LIST_H)
 
   #
diff --git a/tar/test/test_option_acls.c b/tar/test/test_option_acls.c
new file mode 100644
index 0000000..5c3fbfd
--- /dev/null
+++ b/tar/test/test_option_acls.c
@@ -0,0 +1,471 @@
+/*-
+ * 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_FLAG_DEFER_INHERIT,
+    ACL_FLAG_NO_INHERIT,
+    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 */
+}
diff --git a/test_utils/test_common.h b/test_utils/test_common.h
index 1e5c1fe..0078054 100644
--- a/test_utils/test_common.h
+++ b/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
@@ -155,6 +161,9 @@
 #define HAVE_NFS4_ACL   1
 #endif
 
+#define	ARCHIVE_TEST_ACL_TYPE_POSIX1E	1
+#define	ARCHIVE_TEST_ACL_TYPE_NFS4	2
+
 /*
  * Redefine DEFINE_TEST for use in defining the test functions.
  */
@@ -363,9 +372,17 @@
 /* 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 HAVE_SUN_ACL
+/* 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, ...);
diff --git a/test_utils/test_main.c b/test_utils/test_main.c
index ec2fbfe..86ab5f1 100644
--- a/test_utils/test_main.c
+++ b/test_utils/test_main.c
@@ -56,6 +56,20 @@
 #include <stdarg.h>
 #include <time.h>
 
+/* ACL support */
+#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
+#if HAVE_DARWIN_ACL
+#include <membership.h>
+#endif
+
 /*
  *
  * Windows support routines
@@ -2422,6 +2436,227 @@
 	return (0);
 }
 
+#if HAVE_SUN_ACL
+/* Fetch ACLs on Solaris using acl() or facl() */
+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 HAVE_SUN_NFS4_ACL
+	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 /* HAVE_SUN_ACL */
+
+/*
+ * 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 HAVE_POSIX_ACL || HAVE_NFS4_ACL
+	int r = 1;
+#if !HAVE_SUN_ACL
+	acl_t acl;
+#endif
+#if HAVE_POSIX_ACL /* Linux, FreeBSD POSIX.1e */
+	const char *acltext_posix1e = "user:1:rw-,"
+	    "group:15:r-x,"
+	    "user::rwx,"
+	    "group::rwx,"
+	    "other::r-x,"
+	    "mask::rwx";
+#elif HAVE_SUN_ACL /* 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 HAVE_FREEBSD_NFS4_ACL /* 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 HAVE_SUN_NFS4_ACL /* 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 HAVE_DARWIN_ACL /* 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 /* HAVE_DARWIN_ACL */
+
+#if HAVE_FREEBSD_NFS4_ACL
+	acl = acl_from_text(acltext_nfs4);
+	failure("acl_from_text() error: %s", strerror(errno));
+	if (assert(acl != NULL) == 0)
+		return (0);
+#elif HAVE_DARWIN_ACL
+	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_identifier_to_uuid(ID_TYPE_UID, &uid, sizeof(uid_t), uuid);
+	failure("mbr_identifier_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 /* HAVE_DARWIN_ACL */
+
+#if HAVE_NFS4_ACL
+#if HAVE_FREEBSD_NFS4_ACL
+	r = acl_set_file(path, ACL_TYPE_NFS4, acl);
+	acl_free(acl);
+#elif HAVE_SUN_NFS4_ACL
+	r = acl(path, ACE_SETACL,
+	    (int)(sizeof(aclp_nfs4)/sizeof(aclp_nfs4[0])), aclp_nfs4);
+#elif HAVE_DARWIN_ACL
+	r = acl_set_file(path, ACL_TYPE_EXTENDED, acl);
+	acl_free(acl);
+#endif
+	if (r == 0)
+		return (ARCHIVE_TEST_ACL_TYPE_NFS4);
+#endif	/* HAVE_NFS4_ACL */
+
+#if HAVE_POSIX_ACL || HAVE_SUN_ACL
+#if HAVE_POSIX_ACL
+	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 HAVE_SUN_ACL
+	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 /* HAVE_POSIX_ACL || HAVE_SUN_ACL */
+#if HAVE_DARWIN_ACL
+testacl_free:
+	acl_free(acl);
+#endif
+#endif /* HAVE_POSIX_ACL || HAVE_NFS4_ACL */
+	(void)path;	/* UNUSED */
+	return (0);
+}
+
 /*
  * Sleep as needed; useful for verifying disk timestamp changes by
  * ensuring that the wall-clock time has actually changed before we