The original implementation was effectively just writing C in Go. Signed-off-by: Ophestra <cat@gensokyo.uk>
70 lines
1.6 KiB
C
70 lines
1.6 KiB
C
#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;
|
|
}
|