X-Git-Url: https://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=src%2Faclq.c;h=557a70e6e21acf9ebe051275de8d448d930dd2bd;hb=5932197191e4cbeacbab1ff5900a7851fdb85872;hp=19749cdf671b1de3e6e2aa8eb3180e7614aa4159;hpb=3b6789d9406dc890f4c9386c227986739652f97d;p=apply-default-acl.git diff --git a/src/aclq.c b/src/aclq.c index 19749cd..557a70e 100644 --- a/src/aclq.c +++ b/src/aclq.c @@ -32,15 +32,6 @@ mode_t get_mode(const char* path) { } } -bool mode_has_perm(mode_t mode, int perm) { - if (mode & perm) { - return true; - } - else { - return false; - } -} - bool is_regular_file(const char* path) { if (path == NULL) { @@ -73,521 +64,22 @@ bool is_directory(const char* path) { } -int has_type_tag_acl(const char* path, - acl_type_t type, - acl_tag_t desired_tag) { - /* Returns one if the given path has a default ACL for the supplied - tag, zero if it doesn't, and -1 on error. */ - acl_t defacl = acl_get_file(path, type); - - if (defacl == (acl_t)NULL) { - return 0; - } - - acl_entry_t entry; - int result = acl_get_entry(defacl, ACL_FIRST_ENTRY, &entry); - - while (result == 1) { - acl_tag_t tag = ACL_UNDEFINED_TAG; - int tag_result = acl_get_tag_type(entry, &tag); - - if (tag_result == -1) { - perror("has_default_tag_acl (acl_get_tag_type)"); - return -1; - } - else { - if (tag == desired_tag) { - return 1; - } - } - - result = acl_get_entry(defacl, ACL_NEXT_ENTRY, &entry); - } - - if (result == -1) { - perror("has_default_tag_acl (acl_get_entry)"); - return -1; - } - - return 0; -} - -int has_default_tag_acl(const char* path, acl_tag_t desired_tag) { - return has_type_tag_acl(path, ACL_TYPE_DEFAULT, desired_tag); -} - -int has_access_tag_acl(const char* path, acl_tag_t desired_tag) { - return has_type_tag_acl(path, ACL_TYPE_ACCESS, desired_tag); -} - -int has_default_user_obj_acl(const char* path) { - return has_default_tag_acl(path, ACL_USER_OBJ); -} - -int has_default_group_obj_acl(const char* path) { - return has_default_tag_acl(path, ACL_GROUP_OBJ); -} - -int has_default_other_acl(const char* path) { - return has_default_tag_acl(path, ACL_OTHER); -} - -int has_default_mask_acl(const char* path) { - return has_default_tag_acl(path, ACL_MASK); -} - - -int get_type_tag_entry(const char* path, - acl_type_t type, - acl_tag_t desired_tag, - acl_entry_t* entry) { - /* Returns one if successful, zero when the ACL doesn't exist, and - -1 on unexpected errors. */ - acl_t acl = acl_get_file(path, type); - - if (acl == (acl_t)NULL) { - /* Follow the acl_foo convention of -1 == error. */ - return 0; - } - - int result = acl_get_entry(acl, ACL_FIRST_ENTRY, entry); - - while (result == 1) { - acl_tag_t tag = ACL_UNDEFINED_TAG; - int tag_result = acl_get_tag_type(*entry, &tag); - - if (tag_result == -1) { - perror("get_type_tag_entry (acl_get_tag_type)"); - return -1; - } - - if (tag == desired_tag) { - /* We found the right tag, so return successfully. */ - return 1; - } - - result = acl_get_entry(acl, ACL_NEXT_ENTRY, entry); - } - - /* This catches both the initial acl_get_entry and the ones at the - end of the loop. */ - if (result == -1) { - perror("get_type_tag_entry (acl_get_entry)"); - return -1; - } - - return 0; -} - -int get_default_tag_entry(const char* path, - acl_tag_t desired_tag, - acl_entry_t* entry) { - return get_type_tag_entry(path, ACL_TYPE_DEFAULT, desired_tag, entry); -} - -int get_access_tag_entry(const char* path, - acl_tag_t desired_tag, - acl_entry_t* entry) { - return get_type_tag_entry(path, ACL_TYPE_ACCESS, desired_tag, entry); -} - - - -int get_type_tag_permset(const char* path, - acl_type_t type, - acl_tag_t desired_tag, - acl_permset_t* output_perms) { - /* Returns one if successful, zero when the ACL doesn't exist, and - -1 on unexpected errors. */ - acl_t defacl = acl_get_file(path, type); - - if (defacl == (acl_t)NULL) { - /* Follow the acl_foo convention of -1 == error. */ - return 0; - } - - acl_entry_t entry; - int result = get_type_tag_entry(path, type, desired_tag, &entry); - - if (result == 1) { - /* We found the right tag, now get the permset. */ - int ps_result = acl_get_permset(entry, output_perms); - if (ps_result == -1) { - perror("get_type_tag_permset (acl_get_permset)"); - return -1; - } - - if (ps_result == 0) { - return 1; - } - else { - return 0; - } - } - else { - return result; - } -} - -int get_default_tag_permset(const char* path, - acl_tag_t desired_tag, - acl_permset_t* output_perms) { - return get_type_tag_permset(path, - ACL_TYPE_DEFAULT, - desired_tag, - output_perms); -} - -int get_access_tag_permset(const char* path, - acl_tag_t desired_tag, - acl_permset_t* output_perms) { - return get_type_tag_permset(path, ACL_TYPE_ACCESS, desired_tag, output_perms); -} - -int has_default_tag_perm(const char* path, - acl_tag_t tag, - acl_perm_t perm) { - /* Check path to see if tag has the given perm. Returns one if it - does, zero if it doesn't (or there's no ACL), and -1 on unexpected - errors. */ - - if (!has_default_tag_acl(path, tag)) { - return 0; - } - - acl_permset_t permset; - bool ps_result = get_default_tag_permset(path, tag, &permset); - - if (ps_result != 1) { - /* Failure or error. */ - return ps_result; - } - - int p_result = acl_get_perm(permset, perm); - if (p_result == -1) { - perror("has_default_tag_perm (acl_get_perm)"); - } - - return p_result; -} - -int remove_access_tag_perm(const char* path, - acl_tag_t desired_tag, - acl_perm_t perm) { - /* Attempt to remove perm from tag. Returns one if successful, zero - if there was nothing to do, and -1 on errors. */ - acl_t acl = acl_get_file(path, ACL_TYPE_ACCESS); - if (acl == (acl_t)NULL) { - /* Error. */ - return -1; - } - - acl_permset_t permset; - bool ps_result = get_access_tag_permset(path, desired_tag, &permset); - - if (ps_result != 1) { - /* Failure or error. */ - return ps_result; - } - - int d_result = acl_delete_perm(permset, perm); - if (d_result == -1) { - perror("remove_access_tag_perm (acl_delete_perm)"); - return -1; - } - - /* We've only removed perm from the permset; now we have to replace - the permset. */ - acl_entry_t entry; - int result = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry); - - while (result == 1) { - acl_tag_t tag = ACL_UNDEFINED_TAG; - int tag_result = acl_get_tag_type(entry, &tag); - - if (tag_result == -1) { - perror("remove_access_tag_perm (acl_get_tag_type)"); - return -1; - } - - if (tag == desired_tag) { - /* We found the right tag. Update the permset. */ - int s_result = acl_set_permset(entry, permset); - if (s_result == -1) { - perror("remove_access_tag_perm (acl_set_permset)"); - return -1; - } - - int sf_result = acl_set_file(path, ACL_TYPE_ACCESS, acl); - if (sf_result == -1) { - perror("remove_access_tag_perm (acl_set_file)"); - return -1; - } - - return 1; - } - - result = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry); - } - - /* This catches both the initial acl_get_entry and the ones at the - end of the loop. */ - if (result == -1) { - perror("remove_access_tag_perm (acl_get_entry)"); - return -1; - } - - return 0; -} - -int remove_access_group_obj_execute(const char* path) { - return remove_access_tag_perm(path, ACL_GROUP_OBJ, ACL_EXECUTE); -} - - -int has_default_user_obj_read(const char* path) { - return has_default_tag_perm(path, ACL_USER_OBJ, ACL_READ); -} - -int has_default_user_obj_write(const char* path) { - return has_default_tag_perm(path, ACL_USER_OBJ, ACL_WRITE); -} - -int has_default_user_obj_execute(const char* path) { - return has_default_tag_perm(path, ACL_USER_OBJ, ACL_EXECUTE); -} - -int has_default_group_obj_read(const char* path) { - return has_default_tag_perm(path, ACL_GROUP_OBJ, ACL_READ); -} - -int has_default_group_obj_write(const char* path) { - return has_default_tag_perm(path, ACL_GROUP_OBJ, ACL_WRITE); -} - -int has_default_group_obj_execute(const char* path) { - return has_default_tag_perm(path, ACL_GROUP_OBJ, ACL_EXECUTE); -} - -int has_default_other_read(const char* path) { - return has_default_tag_perm(path, ACL_OTHER, ACL_READ); -} - -int has_default_other_write(const char* path) { - return has_default_tag_perm(path, ACL_OTHER, ACL_WRITE); -} - -int has_default_other_execute(const char* path) { - return has_default_tag_perm(path, ACL_OTHER, ACL_EXECUTE); -} - -int has_default_mask_read(const char* path) { - return has_default_tag_perm(path, ACL_MASK, ACL_READ); -} - -int has_default_mask_write(const char* path) { - return has_default_tag_perm(path, ACL_MASK, ACL_WRITE); -} - -int has_default_mask_execute(const char* path) { - return has_default_tag_perm(path, ACL_MASK, ACL_EXECUTE); -} - - -int reapply_default_acl(const char* path) { - /* If this is a normal file or directory (i.e. that has just been - created), we proceed to find its parent directory which will have - a default ACL. - - Returns one for success, zero for failure (i.e. no ACL), and -1 - on unexpected errors. */ - if (path == NULL) { - return 0; - } - - if (!is_regular_file(path) && !is_directory(path)) { - return 0; - } - - /* dirname mangles its argument */ - char path_copy[PATH_MAX]; - strncpy(path_copy, path, PATH_MAX-1); - path_copy[PATH_MAX-1] = 0; - - char* parent = dirname(path_copy); - if (!is_directory(parent)) { - /* Make sure dirname() did what we think it did. */ - return 0; - } - - /* This is the original mode of path. We will simply add permissions - to it, and then later reapply the result via chmod. */ - mode_t path_mode = get_mode(path); - - if (has_default_mask_acl(parent)) { - /* The parent has an extended ACL. Extended ACLs use the mask - entry. */ - - /* For the group bits, we'll use the ACL's mask instead of the group - object bits. If the default ACL had a group entry, it should - already have propagated (but might be masked). */ - if (has_default_mask_read(parent)) { - path_mode |= S_IRGRP; - } - else { - path_mode &= ~S_IRGRP; - } - - if (has_default_mask_write(parent)) { - path_mode |= S_IWGRP; - } - else { - path_mode &= ~S_IWGRP; - } - - if (!mode_has_perm(path_mode, S_IXGRP)) { - /* The group ACL entry should already have been inherited from the - default ACL. If the source was not group executable, we want to - modify the destination so that it is not group executable - either. In the presence of ACLs, the group permissions come not - from the mode bits, but from the group:: ACL entry. So, to do - this, we remove the group::x entry. */ - remove_access_group_obj_execute(path); - } - - /* We need to determine whether or not to mask the execute - bit. This applies not only to the user/group/other entries, but - also to all other named entries. If the original file wasn't - executable, then the result probably should not be. To - determine whether or not "it was executable", we rely on the - user execute bits. Obviously this should be done before we - twiddle that bit. */ - if (has_default_mask_execute(parent)) { - if (mode_has_perm(path_mode, S_IXUSR)) { - /* This just adds the group execute bit, and doesn't actually - grant group execute permissions. */ - path_mode |= S_IXGRP; - } - } - else { - path_mode &= ~S_IXGRP; - } - - } - else { - /* It's a minimal ACL. We'll repeat for the group bits what we - already did for the owner/other bits. */ - if (has_default_group_obj_acl(parent)) { - if (has_default_group_obj_read(parent)) { - path_mode |= S_IRGRP; - } - else { - path_mode &= ~S_IRGRP; - } - - - if (has_default_group_obj_write(parent)) { - path_mode |= S_IWGRP; - } - else { - path_mode &= ~S_IWGRP; - } - - /* We don't want to set the execute bit on via the ACL unless it - was on originally. */ - if (!has_default_group_obj_execute(parent)) { - path_mode &= ~S_IXGRP; - } - } - } - - - /* If parent has a default user ACL, apply it. */ - if (has_default_user_obj_acl(parent)) { - - if (has_default_user_obj_read(parent)) { - /* Add user read. */ - path_mode |= S_IRUSR; - } - else { - /* Remove user read. */ - path_mode &= ~S_IRUSR; - } - - - if (has_default_user_obj_write(parent)) { - /* Add user write. */ - path_mode |= S_IWUSR; - } - else { - /* Remove user write. */ - path_mode &= ~S_IWUSR; - } - - - /* We don't want to set the execute bit on via the ACL unless it - was on originally. */ - if (!has_default_user_obj_execute(parent)) { - /* Remove user execute. */ - path_mode &= ~S_IXUSR; - } - } - - - /* Do the same thing with the other perms/ACL. */ - if (has_default_other_acl(parent)) { - - if (has_default_other_read(parent)) { - path_mode |= S_IROTH; - } - else { - path_mode &= ~S_IROTH; - } - - - if (has_default_other_write(parent)) { - path_mode |= S_IWOTH; - } - else { - path_mode &= ~S_IWOTH; - } - - - /* We don't want to set the execute bit on via the ACL unless it - was on originally. */ - if (!has_default_other_execute(parent)) { - path_mode &= ~S_IXOTH; - } - } - - int chmod_result = chmod(path, path_mode); - if (chmod_result == 0) { - return 1; - } - else { - return 0; - } -} - - - - -int set_acl_entry(acl_t* aclp, +int acl_set_entry(acl_t* aclp, acl_entry_t entry) { /* Update or create the given entry. */ acl_tag_t entry_tag; int gt_result = acl_get_tag_type(entry, &entry_tag); if (gt_result == -1) { - perror("set_acl_entry (acl_get_tag_type)"); + perror("acl_set_entry (acl_get_tag_type)"); return -1; } acl_permset_t entry_permset; int ps_result = acl_get_permset(entry, &entry_permset); if (ps_result == -1) { - perror("set_acl_entry (acl_get_permset)"); + perror("acl_set_entry (acl_get_permset)"); return -1; } @@ -605,69 +97,21 @@ int set_acl_entry(acl_t* aclp, } if (existing_tag == entry_tag) { - bool update_it = true; - - if (entry_tag == ACL_USER || entry_tag == ACL_GROUP) { - void* entry_qual = acl_get_qualifier(entry); - if (entry_qual == (void*)NULL) { - perror("set_acl_entry (acl_get_qualifier - entry_qual)"); - return -1; - } - - void* existing_qual = acl_get_qualifier(existing_entry); - if (existing_qual == (void*)NULL) { - perror("set_acl_entry (acl_get_qualifier - existing_qual)"); - return -1; - } - - if (entry_tag == ACL_USER) { - uid_t* u1p = (uid_t *)entry_qual; - uid_t* u2p = (uid_t *)existing_qual; - if (*u1p != *u2p) { - update_it = false; - } - } - else { - gid_t* g1p = (gid_t *)entry_qual; - gid_t* g2p = (gid_t *)existing_qual; - if (*g1p != *g2p) { - update_it = false; - } - } - - acl_free(entry_qual); - acl_free(existing_qual); - } - - if (update_it) { + if (entry_tag == ACL_USER_OBJ || + entry_tag == ACL_GROUP_OBJ || + entry_tag == ACL_OTHER) { + /* Only update for these three since all other tags will have + been wiped. */ acl_permset_t existing_permset; int gep_result = acl_get_permset(existing_entry, &existing_permset); if (gep_result == -1) { - perror("set_acl_entry (acl_get_permset)"); + perror("acl_set_entry (acl_get_permset)"); return -1; } - /* If an existing entry doesn't have its execute bits set, we - don't want to set them from a default ACL. Unless it's the - mask entry! */ - int gp_result = acl_get_perm(existing_permset, ACL_EXECUTE); - if (gp_result == -1) { - perror("set_acl_entry (acl_get_perm)"); - return -1; - } - - if (gp_result == 0 && existing_tag != ACL_MASK) { - /* It doesn't already have execute perms */ - int d_result = acl_delete_perm(entry_permset, ACL_EXECUTE); - if (d_result == -1) { - perror("set_acl_entry (acl_delete_perm)"); - return -1; - } - } - int s_result = acl_set_permset(existing_entry, entry_permset); if (s_result == -1) { - perror("set_acl_entry (acl_set_permset)"); + perror("acl_set_entry (acl_set_permset)"); return -1; } @@ -682,28 +126,30 @@ int set_acl_entry(acl_t* aclp, /* This catches both the initial acl_get_entry and the ones at the end of the loop. */ if (result == -1) { - perror("set_acl_entry (acl_get_entry)"); + perror("acl_set_entry (acl_get_entry)"); return -1; } /* If we've made it this far, we need to add a new entry to the ACL. */ acl_entry_t new_entry; + + /* We allocate memory here that we should release! */ int c_result = acl_create_entry(aclp, &new_entry); if (c_result == -1) { - perror("set_acl_entry (acl_create_entry)"); + perror("acl_set_entry (acl_create_entry)"); return -1; } int st_result = acl_set_tag_type(new_entry, entry_tag); if (st_result == -1) { - perror("set_acl_entry (acl_set_tag_type)"); + perror("acl_set_entry (acl_set_tag_type)"); return -1; } int s_result = acl_set_permset(new_entry, entry_permset); if (s_result == -1) { - perror("set_acl_entry (acl_set_permset)"); + perror("acl_set_entry (acl_set_permset)"); return -1; } @@ -711,13 +157,13 @@ int set_acl_entry(acl_t* aclp, /* We need to set the qualifier too. */ void* entry_qual = acl_get_qualifier(entry); if (entry_qual == (void*)NULL) { - perror("set_acl_entry (acl_get_qualifier)"); + perror("acl_set_entry (acl_get_qualifier)"); return -1; } int sq_result = acl_set_qualifier(new_entry, entry_qual); if (sq_result == -1) { - perror("set_acl_entry (acl_set_qualifier)"); + perror("acl_set_entry (acl_set_qualifier)"); return -1; } } @@ -727,8 +173,8 @@ int set_acl_entry(acl_t* aclp, -int acl_is_minimal(acl_t* acl) { - /* An ACL is minimal if it has fewer than four entries. */ +int acl_entry_count(acl_t* acl) { + /* Return the number of entries in ACL, or -1 on error. */ acl_entry_t entry; int entry_count = 0; int result = acl_get_entry(*acl, ACL_FIRST_ENTRY, &entry); @@ -743,7 +189,21 @@ int acl_is_minimal(acl_t* acl) { return -1; } - if (entry_count > 3) { + return entry_count; +} + + +int acl_is_minimal(acl_t* acl) { + /* An ACL is minimal if it has fewer than four entries. Return 0 for + false, 1 for true, and -1 on error. */ + + int ec = acl_entry_count(acl); + if (ec == -1) { + perror("acl_is_minimal (acl_entry_count)"); + return -1; + } + + if (ec < 4) { return 1; } else { @@ -751,58 +211,169 @@ int acl_is_minimal(acl_t* acl) { } } + int any_can_execute(const char* path) { + /* Returns 1 if any ACL entry has execute access, 0 if none do, and + -1 on error. */ acl_t acl = acl_get_file(path, ACL_TYPE_ACCESS); + if (acl == (acl_t)NULL) { + return 0; + } + + /* Our return value. */ + int result = 0; + if (acl_is_minimal(&acl)) { mode_t mode = get_mode(path); if (mode & (S_IXUSR | S_IXOTH | S_IXGRP)) { - return 1; + result = 1; + goto cleanup; } else { - return 0; + result = 0; + goto cleanup; } } - - if (acl == (acl_t)NULL) { - return 0; - } - + acl_entry_t entry; - int result = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry); + int ge_result = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry); - while (result == 1) { + while (ge_result == 1) { acl_permset_t permset; int ps_result = acl_get_permset(entry, &permset); if (ps_result == -1) { perror("any_can_execute (acl_get_permset)"); - return -1; + result = -1; + goto cleanup; } int gp_result = acl_get_perm(permset, ACL_EXECUTE); if (gp_result == -1) { perror("any_can_execute (acl_get_perm)"); - return -1; + result = -1; + goto cleanup; } if (gp_result == 1) { - return 1; + result = 1; + goto cleanup; } - result = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry); + ge_result = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry); } - if (result == -1) { + if (ge_result == -1) { perror("any_can_execute (acl_get_entry)"); + result = -1; + goto cleanup; + } + + cleanup: + acl_free(acl); + return result; +} + + +int inherit_default_acl(const char* path, const char* parent) { + /* Inherit the default ACL from parent to path. This overwrites any + existing default ACL. Returns 1 for success, 0 for failure, and + -1 on error. */ + + /* Our return value. */ + int result = 1; + + if (path == NULL) { + errno = ENOENT; + return -1; + } + + if (!is_directory(path) || !is_directory(parent)) { + return 0; + } + + acl_t parent_acl = acl_get_file(parent, ACL_TYPE_DEFAULT); + if (parent_acl == (acl_t)NULL) { + return 0; + } + + acl_t path_acl = acl_dup(parent_acl); + + if (path_acl == (acl_t)NULL) { + perror("inherit_default_acl (acl_dup)"); + acl_free(parent_acl); + return -1; + } + + int sf_result = acl_set_file(path, ACL_TYPE_DEFAULT, path_acl); + if (sf_result == -1) { + perror("inherit_default_acl (acl_set_file)"); + result = -1; + goto cleanup; + } + + cleanup: + acl_free(path_acl); + return result; +} + + +int wipe_acls(const char* path) { + /* Remove ACL_USER, ACL_GROUP, and ACL_MASK entries from + path. Returns 1 for success, 0 for failure, and -1 on error. */ + + if (path == NULL) { + errno = ENOENT; return -1; } - return 0; + /* Finally, remove individual named/mask entries. */ + acl_t acl = acl_get_file(path, ACL_TYPE_ACCESS); + if (acl == (acl_t)NULL) { + perror("wipe_acls (acl_get_file)"); + return -1; + } + + /* Our return value. */ + int result = 1; + + acl_entry_t entry; + int ge_result = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry); + + while (ge_result == 1) { + int d_result = acl_delete_entry(acl, entry); + if (d_result == -1) { + perror("wipe_acls (acl_delete_entry)"); + result = -1; + goto cleanup; + } + + ge_result = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry); + } + + /* Catches the first acl_get_entry as well as the ones at the end of + the loop. */ + if (ge_result == -1) { + perror("reapply_default_acl_ng (acl_get_entry)"); + result = -1; + goto cleanup; + } + + int sf_result = acl_set_file(path, ACL_TYPE_ACCESS, acl); + if (sf_result == -1) { + perror("wipe_acls (acl_set_file)"); + result = -1; + goto cleanup; + } + + cleanup: + acl_free(acl); + return result; } -int reapply_default_acl_ng(const char* path) { +int reapply_default_acl(const char* path) { /* Really reapply the default ACL by looping through it. Returns one for success, zero for failure (i.e. no ACL), and -1 on unexpected errors. */ @@ -834,22 +405,49 @@ int reapply_default_acl_ng(const char* path) { bool allow_exec = (bool)ace_result; acl_t defacl = acl_get_file(parent, ACL_TYPE_DEFAULT); + + if (defacl == (acl_t)NULL) { + perror("reapply_default_acl_ng (acl_get_file)"); + return -1; + } + + /* Our return value. */ + int result = 1; + + int wipe_result = wipe_acls(path); + if (wipe_result == -1) { + perror("reapply_default_acl_ng (wipe_acls)"); + result = -1; + goto cleanup; + } + + /* Do this after wipe_acls(), otherwise we'll overwrite the wiped + ACL with this one. */ acl_t acl = acl_get_file(path, ACL_TYPE_ACCESS); + if (acl == (acl_t)NULL) { + perror("reapply_default_acl_ng (acl_get_file)"); + return -1; + } - if (defacl == (acl_t)NULL || acl == (acl_t)NULL) { - return 0; + /* If it's a directory, inherit the parent's default. */ + int inherit_result = inherit_default_acl(path, parent); + if (inherit_result == -1) { + perror("reapply_default_acl_ng (inherit_acls)"); + result = -1; + goto cleanup; } acl_entry_t entry; - int result = acl_get_entry(defacl, ACL_FIRST_ENTRY, &entry); + int ge_result = acl_get_entry(defacl, ACL_FIRST_ENTRY, &entry); - while (result == 1) { + while (ge_result == 1) { acl_tag_t tag = ACL_UNDEFINED_TAG; int tag_result = acl_get_tag_type(entry, &tag); if (tag_result == -1) { perror("has_default_tag_acl (acl_get_tag_type)"); - return -1; + result = -1; + goto cleanup; } @@ -858,7 +456,8 @@ int reapply_default_acl_ng(const char* path) { int ps_result = acl_get_permset(entry, &permset); if (ps_result == -1) { perror("reapply_default_acl_ng (acl_get_permset)"); - return -1; + result = -1; + goto cleanup; } /* If this is a default mask, fix it up. */ @@ -873,41 +472,48 @@ int reapply_default_acl_ng(const char* path) { int d_result = acl_delete_perm(permset, ACL_EXECUTE); if (d_result == -1) { perror("reapply_default_acl_ng (acl_delete_perm)"); - return -1; + result = -1; + goto cleanup; } int sp_result = acl_set_permset(entry, permset); if (sp_result == -1) { perror("reapply_default_acl_ng (acl_set_permset)"); - return -1; + result = -1; + goto cleanup; } } } /* Finally, add the permset to the access ACL. */ - int set_result = set_acl_entry(&acl, entry); + int set_result = acl_set_entry(&acl, entry); if (set_result == -1) { - perror("reapply_default_acl_ng (set_acl_entry)"); - return -1; + perror("reapply_default_acl_ng (acl_set_entry)"); + result = -1; + goto cleanup; } - result = acl_get_entry(defacl, ACL_NEXT_ENTRY, &entry); + ge_result = acl_get_entry(defacl, ACL_NEXT_ENTRY, &entry); } /* Catches the first acl_get_entry as well as the ones at the end of the loop. */ - if (result == -1) { + if (ge_result == -1) { perror("reapply_default_acl_ng (acl_get_entry)"); - return -1; + result = -1; + goto cleanup; } int sf_result = acl_set_file(path, ACL_TYPE_ACCESS, acl); if (sf_result == -1) { perror("reapply_default_acl_ng (acl_set_file)"); - return -1; + result = -1; + goto cleanup; } - return 1; + cleanup: + acl_free(defacl); + return result; } @@ -915,7 +521,7 @@ int reapply_default_acl_ng(const char* path) { int main(int argc, char* argv[]) { const char* target = argv[1]; - bool result = reapply_default_acl_ng(target); + bool result = reapply_default_acl(target); if (result) { return EXIT_SUCCESS;