diff options
| author | Ophestra <cat@gensokyo.uk> | 2025-02-17 20:37:10 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2025-02-17 21:39:14 +0900 |
| commit | e85be67fd98dd5adb17fefdc52a28c8a7a7c3b28 (patch) | |
| tree | d026ee5cddd84c99349edc19112caa396f5be0bc /acl/acl-update.c | |
| parent | 7e69893264f4b3ee3fc9168a61908552f7fbddac (diff) | |
acl: implement Update in C
The original implementation was effectively just writing C in Go.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'acl/acl-update.c')
| -rw-r--r-- | acl/acl-update.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/acl/acl-update.c b/acl/acl-update.c new file mode 100644 index 00000000..1d83c15d --- /dev/null +++ b/acl/acl-update.c @@ -0,0 +1,69 @@ +#include "acl-update.h" +#include <stdlib.h> +#include <stdbool.h> +#include <sys/acl.h> +#include <acl/libacl.h> + +int f_acl_update_file_by_uid(const char *path_p, uid_t uid, acl_perm_t *perms, size_t plen) { + int ret = -1; + bool v; + int i; + acl_t acl; + acl_entry_t entry; + acl_tag_t tag_type; + void *qualifier_p; + acl_permset_t permset; + + acl = acl_get_file(path_p, ACL_TYPE_ACCESS); + if (acl == NULL) + goto out; + + // prune entries by uid + for (i = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry); i == 1; i = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry)) { + if (acl_get_tag_type(entry, &tag_type) != 0) + return -1; + if (tag_type != ACL_USER) + continue; + + qualifier_p = acl_get_qualifier(entry); + if (qualifier_p == NULL) + return -1; + v = *(uid_t *)qualifier_p == uid; + acl_free(qualifier_p); + + if (!v) + continue; + + acl_delete_entry(acl, entry); + } + + if (plen == 0) + goto set; + + if (acl_create_entry(&acl, &entry) != 0) + goto out; + if (acl_get_permset(entry, &permset) != 0) + goto out; + for (i = 0; i < plen; i++) { + if (acl_add_perm(permset, perms[i]) != 0) + goto out; + } + if (acl_set_tag_type(entry, ACL_USER) != 0) + goto out; + if (acl_set_qualifier(entry, (void *)&uid) != 0) + goto out; + +set: + if (acl_calc_mask(&acl) != 0) + goto out; + if (acl_valid(acl) != 0) + goto out; + if (acl_set_file(path_p, ACL_TYPE_ACCESS, acl) == 0) + ret = 0; + +out: + free((void *)path_p); + if (acl != NULL) + acl_free((void *)acl); + return ret; +} |
