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
This commit is contained in:
Martin Matuska committed 2017-03-02 16:10:26 +01:00
1 parent 60f0931d3b
commit f5d473ed0b
13 files changed
+754 -268

No files matched your search

+1
View File
@@ -579,6 +579,7 @@ int main(void) { return FS_IOC_GETFLAGS; }" HAVE_WORKING_FS_IOC_GETFLAGS)
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)
+1
View File
@@ -951,6 +951,7 @@ 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 \
+3
View File
@@ -773,6 +773,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
+5
View File
@@ -29,6 +29,11 @@ IF(ENABLE_CAT AND ENABLE_TEST)
# 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)
#
+1
View File
@@ -699,6 +699,7 @@ AC_ARG_ENABLE([acl],
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])
+5
View File
@@ -62,6 +62,11 @@ IF(ENABLE_CPIO AND ENABLE_TEST)
# 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)
#
+1 -1
View File
@@ -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
+5 -140
View File
@@ -248,63 +248,6 @@ static struct myacl_t acls_dir[] = {
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 @@ DEFINE_TEST(test_acl_platform_nfs4)
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 @@ DEFINE_TEST(test_acl_platform_nfs4)
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,
+3 -127
View File
@@ -35,63 +35,6 @@ __FBSDID("$FreeBSD: head/lib/libarchive/test/test_acl_freebsd.c 189427 2009-03-0
#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 @@ DEFINE_TEST(test_acl_platform_posix1e_restore)
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 @@ DEFINE_TEST(test_acl_platform_posix1e_restore)
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,
+6
View File
@@ -34,6 +34,7 @@ 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
@@ -72,6 +73,11 @@ IF(ENABLE_TAR AND ENABLE_TEST)
# 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)
#
+471
View File
@@ -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 */
}
+17
View File
@@ -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 @@ 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 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, ...);
+235
View File
@@ -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 @@ canNodump(void)
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