Add NFSv4 support to setfacl(1).
Reviewed by: rwatson
This commit is contained in:
parent
2ef29b4c33
commit
3f22187878
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=196936
@ -40,7 +40,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
/* set the appropriate mask the given ACL's */
|
||||
int
|
||||
set_acl_mask(acl_t *prev_acl)
|
||||
set_acl_mask(acl_t *prev_acl, const char *filename)
|
||||
{
|
||||
acl_entry_t entry;
|
||||
acl_t acl;
|
||||
@ -59,7 +59,7 @@ set_acl_mask(acl_t *prev_acl)
|
||||
|
||||
acl = acl_dup(*prev_acl);
|
||||
if (acl == NULL)
|
||||
err(1, "acl_dup() failed");
|
||||
err(1, "%s: acl_dup() failed", filename);
|
||||
|
||||
if (n_flag == 0) {
|
||||
/*
|
||||
@ -70,7 +70,7 @@ set_acl_mask(acl_t *prev_acl)
|
||||
* class in the resulting ACL
|
||||
*/
|
||||
if (acl_calc_mask(&acl)) {
|
||||
warn("acl_calc_mask() failed");
|
||||
warn("%s: acl_calc_mask() failed", filename);
|
||||
acl_free(acl);
|
||||
return (-1);
|
||||
}
|
||||
@ -86,7 +86,8 @@ set_acl_mask(acl_t *prev_acl)
|
||||
while (acl_get_entry(acl, entry_id, &entry) == 1) {
|
||||
entry_id = ACL_NEXT_ENTRY;
|
||||
if (acl_get_tag_type(entry, &tag) == -1)
|
||||
err(1, "acl_get_tag_type() failed");
|
||||
err(1, "%s: acl_get_tag_type() failed",
|
||||
filename);
|
||||
|
||||
if (tag == ACL_MASK) {
|
||||
acl_free(acl);
|
||||
@ -100,7 +101,7 @@ set_acl_mask(acl_t *prev_acl)
|
||||
* file, then write an error message to standard error and
|
||||
* continue with the next file.
|
||||
*/
|
||||
warnx("warning: no mask entry");
|
||||
warnx("%s: warning: no mask entry", filename);
|
||||
acl_free(acl);
|
||||
return (0);
|
||||
}
|
||||
|
@ -36,12 +36,15 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "setfacl.h"
|
||||
|
||||
static int merge_user_group(acl_entry_t *entry, acl_entry_t *entry_new);
|
||||
static int merge_user_group(acl_entry_t *entry, acl_entry_t *entry_new,
|
||||
int acl_brand);
|
||||
|
||||
static int
|
||||
merge_user_group(acl_entry_t *entry, acl_entry_t *entry_new)
|
||||
merge_user_group(acl_entry_t *entry, acl_entry_t *entry_new, int acl_brand)
|
||||
{
|
||||
acl_permset_t permset;
|
||||
acl_entry_type_t entry_type;
|
||||
acl_flagset_t flagset;
|
||||
int have_entry;
|
||||
uid_t *id, *id_new;
|
||||
|
||||
@ -59,6 +62,18 @@ merge_user_group(acl_entry_t *entry, acl_entry_t *entry_new)
|
||||
err(1, "acl_get_permset() failed");
|
||||
if (acl_set_permset(*entry_new, permset) == -1)
|
||||
err(1, "acl_set_permset() failed");
|
||||
|
||||
if (acl_brand == ACL_BRAND_NFS4) {
|
||||
if (acl_get_entry_type_np(*entry, &entry_type))
|
||||
err(1, "acl_get_entry_type_np() failed");
|
||||
if (acl_set_entry_type_np(*entry_new, entry_type))
|
||||
err(1, "acl_set_entry_type_np() failed");
|
||||
if (acl_get_flagset_np(*entry, &flagset))
|
||||
err(1, "acl_get_flagset_np() failed");
|
||||
if (acl_set_flagset_np(*entry_new, flagset))
|
||||
err(1, "acl_set_flagset_np() failed");
|
||||
}
|
||||
|
||||
have_entry = 1;
|
||||
}
|
||||
acl_free(id);
|
||||
@ -71,20 +86,31 @@ merge_user_group(acl_entry_t *entry, acl_entry_t *entry_new)
|
||||
* merge an ACL into existing file's ACL
|
||||
*/
|
||||
int
|
||||
merge_acl(acl_t acl, acl_t *prev_acl)
|
||||
merge_acl(acl_t acl, acl_t *prev_acl, const char *filename)
|
||||
{
|
||||
acl_entry_t entry, entry_new;
|
||||
acl_permset_t permset;
|
||||
acl_t acl_new;
|
||||
acl_tag_t tag, tag_new;
|
||||
int entry_id, entry_id_new, have_entry;
|
||||
acl_entry_type_t entry_type, entry_type_new;
|
||||
acl_flagset_t flagset;
|
||||
int entry_id, entry_id_new, have_entry, entry_number = 0;
|
||||
int acl_brand, prev_acl_brand;
|
||||
|
||||
if (acl_type == ACL_TYPE_ACCESS)
|
||||
acl_new = acl_dup(prev_acl[ACCESS_ACL]);
|
||||
else
|
||||
acl_new = acl_dup(prev_acl[DEFAULT_ACL]);
|
||||
acl_get_brand_np(acl, &acl_brand);
|
||||
acl_get_brand_np(*prev_acl, &prev_acl_brand);
|
||||
|
||||
if (acl_brand != prev_acl_brand) {
|
||||
warnx("%s: branding mismatch; existing ACL is %s, "
|
||||
"entry to be merged is %s", filename,
|
||||
prev_acl_brand == ACL_BRAND_NFS4 ? "NFSv4" : "POSIX.1e",
|
||||
acl_brand == ACL_BRAND_NFS4 ? "NFSv4" : "POSIX.1e");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
acl_new = acl_dup(*prev_acl);
|
||||
if (acl_new == NULL)
|
||||
err(1, "acl_dup() failed");
|
||||
err(1, "%s: acl_dup() failed", filename);
|
||||
|
||||
entry_id = ACL_FIRST_ENTRY;
|
||||
|
||||
@ -94,28 +120,45 @@ merge_acl(acl_t acl, acl_t *prev_acl)
|
||||
|
||||
/* keep track of existing ACL_MASK entries */
|
||||
if (acl_get_tag_type(entry, &tag) == -1)
|
||||
err(1, "acl_get_tag_type() failed - invalid ACL entry");
|
||||
err(1, "%s: acl_get_tag_type() failed - "
|
||||
"invalid ACL entry", filename);
|
||||
if (tag == ACL_MASK)
|
||||
have_mask = 1;
|
||||
|
||||
/* check against the existing ACL entries */
|
||||
entry_id_new = ACL_FIRST_ENTRY;
|
||||
while (have_entry == 0 &&
|
||||
acl_get_entry(acl_new, entry_id_new, &entry_new) == 1) {
|
||||
while (acl_get_entry(acl_new, entry_id_new, &entry_new) == 1) {
|
||||
entry_id_new = ACL_NEXT_ENTRY;
|
||||
|
||||
if (acl_get_tag_type(entry, &tag) == -1)
|
||||
err(1, "acl_get_tag_type() failed");
|
||||
err(1, "%s: acl_get_tag_type() failed",
|
||||
filename);
|
||||
if (acl_get_tag_type(entry_new, &tag_new) == -1)
|
||||
err(1, "acl_get_tag_type() failed");
|
||||
err(1, "%s: acl_get_tag_type() failed",
|
||||
filename);
|
||||
if (tag != tag_new)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* For NFSv4, in addition to "tag" and "id" we also
|
||||
* compare "entry_type".
|
||||
*/
|
||||
if (acl_brand == ACL_BRAND_NFS4) {
|
||||
if (acl_get_entry_type_np(entry, &entry_type))
|
||||
err(1, "%s: acl_get_entry_type_np() "
|
||||
"failed", filename);
|
||||
if (acl_get_entry_type_np(entry_new, &entry_type_new))
|
||||
err(1, "%s: acl_get_entry_type_np() "
|
||||
"failed", filename);
|
||||
if (entry_type != entry_type_new)
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(tag) {
|
||||
case ACL_USER:
|
||||
case ACL_GROUP:
|
||||
have_entry = merge_user_group(&entry,
|
||||
&entry_new);
|
||||
&entry_new, acl_brand);
|
||||
if (have_entry == 0)
|
||||
break;
|
||||
/* FALLTHROUGH */
|
||||
@ -123,37 +166,127 @@ merge_acl(acl_t acl, acl_t *prev_acl)
|
||||
case ACL_GROUP_OBJ:
|
||||
case ACL_OTHER:
|
||||
case ACL_MASK:
|
||||
case ACL_EVERYONE:
|
||||
if (acl_get_permset(entry, &permset) == -1)
|
||||
err(1, "acl_get_permset() failed");
|
||||
err(1, "%s: acl_get_permset() failed",
|
||||
filename);
|
||||
if (acl_set_permset(entry_new, permset) == -1)
|
||||
err(1, "acl_set_permset() failed");
|
||||
err(1, "%s: acl_set_permset() failed",
|
||||
filename);
|
||||
|
||||
if (acl_brand == ACL_BRAND_NFS4) {
|
||||
if (acl_get_entry_type_np(entry, &entry_type))
|
||||
err(1, "%s: acl_get_entry_type_np() failed",
|
||||
filename);
|
||||
if (acl_set_entry_type_np(entry_new, entry_type))
|
||||
err(1, "%s: acl_set_entry_type_np() failed",
|
||||
filename);
|
||||
if (acl_get_flagset_np(entry, &flagset))
|
||||
err(1, "%s: acl_get_flagset_np() failed",
|
||||
filename);
|
||||
if (acl_set_flagset_np(entry_new, flagset))
|
||||
err(1, "%s: acl_set_flagset_np() failed",
|
||||
filename);
|
||||
}
|
||||
have_entry = 1;
|
||||
break;
|
||||
default:
|
||||
/* should never be here */
|
||||
errx(1, "Invalid tag type: %i", tag);
|
||||
errx(1, "%s: invalid tag type: %i", filename, tag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* if this entry has not been found, it must be new */
|
||||
if (have_entry == 0) {
|
||||
if (acl_create_entry(&acl_new, &entry_new) == -1) {
|
||||
acl_free(acl_new);
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
* NFSv4 ACL entries must be prepended to the ACL.
|
||||
* Appending them at the end makes no sense, since
|
||||
* in most cases they wouldn't even get evaluated.
|
||||
*/
|
||||
if (acl_brand == ACL_BRAND_NFS4) {
|
||||
if (acl_create_entry_np(&acl_new, &entry_new, entry_number) == -1) {
|
||||
warn("%s: acl_create_entry_np() failed", filename);
|
||||
acl_free(acl_new);
|
||||
return (-1);
|
||||
}
|
||||
/*
|
||||
* Without this increment, adding several
|
||||
* entries at once, for example
|
||||
* "setfacl -m user:1:r:allow,user:2:r:allow",
|
||||
* would make them appear in reverse order.
|
||||
*/
|
||||
entry_number++;
|
||||
} else {
|
||||
if (acl_create_entry(&acl_new, &entry_new) == -1) {
|
||||
warn("%s: acl_create_entry() failed", filename);
|
||||
acl_free(acl_new);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
if (acl_copy_entry(entry_new, entry) == -1)
|
||||
err(1, "acl_copy_entry() failed");
|
||||
err(1, "%s: acl_copy_entry() failed", filename);
|
||||
}
|
||||
}
|
||||
|
||||
if (acl_type == ACL_TYPE_ACCESS) {
|
||||
acl_free(prev_acl[ACCESS_ACL]);
|
||||
prev_acl[ACCESS_ACL] = acl_new;
|
||||
} else {
|
||||
acl_free(prev_acl[DEFAULT_ACL]);
|
||||
prev_acl[DEFAULT_ACL] = acl_new;
|
||||
}
|
||||
acl_free(*prev_acl);
|
||||
*prev_acl = acl_new;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
add_acl(acl_t acl, uint entry_number, acl_t *prev_acl, const char *filename)
|
||||
{
|
||||
acl_entry_t entry, entry_new;
|
||||
acl_t acl_new;
|
||||
int entry_id, acl_brand, prev_acl_brand;
|
||||
|
||||
acl_get_brand_np(acl, &acl_brand);
|
||||
acl_get_brand_np(*prev_acl, &prev_acl_brand);
|
||||
|
||||
if (prev_acl_brand != ACL_BRAND_NFS4) {
|
||||
warnx("%s: the '-a' option is only applicable to NFSv4 ACLs",
|
||||
filename);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (acl_brand != ACL_BRAND_NFS4) {
|
||||
warnx("%s: branding mismatch; existing ACL is NFSv4, "
|
||||
"entry to be added is POSIX.1e", filename);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
acl_new = acl_dup(*prev_acl);
|
||||
if (acl_new == NULL)
|
||||
err(1, "%s: acl_dup() failed", filename);
|
||||
|
||||
entry_id = ACL_FIRST_ENTRY;
|
||||
|
||||
while (acl_get_entry(acl, entry_id, &entry) == 1) {
|
||||
entry_id = ACL_NEXT_ENTRY;
|
||||
|
||||
if (acl_create_entry_np(&acl_new, &entry_new, entry_number) == -1) {
|
||||
warn("%s: acl_create_entry_np() failed", filename);
|
||||
acl_free(acl_new);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Without this increment, adding several
|
||||
* entries at once, for example
|
||||
* "setfacl -m user:1:r:allow,user:2:r:allow",
|
||||
* would make them appear in reverse order.
|
||||
*/
|
||||
entry_number++;
|
||||
|
||||
if (acl_copy_entry(entry_new, entry) == -1)
|
||||
err(1, "%s: acl_copy_entry() failed", filename);
|
||||
}
|
||||
|
||||
acl_free(*prev_acl);
|
||||
*prev_acl = acl_new;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -41,21 +41,31 @@ __FBSDID("$FreeBSD$");
|
||||
* remove ACL entries from an ACL
|
||||
*/
|
||||
int
|
||||
remove_acl(acl_t acl, acl_t *prev_acl)
|
||||
remove_acl(acl_t acl, acl_t *prev_acl, const char *filename)
|
||||
{
|
||||
acl_entry_t entry;
|
||||
acl_t acl_new;
|
||||
acl_tag_t tag;
|
||||
int carried_error, entry_id;
|
||||
int carried_error, entry_id, acl_brand, prev_acl_brand;
|
||||
|
||||
carried_error = 0;
|
||||
|
||||
if (acl_type == ACL_TYPE_ACCESS)
|
||||
acl_new = acl_dup(prev_acl[ACCESS_ACL]);
|
||||
else
|
||||
acl_new = acl_dup(prev_acl[DEFAULT_ACL]);
|
||||
acl_get_brand_np(acl, &acl_brand);
|
||||
acl_get_brand_np(*prev_acl, &prev_acl_brand);
|
||||
|
||||
if (acl_brand != prev_acl_brand) {
|
||||
warnx("%s: branding mismatch; existing ACL is %s, "
|
||||
"entry to be removed is %s", filename,
|
||||
prev_acl_brand == ACL_BRAND_NFS4 ? "NFSv4" : "POSIX.1e",
|
||||
acl_brand == ACL_BRAND_NFS4 ? "NFSv4" : "POSIX.1e");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
carried_error = 0;
|
||||
|
||||
acl_new = acl_dup(*prev_acl);
|
||||
if (acl_new == NULL)
|
||||
err(1, "acl_dup() failed");
|
||||
err(1, "%s: acl_dup() failed", filename);
|
||||
|
||||
tag = ACL_UNDEFINED_TAG;
|
||||
|
||||
@ -64,23 +74,68 @@ remove_acl(acl_t acl, acl_t *prev_acl)
|
||||
while (acl_get_entry(acl, entry_id, &entry) == 1) {
|
||||
entry_id = ACL_NEXT_ENTRY;
|
||||
if (acl_get_tag_type(entry, &tag) == -1)
|
||||
err(1, "acl_get_tag_type() failed");
|
||||
err(1, "%s: acl_get_tag_type() failed", filename);
|
||||
if (tag == ACL_MASK)
|
||||
have_mask++;
|
||||
if (acl_delete_entry(acl_new, entry) == -1) {
|
||||
carried_error++;
|
||||
warnx("cannot remove non-existent acl entry");
|
||||
warnx("%s: cannot remove non-existent ACL entry",
|
||||
filename);
|
||||
}
|
||||
}
|
||||
|
||||
if (acl_type == ACL_TYPE_ACCESS) {
|
||||
acl_free(prev_acl[ACCESS_ACL]);
|
||||
prev_acl[ACCESS_ACL] = acl_new;
|
||||
} else {
|
||||
acl_free(prev_acl[DEFAULT_ACL]);
|
||||
prev_acl[DEFAULT_ACL] = acl_new;
|
||||
acl_free(*prev_acl);
|
||||
*prev_acl = acl_new;
|
||||
|
||||
if (carried_error)
|
||||
return (-1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
remove_by_number(uint entry_number, acl_t *prev_acl, const char *filename)
|
||||
{
|
||||
acl_entry_t entry;
|
||||
acl_t acl_new;
|
||||
acl_tag_t tag;
|
||||
int carried_error, entry_id;
|
||||
uint i;
|
||||
|
||||
carried_error = 0;
|
||||
|
||||
acl_new = acl_dup(*prev_acl);
|
||||
if (acl_new == NULL)
|
||||
err(1, "%s: acl_dup() failed", filename);
|
||||
|
||||
tag = ACL_UNDEFINED_TAG;
|
||||
|
||||
/*
|
||||
* Find out whether we're removing the mask entry,
|
||||
* to behave the same as the routine above.
|
||||
*
|
||||
* XXX: Is this loop actually needed?
|
||||
*/
|
||||
entry_id = ACL_FIRST_ENTRY;
|
||||
i = 0;
|
||||
while (acl_get_entry(acl_new, entry_id, &entry) == 1) {
|
||||
entry_id = ACL_NEXT_ENTRY;
|
||||
if (i != entry_number)
|
||||
continue;
|
||||
if (acl_get_tag_type(entry, &tag) == -1)
|
||||
err(1, "%s: acl_get_tag_type() failed", filename);
|
||||
if (tag == ACL_MASK)
|
||||
have_mask++;
|
||||
}
|
||||
|
||||
if (acl_delete_entry_np(acl_new, entry_number) == -1) {
|
||||
carried_error++;
|
||||
warn("%s: acl_delete_entry_np() failed", filename);
|
||||
}
|
||||
|
||||
acl_free(*prev_acl);
|
||||
*prev_acl = acl_new;
|
||||
|
||||
if (carried_error)
|
||||
return (-1);
|
||||
|
||||
@ -91,18 +146,14 @@ remove_acl(acl_t acl, acl_t *prev_acl)
|
||||
* remove default entries
|
||||
*/
|
||||
int
|
||||
remove_default(acl_t *prev_acl)
|
||||
remove_default(acl_t *prev_acl, const char *filename)
|
||||
{
|
||||
|
||||
if (prev_acl[1]) {
|
||||
acl_free(prev_acl[1]);
|
||||
prev_acl[1] = acl_init(ACL_MAX_ENTRIES);
|
||||
if (prev_acl[1] == NULL)
|
||||
err(1, "acl_init() failed");
|
||||
} else {
|
||||
warn("cannot remove default ACL");
|
||||
return (-1);
|
||||
}
|
||||
acl_free(*prev_acl);
|
||||
*prev_acl = acl_init(ACL_MAX_ENTRIES);
|
||||
if (*prev_acl == NULL)
|
||||
err(1, "%s: acl_init() failed", filename);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -110,71 +161,14 @@ remove_default(acl_t *prev_acl)
|
||||
* remove extended entries
|
||||
*/
|
||||
void
|
||||
remove_ext(acl_t *prev_acl)
|
||||
remove_ext(acl_t *prev_acl, const char *filename)
|
||||
{
|
||||
acl_t acl_new, acl_old;
|
||||
acl_entry_t entry, entry_new;
|
||||
acl_permset_t perm;
|
||||
acl_tag_t tag;
|
||||
int entry_id, have_mask_entry;
|
||||
acl_t acl_new;
|
||||
|
||||
if (acl_type == ACL_TYPE_ACCESS)
|
||||
acl_old = acl_dup(prev_acl[ACCESS_ACL]);
|
||||
else
|
||||
acl_old = acl_dup(prev_acl[DEFAULT_ACL]);
|
||||
if (acl_old == NULL)
|
||||
err(1, "acl_dup() failed");
|
||||
|
||||
have_mask_entry = 0;
|
||||
acl_new = acl_init(ACL_MAX_ENTRIES);
|
||||
acl_new = acl_strip_np(*prev_acl, !n_flag);
|
||||
if (acl_new == NULL)
|
||||
err(1, "acl_init() failed");
|
||||
tag = ACL_UNDEFINED_TAG;
|
||||
err(1, "%s: acl_strip_np() failed", filename);
|
||||
|
||||
/* only save the default user/group/other entries */
|
||||
entry_id = ACL_FIRST_ENTRY;
|
||||
while (acl_get_entry(acl_old, entry_id, &entry) == 1) {
|
||||
entry_id = ACL_NEXT_ENTRY;
|
||||
|
||||
if (acl_get_tag_type(entry, &tag) == -1)
|
||||
err(1, "acl_get_tag_type() failed");
|
||||
|
||||
switch(tag) {
|
||||
case ACL_USER_OBJ:
|
||||
case ACL_GROUP_OBJ:
|
||||
case ACL_OTHER:
|
||||
if (acl_get_tag_type(entry, &tag) == -1)
|
||||
err(1, "acl_get_tag_type() failed");
|
||||
if (acl_get_permset(entry, &perm) == -1)
|
||||
err(1, "acl_get_permset() failed");
|
||||
if (acl_create_entry(&acl_new, &entry_new) == -1)
|
||||
err(1, "acl_create_entry() failed");
|
||||
if (acl_set_tag_type(entry_new, tag) == -1)
|
||||
err(1, "acl_set_tag_type() failed");
|
||||
if (acl_set_permset(entry_new, perm) == -1)
|
||||
err(1, "acl_get_permset() failed");
|
||||
if (acl_copy_entry(entry_new, entry) == -1)
|
||||
err(1, "acl_copy_entry() failed");
|
||||
break;
|
||||
case ACL_MASK:
|
||||
have_mask_entry = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (have_mask_entry && n_flag == 0) {
|
||||
if (acl_calc_mask(&acl_new) == -1)
|
||||
err(1, "acl_calc_mask() failed");
|
||||
} else {
|
||||
have_mask = 1;
|
||||
}
|
||||
|
||||
if (acl_type == ACL_TYPE_ACCESS) {
|
||||
acl_free(prev_acl[ACCESS_ACL]);
|
||||
prev_acl[ACCESS_ACL] = acl_new;
|
||||
} else {
|
||||
acl_free(prev_acl[DEFAULT_ACL]);
|
||||
prev_acl[DEFAULT_ACL] = acl_new;
|
||||
}
|
||||
acl_free(*prev_acl);
|
||||
*prev_acl = acl_new;
|
||||
}
|
||||
|
@ -25,7 +25,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd January 7, 2001
|
||||
.Dd September 5, 2009
|
||||
.Dt SETFACL 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -34,9 +34,10 @@
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl bdhkn
|
||||
.Op Fl a Ar position entries
|
||||
.Op Fl m Ar entries
|
||||
.Op Fl M Ar file
|
||||
.Op Fl x Ar entries
|
||||
.Op Fl x Ar entries | position
|
||||
.Op Fl X Ar file
|
||||
.Op Ar
|
||||
.Sh DESCRIPTION
|
||||
@ -50,9 +51,19 @@ the file names are taken from the standard input.
|
||||
.Pp
|
||||
The following options are available:
|
||||
.Bl -tag -width indent
|
||||
.It Fl a Ar position entries
|
||||
Modify the ACL on the specified files by inserting new
|
||||
ACL entries
|
||||
specified in
|
||||
.Ar entries ,
|
||||
starting at position
|
||||
.Ar position ,
|
||||
counting from zero.
|
||||
This option is only applicable to NFSv4 ACLs.
|
||||
.It Fl b
|
||||
Remove all ACL entries except for the three required entries.
|
||||
If the ACL contains a
|
||||
Remove all ACL entries except for the three required entries
|
||||
(POSIX.1e ACLs) or six "canonical" entries (NFSv4 ACLs).
|
||||
If the POSIX.1e ACL contains a
|
||||
.Dq Li mask
|
||||
entry, the permissions of the
|
||||
.Dq Li group
|
||||
@ -66,7 +77,7 @@ entries of the current ACL.
|
||||
The operations apply to the default ACL entries instead of
|
||||
access ACL entries.
|
||||
Currently only directories may have
|
||||
default ACL's.
|
||||
default ACL's. This option is not applicable to NFSv4 ACLs.
|
||||
.It Fl h
|
||||
If the target of the operation is a symbolic link, perform the operation
|
||||
on the symbolic link itself, rather than following the link.
|
||||
@ -77,7 +88,7 @@ is not considered an error if the specified files do not have
|
||||
any default ACL entries.
|
||||
An error will be reported if any of
|
||||
the specified files cannot have a default entry (i.e.\&
|
||||
non-directories).
|
||||
non-directories). This option is not applicable to NFSv4 ACLs.
|
||||
.It Fl m Ar entries
|
||||
Modify the ACL entries on the specified files by adding new
|
||||
entries and modifying existing ACL entries with the ACL entries
|
||||
@ -95,11 +106,15 @@ is
|
||||
the input is taken from stdin.
|
||||
.It Fl n
|
||||
Do not recalculate the permissions associated with the ACL
|
||||
mask entry.
|
||||
.It Fl x Ar entries
|
||||
Remove the ACL entries specified in
|
||||
mask entry. This option is not applicable to NFSv4 ACLs.
|
||||
.It Fl x Ar entries | position
|
||||
If
|
||||
.Ar entries
|
||||
is specified, remove the ACL entries specified there
|
||||
from the access or default ACL of the specified files.
|
||||
Otherwise, remove entry at index
|
||||
.Ar position ,
|
||||
counting from zero.
|
||||
.It Fl X Ar file
|
||||
Remove the ACL entries specified in the file
|
||||
.Ar file
|
||||
@ -108,8 +123,8 @@ from the access or default ACL of the specified files.
|
||||
.Pp
|
||||
The above options are evaluated in the order specified
|
||||
on the command-line.
|
||||
.Sh ACL ENTRIES
|
||||
An ACL entry contains three colon-separated fields:
|
||||
.Sh POSIX.1e ACL ENTRIES
|
||||
A POSIX.1E ACL entry contains three colon-separated fields:
|
||||
an ACL tag, an ACL qualifier, and discretionary access
|
||||
permissions:
|
||||
.Bl -tag -width indent
|
||||
@ -223,7 +238,7 @@ previously specified; whitespace is ignored; any text after a
|
||||
.Ql #
|
||||
is ignored (comments).
|
||||
.Pp
|
||||
When ACL entries are evaluated, the access check algorithm checks
|
||||
When POSIX.1e ACL entries are evaluated, the access check algorithm checks
|
||||
the ACL entries in the following order: file owner,
|
||||
.Dq Li user
|
||||
ACL entries, file owning group,
|
||||
@ -243,13 +258,135 @@ ACL entries for user, group, other and mask must be set.
|
||||
For more details see the examples below.
|
||||
Default ACLs can be created by using
|
||||
.Fl d .
|
||||
.Sh NFSv4 ACL ENTRIES
|
||||
An NFSv4 ACL entry contains four or five colon-separated fields: an ACL tag,
|
||||
an ACL qualifier (only for
|
||||
.Dq Li user
|
||||
and
|
||||
.Dq Li group
|
||||
tags), discretionary access permissions, ACL inheritance flags, and ACL type:
|
||||
.Bl -tag -width indent
|
||||
.It Ar "ACL tag"
|
||||
The ACL tag specifies the ACL entry type and consists of
|
||||
one of the following:
|
||||
.Dq Li user
|
||||
or
|
||||
.Ql u
|
||||
specifying the access
|
||||
granted to the specified user;
|
||||
.Dq Li group
|
||||
or
|
||||
.Ql g
|
||||
specifying the access granted to the specified group;
|
||||
.Dq Li owner@
|
||||
specifying the access granted to the owner of the file;
|
||||
.Dq Li group@
|
||||
specifying the access granted to the file owning group;
|
||||
.Dq Li everyone@
|
||||
specifying everyone. Note that
|
||||
.Dq Li everyone@
|
||||
is not the same as traditional Unix
|
||||
.Dq Li other
|
||||
- it means,
|
||||
literally, everyone, including file owner and owning group.
|
||||
.It Ar "ACL qualifier"
|
||||
The ACL qualifier field describes the user or group associated with
|
||||
the ACL entry.
|
||||
It may consist of one of the following: uid or
|
||||
user name, or gid or group name. In entries whose tag type is
|
||||
one of
|
||||
.Dq Li owner@ ,
|
||||
.Dq Li group@ ,
|
||||
or
|
||||
.Dq Li everyone@ ,
|
||||
this field is ommited altogether, including the trailing comma.
|
||||
.It Ar "access permissions"
|
||||
Access permissions may be specified in either short or long form.
|
||||
Short and long forms may not be mixed.
|
||||
Permissions in long form are separated by the
|
||||
.Ql /
|
||||
character; in short form, they are concatenated together.
|
||||
Valid permissions are:
|
||||
.Bl -tag -width ".Dv short"
|
||||
.It Short
|
||||
Long
|
||||
.It r
|
||||
read_data
|
||||
.It w
|
||||
write_data
|
||||
.It x
|
||||
execute
|
||||
.It p
|
||||
append_data
|
||||
.It d
|
||||
delete_child
|
||||
.It D
|
||||
delete
|
||||
.It a
|
||||
read_attributes
|
||||
.It A
|
||||
write_attributes
|
||||
.It R
|
||||
read_xattr
|
||||
.It W
|
||||
write_xattr
|
||||
.It c
|
||||
read_acl
|
||||
.It C
|
||||
write_acl
|
||||
.It o
|
||||
write_owner
|
||||
.It S
|
||||
synchronize
|
||||
.El
|
||||
.It Ar "ACL inheritance flags"
|
||||
Inheritance flags may be specified in either short or long form.
|
||||
Short and long forms may not be mixed.
|
||||
Access flags in long form are separated by the
|
||||
.Ql /
|
||||
character; in short form, they are concatenated together.
|
||||
Valid inheritance flags are:
|
||||
.Bl -tag -width ".Dv short"
|
||||
.It Short
|
||||
Long
|
||||
.It f
|
||||
file_inherit
|
||||
.It d
|
||||
dir_inherit
|
||||
.It i
|
||||
inherit_only
|
||||
.It n
|
||||
no_propagate
|
||||
.El
|
||||
.Pp
|
||||
Inheritance flags may be only set on directories.
|
||||
.It Ar "ACL type"
|
||||
The ACL type field is either
|
||||
.Dq Li allow
|
||||
or
|
||||
.Dq Li deny .
|
||||
.El
|
||||
.Pp
|
||||
ACL entries applied from a file using the
|
||||
.Fl M
|
||||
or
|
||||
.Fl X
|
||||
options shall be of the following form: one ACL entry per line, as
|
||||
previously specified; whitespace is ignored; any text after a
|
||||
.Ql #
|
||||
is ignored (comments).
|
||||
.Pp
|
||||
NFSv4 ACL entries are evaluated in their visible order.
|
||||
.Pp
|
||||
Multiple ACL entries specified on the command line are
|
||||
separated by commas.
|
||||
.Sh EXIT STATUS
|
||||
.Ex -std
|
||||
.Sh EXAMPLES
|
||||
.Dl setfacl -d -m u::rwx,g::rx,o::rx,mask::rwx dir
|
||||
.Dl setfacl -d -m g:admins:rwx dir
|
||||
.Pp
|
||||
The first command sets the mandatory elements of the default ACL.
|
||||
The first command sets the mandatory elements of the POSIX.1e default ACL.
|
||||
The second command specifies that users in group admins can have read, write, and execute
|
||||
permissions for directory named "dir".
|
||||
It should be noted that any files or directories created underneath "dir" will
|
||||
@ -259,9 +396,13 @@ inherit these default ACLs upon creation.
|
||||
.Pp
|
||||
Sets read, write, and execute permissions for the
|
||||
.Pa file
|
||||
owner's ACL entry and read and write permissions for group mail on
|
||||
owner's POSIX.1e ACL entry and read and write permissions for group mail on
|
||||
.Pa file .
|
||||
.Pp
|
||||
.Dl setfacl -m owner@:rwxp::allow,g:mail:rwp::allow file
|
||||
.Pp
|
||||
Semantically equal to the example above, but for NFSv4 ACL.
|
||||
.Pp
|
||||
.Dl setfacl -M file1 file2
|
||||
.Pp
|
||||
Sets/updates the ACL entries contained in
|
||||
@ -271,10 +412,15 @@ on
|
||||
.Pp
|
||||
.Dl setfacl -x g:mail:rw file
|
||||
.Pp
|
||||
Remove the group mail ACL entry containing read/write permissions
|
||||
Remove the group mail POSIX.1e ACL entry containing read/write permissions
|
||||
from
|
||||
.Pa file .
|
||||
.Pp
|
||||
.Dl setfacl -x0 file
|
||||
.Pp
|
||||
Remove the first entry from the NFSv4 ACL from
|
||||
.Pa file .
|
||||
.Pp
|
||||
.Dl setfacl -bn file
|
||||
.Pp
|
||||
Remove all
|
||||
|
@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -41,9 +42,8 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "setfacl.h"
|
||||
|
||||
static void add_filename(const char *filename);
|
||||
static acl_t *get_file_acls(const char *filename);
|
||||
static void usage(void);
|
||||
static void add_filename(const char *filename);
|
||||
static void usage(void);
|
||||
|
||||
static void
|
||||
add_filename(const char *filename)
|
||||
@ -59,57 +59,28 @@ add_filename(const char *filename)
|
||||
TAILQ_INSERT_TAIL(&filelist, file, next);
|
||||
}
|
||||
|
||||
static acl_t *
|
||||
get_file_acls(const char *filename)
|
||||
{
|
||||
acl_t *acl;
|
||||
struct stat sb;
|
||||
|
||||
if (stat(filename, &sb) == -1) {
|
||||
warn("stat() of %s failed", filename);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
acl = zmalloc(sizeof(acl_t) * 2);
|
||||
if (h_flag)
|
||||
acl[ACCESS_ACL] = acl_get_link_np(filename, ACL_TYPE_ACCESS);
|
||||
else
|
||||
acl[ACCESS_ACL] = acl_get_file(filename, ACL_TYPE_ACCESS);
|
||||
if (acl[ACCESS_ACL] == NULL)
|
||||
err(1, "acl_get_file() failed");
|
||||
if (S_ISDIR(sb.st_mode)) {
|
||||
if (h_flag)
|
||||
acl[DEFAULT_ACL] = acl_get_link_np(filename,
|
||||
ACL_TYPE_DEFAULT);
|
||||
else
|
||||
acl[DEFAULT_ACL] = acl_get_file(filename,
|
||||
ACL_TYPE_DEFAULT);
|
||||
if (acl[DEFAULT_ACL] == NULL)
|
||||
err(1, "acl_get_file() failed");
|
||||
} else
|
||||
acl[DEFAULT_ACL] = NULL;
|
||||
|
||||
return (acl);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
fprintf(stderr, "usage: setfacl [-bdhkn] [-m entries] [-M file] "
|
||||
"[-x entries] [-X file] [file ...]\n");
|
||||
fprintf(stderr, "usage: setfacl [-bdhkn] [-a position entries] "
|
||||
"[-m entries] [-M file] [-x entries] [-X file] [file ...]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
acl_t *acl, final_acl;
|
||||
acl_t acl;
|
||||
acl_type_t acl_type;
|
||||
char filename[PATH_MAX];
|
||||
int local_error, carried_error, ch, i;
|
||||
int local_error, carried_error, ch, i, entry_number, ret;
|
||||
int h_flag;
|
||||
struct sf_file *file;
|
||||
struct sf_entry *entry;
|
||||
const char *fn_dup;
|
||||
char *end;
|
||||
struct stat sb;
|
||||
|
||||
acl_type = ACL_TYPE_ACCESS;
|
||||
carried_error = local_error = 0;
|
||||
@ -118,13 +89,13 @@ main(int argc, char *argv[])
|
||||
TAILQ_INIT(&entrylist);
|
||||
TAILQ_INIT(&filelist);
|
||||
|
||||
while ((ch = getopt(argc, argv, "M:X:bdhkm:nx:")) != -1)
|
||||
while ((ch = getopt(argc, argv, "M:X:a:bdhkm:nx:")) != -1)
|
||||
switch(ch) {
|
||||
case 'M':
|
||||
entry = zmalloc(sizeof(struct sf_entry));
|
||||
entry->acl = get_acl_from_file(optarg);
|
||||
if (entry->acl == NULL)
|
||||
err(1, "get_acl_from_file() failed");
|
||||
err(1, "%s: get_acl_from_file() failed", optarg);
|
||||
entry->op = OP_MERGE_ACL;
|
||||
TAILQ_INSERT_TAIL(&entrylist, entry, next);
|
||||
break;
|
||||
@ -134,6 +105,25 @@ main(int argc, char *argv[])
|
||||
entry->op = OP_REMOVE_ACL;
|
||||
TAILQ_INSERT_TAIL(&entrylist, entry, next);
|
||||
break;
|
||||
case 'a':
|
||||
entry = zmalloc(sizeof(struct sf_entry));
|
||||
|
||||
entry_number = strtol(optarg, &end, 10);
|
||||
if (end - optarg != (int)strlen(optarg))
|
||||
errx(1, "%s: invalid entry number", optarg);
|
||||
if (entry_number < 0)
|
||||
errx(1, "%s: entry number cannot be less than zero", optarg);
|
||||
entry->entry_number = entry_number;
|
||||
|
||||
if (argv[optind] == NULL)
|
||||
errx(1, "missing ACL");
|
||||
entry->acl = acl_from_text(argv[optind]);
|
||||
if (entry->acl == NULL)
|
||||
err(1, "%s", argv[optind]);
|
||||
optind++;
|
||||
entry->op = OP_ADD_ACL;
|
||||
TAILQ_INSERT_TAIL(&entrylist, entry, next);
|
||||
break;
|
||||
case 'b':
|
||||
entry = zmalloc(sizeof(struct sf_entry));
|
||||
entry->op = OP_REMOVE_EXT;
|
||||
@ -163,10 +153,18 @@ main(int argc, char *argv[])
|
||||
break;
|
||||
case 'x':
|
||||
entry = zmalloc(sizeof(struct sf_entry));
|
||||
entry->acl = acl_from_text(optarg);
|
||||
if (entry->acl == NULL)
|
||||
err(1, "%s", optarg);
|
||||
entry->op = OP_REMOVE_ACL;
|
||||
entry_number = strtol(optarg, &end, 10);
|
||||
if (end - optarg == (int)strlen(optarg)) {
|
||||
if (entry_number < 0)
|
||||
errx(1, "%s: entry number cannot be less than zero", optarg);
|
||||
entry->entry_number = entry_number;
|
||||
entry->op = OP_REMOVE_BY_NUMBER;
|
||||
} else {
|
||||
entry->acl = acl_from_text(optarg);
|
||||
if (entry->acl == NULL)
|
||||
err(1, "%s", optarg);
|
||||
entry->op = OP_REMOVE_ACL;
|
||||
}
|
||||
TAILQ_INSERT_TAIL(&entrylist, entry, next);
|
||||
break;
|
||||
default:
|
||||
@ -199,16 +197,51 @@ main(int argc, char *argv[])
|
||||
|
||||
/* cycle through each file */
|
||||
TAILQ_FOREACH(file, &filelist, next) {
|
||||
/* get our initial access and default ACL's */
|
||||
acl = get_file_acls(file->filename);
|
||||
if (acl == NULL)
|
||||
continue;
|
||||
if ((acl_type == ACL_TYPE_DEFAULT) && !acl[1]) {
|
||||
warnx("Default ACL not valid for %s", file->filename);
|
||||
local_error = 0;
|
||||
|
||||
if (stat(file->filename, &sb) == -1) {
|
||||
warn("%s: stat() failed", file->filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
local_error = 0;
|
||||
if (acl_type == ACL_TYPE_DEFAULT && S_ISDIR(sb.st_mode) == 0) {
|
||||
warnx("%s: default ACL may only be set on a directory",
|
||||
file->filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (h_flag)
|
||||
ret = lpathconf(file->filename, _PC_ACL_NFS4);
|
||||
else
|
||||
ret = pathconf(file->filename, _PC_ACL_NFS4);
|
||||
if (ret > 0) {
|
||||
if (acl_type == ACL_TYPE_DEFAULT) {
|
||||
warnx("%s: there are no default entries "
|
||||
"in NFSv4 ACLs", file->filename);
|
||||
continue;
|
||||
}
|
||||
acl_type = ACL_TYPE_NFS4;
|
||||
} else if (ret == 0) {
|
||||
if (acl_type == ACL_TYPE_NFS4)
|
||||
acl_type = ACL_TYPE_ACCESS;
|
||||
} else if (ret < 0 && errno != EINVAL) {
|
||||
warn("%s: pathconf(..., _PC_ACL_NFS4) failed",
|
||||
file->filename);
|
||||
}
|
||||
|
||||
if (h_flag)
|
||||
acl = acl_get_link_np(file->filename, acl_type);
|
||||
else
|
||||
acl = acl_get_file(file->filename, acl_type);
|
||||
if (acl == NULL) {
|
||||
if (h_flag)
|
||||
warn("%s: acl_get_link_np() failed",
|
||||
file->filename);
|
||||
else
|
||||
warn("%s: acl_get_file() failed",
|
||||
file->filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* cycle through each option */
|
||||
TAILQ_FOREACH(entry, &entrylist, next) {
|
||||
@ -216,24 +249,44 @@ main(int argc, char *argv[])
|
||||
continue;
|
||||
|
||||
switch(entry->op) {
|
||||
case OP_ADD_ACL:
|
||||
local_error += add_acl(entry->acl,
|
||||
entry->entry_number, &acl, file->filename);
|
||||
break;
|
||||
case OP_MERGE_ACL:
|
||||
local_error += merge_acl(entry->acl, acl);
|
||||
local_error += merge_acl(entry->acl, &acl,
|
||||
file->filename);
|
||||
need_mask = 1;
|
||||
break;
|
||||
case OP_REMOVE_EXT:
|
||||
remove_ext(acl);
|
||||
remove_ext(&acl, file->filename);
|
||||
need_mask = 0;
|
||||
break;
|
||||
case OP_REMOVE_DEF:
|
||||
if (acl_type == ACL_TYPE_NFS4) {
|
||||
warnx("%s: there are no default entries in NFSv4 ACLs; "
|
||||
"cannot remove", file->filename);
|
||||
local_error++;
|
||||
break;
|
||||
}
|
||||
if (acl_delete_def_file(file->filename) == -1) {
|
||||
warn("acl_delete_def_file() failed");
|
||||
warn("%s: acl_delete_def_file() failed",
|
||||
file->filename);
|
||||
local_error++;
|
||||
}
|
||||
local_error += remove_default(acl);
|
||||
if (acl_type == ACL_TYPE_DEFAULT)
|
||||
local_error += remove_default(&acl,
|
||||
file->filename);
|
||||
need_mask = 0;
|
||||
break;
|
||||
case OP_REMOVE_ACL:
|
||||
local_error += remove_acl(entry->acl, acl);
|
||||
local_error += remove_acl(entry->acl, &acl,
|
||||
file->filename);
|
||||
need_mask = 1;
|
||||
break;
|
||||
case OP_REMOVE_BY_NUMBER:
|
||||
local_error += remove_by_number(entry->entry_number,
|
||||
&acl, file->filename);
|
||||
need_mask = 1;
|
||||
break;
|
||||
}
|
||||
@ -245,35 +298,27 @@ main(int argc, char *argv[])
|
||||
continue;
|
||||
}
|
||||
|
||||
if (acl_type == ACL_TYPE_ACCESS) {
|
||||
final_acl = acl[ACCESS_ACL];
|
||||
acl_free(acl[DEFAULT_ACL]);
|
||||
} else {
|
||||
final_acl = acl[DEFAULT_ACL];
|
||||
acl_free(acl[ACCESS_ACL]);
|
||||
}
|
||||
|
||||
if (need_mask && (set_acl_mask(&final_acl) == -1)) {
|
||||
warnx("failed to set ACL mask on %s", file->filename);
|
||||
if (acl_type != ACL_TYPE_NFS4 && need_mask &&
|
||||
set_acl_mask(&acl, file->filename) == -1) {
|
||||
warnx("%s: failed to set ACL mask", file->filename);
|
||||
carried_error++;
|
||||
} else if (h_flag) {
|
||||
if (acl_set_link_np(file->filename, acl_type,
|
||||
final_acl) == -1) {
|
||||
acl) == -1) {
|
||||
carried_error++;
|
||||
warn("acl_set_link_np() failed for %s",
|
||||
warn("%s: acl_set_link_np() failed",
|
||||
file->filename);
|
||||
}
|
||||
} else {
|
||||
if (acl_set_file(file->filename, acl_type,
|
||||
final_acl) == -1) {
|
||||
acl) == -1) {
|
||||
carried_error++;
|
||||
warn("acl_set_file() failed for %s",
|
||||
warn("%s: acl_set_file() failed",
|
||||
file->filename);
|
||||
}
|
||||
}
|
||||
|
||||
acl_free(final_acl);
|
||||
free(acl);
|
||||
acl_free(acl);
|
||||
}
|
||||
|
||||
return (carried_error);
|
||||
|
@ -38,15 +38,14 @@
|
||||
#define OP_REMOVE_DEF 0x01 /* remove default acl's (-k) */
|
||||
#define OP_REMOVE_EXT 0x02 /* remove extended acl's (-b) */
|
||||
#define OP_REMOVE_ACL 0x03 /* remove acl's (-xX) */
|
||||
|
||||
/* ACL types for the acl array */
|
||||
#define ACCESS_ACL 0
|
||||
#define DEFAULT_ACL 1
|
||||
#define OP_REMOVE_BY_NUMBER 0x04 /* remove acl's (-xX) by acl entry number */
|
||||
#define OP_ADD_ACL 0x05 /* add acls entries at a given position */
|
||||
|
||||
/* TAILQ entry for acl operations */
|
||||
struct sf_entry {
|
||||
uint op;
|
||||
acl_t acl;
|
||||
uint entry_number;
|
||||
TAILQ_ENTRY(sf_entry) next;
|
||||
};
|
||||
TAILQ_HEAD(, sf_entry) entrylist;
|
||||
@ -61,21 +60,21 @@ TAILQ_HEAD(, sf_file) filelist;
|
||||
/* files.c */
|
||||
acl_t get_acl_from_file(const char *filename);
|
||||
/* merge.c */
|
||||
int merge_acl(acl_t acl, acl_t *prev_acl);
|
||||
int merge_acl(acl_t acl, acl_t *prev_acl, const char *filename);
|
||||
int add_acl(acl_t acl, uint entry_number, acl_t *prev_acl, const char *filename);
|
||||
/* remove.c */
|
||||
int remove_acl(acl_t acl, acl_t *prev_acl);
|
||||
int remove_default(acl_t *prev_acl);
|
||||
void remove_ext(acl_t *prev_acl);
|
||||
int remove_acl(acl_t acl, acl_t *prev_acl, const char *filename);
|
||||
int remove_by_number(uint entry_number, acl_t *prev_acl, const char *filename);
|
||||
int remove_default(acl_t *prev_acl, const char *filename);
|
||||
void remove_ext(acl_t *prev_acl, const char *filename);
|
||||
/* mask.c */
|
||||
int set_acl_mask(acl_t *prev_acl);
|
||||
int set_acl_mask(acl_t *prev_acl, const char *filename);
|
||||
/* util.c */
|
||||
void *zmalloc(size_t size);
|
||||
|
||||
acl_type_t acl_type;
|
||||
uint have_mask;
|
||||
uint need_mask;
|
||||
uint have_stdin;
|
||||
uint h_flag;
|
||||
uint n_flag;
|
||||
|
||||
#endif /* _SETFACL_H */
|
||||
|
Loading…
Reference in New Issue
Block a user