summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Matuska <martin@matuska.org>2017-03-15 23:27:48 +0100
committerMartin Matuska <martin@matuska.org>2017-03-16 11:39:08 +0100
commitbea9f9cf03b97018f2398df070193835b3822713 (patch)
tree843247e3d304df3a70d0b9ecee641b8e8ca33942
parentf57d129d828f411d6f1eb81ca51dfd9e1fead353 (diff)
downloadlibarchive-bea9f9cf03b97018f2398df070193835b3822713.tar.gz
Add NFSv4 ACL support for Linux via librichacl
Richacls are interpreted as NFSv4 ACLs and stored in archive_acl (Richacl flags and masks are not stored). Analog to mac_metadata, NFSv4 ACLs do not get extracted when the extraction of extended attributes is enabled and the "trusted.richacl" extended attribute is present. RichACL masks and are calculated from file mode on extraction. mac_metadata acl check has been moved in the code to be together with the richacl check.
-rw-r--r--CMakeLists.txt69
-rw-r--r--NEWS2
-rw-r--r--build/cmake/config.h.in8
-rw-r--r--cat/test/CMakeLists.txt7
-rw-r--r--configure.ac45
-rw-r--r--cpio/test/CMakeLists.txt7
-rw-r--r--libarchive/archive_acl_maps_linux.c41
-rw-r--r--libarchive/archive_platform_acl.h3
-rw-r--r--libarchive/archive_read_disk_acl_linux.c142
-rw-r--r--libarchive/archive_write_disk_acl_darwin.c4
-rw-r--r--libarchive/archive_write_disk_acl_freebsd.c4
-rw-r--r--libarchive/archive_write_disk_acl_linux.c198
-rw-r--r--libarchive/archive_write_disk_acl_sunos.c4
-rw-r--r--libarchive/archive_write_disk_posix.c103
-rw-r--r--libarchive/archive_write_disk_private.h7
-rw-r--r--libarchive/test/test_acl_platform_nfs4.c324
-rw-r--r--tar/test/CMakeLists.txt7
-rw-r--r--test_utils/test_main.c25
18 files changed, 827 insertions, 173 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c91b1dea..f62153cb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -602,6 +602,7 @@ LA_CHECK_INCLUDE_FILE("sys/mkdev.h" HAVE_SYS_MKDEV_H)
LA_CHECK_INCLUDE_FILE("sys/mount.h" HAVE_SYS_MOUNT_H)
LA_CHECK_INCLUDE_FILE("sys/param.h" HAVE_SYS_PARAM_H)
LA_CHECK_INCLUDE_FILE("sys/poll.h" HAVE_SYS_POLL_H)
+LA_CHECK_INCLUDE_FILE("sys/richacl.h" HAVE_SYS_RICHACL_H)
LA_CHECK_INCLUDE_FILE("sys/select.h" HAVE_SYS_SELECT_H)
LA_CHECK_INCLUDE_FILE("sys/stat.h" HAVE_SYS_STAT_H)
LA_CHECK_INCLUDE_FILE("sys/statfs.h" HAVE_SYS_STATFS_H)
@@ -1739,21 +1740,59 @@ int main(void) { return ACL_SYNCHRONIZE; }" HAVE_DECL_ACL_SYNCHRONIZE)
ENDIF(HAVE_ACL_T AND HAVE_ACL_ENTRY_T AND HAVE_ACL_PERMSET_T AND
HAVE_ACL_TAG_T)
-IF(ARCHIVE_ACL_DARWIN)
- MESSAGE(STATUS "ACL support: Darwin (limited NFSv4)")
-ELSEIF(ARCHIVE_ACL_FREEBSD_NFS4)
- MESSAGE(STATUS "ACL support: FreeBSD (POSIX.1e and NFSv4)")
-ELSEIF(ARCHIVE_ACL_FREEBSD)
- MESSAGE(STATUS "ACL support: FreeBSD (POSIX.1e)")
-ELSEIF(ARCHIVE_ACL_LIBACL)
- MESSAGE(STATUS "ACL support: libacl (POSIX.1e)")
-ELSEIF(ARCHIVE_ACL_SUNOS_NFS4)
- MESSAGE(STATUS "ACL support: Solaris (POSIX.1e and NFSv4)")
-ELSEIF(ARCHIVE_ACL_SUNOS)
- MESSAGE(STATUS "ACL support: Solaris (POSIX.1e)")
-ELSE()
- MESSAGE(STATUS "ACL support: none")
-ENDIF()
+ # Richacl
+ CHECK_LIBRARY_EXISTS(richacl "richacl_get_file" "" HAVE_LIBRICHACL)
+ IF(HAVE_LIBRICHACL)
+ SET(CMAKE_REQUIRED_LIBRARIES "richacl")
+ FIND_LIBRARY(RICHACL_LIBRARY NAMES richacl)
+ LIST(APPEND ADDITIONAL_LIBS ${RICHACL_LIBRARY})
+ ENDIF(HAVE_LIBRICHACL)
+
+ CHECK_STRUCT_HAS_MEMBER("struct richace" e_type "sys/richacl.h"
+ HAVE_STRUCT_RICHACE)
+ CHECK_STRUCT_HAS_MEMBER("struct richacl" a_flags "sys/richacl.h"
+ HAVE_STRUCT_RICHACL)
+
+ IF(HAVE_LIBRICHACL AND HAVE_STRUCT_RICHACL AND HAVE_STRUCT_RICHACE)
+ CHECK_FUNCTION_EXISTS_GLIBC(richacl_alloc HAVE_RICHACL_ALLOC)
+ CHECK_FUNCTION_EXISTS_GLIBC(richacl_equiv_mode HAVE_RICHACL_EQUIV_MODE)
+ CHECK_FUNCTION_EXISTS_GLIBC(richacl_free HAVE_RICHACL_FREE)
+ CHECK_FUNCTION_EXISTS_GLIBC(richacl_get_fd HAVE_RICHACL_GET_FD)
+ CHECK_FUNCTION_EXISTS_GLIBC(richacl_get_file HAVE_RICHACL_GET_FILE)
+ CHECK_FUNCTION_EXISTS_GLIBC(richacl_set_fd HAVE_RICHACL_SET_FD)
+ CHECK_FUNCTION_EXISTS_GLIBC(richacl_set_file HAVE_RICHACL_SET_FILE)
+ IF(HAVE_RICHACL_ALLOC AND
+ HAVE_RICHACL_EQUIV_MODE AND
+ HAVE_RICHACL_FREE AND
+ HAVE_RICHACL_GET_FD AND
+ HAVE_RICHACL_GET_FILE AND
+ HAVE_RICHACL_SET_FD AND
+ HAVE_RICHACL_SET_FILE)
+ SET(ARCHIVE_ACL_LIBRICHACL TRUE)
+ ENDIF()
+ ENDIF(HAVE_LIBRICHACL AND HAVE_STRUCT_RICHACL AND HAVE_STRUCT_RICHACE)
+
+ IF(ARCHIVE_ACL_DARWIN)
+ MESSAGE(STATUS "ACL support: Darwin (limited NFSv4)")
+ ELSEIF(ARCHIVE_ACL_FREEBSD_NFS4)
+ MESSAGE(STATUS "ACL support: FreeBSD (POSIX.1e and NFSv4)")
+ ELSEIF(ARCHIVE_ACL_FREEBSD)
+ MESSAGE(STATUS "ACL support: FreeBSD (POSIX.1e)")
+ ELSEIF(ARCHIVE_ACL_LIBACL OR ARCHIVE_ACL_LIBRICHACL)
+ IF(ARCHIVE_ACL_LIBACL AND ARCHIVE_ACL_LIBRICHACL)
+ MESSAGE(STATUS "ACL support: libacl (POSIX.1e) + librichacl (NFSv4)")
+ ELSEIF(ARCHIVE_ACL_LIBRICHACL)
+ MESSAGE(STATUS "ACL support: librichacl (NFSv4)")
+ ELSE()
+ MESSAGE(STATUS "ACL support: libacl (POSIX.1e)")
+ ENDIF()
+ ELSEIF(ARCHIVE_ACL_SUNOS_NFS4)
+ MESSAGE(STATUS "ACL support: Solaris (POSIX.1e and NFSv4)")
+ ELSEIF(ARCHIVE_ACL_SUNOS)
+ MESSAGE(STATUS "ACL support: Solaris (POSIX.1e)")
+ ELSE()
+ MESSAGE(STATUS "ACL support: none")
+ ENDIF()
ELSE(ENABLE_ACL)
# If someone runs cmake, then disables ACL support, we need
diff --git a/NEWS b/NEWS
index fdd971d7..9e517934 100644
--- a/NEWS
+++ b/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
diff --git a/build/cmake/config.h.in b/build/cmake/config.h.in
index c46a341a..cfd2a5c0 100644
--- a/build/cmake/config.h.in
+++ b/build/cmake/config.h.in
@@ -188,9 +188,12 @@ typedef uint64_t uintmax_t;
/* FreeBSD NFSv4 ACL support */
#cmakedefine ARCHIVE_ACL_FREEBSD_NFS4 1
-/* Linux ACL support via libacl */
+/* 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
@@ -1031,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
diff --git a/cat/test/CMakeLists.txt b/cat/test/CMakeLists.txt
index 0623cc36..0cd3aad8 100644
--- a/cat/test/CMakeLists.txt
+++ b/cat/test/CMakeLists.txt
@@ -30,9 +30,14 @@ IF(ENABLE_CAT AND ENABLE_TEST)
#
ADD_EXECUTABLE(bsdcat_test ${bsdcat_test_SOURCES})
IF(ENABLE_ACL)
+ SET(TEST_ACL_LIBS "")
IF(HAVE_LIBACL)
- TARGET_LINK_LIBRARIES(bsdcat_test ${ACL_LIBRARY})
+ 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)
diff --git a/configure.ac b/configure.ac
index 24e96d68..05b5a099 100644
--- a/configure.ac
+++ b/configure.ac
@@ -289,7 +289,8 @@ AC_CHECK_HEADERS([readpassphrase.h signal.h spawn.h])
AC_CHECK_HEADERS([stdarg.h stdint.h stdlib.h string.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])
@@ -712,9 +713,31 @@ if test "x$enable_acl" != "xno"; then
#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
+ ])
+
# 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
+
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>]])
@@ -833,9 +856,21 @@ if test "x$enable_acl" != "xno"; then
fi
fi
AC_MSG_CHECKING([for ACL support])
- if test "x$ac_cv_archive_acl_libacl" = "xyes"; then
+ 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 ACL support via libacl])
+ 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)])
@@ -863,7 +898,9 @@ if test "x$enable_acl" != "xno"; then
fi
-AM_CONDITIONAL([INC_LINUX_ACL], [test "x$ac_cv_archive_acl_libacl" = "xyes"])
+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"])
diff --git a/cpio/test/CMakeLists.txt b/cpio/test/CMakeLists.txt
index cc5fe011..4c3fb88a 100644
--- a/cpio/test/CMakeLists.txt
+++ b/cpio/test/CMakeLists.txt
@@ -63,9 +63,14 @@ IF(ENABLE_CPIO AND ENABLE_TEST)
#
ADD_EXECUTABLE(bsdcpio_test ${bsdcpio_test_SOURCES})
IF(ENABLE_ACL)
+ SET(TEST_ACL_LIBS "")
IF(HAVE_LIBACL)
- TARGET_LINK_LIBRARIES(bsdcpio_test ${ACL_LIBRARY})
+ 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)
diff --git a/libarchive/archive_acl_maps_linux.c b/libarchive/archive_acl_maps_linux.c
index c184f20b..3476e12c 100644
--- a/libarchive/archive_acl_maps_linux.c
+++ b/libarchive/archive_acl_maps_linux.c
@@ -32,6 +32,9 @@
#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"
@@ -39,6 +42,7 @@
#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},
@@ -47,3 +51,40 @@ const acl_perm_map_t acl_posix_perm_map[] = {
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 */
diff --git a/libarchive/archive_platform_acl.h b/libarchive/archive_platform_acl.h
index 8c091cf5..3498f78b 100644
--- a/libarchive/archive_platform_acl.h
+++ b/libarchive/archive_platform_acl.h
@@ -37,7 +37,8 @@
#define ARCHIVE_ACL_POSIX1E 1
#endif
-#if ARCHIVE_ACL_FREEBSD_NFS4 || ARCHIVE_ACL_SUNOS_NFS4 || ARCHIVE_ACL_DARWIN
+#if ARCHIVE_ACL_FREEBSD_NFS4 || ARCHIVE_ACL_SUNOS_NFS4 || \
+ ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBRICHACL
#define ARCHIVE_ACL_NFS4 1
#endif
diff --git a/libarchive/archive_read_disk_acl_linux.c b/libarchive/archive_read_disk_acl_linux.c
index 23146dba..3ddee2fe 100644
--- a/libarchive/archive_read_disk_acl_linux.c
+++ b/libarchive/archive_read_disk_acl_linux.c
@@ -33,12 +33,15 @@
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
-#if HAVE_ACL_LIBACL_H && HAVE_LIBACL
+#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"
@@ -49,6 +52,7 @@
#include <acl/libacl.h>
#endif
+#if ARCHIVE_ACL_LIBACL
/*
* Translate POSIX.1e ACLs into libarchive internal structure
*/
@@ -154,15 +158,104 @@ translate_acl(struct archive_read_disk *a,
}
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;
- acl_t acl;
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)))
@@ -185,8 +278,50 @@ archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
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);
@@ -224,5 +359,6 @@ archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
}
}
}
- return (ARCHIVE_OK);
+#endif /* ARCHIVE_ACL_LIBACL */
+ return (r);
}
diff --git a/libarchive/archive_write_disk_acl_darwin.c b/libarchive/archive_write_disk_acl_darwin.c
index 22375c76..4ffdd66b 100644
--- a/libarchive/archive_write_disk_acl_darwin.c
+++ b/libarchive/archive_write_disk_acl_darwin.c
@@ -219,10 +219,12 @@ exit_free:
int
archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
- struct archive_acl *abstract_acl)
+ 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,
diff --git a/libarchive/archive_write_disk_acl_freebsd.c b/libarchive/archive_write_disk_acl_freebsd.c
index d6b87671..29e64adf 100644
--- a/libarchive/archive_write_disk_acl_freebsd.c
+++ b/libarchive/archive_write_disk_acl_freebsd.c
@@ -287,10 +287,12 @@ exit_free:
int
archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
- struct archive_acl *abstract_acl)
+ 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)
diff --git a/libarchive/archive_write_disk_acl_linux.c b/libarchive/archive_write_disk_acl_linux.c
index 15af1a1b..2239df6c 100644
--- a/libarchive/archive_write_disk_acl_linux.c
+++ b/libarchive/archive_write_disk_acl_linux.c
@@ -32,41 +32,206 @@
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
-#if HAVE_ACL_LIBACL_H && HAVE_LIBACL
+#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;
- acl_t acl;
- acl_entry_t acl_entry;
- acl_permset_t acl_permset;
- int ret;
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;
@@ -89,12 +254,14 @@ set_acl(struct archive *a, int fd, const char *name,
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);
@@ -179,13 +346,29 @@ 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)
+ 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)
@@ -200,5 +383,6 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
ret = set_acl(a, fd, name, abstract_acl,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
}
+#endif /* ARCHIVE_ACL_LIBACL */
return (ret);
}
diff --git a/libarchive/archive_write_disk_acl_sunos.c b/libarchive/archive_write_disk_acl_sunos.c
index e8002396..ebc0b095 100644
--- a/libarchive/archive_write_disk_acl_sunos.c
+++ b/libarchive/archive_write_disk_acl_sunos.c
@@ -303,10 +303,12 @@ exit_free:
int
archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
- struct archive_acl *abstract_acl)
+ 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 */
diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c
index 6c0dd19b..adb15c0e 100644
--- a/libarchive/archive_write_disk_posix.c
+++ b/libarchive/archive_write_disk_posix.c
@@ -369,10 +369,6 @@ static ssize_t hfs_write_data_block(struct archive_write_disk *,
static int fixup_appledouble(struct archive_write_disk *, const char *);
static int older(struct stat *, struct archive_entry *);
static int restore_entry(struct archive_write_disk *);
-#ifndef ARCHIVE_ACL_SUPPORT
-static int archive_write_disk_set_acls(struct archive *, int, const char *,
- struct archive_acl *);
-#endif
static int set_mac_metadata(struct archive_write_disk *, const char *,
const void *, size_t);
static int set_xattrs(struct archive_write_disk *);
@@ -429,19 +425,6 @@ lazy_stat(struct archive_write_disk *a)
return (ARCHIVE_WARN);
}
-#ifndef ARCHIVE_ACL_SUPPORT
-static 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);
-}
-#endif
-
static struct archive_vtable *
archive_write_disk_vtable(void)
{
@@ -592,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)
@@ -1720,25 +1748,11 @@ _archive_write_disk_finish_entry(struct archive *_a)
*/
if (a->todo & TODO_ACLS) {
int r2;
-#if ARCHIVE_ACL_DARWIN
- /*
- * 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;
-#if ARCHIVE_ACL_DARWIN
- }
-#endif
}
finish_metadata:
@@ -2310,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)
-#if ARCHIVE_ACL_DARWIN
- 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);
@@ -4256,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__ */
diff --git a/libarchive/archive_write_disk_private.h b/libarchive/archive_write_disk_private.h
index c5814b4b..b655dea2 100644
--- a/libarchive/archive_write_disk_private.h
+++ b/libarchive/archive_write_disk_private.h
@@ -35,12 +35,11 @@
#include "archive_platform_acl.h"
#include "archive_acl_private.h"
+#include "archive_entry.h"
struct archive_write_disk;
-#if ARCHIVE_ACL_SUPPORT
-int
-archive_write_disk_set_acls(struct archive *, int /* fd */, const char * /* pathname */, struct archive_acl *);
-#endif
+int archive_write_disk_set_acls(struct archive *, int, const char *,
+ struct archive_acl *, __LA_MODE_T);
#endif
diff --git a/libarchive/test/test_acl_platform_nfs4.c b/libarchive/test/test_acl_platform_nfs4.c
index b8dce122..a3868a62 100644
--- a/libarchive/test/test_acl_platform_nfs4.c
+++ b/libarchive/test/test_acl_platform_nfs4.c
@@ -27,8 +27,13 @@
__FBSDID("$FreeBSD$");
#if ARCHIVE_ACL_NFS4
+#if HAVE_SYS_ACL_H
#define _ACL_PRIVATE
#include <sys/acl.h>
+#endif
+#if HAVE_SYS_RICHACL_H
+#include <sys/richacl.h>
+#endif
#if HAVE_MEMBERSHIP_H
#include <membership.h>
#endif
@@ -273,78 +278,96 @@ set_acls(struct archive_entry *ae, struct myacl_t *acls, int start, int end)
}
static int
-#ifdef ARCHIVE_ACL_SUNOS_NFS4
-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[] = {
+ static struct { int portable; int machine; } perms[] = {
#ifdef ARCHIVE_ACL_SUNOS_NFS4 /* 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}
+ {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 */
- {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},
+ {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
- {ACL_SYNCHRONIZE, ARCHIVE_ENTRY_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 ARCHIVE_ACL_SUNOS_NFS4
- 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
@@ -354,47 +377,55 @@ acl_permset_to_bitmap(acl_permset_t opaque_ps)
static int
#if ARCHIVE_ACL_SUNOS_NFS4
-acl_flagset_to_bitmap(uint16_t a_flags)
+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[] = {
+ static struct { int portable; int machine; } perms[] = {
#if ARCHIVE_ACL_SUNOS_NFS4 /* 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},
+ {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
- {ACE_INHERITED_ACE, ARCHIVE_ENTRY_ACL_ENTRY_INHERITED}
+ {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}
#endif
#elif ARCHIVE_ACL_DARWIN /* 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}
+ {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_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_NO_PROPAGATE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT},
- {ACL_ENTRY_SUCCESSFUL_ACCESS, ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS},
- {ACL_ENTRY_FAILED_ACCESS, 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 ARCHIVE_ACL_SUNOS_NFS4
- 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;
}
@@ -452,6 +483,62 @@ acl_match(ace_t *ace, struct myacl_t *myacl)
}
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)
@@ -593,6 +680,8 @@ compare_acls(
#if ARCHIVE_ACL_SUNOS_NFS4
void *aclp,
int aclcnt,
+#elif ARCHIVE_ACL_LIBRICHACL
+ struct richacl *richacl,
#else
acl_t acl,
#endif
@@ -604,6 +693,10 @@ compare_acls(
#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;
@@ -614,6 +707,18 @@ compare_acls(
#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++)
@@ -630,7 +735,7 @@ compare_acls(
* Iterate over acls in system acl object, try to match each
* one with an item in the myacls array.
*/
-#if ARCHIVE_ACL_SUNOS_NFS4
+#if ARCHIVE_ACL_SUNOS_NFS4 || ARCHIVE_ACL_LIBRICHACL
for (e = 0; e < aclcnt; e++)
#else
while (acl_get_entry_ret == acl_get_entry(acl, entry_id, &acl_entry))
@@ -638,6 +743,8 @@ compare_acls(
{
#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;
@@ -756,6 +863,8 @@ DEFINE_TEST(test_acl_platform_nfs4)
#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
@@ -814,21 +923,31 @@ DEFINE_TEST(test_acl_platform_nfs4)
assertEqualInt(st.st_mtime, 123456);
#if ARCHIVE_ACL_SUNOS_NFS4
aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, "testall");
- failure("acl(): errno = %d (%s)", errno, strerror(errno));
+ 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 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);
@@ -842,15 +961,25 @@ DEFINE_TEST(test_acl_platform_nfs4)
assertEqualInt(st.st_mtime, 123456 + i);
#if ARCHIVE_ACL_SUNOS_NFS4
aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, buff);
- failure("acl(): errno = %d (%s)", errno, strerror(errno));
+ 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 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
@@ -858,6 +987,9 @@ DEFINE_TEST(test_acl_platform_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);
@@ -869,21 +1001,31 @@ DEFINE_TEST(test_acl_platform_nfs4)
assertEqualInt(st.st_mtime, 123456);
#if ARCHIVE_ACL_SUNOS_NFS4
aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, "dirall");
- failure("acl(): errno = %d (%s)", errno, strerror(errno));
+ 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 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);
diff --git a/tar/test/CMakeLists.txt b/tar/test/CMakeLists.txt
index e6054bab..318eb06e 100644
--- a/tar/test/CMakeLists.txt
+++ b/tar/test/CMakeLists.txt
@@ -74,9 +74,14 @@ IF(ENABLE_TAR AND ENABLE_TEST)
#
ADD_EXECUTABLE(bsdtar_test ${bsdtar_test_SOURCES})
IF(ENABLE_ACL)
+ SET(TEST_ACL_LIBS "")
IF(HAVE_LIBACL)
- TARGET_LINK_LIBRARIES(bsdtar_test ${ACL_LIBRARY})
+ 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)
diff --git a/test_utils/test_main.c b/test_utils/test_main.c
index 699dcf8d..0ef6d6fc 100644
--- a/test_utils/test_main.c
+++ b/test_utils/test_main.c
@@ -67,6 +67,9 @@
#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
@@ -2507,9 +2510,12 @@ setTestAcl(const char *path)
{
#if ARCHIVE_ACL_SUPPORT
int r = 1;
-#if !ARCHIVE_ACL_SUNOS
+#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,"
@@ -2533,6 +2539,15 @@ setTestAcl(const char *path)
"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 |
@@ -2579,6 +2594,11 @@ setTestAcl(const char *path)
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));
@@ -2620,6 +2640,9 @@ setTestAcl(const char *path)
#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);