aboutsummaryrefslogtreecommitdiffhomepage
path: root/system/acl/libacl-helper.c
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2025-07-02 21:52:07 +0900
committerOphestra <cat@gensokyo.uk>2025-07-02 21:52:07 +0900
commit82561d62b66f17c05604e87f18187bb3a91f00d2 (patch)
treec1543f85b4458b7d5cb2cf7b1baa9dee318debfe /system/acl/libacl-helper.c
parenteec021cc4b4eb42bc9c8311755826828bfba1996 (diff)
system: move system access packages
These packages loosely belong in the "system" package and "system" provides high level wrappers for all of them. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'system/acl/libacl-helper.c')
-rw-r--r--system/acl/libacl-helper.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/system/acl/libacl-helper.c b/system/acl/libacl-helper.c
new file mode 100644
index 00000000..905cfa52
--- /dev/null
+++ b/system/acl/libacl-helper.c
@@ -0,0 +1,71 @@
+#include "libacl-helper.h"
+#include <acl/libacl.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <sys/acl.h>
+
+int hakurei_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;
+}