libarchive/test/main.c \
libarchive/test/read_open_memory.c \
libarchive/test/test.h \
- libarchive/test/test_acl_freebsd_nfs4.c \
- libarchive/test/test_acl_freebsd_posix1e.c \
libarchive/test/test_acl_nfs4.c \
libarchive/test/test_acl_pax.c \
+ libarchive/test/test_acl_platform_nfs4.c \
+ libarchive/test/test_acl_platform_posix1e.c \
libarchive/test/test_acl_posix1e.c \
- libarchive/test/test_acl_solaris_nfs4.c \
- libarchive/test/test_acl_solaris_posix1e.c \
libarchive/test/test_acl_text.c \
libarchive/test/test_archive_api_feature.c \
libarchive/test/test_archive_clear_error.c \
main.c
read_open_memory.c
test.h
- test_acl_freebsd_nfs4.c
- test_acl_freebsd_posix1e.c
test_acl_nfs4.c
test_acl_pax.c
+ test_acl_platform_nfs4.c
+ test_acl_platform_posix1e.c
test_acl_posix1e.c
- test_acl_solaris_nfs4.c
- test_acl_solaris_posix1e.c
test_acl_text.c
test_archive_api_feature.c
test_archive_clear_error.c
#define O_BINARY 0
#endif
+/*
+ * If this platform has <sys/acl.h>, acl_create(), acl_init(),
+ * acl_set_file(), and ACL_USER, we assume it has the rest of the
+ * POSIX.1e draft functions used in archive_read_extract.c.
+ */
+#if HAVE_SYS_ACL_H && HAVE_ACL_CREATE_ENTRY && HAVE_ACL_INIT && HAVE_ACL_SET_FILE && HAVE_ACL_USER
+#define HAVE_POSIX_ACL 1
+#endif
+
+/*
+ * If this platform has <sys/acl.h>, acl_get(), facl_get(), acl_set(),
+ * facl_set() and types aclent_t and ace_t it uses Solaris-style ACL functions
+ */
+#if HAVE_SYS_ACL_H && HAVE_ACL_GET && HAVE_FACL_GET && HAVE_ACL_SET && HAVE_FACL_SET && HAVE_ACLENT_T && HAVE_ACE_T
+#define HAVE_SUN_ACL 1
+#endif
+
/*
* Redefine DEFINE_TEST for use in defining the test functions.
*/
/*-
* Copyright (c) 2003-2010 Tim Kientzle
+ * Copyright (c) 2017 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#include "test.h"
__FBSDID("$FreeBSD$");
-#if defined(__FreeBSD__) && __FreeBSD__ >= 8
+#if HAVE_SUN_ACL || HAVE_POSIX_ACL
#define _ACL_PRIVATE
#include <sys/acl.h>
+#endif
+
+#if HAVE_SUN_ACL || (HAVE_POSIX_ACL && defined(ACL_TYPE_NFS4))
struct myacl_t {
int type;
ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }
};
-
static struct myacl_t acls_dir[] = {
/* For this test, we need to be able to read and write the ACL. */
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_READ_ACL,
}
static int
+#ifdef HAVE_SUN_ACL
+acl_permset_to_bitmap(uint32_t a_access_mask)
+#else
acl_permset_to_bitmap(acl_permset_t opaque_ps)
+#endif
{
static struct { int machine; int portable; } perms[] = {
+#ifdef HAVE_SUN_ACL
+ {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}
+#else
{ACL_EXECUTE, ARCHIVE_ENTRY_ACL_EXECUTE},
{ACL_WRITE, ARCHIVE_ENTRY_ACL_WRITE},
{ACL_READ, ARCHIVE_ENTRY_ACL_READ},
{ACL_WRITE_ACL, ARCHIVE_ENTRY_ACL_WRITE_ACL},
{ACL_WRITE_OWNER, ARCHIVE_ENTRY_ACL_WRITE_OWNER},
{ACL_SYNCHRONIZE, ARCHIVE_ENTRY_ACL_SYNCHRONIZE}
+#endif
};
int i, permset = 0;
for (i = 0; i < (int)(sizeof(perms)/sizeof(perms[0])); ++i)
+#if HAVE_SUN_ACL
+ if (a_access_mask & perms[i].machine)
+#else
if (acl_get_perm_np(opaque_ps, perms[i].machine))
+#endif
permset |= perms[i].portable;
return permset;
}
static int
+#if HAVE_SUN_ACL
+acl_flagset_to_bitmap(uint16_t a_flags)
+#else
acl_flagset_to_bitmap(acl_flagset_t opaque_fs)
+#endif
{
static struct { int machine; int portable; } flags[] = {
+#if HAVE_SUN_ACL
+ {ACE_FILE_INHERIT_ACE, ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT},
+ {ACE_DIRECTORY_INHERIT_ACE, ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT},
+ {ACE_NO_PROPAGATE_INHERIT_ACE, ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT},
+ {ACE_INHERIT_ONLY_ACE, ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY},
+ {ACE_SUCCESSFUL_ACCESS_ACE_FLAG, ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS},
+ {ACE_FAILED_ACCESS_ACE_FLAG, ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS},
+ {ACE_INHERITED_ACE, ARCHIVE_ENTRY_ACL_ENTRY_INHERITED}
+#else
{ACL_ENTRY_FILE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT},
{ACL_ENTRY_DIRECTORY_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT},
{ACL_ENTRY_NO_PROPAGATE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT},
+ {ACL_ENTRY_SUCCESSFUL_ACCESS, ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS},
+ {ACL_ENTRY_NO_PROPAGATE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS},
+
{ACL_ENTRY_INHERIT_ONLY, ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY},
+#endif
};
int i, flagset = 0;
for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); ++i)
+#if HAVE_SUN_ACL
+ if (a_flags & flags[i].machine)
+#else
if (acl_get_flag_np(opaque_fs, flags[i].machine))
+#endif
flagset |= flags[i].portable;
return flagset;
}
static int
+#if HAVE_SUN_ACL
+acl_match(ace_t *ace, struct myacl_t *myacl)
+#else
acl_match(acl_entry_t aclent, struct myacl_t *myacl)
+#endif
{
+#if !HAVE_SUN_ACL
gid_t g, *gp;
uid_t u, *up;
acl_tag_t tag_type;
acl_permset_t opaque_ps;
acl_flagset_t opaque_fs;
+#endif
int perms;
+#if HAVE_SUN_ACL
+ perms = acl_permset_to_bitmap(ace->a_access_mask) | acl_flagset_to_bitmap(ace->a_flags);
+#else
acl_get_tag_type(aclent, &tag_type);
/* translate the silly opaque permset to a bitmap */
acl_get_permset(aclent, &opaque_ps);
acl_get_flagset_np(aclent, &opaque_fs);
perms = acl_permset_to_bitmap(opaque_ps) | acl_flagset_to_bitmap(opaque_fs);
+#endif
if (perms != myacl->permset)
return (0);
+#if HAVE_SUN_ACL
+ if (ace->a_flags & ACE_OWNER) {
+ if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ)
+ return (0);
+ } else if (ace->a_flags & ACE_GROUP) {
+ if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ)
+ return (0);
+ } else if (ace->a_flags & ACE_EVERYONE) {
+ if (myacl->tag != ARCHIVE_ENTRY_ACL_EVERYONE)
+ return (0);
+ } else if (ace->a_flags & ACE_IDENTIFIER_GROUP) {
+ if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
+ return (0);
+ if ((gid_t)myacl->qual != ace->a_who)
+ return (0);
+ } else {
+ if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
+ return (0);
+ if ((uid_t)myacl->qual != ace->a_who)
+ return (0);
+ }
+#else /* !HAVE_SUN_ACL */
switch (tag_type) {
case ACL_USER_OBJ:
if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) return (0);
if (myacl->tag != ARCHIVE_ENTRY_ACL_EVERYONE) return (0);
break;
}
+#endif /* !HAVE_SUN_ACL */
return (1);
}
static void
-compare_acls(acl_t acl, struct myacl_t *myacls, const char *filename, int start, int end)
+compare_acls(
+#if HAVE_SUN_ACL
+ acl_t *acl,
+#else
+ acl_t acl,
+#endif
+ struct myacl_t *myacls, const char *filename, int start, int end)
{
int *marker;
- int entry_id = ACL_FIRST_ENTRY;
int matched;
int i, n;
+#if HAVE_SUN_ACL
+ int e;
+ ace_t *acl_entry;
+#else
+ int entry_id = ACL_FIRST_ENTRY;
acl_entry_t acl_entry;
+#endif
n = end - start;
marker = malloc(sizeof(marker[0]) * (n + 1));
* Iterate over acls in system acl object, try to match each
* one with an item in the myacls array.
*/
- while (1 == acl_get_entry(acl, entry_id, &acl_entry)) {
+#if HAVE_SUN_ACL
+ for (e = 0; e < acl->acl_cnt; e++)
+#else
+ while (1 == acl_get_entry(acl, entry_id, &acl_entry))
+#endif
+ {
+#if HAVE_SUN_ACL
+ acl_entry = &((ace_t *)acl->acl_aclp)[e];
+#else
/* After the first time... */
entry_id = ACL_NEXT_ENTRY;
-
+#endif
/* Search for a matching entry (tag and qualifier) */
for (i = 0, matched = 0; i < n && !matched; i++) {
if (acl_match(acl_entry, &myacls[marker[i]])) {
}
}
- failure("ACL entry on file %s that shouldn't be there", filename);
+ failure("ACL entry on file %s that shouldn't be there",
+ filename);
assert(matched == 1);
}
* Iterate over acls in entry, try to match each
* one with an item in the myacls array.
*/
- assertEqualInt(n, archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4));
+ assertEqualInt(n, archive_entry_acl_reset(ae,
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4));
while (ARCHIVE_OK == archive_entry_acl_next(ae,
ARCHIVE_ENTRY_ACL_TYPE_NFS4, &type, &permset, &tag, &qual, &name)) {
}
free(marker);
}
-#endif
+#endif /* HAVE_SUN_ACL || (HAVE_POSIX_ACL && defined(ACL_TYPE_NFS4)) */
/*
- * Verify ACL restore-to-disk. This test is FreeBSD-specific.
+ * Verify ACL restore-to-disk. This test is Platform-specific.
*/
-DEFINE_TEST(test_acl_freebsd_nfs4)
+DEFINE_TEST(test_acl_platform_nfs4)
{
-#if !defined(__FreeBSD__)
- skipping("FreeBSD-specific NFS4 ACL restore test");
-#elif __FreeBSD__ < 8
- skipping("NFS4 ACLs supported only on FreeBSD 8.0 and later");
+#if !HAVE_SUN_ACL && (!HAVE_POSIX_ACL || !defined(ACL_TYPE_NFS4))
+ skipping("NFS4 ACLs are not supported on this platform");
#else
char buff[64];
struct stat st;
struct archive *a;
struct archive_entry *ae;
int i, n;
+ char *func;
+#if HAVE_SUN_ACL
+ acl_t *acl;
+#else
acl_t acl;
+#endif
/*
* First, do a quick manual set/read of ACL data to
* verify that the local filesystem does support ACLs.
* If it doesn't, we'll simply skip the remaining tests.
*/
+#if !HAVE_SUN_ACL
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);
+#endif
+
/* Create a test dir and try to set an ACL on it. */
if (!assertMakeDir("pretest", 0755)) {
+#if !HAVE_SUN_ACL
acl_free(acl);
+#endif
return;
}
+#if HAVE_SUN_ACL
+ func = "acl_get()";
+ n = acl_get("pretest", 0, &acl);
+#else
+ func = "acl_set_file()";
n = acl_set_file("pretest", ACL_TYPE_NFS4, acl);
acl_free(acl);
- if (n != 0 && errno == EOPNOTSUPP) {
- skipping("NFS4 ACL tests require that NFS4 ACLs"
- " be enabled on the filesystem");
- return;
+#endif
+ if (n != 0) {
+#if HAVE_SUN_ACL
+ if (errno == ENOSYS)
+#else
+ if (errno == EOPNOTSUPP || errno == EINVAL)
+#endif
+ {
+ skipping("NFS4 ACL is not supported on this filesystem");
+ return;
+ }
}
- if (n != 0 && errno == EINVAL) {
- skipping("This filesystem does not support NFS4 ACLs");
+ failure("%s: errno = %d (%s)", func, errno, strerror(errno));
+ assertEqualInt(0, n);
+
+#if HAVE_SUN_ACL
+ if (acl->acl_type != ACE_T) {
+ acl_free(acl);
+ skipping("NFS4 ACL is not supported on this filesystem");
return;
}
- failure("acl_set_file(): errno = %d (%s)",
- errno, strerror(errno));
- assertEqualInt(0, n);
+ acl_free(acl);
+#endif
/* Create a write-to-disk object. */
assert(NULL != (a = archive_write_disk_new()));
/* Verify the data on disk. */
assertEqualInt(0, stat("testall", &st));
assertEqualInt(st.st_mtime, 123456);
+#if HAVE_SUN_ACL
+ n = acl_get("testall", 0, &acl);
+ failure("acl_get(): errno = %d (%s)", errno, strerror(errno));
+ assertEqualInt(0, n);
+#else
acl = acl_get_file("testall", ACL_TYPE_NFS4);
+ failure("acl_get_file(): errno = %d (%s)", errno, strerror(errno));
assert(acl != (acl_t)NULL);
+#endif
compare_acls(acl, acls_reg, "testall", 0, (int)(sizeof(acls_reg)/sizeof(acls_reg[0])));
acl_free(acl);
/* Verify single-permission dirs on disk. */
for (i = 0; i < (int)(sizeof(acls_dir)/sizeof(acls_dir[0])); ++i) {
- sprintf(buff, "dir%d", i);
- assertEqualInt(0, stat(buff, &st));
- assertEqualInt(st.st_mtime, 123456 + i);
- acl = acl_get_file(buff, ACL_TYPE_NFS4);
- assert(acl != (acl_t)NULL);
- compare_acls(acl, acls_dir, buff, i, i + 1);
- acl_free(acl);
+ sprintf(buff, "dir%d", i);
+ assertEqualInt(0, stat(buff, &st));
+ assertEqualInt(st.st_mtime, 123456 + i);
+#if HAVE_SUN_ACL
+ n = acl_get(buff, 0, &acl);
+ failure("acl_get(): errno = %d (%s)", errno, strerror(errno));
+ assertEqualInt(0, n);
+#else
+ acl = acl_get_file(buff, ACL_TYPE_NFS4);
+ failure("acl_get_file(): errno = %d (%s)", errno,
+ strerror(errno));
+ assert(acl != (acl_t)NULL);
+#endif
+ compare_acls(acl, acls_dir, buff, i, i + 1);
+ acl_free(acl);
}
/* Verify "dirall" on disk. */
assertEqualInt(0, stat("dirall", &st));
assertEqualInt(st.st_mtime, 123456);
+#if HAVE_SUN_ACL
+ n = acl_get("dirall", 0, &acl);
+ failure("acl_get(): errno = %d (%s)", errno, strerror(errno));
+ assertEqualInt(0, n);
+#else
acl = acl_get_file("dirall", ACL_TYPE_NFS4);
+ failure("acl_get_file(): errno = %d (%s)", errno, strerror(errno));
assert(acl != (acl_t)NULL);
- compare_acls(acl, acls_dir, "dirall", 0, (int)(sizeof(acls_dir)/sizeof(acls_dir[0])));
+#endif
+ compare_acls(acl, acls_dir, "dirall", 0,
+ (int)(sizeof(acls_dir)/sizeof(acls_dir[0])));
acl_free(acl);
/* Read and compare ACL via archive_read_disk */
archive_entry_set_pathname(ae, "testall");
assertEqualInt(ARCHIVE_OK,
archive_read_disk_entry_from_file(a, ae, -1, NULL));
- compare_entry_acls(ae, acls_reg, "testall", 0, (int)(sizeof(acls_reg)/sizeof(acls_reg[0])));
+ compare_entry_acls(ae, acls_reg, "testall", 0,
+ (int)(sizeof(acls_reg)/sizeof(acls_reg[0])));
archive_entry_free(ae);
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
assert(ae != NULL);
archive_entry_set_pathname(ae, "dirall");
assertEqualInt(ARCHIVE_OK,
- archive_read_disk_entry_from_file(a, ae, -1, NULL));
- compare_entry_acls(ae, acls_dir, "dirall", 0, (int)(sizeof(acls_dir)/sizeof(acls_dir[0])));
+ archive_read_disk_entry_from_file(a, ae, -1, NULL));
+ compare_entry_acls(ae, acls_dir, "dirall", 0,
+ (int)(sizeof(acls_dir)/sizeof(acls_dir[0])));
archive_entry_free(ae);
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
-#endif
+#endif /* HAVE_SUN_ACL || (HAVE_POSIX_ACL && defined(ACL_TYPE_NFS4)) */
}
/*-
* Copyright (c) 2003-2008 Tim Kientzle
+ * Copyright (c) 2017 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#include "test.h"
__FBSDID("$FreeBSD: head/lib/libarchive/test/test_acl_freebsd.c 189427 2009-03-06 04:21:23Z kientzle $");
-#if defined(__FreeBSD__) && __FreeBSD__ > 4
+#if HAVE_POSIX_ACL || HAVE_SUN_ACL
#include <sys/acl.h>
+#if HAVE_ACL_GET_PERM
+#include <acl/libacl.h>
+#define ACL_GET_PERM acl_get_perm
+#elif HAVE_ACL_GET_PERM_NP
+#define ACL_GET_PERM acl_get_perm_np
+#endif
static struct archive_test_acl_t acls2[] = {
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE | ARCHIVE_ENTRY_ACL_READ,
};
static int
-acl_entry_get_perm(acl_entry_t aclent) {
+#if HAVE_SUN_ACL
+acl_entry_get_perm(aclent_t *aclent)
+#else
+acl_entry_get_perm(acl_entry_t aclent)
+#endif
+{
int permset = 0;
+#if HAVE_POSIX_ACL
acl_permset_t opaque_ps;
+#endif
+#if HAVE_SUN_ACL
+ if (aclent->a_perm & 1)
+ permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
+ if (aclent->a_perm & 2)
+ permset |= ARCHIVE_ENTRY_ACL_WRITE;
+ if (aclent->a_perm & 4)
+ permset |= ARCHIVE_ENTRY_ACL_READ;
+#else
/* translate the silly opaque permset to a bitmap */
acl_get_permset(aclent, &opaque_ps);
- if (acl_get_perm_np(opaque_ps, ACL_EXECUTE))
+ if (ACL_GET_PERM(opaque_ps, ACL_EXECUTE))
permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
- if (acl_get_perm_np(opaque_ps, ACL_WRITE))
+ if (ACL_GET_PERM(opaque_ps, ACL_WRITE))
permset |= ARCHIVE_ENTRY_ACL_WRITE;
- if (acl_get_perm_np(opaque_ps, ACL_READ))
+ if (ACL_GET_PERM(opaque_ps, ACL_READ))
permset |= ARCHIVE_ENTRY_ACL_READ;
+#endif
return permset;
}
#endif
static int
+#if HAVE_SUN_ACL
+acl_match(aclent_t *aclent, struct archive_test_acl_t *myacl)
+#else
acl_match(acl_entry_t aclent, struct archive_test_acl_t *myacl)
+#endif
{
+#if HAVE_POSIX_ACL
gid_t g, *gp;
uid_t u, *up;
acl_tag_t tag_type;
+#endif
if (myacl->permset != acl_entry_get_perm(aclent))
return (0);
+#if HAVE_SUN_ACL
+ switch (aclent->a_type)
+#else
acl_get_tag_type(aclent, &tag_type);
- switch (tag_type) {
+ switch (tag_type)
+#endif
+ {
+#if HAVE_SUN_ACL
+ case DEF_USER_OBJ:
+ case USER_OBJ:
+#else
case ACL_USER_OBJ:
+#endif
if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) return (0);
break;
+#if HAVE_SUN_ACL
+ case DEF_USER:
+ case USER:
+#else
case ACL_USER:
+#endif
if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
return (0);
+#if HAVE_SUN_ACL
+ if ((uid_t)myacl->qual != aclent->a_id)
+ return (0);
+#else
up = acl_get_qualifier(aclent);
u = *up;
acl_free(up);
if ((uid_t)myacl->qual != u)
return (0);
+#endif
break;
+#if HAVE_SUN_ACL
+ case DEF_GROUP_OBJ:
+ case GROUP_OBJ:
+#else
case ACL_GROUP_OBJ:
+#endif
if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ) return (0);
break;
+#if HAVE_SUN_ACL
+ case DEF_GROUP:
+ case GROUP:
+#else
case ACL_GROUP:
+#endif
if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
return (0);
+#if HAVE_SUN_ACL
+ if ((gid_t)myacl->qual != aclent->a_id)
+ return (0);
+#else
gp = acl_get_qualifier(aclent);
g = *gp;
acl_free(gp);
if ((gid_t)myacl->qual != g)
return (0);
+#endif
break;
+#if HAVE_SUN_ACL
+ case DEF_CLASS_OBJ:
+ case CLASS_OBJ:
+#else
case ACL_MASK:
+#endif
if (myacl->tag != ARCHIVE_ENTRY_ACL_MASK) return (0);
break;
+#if HAVE_SUN_ACL
+ case DEF_OTHER_OBJ:
+ case OTHER_OBJ:
+#else
case ACL_OTHER:
+#endif
if (myacl->tag != ARCHIVE_ENTRY_ACL_OTHER) return (0);
break;
}
}
static void
+#if HAVE_SUN_ACL
+compare_acls(acl_t *acl, struct archive_test_acl_t *myacls, int n)
+#else
compare_acls(acl_t acl, struct archive_test_acl_t *myacls, int n)
+#endif
{
int *marker;
- int entry_id = ACL_FIRST_ENTRY;
int matched;
int i;
+#if HAVE_SUN_ACL
+ int e;
+ aclent_t *acl_entry;
+#else
+ int entry_id = ACL_FIRST_ENTRY;
acl_entry_t acl_entry;
+#endif
/* Count ACL entries in myacls array and allocate an indirect array. */
marker = malloc(sizeof(marker[0]) * n);
* Iterate over acls in system acl object, try to match each
* one with an item in the myacls array.
*/
+#if HAVE_SUN_ACL
+ for(e = 0; e < acl->acl_cnt; e++) {
+ acl_entry = &((aclent_t *)acl->acl_aclp)[e];
+#else
while (1 == acl_get_entry(acl, entry_id, &acl_entry)) {
/* After the first time... */
entry_id = ACL_NEXT_ENTRY;
+#endif
/* Search for a matching entry (tag and qualifier) */
for (i = 0, matched = 0; i < n && !matched; i++) {
/*
- * Verify ACL restore-to-disk. This test is FreeBSD-specific.
+ * Verify ACL restore-to-disk. This test is Platform-specific.
*/
-DEFINE_TEST(test_acl_freebsd_posix1e_restore)
+DEFINE_TEST(test_acl_platform_posix1e_restore)
{
-#if !defined(__FreeBSD__)
- skipping("FreeBSD-specific ACL restore test");
-#elif __FreeBSD__ < 5
- skipping("ACL restore supported only on FreeBSD 5.0 and later");
-#else
+#if !HAVE_SUN_ACL && !HAVE_POSIX_ACL
+ skipping("POSIX.1e ACLs are not supported on this platform");
+#else /* HAVE_SUN_ACL || HAVE_POSIX_ACL */
struct stat st;
struct archive *a;
struct archive_entry *ae;
int n, fd;
+ char *func;
+#if HAVE_SUN_ACL
+ acl_t *acl, *acl2;
+#else
acl_t acl;
+#endif
/*
* First, do a quick manual set/read of ACL data to
* verify that the local filesystem does support ACLs.
* If it doesn't, we'll simply skip the remaining tests.
*/
+#if HAVE_SUN_ACL
+ n = acl_fromtext("user::rwx,user:1:rw-,group::rwx,group:15:r-x,other:rwx,mask:rwx", &acl);
+ failure("acl_fromtext(): errno = %d (%s)", errno, strerror(errno));
+ assertEqualInt(0, n);
+#else
acl = acl_from_text("u::rwx,u:1:rw,g::rwx,g:15:rx,o::rwx,m::rwx");
+ failure("acl_from_text(): errno = %d (%s)", errno, strerror(errno));
assert((void *)acl != NULL);
- /* Create a test file and try to set an ACL on it. */
+#endif
+
+ /* Create a test file and try ACL on it. */
fd = open("pretest", O_WRONLY | O_CREAT | O_EXCL, 0777);
failure("Could not create test file?!");
if (!assert(fd >= 0)) {
return;
}
- n = acl_set_fd(fd, acl);
- acl_free(acl);
- if (n != 0 && errno == EOPNOTSUPP) {
+#if HAVE_SUN_ACL
+ n = facl_get(fd, 0, &acl2);
+ if (n != 0) {
close(fd);
- skipping("ACL tests require that ACL support be enabled on the filesystem");
+ acl_free(acl);
+ }
+ if (errno == ENOSYS) {
+ skipping("POSIX.1e ACLs are not supported on this filesystem");
return;
}
- if (n != 0 && errno == EINVAL) {
- close(fd);
- skipping("This filesystem does not support POSIX.1e ACLs");
+ failure("facl_get(): errno = %d (%s)", errno, strerror(errno));
+ assertEqualInt(0, n);
+
+ if (acl2->acl_type != ACLENT_T) {
+ acl_free(acl2);
+ skipping("POSIX.1e ACLs are not supported on this filesystem");
return;
}
- failure("acl_set_fd(): errno = %d (%s)",
- errno, strerror(errno));
+ acl_free(acl2);
+
+ func = "facl_set()";
+ n = facl_set(fd, acl);
+#else
+ func = "acl_set_fd()";
+ n = acl_set_fd(fd, acl);
+#endif
+ acl_free(acl);
+ if (n != 0) {
+#if HAVE_SUN_ACL
+ if (errno == ENOSYS)
+#else
+ if (errno == EOPNOTSUPP || errno == EINVAL)
+#endif
+ {
+ close(fd);
+ skipping("POSIX.1e ACLs are not supported on this filesystem");
+ return;
+ }
+ }
+ failure("%s: errno = %d (%s)", func, errno, strerror(errno));
assertEqualInt(0, n);
+
+#if HAVE_SUN_ACL
+
+#endif
close(fd);
/* Create a write-to-disk object. */
/* Verify the data on disk. */
assertEqualInt(0, stat("test0", &st));
assertEqualInt(st.st_mtime, 123456);
+#if HAVE_SUN_ACL
+ n = acl_get("test0", 0, &acl);
+ failure("acl_get(): errno = %d (%s)", errno, strerror(errno));
+ assertEqualInt(0, n);
+#else
acl = acl_get_file("test0", ACL_TYPE_ACCESS);
+ failure("acl_get_file(): errno = %d (%s)", errno, strerror(errno));
assert(acl != (acl_t)NULL);
+#endif
compare_acls(acl, acls2, sizeof(acls2)/sizeof(acls2[0]));
acl_free(acl);
-#endif
+#endif /* HAVE_SUN_ACL || HAVE_POSIX_ACL */
}
/*
- * Verify ACL read-from-disk. This test is FreeBSD-specific.
+ * Verify ACL read-from-disk. This test is Platform-specific.
*/
-DEFINE_TEST(test_acl_freebsd_posix1e_read)
+DEFINE_TEST(test_acl_platform_posix1e_read)
{
-#if !defined(__FreeBSD__)
- skipping("FreeBSD-specific ACL read test");
-#elif __FreeBSD__ < 5
- skipping("ACL read supported only on FreeBSD 5.0 and later");
+#if !HAVE_SUN_ACL && !HAVE_POSIX_ACL
+ skipping("POSIX.1e ACLs are not supported on this platform");
#else
struct archive *a;
struct archive_entry *ae;
- int n, fd;
- const char *acl1_text, *acl2_text;
- acl_t acl1, acl2;
+ int n, fd, flags, dflags;
+ char *func;
+ const char *acl1_text, *acl2_text, *acl3_text;
+#if HAVE_SUN_ACL
+ acl_t *acl, *acl1, *acl2, *acl3;
+#else
+ acl_t acl1, acl2, acl3;
+#endif
/*
* Manually construct a directory and two files with
*/
/* Create a test file f1 with acl1 */
+#if HAVE_SUN_ACL
+ acl1_text = "user::rwx,"
+ "group::rwx,"
+ "other:rwx,"
+ "user:1:rw-,"
+ "group:15:r-x,"
+ "mask:rwx";
+ n = acl_fromtext(acl1_text, &acl1);
+ failure("acl_fromtext(): errno = %d (%s)", errno, strerror(errno));
+ assertEqualInt(0, n);
+#else
acl1_text = "user::rwx\n"
"group::rwx\n"
"other::rwx\n"
"group:15:r-x\n"
"mask::rwx";
acl1 = acl_from_text(acl1_text);
+ failure("acl_from_text(): errno = %d (%s)", errno, strerror(errno));
assert((void *)acl1 != NULL);
+#endif
fd = open("f1", O_WRONLY | O_CREAT | O_EXCL, 0777);
failure("Could not create test file?!");
if (!assert(fd >= 0)) {
acl_free(acl1);
return;
}
- n = acl_set_fd(fd, acl1);
- acl_free(acl1);
- if (n != 0 && errno == EOPNOTSUPP) {
+#if HAVE_SUN_ACL
+ /* Check if Solars filesystem supports POSIX.1e ACLs */
+ n = facl_get(fd, 0, &acl);
+ if (n != 0)
close(fd);
- skipping("ACL tests require that ACL support be enabled on the filesystem");
+ if (n != 0 && errno == ENOSYS) {
+ acl_free(acl1);
+ skipping("POSIX.1e ACLs are not supported on this filesystem");
return;
}
- if (n != 0 && errno == EINVAL) {
+ failure("facl_get(): errno = %d (%s)", errno, strerror(errno));
+ assertEqualInt(0, n);
+
+ if (acl->acl_type != ACLENT_T) {
+ acl_free(acl);
+ acl_free(acl1);
close(fd);
- skipping("This filesystem does not support POSIX.1e ACLs");
+ skipping("POSIX.1e ACLs are not supported on this filesystem");
return;
}
- failure("acl_set_fd(): errno = %d (%s)",
- errno, strerror(errno));
+
+ func = "facl_set()";
+ n = facl_set(fd, acl1);
+#else
+ func = "acl_set_fd()";
+ n = acl_set_fd(fd, acl1);
+#endif
+ if (n != 0) {
+#if HAVE_SUN_ACL
+ if (errno == ENOSYS)
+#else
+ if (errno == EOPNOTSUPP || errno == EINVAL)
+#endif
+ {
+ close(fd);
+ skipping("POSIX.1e ACLs are not supported on this filesystem");
+ return;
+ }
+ }
+ failure("%s: errno = %d (%s)", func, errno, strerror(errno));
assertEqualInt(0, n);
+
close(fd);
assertMakeDir("d", 0700);
* to read ACLs, resulting in reading the ACL from a like-named
* file in the wrong directory.
*/
+#if HAVE_SUN_ACL
+ acl2_text = "user::rwx,"
+ "group::rwx,"
+ "other:---,"
+ "user:1:r--,"
+ "group:15:r--,"
+ "mask:rwx";
+ n = acl_fromtext(acl2_text, &acl2);
+ failure("acl_fromtext(): errno = %d (%s)", errno, strerror(errno));
+ assertEqualInt(0, n);
+#else
acl2_text = "user::rwx\n"
"group::rwx\n"
"other::---\n"
"group:15:r--\n"
"mask::rwx";
acl2 = acl_from_text(acl2_text);
+ failure("acl_from_text(): errno = %d (%s)", errno, strerror(errno));
assert((void *)acl2 != NULL);
+#endif
fd = open("d/f1", O_WRONLY | O_CREAT | O_EXCL, 0777);
failure("Could not create test file?!");
if (!assert(fd >= 0)) {
acl_free(acl2);
return;
}
+#if HAVE_SUN_ACL
+ func = "facl_set()";
+ n = facl_set(fd, acl2);
+#else
+ func = "acl_set_fd()";
n = acl_set_fd(fd, acl2);
- acl_free(acl2);
- if (n != 0 && errno == EOPNOTSUPP) {
+#endif
+ if (n != 0) {
+ acl_free(acl2);
close(fd);
- skipping("ACL tests require that ACL support be enabled on the filesystem");
- return;
}
- if (n != 0 && errno == EINVAL) {
- close(fd);
- skipping("This filesystem does not support POSIX.1e ACLs");
- return;
- }
- failure("acl_set_fd(): errno = %d (%s)",
- errno, strerror(errno));
+ failure("%s: errno = %d (%s)", func, errno, strerror(errno));
assertEqualInt(0, n);
close(fd);
+ /* Create directory d2 with default ACLs */
+ assertMakeDir("d2", 0755);
+
+#if HAVE_SUN_ACL
+ acl3_text = "user::rwx,"
+ "group::r-x,"
+ "other:r-x,"
+ "user:2:r--,"
+ "group:16:-w-,"
+ "mask:rwx,"
+ "default:user::rwx,"
+ "default:user:1:r--,"
+ "default:group::r-x,"
+ "default:group:15:r--,"
+ "default:mask:rwx,"
+ "default:other:r-x";
+ n = acl_fromtext(acl3_text, &acl3);
+ failure("acl_fromtext(): errno = %d (%s)", errno, strerror(errno));
+ assertEqualInt(0, n);
+#else
+ acl3_text = "user::rwx\n"
+ "user:1:r--\n"
+ "group::r-x\n"
+ "group:15:r--\n"
+ "mask::rwx\n"
+ "other::r-x";
+ acl3 = acl_from_text(acl3_text);
+ failure("acl_from_text(): errno = %d (%s)", errno, strerror(errno));
+ assert((void *)acl3 != NULL);
+#endif
+
+#if HAVE_SUN_ACL
+ func = "acl_set()";
+ n = acl_set("d2", acl3);
+#else
+ func = "acl_set_file()";
+ n = acl_set_file("d2", ACL_TYPE_DEFAULT, acl3);
+#endif
+ if (n != 0)
+ acl_free(acl3);
+ failure("%s: errno = %d (%s)", func, errno, strerror(errno));
+ assertEqualInt(0, n);
+
/* Create a read-from-disk object. */
assert(NULL != (a = archive_read_disk_new()));
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "."));
assert(NULL != (ae = archive_entry_new()));
+#if HAVE_SUN_ACL
+ flags = ARCHIVE_ENTRY_ACL_TYPE_POSIX1E
+ | ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA
+ | ARCHIVE_ENTRY_ACL_STYLE_SOLARIS;
+ dflags = flags;
+#else
+ flags = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+ dflags = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
+#endif
+
/* Walk the dir until we see both of the files */
while (ARCHIVE_OK == archive_read_next_header2(a, ae)) {
archive_read_disk_descend(a);
if (strcmp(archive_entry_pathname(ae), "./f1") == 0) {
- assertEqualString(archive_entry_acl_to_text(ae, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS), acl1_text);
+ assertEqualString(archive_entry_acl_to_text(ae, NULL, flags), acl1_text);
} else if (strcmp(archive_entry_pathname(ae), "./d/f1") == 0) {
- assertEqualString(archive_entry_acl_to_text(ae, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS), acl2_text);
+ assertEqualString(archive_entry_acl_to_text(ae, NULL, flags), acl2_text);
+ } else if (strcmp(archive_entry_pathname(ae), "./d2") == 0) {
+ assertEqualString(archive_entry_acl_to_text(ae, NULL, dflags), acl3_text);
}
}
+++ /dev/null
-/*-
- * Copyright (c) 2003-2010 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 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"
-
-#if defined(__sun__)
-#include <sys/acl.h>
-
-struct myacl_t {
- int type;
- int permset;
- int tag;
- int qual; /* GID or UID of user/group, depending on tag. */
- const char *name; /* Name of user/group, depending on tag. */
-};
-
-static struct myacl_t acls_reg[] = {
- /* For this test, we need the file owner to be able to read and write the ACL. */
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
- ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_READ_ACL | ARCHIVE_ENTRY_ACL_WRITE_ACL | ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES,
- ARCHIVE_ENTRY_ACL_USER_OBJ, -1, ""},
-
- /* An entry for each type. */
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
- ARCHIVE_ENTRY_ACL_USER, 108, "user108" },
- { ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_EXECUTE,
- ARCHIVE_ENTRY_ACL_USER, 109, "user109" },
-
- /* An entry for each permission. */
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
- ARCHIVE_ENTRY_ACL_USER, 112, "user112" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_DATA,
- ARCHIVE_ENTRY_ACL_USER, 113, "user113" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_DATA,
- ARCHIVE_ENTRY_ACL_USER, 115, "user115" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_APPEND_DATA,
- ARCHIVE_ENTRY_ACL_USER, 117, "user117" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS,
- ARCHIVE_ENTRY_ACL_USER, 119, "user119" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS,
- ARCHIVE_ENTRY_ACL_USER, 120, "user120" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES,
- ARCHIVE_ENTRY_ACL_USER, 122, "user122" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES,
- ARCHIVE_ENTRY_ACL_USER, 123, "user123" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_DELETE,
- ARCHIVE_ENTRY_ACL_USER, 124, "user124" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ACL,
- ARCHIVE_ENTRY_ACL_USER, 125, "user125" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ACL,
- ARCHIVE_ENTRY_ACL_USER, 126, "user126" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_OWNER,
- ARCHIVE_ENTRY_ACL_USER, 127, "user127" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
- ARCHIVE_ENTRY_ACL_USER, 128, "user128" },
-
- /* One entry for each qualifier. */
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
- ARCHIVE_ENTRY_ACL_USER, 135, "user135" },
-// { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
-// ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
- ARCHIVE_ENTRY_ACL_GROUP, 136, "group136" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
- ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
- ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }
-};
-
-
-static struct myacl_t acls_dir[] = {
- /* For this test, we need to be able to read and write the ACL. */
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_READ_ACL,
- ARCHIVE_ENTRY_ACL_USER_OBJ, -1, ""},
-
- /* An entry for each type. */
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
- ARCHIVE_ENTRY_ACL_USER, 101, "user101" },
- { ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
- ARCHIVE_ENTRY_ACL_USER, 102, "user102" },
-
- /* An entry for each permission. */
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
- ARCHIVE_ENTRY_ACL_USER, 201, "user201" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_ADD_FILE,
- ARCHIVE_ENTRY_ACL_USER, 202, "user202" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY,
- ARCHIVE_ENTRY_ACL_USER, 203, "user203" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS,
- ARCHIVE_ENTRY_ACL_USER, 204, "user204" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS,
- ARCHIVE_ENTRY_ACL_USER, 205, "user205" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_DELETE_CHILD,
- ARCHIVE_ENTRY_ACL_USER, 206, "user206" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES,
- ARCHIVE_ENTRY_ACL_USER, 207, "user207" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES,
- ARCHIVE_ENTRY_ACL_USER, 208, "user208" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_DELETE,
- ARCHIVE_ENTRY_ACL_USER, 209, "user209" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ACL,
- ARCHIVE_ENTRY_ACL_USER, 210, "user210" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ACL,
- ARCHIVE_ENTRY_ACL_USER, 211, "user211" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_OWNER,
- ARCHIVE_ENTRY_ACL_USER, 212, "user212" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
- ARCHIVE_ENTRY_ACL_USER, 213, "user213" },
-
- /* One entry with each inheritance value. */
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
- ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT,
- ARCHIVE_ENTRY_ACL_USER, 301, "user301" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
- ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT,
- ARCHIVE_ENTRY_ACL_USER, 302, "user302" },
-#if 0
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
- ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT,
- ARCHIVE_ENTRY_ACL_USER, 303, "user303" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
- ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY,
- ARCHIVE_ENTRY_ACL_USER, 304, "user304" },
-#endif
-
-#if 0
- /* FreeBSD does not support audit entries. */
- { ARCHIVE_ENTRY_ACL_TYPE_AUDIT,
- ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS,
- ARCHIVE_ENTRY_ACL_USER, 401, "user401" },
- { ARCHIVE_ENTRY_ACL_TYPE_AUDIT,
- ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS,
- ARCHIVE_ENTRY_ACL_USER, 402, "user402" },
-#endif
-
- /* One entry for each qualifier. */
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
- ARCHIVE_ENTRY_ACL_USER, 501, "user501" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
- ARCHIVE_ENTRY_ACL_GROUP, 502, "group502" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
- ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
- ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }
-};
-
-static void
-set_acls(struct archive_entry *ae, struct myacl_t *acls, int start, int end)
-{
- int i;
-
- archive_entry_acl_clear(ae);
- if (start > 0) {
- assertEqualInt(ARCHIVE_OK,
- archive_entry_acl_add_entry(ae,
- acls[0].type, acls[0].permset, acls[0].tag,
- acls[0].qual, acls[0].name));
- }
- for (i = start; i < end; i++) {
- assertEqualInt(ARCHIVE_OK,
- archive_entry_acl_add_entry(ae,
- acls[i].type, acls[i].permset, acls[i].tag,
- acls[i].qual, acls[i].name));
- }
-}
-
-static int
-acl_permset_to_bitmap(uint32_t a_access_mask)
-{
- static struct { int machine; int portable; } perms[] = {
- {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}
- };
- int i, permset = 0;
-
- for (i = 0; i < (int)(sizeof(perms)/sizeof(perms[0])); ++i)
- if (a_access_mask & perms[i].machine)
- permset |= perms[i].portable;
- return permset;
-}
-
-static int
-acl_flagset_to_bitmap(uint16_t a_flags)
-{
- static struct { int machine; int portable; } flags[] = {
- {ACE_FILE_INHERIT_ACE, ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT},
- {ACE_DIRECTORY_INHERIT_ACE, ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT},
- {ACE_NO_PROPAGATE_INHERIT_ACE, ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT},
- {ACE_INHERIT_ONLY_ACE, ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY},
- {ACE_SUCCESSFUL_ACCESS_ACE_FLAG, ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS},
- {ACE_FAILED_ACCESS_ACE_FLAG, ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS},
- {ACE_INHERITED_ACE, ARCHIVE_ENTRY_ACL_ENTRY_INHERITED}
- };
- int i, flagset = 0;
-
- for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); ++i)
- if (a_flags & flags[i].machine)
- flagset |= flags[i].portable;
- return flagset;
-}
-
-static int
-acl_match(ace_t *ace, struct myacl_t *myacl)
-{
- int perms;
-
- /* translate the silly opaque permset to a bitmap */
- perms = acl_permset_to_bitmap(ace->a_access_mask) | acl_flagset_to_bitmap(ace->a_flags);
- if (perms != myacl->permset)
- return (0);
-
- if (ace->a_flags & ACE_OWNER) {
- if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ)
- return (0);
- } else if (ace->a_flags & ACE_GROUP) {
- if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ)
- return (0);
- } else if (ace->a_flags & ACE_EVERYONE) {
- if (myacl->tag != ARCHIVE_ENTRY_ACL_EVERYONE)
- return (0);
- } else if (ace->a_flags & ACE_IDENTIFIER_GROUP) {
- if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
- return (0);
- if ((gid_t)myacl->qual != ace->a_who)
- return (0);
- } else {
- if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
- return (0);
- if ((uid_t)myacl->qual != ace->a_who)
- return (0);
- }
- return (1);
-}
-
-static void
-compare_acls(acl_t *acl, struct myacl_t *myacls, const char *filename, int start, int end)
-{
- int *marker;
- int matched;
- int e, i, n;
- ace_t *ace;
-
- n = end - start;
- marker = malloc(sizeof(marker[0]) * (n + 1));
- for (i = 0; i < n; i++)
- marker[i] = i + start;
- /* Always include the first ACE. */
- if (start > 0) {
- marker[n] = 0;
- ++n;
- }
-
- /*
- * Iterate over acls in system acl object, try to match each
- * one with an item in the myacls array.
- */
- for (e = 0; e < acl->acl_cnt; e++) {
- ace = &((ace_t *)acl->acl_aclp)[e];
- /* Search for a matching entry (tag and qualifier) */
- for (i = 0, matched = 0; i < n && !matched; i++) {
- if (acl_match(ace, &myacls[marker[i]])) {
- /* We found a match; remove it. */
- marker[i] = marker[n - 1];
- n--;
- matched = 1;
- }
- }
-
- failure("ACL entry on file %s that shouldn't be there", filename);
- assert(matched == 1);
- }
-
- /* Dump entries in the myacls array that weren't in the system acl. */
- for (i = 0; i < n; ++i) {
- failure(" ACL entry %d missing from %s: "
- "type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s''\n",
- marker[i], filename,
- myacls[marker[i]].type, myacls[marker[i]].permset,
- myacls[marker[i]].tag, myacls[marker[i]].qual,
- myacls[marker[i]].name);
- assert(0); /* Record this as a failure. */
- }
- free(marker);
-}
-
-static void
-compare_entry_acls(struct archive_entry *ae, struct myacl_t *myacls, const char *filename, int start, int end)
-{
- int *marker;
- int matched;
- int i, n;
- int type, permset, tag, qual;
- const char *name;
-
- /* Count ACL entries in myacls array and allocate an indirect array. */
- n = end - start;
- marker = malloc(sizeof(marker[0]) * (n + 1));
- for (i = 0; i < n; i++)
- marker[i] = i + start;
- /* Always include the first ACE. */
- if (start > 0) {
- marker[n] = 0;
- ++n;
- }
-
- /*
- * Iterate over acls in entry, try to match each
- * one with an item in the myacls array.
- */
- assertEqualInt(n, archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4));
- while (ARCHIVE_OK == archive_entry_acl_next(ae,
- ARCHIVE_ENTRY_ACL_TYPE_NFS4, &type, &permset, &tag, &qual, &name)) {
-
- /* Search for a matching entry (tag and qualifier) */
- for (i = 0, matched = 0; i < n && !matched; i++) {
- if (tag == myacls[marker[i]].tag
- && qual == myacls[marker[i]].qual
- && permset == myacls[marker[i]].permset
- && type == myacls[marker[i]].type) {
- /* We found a match; remove it. */
- marker[i] = marker[n - 1];
- n--;
- matched = 1;
- }
- }
-
- failure("ACL entry on file that shouldn't be there: "
- "type=%#010x,permset=%#010x,tag=%d,qual=%d",
- type,permset,tag,qual);
- assert(matched == 1);
- }
-
- /* Dump entries in the myacls array that weren't in the system acl. */
- for (i = 0; i < n; ++i) {
- failure(" ACL entry %d missing from %s: "
- "type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s''\n",
- marker[i], filename,
- myacls[marker[i]].type, myacls[marker[i]].permset,
- myacls[marker[i]].tag, myacls[marker[i]].qual,
- myacls[marker[i]].name);
- assert(0); /* Record this as a failure. */
- }
- free(marker);
-}
-#endif
-
-/*
- * Verify ACL restore-to-disk. This test is FreeBSD-specific.
- */
-
-DEFINE_TEST(test_acl_solaris_nfs4)
-{
-#if !defined(__sun__)
- skipping("Solaris-specific NFS4 ACL restore test");
-#else
- char buff[64];
- struct stat st;
- struct archive *a;
- struct archive_entry *ae;
- int i, n;
- acl_t *acl;
-
- /* Create a test dir and try to get trivial ACL from it. */
- if (!assertMakeDir("pretest", 0755))
- return;
-
- n = acl_get("pretest", 0, &acl);
- if (n != 0 && errno == ENOSYS) {
- skipping("ACL tests require ACL support on the filesystem");
- return;
- }
- failure("acl_get(): errno = %d (%s)", errno, strerror(errno));
- assertEqualInt(0, n);
-
- if (acl->acl_type != ACE_T) {
- acl_free(acl);
- skipping("Filesystem does not use NFSv4 ACLs");
- return;
- }
-
- acl_free(acl);
-
- /* Create a write-to-disk object. */
- assert(NULL != (a = archive_write_disk_new()));
- archive_write_disk_set_options(a,
- ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL);
-
- /* Populate an archive entry with some metadata, including ACL info */
- ae = archive_entry_new();
- assert(ae != NULL);
- archive_entry_set_pathname(ae, "testall");
- archive_entry_set_filetype(ae, AE_IFREG);
- archive_entry_set_perm(ae, 0654);
- archive_entry_set_mtime(ae, 123456, 7890);
- archive_entry_set_size(ae, 0);
- set_acls(ae, acls_reg, 0, (int)(sizeof(acls_reg)/sizeof(acls_reg[0])));
-
- /* Write the entry to disk, including ACLs. */
- assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
-
- /* Likewise for a dir. */
- archive_entry_set_pathname(ae, "dirall");
- archive_entry_set_filetype(ae, AE_IFDIR);
- archive_entry_set_perm(ae, 0654);
- archive_entry_set_mtime(ae, 123456, 7890);
- set_acls(ae, acls_dir, 0, (int)(sizeof(acls_dir)/sizeof(acls_dir[0])));
- assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
-
- for (i = 0; i < (int)(sizeof(acls_dir)/sizeof(acls_dir[0])); ++i) {
- sprintf(buff, "dir%d", i);
- archive_entry_set_pathname(ae, buff);
- archive_entry_set_filetype(ae, AE_IFDIR);
- archive_entry_set_perm(ae, 0654);
- archive_entry_set_mtime(ae, 123456 + i, 7891 + i);
- set_acls(ae, acls_dir, i, i + 1);
- assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
- }
-
- archive_entry_free(ae);
-
- /* Close the archive. */
- assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
- assertEqualInt(ARCHIVE_OK, archive_write_free(a));
-
- /* Verify the data on disk. */
- assertEqualInt(0, stat("testall", &st));
- assertEqualInt(st.st_mtime, 123456);
- n = acl_get("testall", 0, &acl);
- failure("acl_get(): errno = %d (%s)", errno, strerror(errno));
- assertEqualInt(0, n);
- compare_acls(acl, acls_reg, "testall", 0, (int)(sizeof(acls_reg)/sizeof(acls_reg[0])));
- acl_free(acl);
-
- /* Verify single-permission dirs on disk. */
- for (i = 0; i < (int)(sizeof(acls_dir)/sizeof(acls_dir[0])); ++i) {
- sprintf(buff, "dir%d", i);
- assertEqualInt(0, stat(buff, &st));
- assertEqualInt(st.st_mtime, 123456 + i);
- n = acl_get(buff, 0, &acl);
- failure("acl_get(): errno = %d (%s)", errno, strerror(errno));
- assertEqualInt(0, n);
- compare_acls(acl, acls_dir, buff, i, i + 1);
- acl_free(acl);
- }
-
- /* Verify "dirall" on disk. */
- assertEqualInt(0, stat("dirall", &st));
- assertEqualInt(st.st_mtime, 123456);
- n = acl_get("dirall", 0, &acl);
- failure("acl_get(): errno = %d (%s)", errno, strerror(errno));
- assertEqualInt(0, n);
- compare_acls(acl, acls_dir, "dirall", 0, (int)(sizeof(acls_dir)/sizeof(acls_dir[0])));
- acl_free(acl);
-
- /* Read and compare ACL via archive_read_disk */
- a = archive_read_disk_new();
- assert(a != NULL);
- ae = archive_entry_new();
- assert(ae != NULL);
- archive_entry_set_pathname(ae, "testall");
- assertEqualInt(ARCHIVE_OK,
- archive_read_disk_entry_from_file(a, ae, -1, NULL));
- compare_entry_acls(ae, acls_reg, "testall", 0, (int)(sizeof(acls_reg)/sizeof(acls_reg[0])));
- archive_entry_free(ae);
- assertEqualInt(ARCHIVE_OK, archive_read_free(a));
-
- /* Read and compare ACL via archive_read_disk */
- a = archive_read_disk_new();
- assert(a != NULL);
- ae = archive_entry_new();
- assert(ae != NULL);
- archive_entry_set_pathname(ae, "dirall");
- assertEqualInt(ARCHIVE_OK,
- archive_read_disk_entry_from_file(a, ae, -1, NULL));
- compare_entry_acls(ae, acls_dir, "dirall", 0, (int)(sizeof(acls_dir)/sizeof(acls_dir[0])));
- archive_entry_free(ae);
- assertEqualInt(ARCHIVE_OK, archive_read_free(a));
-#endif
-}
+++ /dev/null
-/*-
- * Copyright (c) 2003-2008 Tim Kientzle
- * 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"
-
-#if defined(__sun__)
-#include <sys/acl.h>
-
-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, "" },
- { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
- ARCHIVE_ENTRY_ACL_USER, 77, "user77" },
- { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0,
- ARCHIVE_ENTRY_ACL_USER, 78, "user78" },
- { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
- ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
- { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0007,
- ARCHIVE_ENTRY_ACL_GROUP, 78, "group78" },
- { ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
- ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_EXECUTE,
- ARCHIVE_ENTRY_ACL_OTHER, -1, "" },
- { ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
- ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_READ | ARCHIVE_ENTRY_ACL_EXECUTE,
- ARCHIVE_ENTRY_ACL_MASK, -1, "" },
-};
-
-static int
-acl_entry_get_perm(aclent_t *aclent) {
- int permset = 0;
-
- if (aclent->a_perm & 1)
- permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
- if (aclent->a_perm & 2)
- permset |= ARCHIVE_ENTRY_ACL_WRITE;
- if (aclent->a_perm & 4)
- permset |= ARCHIVE_ENTRY_ACL_READ;
-
- return permset;
-}
-
-static int
-acl_match(aclent_t *aclent, struct archive_test_acl_t *myacl)
-{
- if (myacl->permset != acl_entry_get_perm(aclent))
- return (0);
-
- switch (aclent->a_type) {
- case DEF_USER_OBJ:
- case USER_OBJ:
- if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) return (0);
- break;
- case DEF_USER:
- case USER:
- if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
- return (0);
- if ((uid_t)myacl->qual != aclent->a_id)
- return (0);
- break;
- case DEF_GROUP_OBJ:
- case GROUP_OBJ:
- if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ) return (0);
- break;
- case DEF_GROUP:
- case GROUP:
- if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
- return (0);
- if ((gid_t)myacl->qual != aclent->a_id)
- return (0);
- break;
- case DEF_CLASS_OBJ:
- case CLASS_OBJ:
- if (myacl->tag != ARCHIVE_ENTRY_ACL_MASK) return (0);
- break;
- case DEF_OTHER_OBJ:
- case OTHER_OBJ:
- if (myacl->tag != ARCHIVE_ENTRY_ACL_OTHER) return (0);
- break;
- }
- return (1);
-}
-
-static void
-compare_acls(acl_t *acl, struct archive_test_acl_t *myacls, int n)
-{
- int *marker;
- int matched;
- int e, i;
- aclent_t *aclent;
-
- /* Count ACL entries in myacls array and allocate an indirect array. */
- marker = malloc(sizeof(marker[0]) * n);
- if (marker == NULL)
- return;
- for (i = 0; i < n; i++)
- marker[i] = i;
-
- /*
- * Iterate over acls in system acl object, try to match each
- * one with an item in the myacls array.
- */
- for(e = 0; e < acl->acl_cnt; e++) {
- aclent = &((aclent_t *)acl->acl_aclp)[e];
-
- /* Search for a matching entry (tag and qualifier) */
- for (i = 0, matched = 0; i < n && !matched; i++) {
- if (acl_match(aclent, &myacls[marker[i]])) {
- /* We found a match; remove it. */
- marker[i] = marker[n - 1];
- n--;
- matched = 1;
- }
- }
-
- /* TODO: Print out more details in this case. */
- failure("ACL entry on file that shouldn't be there");
- assert(matched == 1);
- }
-
- /* Dump entries in the myacls array that weren't in the system acl. */
- for (i = 0; i < n; ++i) {
- failure(" ACL entry missing from file: "
- "type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s''\n",
- myacls[marker[i]].type, myacls[marker[i]].permset,
- myacls[marker[i]].tag, myacls[marker[i]].qual,
- myacls[marker[i]].name);
- assert(0); /* Record this as a failure. */
- }
- free(marker);
-}
-
-#endif
-
-
-/*
- * Verify ACL restore-to-disk. This test is Solaris-specific.
- */
-
-DEFINE_TEST(test_acl_solaris_posix1e_restore)
-{
-#if !defined(__sun__)
- skipping("Solaris-specific ACL restore test");
-#else
- struct stat st;
- struct archive *a;
- struct archive_entry *ae;
- int n, fd;
- acl_t *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.
- */
- acl = NULL;
-
- /* Create a test file and try to set an ACL on it. */
- fd = open("pretest", O_WRONLY | O_CREAT | O_EXCL, 0777);
- failure("Could not create test file?!");
- if (!assert(fd >= 0))
- return;
- n = facl_get(fd, 0, &acl);
- if (n != 0)
- close(fd);
- if (n != 0 && errno == ENOSYS) {
- skipping("ACL tests require ACL support on the filesystem");
- return;
- }
- failure("facl_get(): errno = %d (%s)", errno, strerror(errno));
- assertEqualInt(0, n);
-
- if (acl->acl_type != ACLENT_T) {
- acl_free(acl);
- close(fd);
- skipping("Filesystem does not use POSIX.1e ACLs");
- return;
- }
-
- acl_free(acl);
-
- n = acl_fromtext("user::rwx,user:1:rw-,group::rwx,group:15:r-x,other:rwx,mask:rwx", &acl);
- if (n != 0)
- close(fd);
- failure("acl_fromtext(): errno = %d (%s)", errno, strerror(errno));
- assertEqualInt(0, n);
-
- n = facl_set(fd, acl);
- acl_free(acl);
- if (n != 0 && errno == ENOSYS) {
- close(fd);
- skipping("ACL tests require ACL support on the filesystem");
- return;
- }
- failure("facl_set(): errno = %d (%s)",
- 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,
- ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL);
-
- /* Populate an archive entry with some metadata, including ACL info */
- ae = archive_entry_new();
- assert(ae != NULL);
- archive_entry_set_pathname(ae, "test0");
- archive_entry_set_mtime(ae, 123456, 7890);
- archive_entry_set_size(ae, 0);
- archive_test_set_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
- assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
- archive_entry_free(ae);
-
- /* Close the archive. */
- assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
- assertEqualInt(ARCHIVE_OK, archive_write_free(a));
-
- /* Verify the data on disk. */
- assertEqualInt(0, stat("test0", &st));
- assertEqualInt(st.st_mtime, 123456);
- n = acl_get("test0", 0, &acl);
- failure("acl_get(): errno = %d (%s)",
- errno, strerror(errno));
- assert(n == 0);
- if (acl->acl_type != ACLENT_T) {
- acl_free(acl);
- skipping("Filesystem uses other than POSIX.1e ACLs");
- return;
- }
- assertEqualInt(ACLENT_T, acl->acl_type);
- compare_acls(acl, acls2, sizeof(acls2)/sizeof(acls2[0]));
- acl_free(acl);
-#endif
-}
-
-/*
- * Verify ACL read-from-disk. This test is FreeBSD-specific.
- */
-DEFINE_TEST(test_acl_solaris_posix1e_read)
-{
-#if !defined(__sun__)
- skipping("Solaris-specific ACL read test");
-#else
- struct archive *a;
- struct archive_entry *ae;
- int n, fd;
- const char *acl1_text, *acl2_text, *acl3_text;
- acl_t *acl;
-
- /*
- * Manually construct a directory and two files with
- * different ACLs. This also serves to verify that ACLs
- * are supported on the local filesystem.
- */
-
- /* Create a test file f1 with acl1_text */
- fd = open("f1", O_WRONLY | O_CREAT | O_EXCL, 0777);
- failure("Could not create test file?!");
- if (!assert(fd >= 0))
- return;
- n = facl_get(fd, 0, &acl);
- if (n != 0)
- close(fd);
- if (n != 0 && errno == ENOSYS) {
- skipping("ACL tests require ACL support on the filesystem");
- return;
- }
- failure("facl_get(): errno = %d (%s)", errno, strerror(errno));
- assertEqualInt(0, n);
-
- if (acl->acl_type != ACLENT_T) {
- acl_free(acl);
- close(fd);
- skipping("Filesystem does not use POSIX.1e ACLs");
- return;
- }
-
- acl_free(acl);
-
- acl1_text = "user::rwx,"
- "group::rwx,"
- "other:rwx,"
- "user:1:rw-,"
- "group:15:r-x,"
- "mask:rwx";
- n = acl_fromtext(acl1_text, &acl);
- failure("acl_fromtext(): errno = %d (%s)", errno, strerror(errno));
- assertEqualInt(0, n);
-
- n = facl_set(fd, acl);
- acl_free(acl);
- if (n != 0 && errno == ENOSYS) {
- close(fd);
- skipping("ACL tests require ACL support on the filesystem");
- return;
- }
- failure("facl_set(): errno = %d (%s)",
- errno, strerror(errno));
- assertEqualInt(0, n);
- close(fd);
-
- assertMakeDir("d1", 0700);
-
- /*
- * Create file d/f1 with acl2_text
- *
- * This differs from acl1_text in the u:1: and g:15: permissions.
- *
- * This file deliberately has the same name but a different ACL.
- * Github Issue #777 explains how libarchive's directory traversal
- * did not always correctly enter directories before attempting
- * to read ACLs, resulting in reading the ACL from a like-named
- * file in the wrong directory.
- */
- acl2_text = "user::rwx,"
- "group::rwx,"
- "other:---,"
- "user:1:r--,"
- "group:15:r--,"
- "mask:rwx";
- n = acl_fromtext(acl2_text, &acl);
- failure("acl_fromtext(): errno = %d (%s)", errno, strerror(errno));
- assertEqualInt(0, n);
-
- fd = open("d1/f1", O_WRONLY | O_CREAT | O_EXCL, 0777);
- failure("Could not create test file?!");
- if (!assert(fd >= 0)) {
- acl_free(acl);
- return;
- }
- n = facl_set(fd, acl);
- acl_free(acl);
- if (n != 0 && errno == ENOSYS) {
- close(fd);
- skipping("ACL tests require ACL support on the filesystem");
- return;
- }
- failure("facl_set(): errno = %d (%s)",
- errno, strerror(errno));
- assertEqualInt(0, n);
- close(fd);
-
- /* Create directory d2 with access and default ACLs */
- assertMakeDir("d2", 0755);
-
- acl3_text = "user::rwx,"
- "group::r-x,"
- "other:r-x,"
- "user:2:r--,"
- "group:16:-w-,"
- "mask:rwx,"
- "default:user::rwx,"
- "default:user:1:r--,"
- "default:group::r-x,"
- "default:group:15:r--,"
- "default:mask:rwx,"
- "default:other:r-x";
-
- n = acl_fromtext(acl3_text, &acl);
- failure("acl_fromtext(): errno = %d (%s)", errno, strerror(errno));
- assertEqualInt(0, n);
-
- n = acl_set("d2", acl);
- acl_free(acl);
- if (n != 0 && errno == ENOSYS) {
- close(fd);
- skipping("ACL tests require ACL support on the filesystem");
- return;
- }
- failure("acl_set(): errno = %d (%s)",
- errno, strerror(errno));
- assertEqualInt(0, n);
-
- /* Create a read-from-disk object. */
- assert(NULL != (a = archive_read_disk_new()));
- assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "."));
- assert(NULL != (ae = archive_entry_new()));
-
- /* Walk the dir until we see both of the files */
- while (ARCHIVE_OK == archive_read_next_header2(a, ae)) {
- archive_read_disk_descend(a);
- if (strcmp(archive_entry_pathname(ae), "./f1") == 0) {
- assertEqualString(archive_entry_acl_to_text(ae, NULL, ARCHIVE_ENTRY_ACL_TYPE_POSIX1E | ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA | ARCHIVE_ENTRY_ACL_STYLE_SOLARIS), acl1_text);
- } else if (strcmp(archive_entry_pathname(ae), "./d1/f1") == 0) {
- assertEqualString(archive_entry_acl_to_text(ae, NULL, ARCHIVE_ENTRY_ACL_TYPE_POSIX1E | ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA | ARCHIVE_ENTRY_ACL_STYLE_SOLARIS), acl2_text);
- } else if (strcmp(archive_entry_pathname(ae), "./d2") == 0) {
- assertEqualString(archive_entry_acl_to_text(ae, NULL, ARCHIVE_ENTRY_ACL_TYPE_POSIX1E | ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA | ARCHIVE_ENTRY_ACL_STYLE_SOLARIS), acl3_text);
- }
- }
-
- archive_free(a);
-#endif
-}