summaryrefslogtreecommitdiffstats
path: root/bin/setfacl
diff options
context:
space:
mode:
authorjedgar <jedgar@FreeBSD.org>2001-04-24 22:45:41 +0000
committerjedgar <jedgar@FreeBSD.org>2001-04-24 22:45:41 +0000
commit2da23531d99e45f34811fd6982a681112de0e182 (patch)
tree0b8830fcccafadf6607f3658e96733124ef8617d /bin/setfacl
parentecbf3eacd9a17a3a9b238e2fa65b2d33d85e8d1f (diff)
downloadFreeBSD-src-2da23531d99e45f34811fd6982a681112de0e182.zip
FreeBSD-src-2da23531d99e45f34811fd6982a681112de0e182.tar.gz
o Separate acl_t into internal and external representations as
required by POSIX.1e. This maintains the current 'struct acl' in the kernel while providing the generic external acl_t interface required to complete the ACL editing library. o Add the acl_get_entry() function. o Convert the existing ACL utilities, getfacl and setfacl, to fully make use of the ACL editing library. Obtained from: TrustedBSD Project
Diffstat (limited to 'bin/setfacl')
-rw-r--r--bin/setfacl/mask.c24
-rw-r--r--bin/setfacl/merge.c121
-rw-r--r--bin/setfacl/remove.c81
-rw-r--r--bin/setfacl/setfacl.c26
-rw-r--r--bin/setfacl/setfacl.h14
5 files changed, 168 insertions, 98 deletions
diff --git a/bin/setfacl/mask.c b/bin/setfacl/mask.c
index 5992e94..595ab44 100644
--- a/bin/setfacl/mask.c
+++ b/bin/setfacl/mask.c
@@ -40,10 +40,14 @@
/* set the appropriate mask the given ACL's */
int
-set_acl_mask(acl_t prev_acl)
+set_acl_mask(acl_t *prev_acl)
{
+ acl_entry_t entry;
acl_t acl;
- int i;
+ acl_tag_t tag;
+ int entry_id;
+
+ entry = NULL;
/*
* ... if a mask entry is specified, then the permissions of the mask
@@ -53,7 +57,7 @@ set_acl_mask(acl_t prev_acl)
if (have_mask)
return 0;
- acl = acl_dup(prev_acl);
+ acl = acl_dup(*prev_acl);
if (!acl)
err(EX_OSERR, "acl_dup() failed");
@@ -76,11 +80,19 @@ set_acl_mask(acl_t prev_acl)
* specified, then the permissions of the resulting ACL
* mask entry shall remain unchanged ...
*/
- for (i = 0; i < acl->acl_cnt; i++)
- if (acl->acl_entry[i].ae_tag == ACL_MASK) {
+
+ entry_id = ACL_FIRST_ENTRY;
+
+ 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");
+
+ if (tag == ACL_MASK) {
acl_free(acl);
return 0;
}
+ }
/*
* If no mask entry is specified, the -n option is specified,
@@ -93,7 +105,7 @@ set_acl_mask(acl_t prev_acl)
return 0;
}
- *prev_acl = *acl;
+ prev_acl = &acl;
acl_free(acl);
return 0;
diff --git a/bin/setfacl/merge.c b/bin/setfacl/merge.c
index c739b26..acb01f4 100644
--- a/bin/setfacl/merge.c
+++ b/bin/setfacl/merge.c
@@ -40,11 +40,12 @@
int
merge_acl(acl_t acl, acl_t *prev_acl)
{
+ acl_entry_t entry, entry_new;
+ acl_permset_t permset;
acl_t acl_new;
- int blank_acl_user, blank_acl_group, have_entry, i, j;
- struct stat sb;
-
- blank_acl_user = blank_acl_group = 0;
+ acl_tag_t tag, tag_new;
+ int entry_id, entry_id_new, have_entry;
+ uid_t *id, *id_new;
if (acl_type == ACL_TYPE_ACCESS)
acl_new = acl_dup(prev_acl[0]);
@@ -53,61 +54,99 @@ merge_acl(acl_t acl, acl_t *prev_acl)
if (!acl_new)
err(EX_OSERR, "acl_dup() failed");
- /* step through new ACL entries */
- for (i = 0; i < acl->acl_cnt; i++) {
+ entry_id = ACL_FIRST_ENTRY;
+
+ while (acl_get_entry(acl, entry_id, &entry) == 1) {
+ entry_id = ACL_NEXT_ENTRY;
have_entry = 0;
- /* oh look, we have an ACL_MASK entry */
- if (acl->acl_entry[i].ae_tag == ACL_MASK)
+ /* keep track of existing ACL_MASK entries */
+ if (acl_get_tag_type(entry, &tag) == -1)
+ err(EX_OSERR,
+ "acl_get_tag_type() failed - invalid ACL entry");
+ if (tag == ACL_MASK)
have_mask = 1;
/* check against the existing ACL entries */
- for (j = 0; j < acl_new->acl_cnt && !have_entry; j++) {
- if (acl_new->acl_entry[j].ae_tag ==
- acl->acl_entry[i].ae_tag) {
- switch(acl->acl_entry[i].ae_tag) {
- case ACL_USER_OBJ:
- acl_new->acl_entry[j].ae_perm =
- acl->acl_entry[i].ae_perm;
- acl_new->acl_entry[j].ae_id = sb.st_uid;
- have_entry = 1;
- break;
- case ACL_GROUP_OBJ:
- acl_new->acl_entry[j].ae_perm =
- acl->acl_entry[i].ae_perm;
- acl_new->acl_entry[j].ae_id = sb.st_gid;
+ entry_id_new = ACL_FIRST_ENTRY;
+ while (!have_entry &&
+ 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(EX_OSERR, "acl_get_tag_type() failed");
+ if (acl_get_tag_type(entry_new, &tag_new) == -1)
+ err(EX_OSERR, "acl_get_tag_type() failed");
+ if (tag != tag_new)
+ continue;
+
+ switch(tag) {
+ case ACL_USER:
+ case ACL_GROUP:
+ id = acl_get_qualifier(entry);
+ if (id == NULL)
+ err(EX_OSERR,
+ "acl_get_qualifier() failed");
+ id_new = acl_get_qualifier(entry_new);
+ if (id_new == NULL)
+ err(EX_OSERR,
+ "acl_get_qualifier() failed");
+ if (*id == *id_new) {
+ /* any other matches */
+ if (acl_get_permset(entry, &permset)
+ == -1)
+ err(EX_OSERR,
+ "acl_get_permset() failed");
+ if (acl_set_permset(entry_new, permset)
+ == -1)
+ err(EX_OSERR,
+ "acl_set_permset() failed");
have_entry = 1;
- break;
- default:
- if (acl_new->acl_entry[j].ae_id ==
- acl->acl_entry[i].ae_id) {
- /* any other matches */
- acl_new->acl_entry[j].ae_perm =
- acl->acl_entry[i].ae_perm;
- have_entry = 1;
- }
- break;
}
+ acl_free(id);
+ acl_free(id_new);
+ if (!have_entry)
+ break;
+ /* FALLTHROUGH */
+ case ACL_USER_OBJ:
+ case ACL_GROUP_OBJ:
+ case ACL_OTHER:
+ case ACL_MASK:
+ if (acl_get_permset(entry, &permset) == -1)
+ err(EX_OSERR,
+ "acl_get_permset() failed");
+ if (acl_set_permset(entry_new, permset) == -1)
+ err(EX_OSERR,
+ "acl_set_permset() failed");
+ have_entry = 1;
+ break;
+ default:
+ /* should never be here */
+ errx(EX_OSERR, "Invalid tag type: %i", tag);
+ break;
}
}
/* if this entry has not been found, it must be new */
if (!have_entry) {
- if (acl_new->acl_cnt == ACL_MAX_ENTRIES) {
- warn("too many ACL entries");
+ if (acl_create_entry(&acl_new, &entry_new) == -1) {
acl_free(acl_new);
return -1;
}
- acl_new->acl_entry[acl_new->acl_cnt++] =
- acl->acl_entry[i];
+ if (acl_copy_entry(entry_new, entry) == -1)
+ err(EX_OSERR, "acl_copy_entry() failed");
}
}
- if (acl_type == ACL_TYPE_ACCESS)
- *prev_acl[0] = *acl_new;
- else
- *prev_acl[1] = *acl_new;
- acl_free(acl_new);
+
+ if (acl_type == ACL_TYPE_ACCESS) {
+ acl_free(prev_acl[0]);
+ prev_acl[0] = acl_new;
+ } else {
+ acl_free(prev_acl[1]);
+ prev_acl[1] = acl_new;
+ }
+
return 0;
}
diff --git a/bin/setfacl/remove.c b/bin/setfacl/remove.c
index 0fe02d1..e987df7 100644
--- a/bin/setfacl/remove.c
+++ b/bin/setfacl/remove.c
@@ -41,8 +41,10 @@
int
remove_acl(acl_t acl, acl_t *prev_acl)
{
- acl_t acl_new;
- int carried_error, i;
+ acl_entry_t entry;
+ acl_t acl_new;
+ acl_tag_t tag;
+ int carried_error, entry_id;
carried_error = 0;
@@ -53,11 +55,17 @@ remove_acl(acl_t acl, acl_t *prev_acl)
if (!acl_new)
err(EX_OSERR, "acl_dup() failed");
+ tag = ACL_UNDEFINED_TAG;
+
/* find and delete the entry */
- for (i = 0; i < acl->acl_cnt; i++) {
- if (acl->acl_entry[i].ae_tag == ACL_MASK)
+ entry_id = ACL_FIRST_ENTRY;
+ 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");
+ if (tag == ACL_MASK)
have_mask++;
- if (acl_delete_entry(acl_new, &acl->acl_entry[i]) == -1) {
+ if (acl_delete_entry(acl_new, entry) == -1) {
carried_error++;
warnx("cannot remove non-existent acl entry");
}
@@ -83,8 +91,10 @@ remove_default(acl_t *prev_acl)
{
if (prev_acl[1]) {
- bzero(prev_acl[1], sizeof(struct acl));
- prev_acl[1]->acl_cnt = 0;
+ acl_free(prev_acl[1]);
+ prev_acl[1] = acl_init(ACL_MAX_ENTRIES);
+ if (!prev_acl[1])
+ err(1, "acl_init() failed");
} else {
warn("cannot remove default ACL");
return -1;
@@ -97,8 +107,10 @@ void
remove_ext(acl_t *prev_acl)
{
acl_t acl_new, acl_old;
- acl_perm_t group_perm, mask_perm;
- int have_mask_entry, i;
+ acl_entry_t entry, entry_new;
+ acl_permset_t perm;
+ acl_tag_t tag;
+ int entry_id, have_mask_entry;
if (acl_type == ACL_TYPE_ACCESS)
acl_old = acl_dup(prev_acl[0]);
@@ -107,41 +119,50 @@ remove_ext(acl_t *prev_acl)
if (!acl_old)
err(EX_OSERR, "acl_dup() failed");
- group_perm = mask_perm = 0;
have_mask_entry = 0;
acl_new = acl_init(ACL_MAX_ENTRIES);
if (!acl_new)
err(EX_OSERR, "%s", "acl_init() failed");
+ tag = ACL_UNDEFINED_TAG;
/* only save the default user/group/other entries */
- for (i = 0; i < acl_old->acl_cnt; i++)
- switch(acl_old->acl_entry[i].ae_tag) {
+ 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:
- acl_new->acl_entry[0] = acl_old->acl_entry[i];
- break;
case ACL_GROUP_OBJ:
- acl_new->acl_entry[1] = acl_old->acl_entry[i];
- group_perm = acl_old->acl_entry[i].ae_perm;
- break;
- case ACL_OTHER_OBJ:
- acl_new->acl_entry[2] = acl_old->acl_entry[i];
+ 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:
- mask_perm = acl_old->acl_entry[i].ae_perm;
have_mask_entry = 1;
break;
default:
break;
}
- /*
- * If the ACL contains a mask entry, then the permissions associated
- * with the owning group entry in the resulting ACL shall be set to
- * only those permissions associated with both the owning group entry
- * and the mask entry of the current ACL.
- */
- if (have_mask_entry)
- acl_new->acl_entry[1].ae_perm = group_perm & mask_perm;
- acl_new->acl_cnt = 3;
+ }
+ if (have_mask_entry && !n_flag) {
+ 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[0]);
@@ -150,6 +171,4 @@ remove_ext(acl_t *prev_acl)
acl_free(prev_acl[1]);
prev_acl[1] = acl_new;
}
-
- have_mask = 0;
}
diff --git a/bin/setfacl/setfacl.c b/bin/setfacl/setfacl.c
index c18c3f9..b2d8578 100644
--- a/bin/setfacl/setfacl.c
+++ b/bin/setfacl/setfacl.c
@@ -56,7 +56,7 @@ add_filename(const char *filename)
}
file = zmalloc(sizeof(struct sf_file));
file->filename = filename;
- STAILQ_INSERT_TAIL(&filelist, file, next);
+ TAILQ_INSERT_TAIL(&filelist, file, next);
}
static acl_t *
@@ -106,8 +106,8 @@ main(int argc, char *argv[])
carried_error = local_error = 0;
have_mask = have_stdin = n_flag = need_mask = 0;
- STAILQ_INIT(&entrylist);
- STAILQ_INIT(&filelist);
+ TAILQ_INIT(&entrylist);
+ TAILQ_INIT(&filelist);
while ((ch = getopt(argc, argv, "M:X:bdkm:nx:")) != -1)
switch(ch) {
@@ -117,18 +117,18 @@ main(int argc, char *argv[])
if (!entry->acl)
err(EX_OSERR, "get_acl_from_file() failed");
entry->op = OP_MERGE_ACL;
- STAILQ_INSERT_TAIL(&entrylist, entry, next);
+ TAILQ_INSERT_TAIL(&entrylist, entry, next);
break;
case 'X':
entry = zmalloc(sizeof(struct sf_entry));
entry->acl = get_acl_from_file(optarg);
entry->op = OP_REMOVE_ACL;
- STAILQ_INSERT_TAIL(&entrylist, entry, next);
+ TAILQ_INSERT_TAIL(&entrylist, entry, next);
break;
case 'b':
entry = zmalloc(sizeof(struct sf_entry));
entry->op = OP_REMOVE_EXT;
- STAILQ_INSERT_TAIL(&entrylist, entry, next);
+ TAILQ_INSERT_TAIL(&entrylist, entry, next);
break;
case 'd':
acl_type = ACL_TYPE_DEFAULT;
@@ -136,7 +136,7 @@ main(int argc, char *argv[])
case 'k':
entry = zmalloc(sizeof(struct sf_entry));
entry->op = OP_REMOVE_DEF;
- STAILQ_INSERT_TAIL(&entrylist, entry, next);
+ TAILQ_INSERT_TAIL(&entrylist, entry, next);
break;
case 'm':
entry = zmalloc(sizeof(struct sf_entry));
@@ -144,7 +144,7 @@ main(int argc, char *argv[])
if (!entry->acl)
err(EX_USAGE, "acl_from_text() failed");
entry->op = OP_MERGE_ACL;
- STAILQ_INSERT_TAIL(&entrylist, entry, next);
+ TAILQ_INSERT_TAIL(&entrylist, entry, next);
break;
case 'n':
n_flag++;
@@ -155,7 +155,7 @@ main(int argc, char *argv[])
if (!entry->acl)
err(EX_USAGE, "acl_from_text() failed");
entry->op = OP_REMOVE_ACL;
- STAILQ_INSERT_TAIL(&entrylist, entry, next);
+ TAILQ_INSERT_TAIL(&entrylist, entry, next);
break;
default:
usage();
@@ -164,7 +164,7 @@ main(int argc, char *argv[])
argc -= optind;
argv += optind;
- if (STAILQ_EMPTY(&entrylist))
+ if (!n_flag && TAILQ_EMPTY(&entrylist))
usage();
/* take list of files from stdin */
@@ -183,7 +183,7 @@ main(int argc, char *argv[])
add_filename(argv[i]);
/* cycle through each file */
- STAILQ_FOREACH(file, &filelist, next) {
+ TAILQ_FOREACH(file, &filelist, next) {
/* get our initial access and default ACL's */
acl = get_file_acls(file->filename);
if (!acl)
@@ -196,7 +196,7 @@ main(int argc, char *argv[])
local_error = 0;
/* cycle through each option */
- STAILQ_FOREACH(entry, &entrylist, next) {
+ TAILQ_FOREACH(entry, &entrylist, next) {
if (local_error)
continue;
@@ -236,7 +236,7 @@ main(int argc, char *argv[])
else
final_acl = acl[1];
- if (need_mask && (set_acl_mask(final_acl) == -1)) {
+ if (need_mask && (set_acl_mask(&final_acl) == -1)) {
warnx("failed to set ACL mask on %s", file->filename);
carried_error++;
} else if (acl_set_file(file->filename, acl_type,
diff --git a/bin/setfacl/setfacl.h b/bin/setfacl/setfacl.h
index b80fa44..d3c7923 100644
--- a/bin/setfacl/setfacl.h
+++ b/bin/setfacl/setfacl.h
@@ -39,20 +39,20 @@
#define OP_REMOVE_EXT 0x02 /* remove extended acl's (-b) */
#define OP_REMOVE_ACL 0x03 /* remove acl's (-xX) */
-/* STAILQ entry for acl operations */
+/* TAILQ entry for acl operations */
struct sf_entry {
uint op;
acl_t acl;
- STAILQ_ENTRY(sf_entry) next;
+ TAILQ_ENTRY(sf_entry) next;
};
-STAILQ_HEAD(, sf_entry) entrylist;
+TAILQ_HEAD(, sf_entry) entrylist;
-/* STAILQ entry for files */
+/* TAILQ entry for files */
struct sf_file {
const char *filename;
- STAILQ_ENTRY(sf_file) next;
+ TAILQ_ENTRY(sf_file) next;
};
-STAILQ_HEAD(, sf_file) filelist;
+TAILQ_HEAD(, sf_file) filelist;
/* files.c */
acl_t get_acl_from_file(const char *filename);
@@ -63,7 +63,7 @@ int remove_acl(acl_t acl, acl_t *prev_acl);
int remove_default(acl_t *prev_acl);
void remove_ext(acl_t *prev_acl);
/* mask.c */
-int set_acl_mask(acl_t prev_acl);
+int set_acl_mask(acl_t *prev_acl);
/* util.c */
void *zmalloc(size_t size);
OpenPOWER on IntegriCloud