diff options
author | trasz <trasz@FreeBSD.org> | 2009-06-25 12:46:59 +0000 |
---|---|---|
committer | trasz <trasz@FreeBSD.org> | 2009-06-25 12:46:59 +0000 |
commit | ff2751123334f5d80faa47567304d59aed236eba (patch) | |
tree | 2ef84b1a3d387c8edf2b81194552ad8337bd003b /lib/libc/posix1e/acl_delete_entry.c | |
parent | 9a27798fa1cde67ed249d166ee358fee1a684179 (diff) | |
download | FreeBSD-src-ff2751123334f5d80faa47567304d59aed236eba.zip FreeBSD-src-ff2751123334f5d80faa47567304d59aed236eba.tar.gz |
Add NFSv4 ACL support to libc.
This adds the following functions to the acl(3) API: acl_add_flag_np,
acl_clear_flags_np, acl_create_entry_np, acl_delete_entry_np,
acl_delete_flag_np, acl_get_extended_np, acl_get_flag_np, acl_get_flagset_np,
acl_set_extended_np, acl_set_flagset_np, acl_to_text_np, acl_is_trivial_np,
acl_strip_np, acl_get_brand_np. Most of them are similar to what Darwin
does. There are no backward-incompatible changes.
Approved by: rwatson@
Diffstat (limited to 'lib/libc/posix1e/acl_delete_entry.c')
-rw-r--r-- | lib/libc/posix1e/acl_delete_entry.c | 100 |
1 files changed, 89 insertions, 11 deletions
diff --git a/lib/libc/posix1e/acl_delete_entry.c b/lib/libc/posix1e/acl_delete_entry.c index 3195fac..7dd60b8 100644 --- a/lib/libc/posix1e/acl_delete_entry.c +++ b/lib/libc/posix1e/acl_delete_entry.c @@ -33,6 +33,39 @@ __FBSDID("$FreeBSD$"); #include "un-namespace.h" #include <errno.h> #include <string.h> +#include <stdio.h> + +#include "acl_support.h" + +static int +_entry_matches(const acl_entry_t a, const acl_entry_t b) +{ + /* + * There is a semantical difference here between NFSv4 and POSIX + * draft ACLs. In POSIX, there may be only one entry for the particular + * user or group. In NFSv4 ACL, there may be any number of them. We're + * trying to be more specific here in that case. + */ + switch (_entry_brand(a)) { + case ACL_BRAND_NFS4: + if (a->ae_tag != b->ae_tag || a->ae_entry_type != b->ae_entry_type) + return (0); + + /* If ae_ids matter, compare them as well. */ + if (a->ae_tag == ACL_USER || a->ae_tag == ACL_GROUP) { + if (a->ae_id != b->ae_id) + return (0); + } + + return (1); + + default: + if ((a->ae_tag == b->ae_tag) && (a->ae_id == b->ae_id)) + return (1); + } + + return (0); +} /* * acl_delete_entry() (23.4.9): remove the ACL entry indicated by entry_d @@ -42,7 +75,7 @@ int acl_delete_entry(acl_t acl, acl_entry_t entry_d) { struct acl *acl_int; - int i; + int i, j, found = 0; if (acl == NULL || entry_d == NULL) { errno = EINVAL; @@ -51,29 +84,74 @@ acl_delete_entry(acl_t acl, acl_entry_t entry_d) acl_int = &acl->ats_acl; + if (_entry_brand(entry_d) != _acl_brand(acl)) { + errno = EINVAL; + return (-1); + } + if ((acl->ats_acl.acl_cnt < 1) || (acl->ats_acl.acl_cnt > ACL_MAX_ENTRIES)) { errno = EINVAL; return (-1); } - for (i = 0; i < acl->ats_acl.acl_cnt; i++) { - /* if this is our entry... */ - if ((acl->ats_acl.acl_entry[i].ae_tag == entry_d->ae_tag) && - (acl->ats_acl.acl_entry[i].ae_id == entry_d->ae_id)) { + for (i = 0; i < acl->ats_acl.acl_cnt;) { + if (_entry_matches(&(acl->ats_acl.acl_entry[i]), entry_d)) { /* ...shift the remaining entries... */ - for (; i < acl->ats_acl.acl_cnt - 1; ++i) - acl->ats_acl.acl_entry[i] = - acl->ats_acl.acl_entry[i+1]; + for (j = i; j < acl->ats_acl.acl_cnt - 1; ++j) + acl->ats_acl.acl_entry[j] = + acl->ats_acl.acl_entry[j+1]; /* ...drop the count and zero the unused entry... */ acl->ats_acl.acl_cnt--; - bzero(&acl->ats_acl.acl_entry[i], + bzero(&acl->ats_acl.acl_entry[j], sizeof(struct acl_entry)); acl->ats_cur_entry = 0; - return (0); - } + + /* Continue with the loop to remove all maching entries. */ + found = 1; + } else + i++; } + if (found) + return (0); errno = EINVAL; return (-1); } + +int +acl_delete_entry_np(acl_t acl, int offset) +{ + struct acl *acl_int; + int i; + + if (acl == NULL) { + errno = EINVAL; + return (-1); + } + + acl_int = &acl->ats_acl; + + if (offset < 0 || offset >= acl_int->acl_cnt) { + errno = EINVAL; + return (-1); + } + + if ((acl->ats_acl.acl_cnt < 1) || + (acl->ats_acl.acl_cnt > ACL_MAX_ENTRIES)) { + errno = EINVAL; + return (-1); + } + + /* ...shift the remaining entries... */ + for (i = offset; i < acl->ats_acl.acl_cnt - 1; ++i) + acl->ats_acl.acl_entry[i] = + acl->ats_acl.acl_entry[i+1]; + /* ...drop the count and zero the unused entry... */ + acl->ats_acl.acl_cnt--; + bzero(&acl->ats_acl.acl_entry[i], + sizeof(struct acl_entry)); + acl->ats_cur_entry = 0; + + return (0); +} |