aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/acl/libacl-helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'internal/acl/libacl-helper.c')
-rw-r--r--internal/acl/libacl-helper.c87
1 files changed, 65 insertions, 22 deletions
diff --git a/internal/acl/libacl-helper.c b/internal/acl/libacl-helper.c
index 259dfb2b..065c1928 100644
--- a/internal/acl/libacl-helper.c
+++ b/internal/acl/libacl-helper.c
@@ -4,18 +4,22 @@
#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;
+enum hakurei_acl_status hakurei_update_acl(
+ const char *path_p,
+ uid_t uid,
+ acl_perm_t perms) {
+ enum hakurei_acl_status ret;
+
bool v;
int i;
- acl_t acl;
+ acl_t acl, acl_d = NULL;
acl_entry_t entry;
acl_tag_t tag_type;
void *qualifier_p;
acl_permset_t permset;
+ acl_perm_t has_perms;
- ret = -1; /* acl_get_file */
+ ret = HAKUREI_ACL_GET_FILE;
acl = acl_get_file(path_p, ACL_TYPE_ACCESS);
if (acl == NULL)
goto out;
@@ -23,13 +27,13 @@ int hakurei_acl_update_file_by_uid(const char *path_p, uid_t uid,
/* 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)) {
- ret = -2; /* acl_get_tag_type */
+ ret = HAKUREI_ACL_GET_TAG_TYPE;
if (acl_get_tag_type(entry, &tag_type) != 0)
goto out;
if (tag_type != ACL_USER)
continue;
- ret = -3; /* acl_get_qualifier */
+ ret = HAKUREI_ACL_GET_QUALIFIER;
qualifier_p = acl_get_qualifier(entry);
if (qualifier_p == NULL)
goto out;
@@ -39,52 +43,91 @@ int hakurei_acl_update_file_by_uid(const char *path_p, uid_t uid,
if (!v)
continue;
- ret = -4; /* acl_delete_entry */
+ ret = HAKUREI_ACL_GET_PERMSET;
+ if (acl_get_permset(entry, &permset) != 0)
+ goto out;
+
+ if (perms == 0)
+ goto delete;
+
+ /* this is quite ugly, but the standard makes it impossible to directly
+ * obtain these bits */
+ has_perms = 0;
+#define COPY_PERM_BIT(perm) \
+ do { \
+ ret = HAKUREI_ACL_GET_PERM; \
+ i = acl_get_perm(permset, perm); \
+ if (i < 0) \
+ goto out; \
+ if (i > 0) \
+ has_perms |= perm; \
+ } while (0)
+ COPY_PERM_BIT(ACL_READ);
+ COPY_PERM_BIT(ACL_WRITE);
+ COPY_PERM_BIT(ACL_EXECUTE);
+
+ if (perms == has_perms) {
+ ret = HAKUREI_ACL_DUP;
+ acl_d = acl_dup(acl);
+ if (acl_d == NULL)
+ goto out;
+
+ ret = HAKUREI_ACL_CALC_MASK;
+ if (acl_calc_mask(&acl_d) != 0)
+ goto out;
+
+ ret = HAKUREI_ACL_OK;
+ if (acl_cmp(acl, acl_d) == 0)
+ goto out;
+ }
+
+ delete:
+ ret = HAKUREI_ACL_DELETE_ENTRY;
if (acl_delete_entry(acl, entry) != 0)
goto out;
}
- if (plen == 0)
+ if (perms == 0)
goto set;
- ret = -5; /* acl_create_entry */
+ ret = HAKUREI_ACL_CREATE_ENTRY;
if (acl_create_entry(&acl, &entry) != 0)
goto out;
- ret = -6; /* acl_get_permset */
+ ret = HAKUREI_ACL_GET_PERMSET;
if (acl_get_permset(entry, &permset) != 0)
goto out;
- ret = -7; /* acl_add_perm */
- for (i = 0; i < plen; i++) {
- if (acl_add_perm(permset, perms[i]) != 0)
- goto out;
- }
+ ret = HAKUREI_ACL_ADD_PERM;
+ if (acl_add_perm(permset, perms) != 0)
+ goto out;
- ret = -8; /* acl_set_tag_type */
+ ret = HAKUREI_ACL_SET_TAG_TYPE;
if (acl_set_tag_type(entry, ACL_USER) != 0)
goto out;
- ret = -9; /* acl_set_qualifier */
+ ret = HAKUREI_ACL_SET_QUALIFIER;
if (acl_set_qualifier(entry, (void *)&uid) != 0)
goto out;
set:
- ret = -10; /* acl_calc_mask */
+ ret = HAKUREI_ACL_CALC_MASK;
if (acl_calc_mask(&acl) != 0)
goto out;
- ret = -11; /* acl_valid */
+ ret = HAKUREI_ACL_VALID;
if (acl_valid(acl) != 0)
goto out;
- ret = -12; /* acl_set_file */
+ ret = HAKUREI_ACL_SET_FILE;
if (acl_set_file(path_p, ACL_TYPE_ACCESS, acl) == 0)
- ret = 0;
+ ret = HAKUREI_ACL_OK;
out:
free((void *)path_p);
if (acl != NULL)
acl_free((void *)acl);
+ if (acl_d != NULL)
+ acl_free((void *)acl_d);
return ret;
}