Changeset View
Changeset View
Standalone View
Standalone View
tests/sys/acl/acl-api-test.c
- This file was added.
/*- | |||||
* Copyright (c) 2021 Gleb Popov | |||||
* 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 <sys/param.h> | |||||
#include <sys/acl.h> | |||||
#include <sys/stat.h> | |||||
kib: sys/param.h already includes sys/types.h | |||||
#include <stdlib.h> | |||||
#include <errno.h> | |||||
#include <atf-c.h> | |||||
/* Compatibility shim to make it possible to run this test on Linux | |||||
* gcc -I/path/to/atf/include -L/path/to/atf/lib -latf-c -lacl acl-api-test.c | |||||
*/ | |||||
#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[] = { | |||||
Done Inline Actionsstatic const? kib: static const? | |||||
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); | |||||
} | |||||
/* Generate a random mode_t, produce an acl_t from it, | |||||
* then use acl_equiv_mode_np to produce a mode_t again. | |||||
* The call should succeed and mode_t's should be equal | |||||
*/ | |||||
ATF_TC_WITHOUT_HEAD(acl_mode_roundup); | |||||
ATF_TC_BODY(acl_mode_roundup, tc) | |||||
{ | |||||
int num_tests = 100; | |||||
while (num_tests--) { | |||||
Done Inline ActionsBlank line is needed after declaration block. Space is needed there: while (num_tests--) kib: Blank line is needed after declaration block. Space is needed there: `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); | |||||
} | |||||
} | |||||
/* Successfull acl_equiv_mode_np calls are tested in acl_mode_roundup. | |||||
* Here some specific cases are tested. | |||||
*/ | |||||
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); | |||||
/* empty acl maps to 0000 UNIX mode */ | |||||
ATF_CHECK_EQ(0, acl_equiv_mode_np(acl, &mode)); | |||||
ATF_CHECK_EQ(0, mode); | |||||
#ifndef __linux__ | |||||
/* NFS-branded acl's can't be converted to UNIX mode */ | |||||
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's with qualified user entries can't be converted to UNIX mode */ | |||||
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)); | |||||
/* passing NULL causes EINVAL */ | |||||
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); | |||||
/* first, check that two empty acls are equal */ | |||||
ATF_CHECK_EQ(0, acl_cmp_np(acl1, empty_acl)); | |||||
/* now create an entry and compare against 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)); | |||||
/* make a dup of non-empty acl and check that they are equal */ | |||||
acl2 = acl_dup(acl1); | |||||
ATF_REQUIRE(acl2 != NULL); | |||||
ATF_CHECK_EQ(0, acl_cmp_np(acl1, acl2)); | |||||
/* change the tag type and compare */ | |||||
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)); | |||||
/* change the permset and compare */ | |||||
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)); | |||||
/* check that passing NULL yields EINVAL */ | |||||
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()); | |||||
} |
sys/param.h already includes sys/types.h