#include <sys/param.h>
#include <sys/acl.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <errno.h>
#include <atf-c.h>
#ifdef __linux__
#include <acl/libacl.h>
#define acl_from_mode_np acl_from_mode
#define acl_equiv_mode_np acl_equiv_mode
#define acl_cmp_np acl_cmp
#endif
static const mode_t all_modes[] = {
S_IRUSR,
S_IWUSR,
S_IXUSR,
S_IRGRP,
S_IWGRP,
S_IXGRP,
S_IROTH,
S_IWOTH,
S_IXOTH
};
static mode_t gen_random_mode(void)
{
mode_t mode = 0;
for (unsigned i = 0; i < sizeof(all_modes) / sizeof(mode_t); i++) {
if (rand() % 2)
mode |= all_modes[i];
}
return (mode);
}
ATF_TC_WITHOUT_HEAD(acl_mode_roundup);
ATF_TC_BODY(acl_mode_roundup, tc)
{
int num_tests = 100;
while (num_tests--) {
mode_t src_mode, equiv_mode;
acl_t acl;
src_mode = gen_random_mode();
acl = acl_from_mode_np(src_mode);
ATF_REQUIRE(acl != NULL);
ATF_CHECK_EQ(0, acl_equiv_mode_np(acl, &equiv_mode));
ATF_CHECK_EQ(src_mode, equiv_mode);
acl_free(acl);
}
}
ATF_TC_WITHOUT_HEAD(acl_equiv_mode_test);
ATF_TC_BODY(acl_equiv_mode_test, tc)
{
acl_t acl;
acl_entry_t entry;
mode_t mode;
int uid = 0;
acl = acl_init(1);
ATF_REQUIRE(acl != NULL);
ATF_CHECK_EQ(0, acl_equiv_mode_np(acl, &mode));
ATF_CHECK_EQ(0, mode);
#ifndef __linux__
ATF_REQUIRE_EQ(0, acl_create_entry(&acl, &entry));
ATF_REQUIRE_EQ(0, acl_set_tag_type(entry, ACL_EVERYONE));
ATF_CHECK_EQ(1, acl_equiv_mode_np(acl, &mode));
#endif
acl_free(acl);
acl = acl_init(1);
ATF_REQUIRE(acl != NULL);
ATF_REQUIRE_EQ(0, acl_create_entry(&acl, &entry));
ATF_REQUIRE_EQ(0, acl_set_tag_type(entry, ACL_USER));
ATF_REQUIRE_EQ(0, acl_set_qualifier(entry, &uid));
ATF_CHECK_EQ(1, acl_equiv_mode_np(acl, &mode));
ATF_CHECK_ERRNO(EINVAL, acl_equiv_mode_np(NULL, &mode));
}
ATF_TC_WITHOUT_HEAD(acl_cmp_test);
ATF_TC_BODY(acl_cmp_test, tc)
{
acl_t empty_acl, acl1, acl2;
acl_entry_t entry;
acl_permset_t perms;
empty_acl = acl_init(1);
ATF_REQUIRE(empty_acl != NULL);
acl1 = acl_init(3);
ATF_REQUIRE(acl1 != NULL);
ATF_CHECK_EQ(0, acl_cmp_np(acl1, empty_acl));
ATF_REQUIRE_EQ(0, acl_create_entry(&acl1, &entry));
ATF_REQUIRE_EQ(0, acl_set_tag_type(entry, ACL_USER_OBJ));
ATF_REQUIRE_EQ(0, acl_get_permset(entry, &perms));
ATF_REQUIRE_EQ(0, acl_clear_perms(perms));
ATF_REQUIRE_EQ(0, acl_add_perm(perms, ACL_READ));
ATF_CHECK_EQ(1, acl_cmp_np(empty_acl, acl1));
acl2 = acl_dup(acl1);
ATF_REQUIRE(acl2 != NULL);
ATF_CHECK_EQ(0, acl_cmp_np(acl1, acl2));
ATF_REQUIRE_EQ(1, acl_get_entry(acl1, ACL_FIRST_ENTRY, &entry));
ATF_REQUIRE_EQ(0, acl_set_tag_type(entry, ACL_GROUP_OBJ));
ATF_CHECK_EQ(1, acl_cmp_np(acl1, acl2));
acl_free(acl2);
acl2 = acl_dup(acl1);
ATF_REQUIRE(acl2 != NULL);
ATF_REQUIRE_EQ(1, acl_get_entry(acl1, ACL_FIRST_ENTRY, &entry));
ATF_REQUIRE_EQ(0, acl_get_permset(entry, &perms));
ATF_REQUIRE_EQ(0, acl_clear_perms(perms));
ATF_CHECK_EQ(1, acl_cmp_np(acl1, acl2));
ATF_CHECK_ERRNO(EINVAL, acl_cmp_np(NULL, NULL));
ATF_CHECK_ERRNO(EINVAL, acl_cmp_np(acl1, NULL));
ATF_CHECK_ERRNO(EINVAL, acl_cmp_np(NULL, acl1));
acl_free(empty_acl);
acl_free(acl1);
acl_free(acl2);
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, acl_mode_roundup);
ATF_TP_ADD_TC(tp, acl_equiv_mode_test);
ATF_TP_ADD_TC(tp, acl_cmp_test);
return (atf_no_error());
}