- $Id: acls.c,v 1.6 2009-11-26 18:17:12 franklahm Exp $
- Copyright (c) 2008,2009 Frank Lahm <franklahm@gmail.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- */
+ $Id: acls.c,v 1.7 2009-11-28 13:06:30 franklahm Exp $
+ Copyright (c) 2008,2009 Frank Lahm <franklahm@gmail.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+*/
- LOG(log_debug7, logtype_afpd, "map_aces_solaris_to_darwin: parsing ACE No. %d", ace_count + 1);
- /* if its a ACE resulting from nfsv4 mode mapping, discard it */
- if (aces->a_flags & (ACE_OWNER | ACE_GROUP | ACE_EVERYONE)) {
- LOG(log_debug, logtype_afpd, "map_aces_solaris_to_darwin: trivial ACE");
- aces++;
- continue;
- }
-
- if ( ! (aces->a_flags & ACE_IDENTIFIER_GROUP) ) {
- /* its a user ace */
- LOG(log_debug, logtype_afpd, "map_aces_solaris_to_darwin: found user ACE with uid: %d", aces->a_who);
- pwd = getpwuid(aces->a_who);
- if (!pwd) {
- LOG(log_error, logtype_afpd, "map_aces_solaris_to_darwin: getpwuid error: %s", strerror(errno));
- return -1;
- }
- LOG(log_debug, logtype_afpd, "map_aces_solaris_to_darwin: uid: %d -> name: %s", aces->a_who, pwd->pw_name);
- if ( (getuuidfromname(pwd->pw_name, UUID_USER, darwin_aces->darwin_ace_uuid)) != 0) {
- LOG(log_error, logtype_afpd, "map_aces_solaris_to_darwin: getuuidfromname error");
- return -1;
- }
- } else {
- /* its a group ace */
- LOG(log_debug, logtype_afpd, "map_aces_solaris_to_darwin: found group ACE with gid: %d", aces->a_who);
- grp = getgrgid(aces->a_who);
- if (!grp) {
- LOG(log_error, logtype_afpd, "map_aces_solaris_to_darwin: getgrgid error: %s", strerror(errno));
- return -1;
- }
- LOG(log_debug, logtype_afpd, "map_aces_solaris_to_darwin: gid: %d -> name: %s", aces->a_who, grp->gr_name);
- if ( (getuuidfromname(grp->gr_name, UUID_GROUP, darwin_aces->darwin_ace_uuid)) != 0) {
- LOG(log_error, logtype_afpd, "map_aces_solaris_to_darwin: getuuidfromname error");
- return -1;
- }
- }
-
- /* map flags */
- if (aces->a_type == ACE_ACCESS_ALLOWED_ACE_TYPE)
- flags = DARWIN_ACE_FLAGS_PERMIT;
- else if (aces->a_type == ACE_ACCESS_DENIED_ACE_TYPE)
- flags = DARWIN_ACE_FLAGS_DENY;
- else { /* unsupported type */
- aces++;
- continue;
- }
- for(i=0; nfsv4_to_darwin_flags[i].from != 0; i++) {
- if (aces->a_flags & nfsv4_to_darwin_flags[i].from)
- flags |= nfsv4_to_darwin_flags[i].to;
- }
- darwin_aces->darwin_ace_flags = htonl(flags);
-
- /* map rights */
- rights = 0;
- for (i=0; nfsv4_to_darwin_rights[i].from != 0; i++) {
- if (aces->a_access_mask & nfsv4_to_darwin_rights[i].from)
- rights |= nfsv4_to_darwin_rights[i].to;
- }
- darwin_aces->darwin_ace_rights = htonl(rights);
-
- count++;
- aces++;
- darwin_aces++;
+ LOG(log_debug7, logtype_afpd, "map_aces_solaris_to_darwin: parsing ACE No. %d", ace_count + 1);
+ /* if its a ACE resulting from nfsv4 mode mapping, discard it */
+ if (aces->a_flags & (ACE_OWNER | ACE_GROUP | ACE_EVERYONE)) {
+ LOG(log_debug, logtype_afpd, "map_aces_solaris_to_darwin: trivial ACE");
+ aces++;
+ continue;
+ }
+
+ if ( ! (aces->a_flags & ACE_IDENTIFIER_GROUP) ) {
+ /* its a user ace */
+ LOG(log_debug, logtype_afpd, "map_aces_solaris_to_darwin: found user ACE with uid: %d", aces->a_who);
+ pwd = getpwuid(aces->a_who);
+ if (!pwd) {
+ LOG(log_error, logtype_afpd, "map_aces_solaris_to_darwin: getpwuid error: %s", strerror(errno));
+ return -1;
+ }
+ LOG(log_debug, logtype_afpd, "map_aces_solaris_to_darwin: uid: %d -> name: %s", aces->a_who, pwd->pw_name);
+ if ( (getuuidfromname(pwd->pw_name, UUID_USER, darwin_aces->darwin_ace_uuid)) != 0) {
+ LOG(log_error, logtype_afpd, "map_aces_solaris_to_darwin: getuuidfromname error");
+ return -1;
+ }
+ } else {
+ /* its a group ace */
+ LOG(log_debug, logtype_afpd, "map_aces_solaris_to_darwin: found group ACE with gid: %d", aces->a_who);
+ grp = getgrgid(aces->a_who);
+ if (!grp) {
+ LOG(log_error, logtype_afpd, "map_aces_solaris_to_darwin: getgrgid error: %s", strerror(errno));
+ return -1;
+ }
+ LOG(log_debug, logtype_afpd, "map_aces_solaris_to_darwin: gid: %d -> name: %s", aces->a_who, grp->gr_name);
+ if ( (getuuidfromname(grp->gr_name, UUID_GROUP, darwin_aces->darwin_ace_uuid)) != 0) {
+ LOG(log_error, logtype_afpd, "map_aces_solaris_to_darwin: getuuidfromname error");
+ return -1;
+ }
+ }
+
+ /* map flags */
+ if (aces->a_type == ACE_ACCESS_ALLOWED_ACE_TYPE)
+ flags = DARWIN_ACE_FLAGS_PERMIT;
+ else if (aces->a_type == ACE_ACCESS_DENIED_ACE_TYPE)
+ flags = DARWIN_ACE_FLAGS_DENY;
+ else { /* unsupported type */
+ aces++;
+ continue;
+ }
+ for(i=0; nfsv4_to_darwin_flags[i].from != 0; i++) {
+ if (aces->a_flags & nfsv4_to_darwin_flags[i].from)
+ flags |= nfsv4_to_darwin_flags[i].to;
+ }
+ darwin_aces->darwin_ace_flags = htonl(flags);
+
+ /* map rights */
+ rights = 0;
+ for (i=0; nfsv4_to_darwin_rights[i].from != 0; i++) {
+ if (aces->a_access_mask & nfsv4_to_darwin_rights[i].from)
+ rights |= nfsv4_to_darwin_rights[i].to;
+ }
+ darwin_aces->darwin_ace_rights = htonl(rights);
+
+ count++;
+ aces++;
+ darwin_aces++;
- nfsv4_ace_flags = 0;
- nfsv4_ace_rights = 0;
-
- /* uid/gid first */
- if ( (getnamefromuuid(darwin_aces->darwin_ace_uuid, &name, &uuidtype)) != 0)
- return -1;
- if (uuidtype == UUID_USER) {
- pwd = getpwnam(name);
- if (!pwd) {
- LOG(log_error, logtype_afpd, "map_aces_darwin_to_solaris: getpwnam: %s", strerror(errno));
- return -1;
- }
- nfsv4_aces->a_who = pwd->pw_uid;
- } else { /* hopefully UUID_GROUP*/
- grp = getgrnam(name);
- if (!grp) {
- LOG(log_error, logtype_afpd, "map_aces_darwin_to_solaris: getgrnam: %s", strerror(errno));
- return -1;
- }
- nfsv4_aces->a_who = (uid_t)(grp->gr_gid);
- nfsv4_ace_flags |= ACE_IDENTIFIER_GROUP;
- }
- free(name);
- name = NULL;
-
- /* now type: allow/deny */
- darwin_ace_flags = ntohl(darwin_aces->darwin_ace_flags);
- if (darwin_ace_flags & DARWIN_ACE_FLAGS_PERMIT)
- nfsv4_aces->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
- else if (darwin_ace_flags & DARWIN_ACE_FLAGS_DENY)
- nfsv4_aces->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
- else { /* unsupported type */
- darwin_aces++;
- continue;
- }
- /* map flags */
- for(i=0; darwin_to_nfsv4_flags[i].from != 0; i++) {
- if (darwin_ace_flags & darwin_to_nfsv4_flags[i].from)
- nfsv4_ace_flags |= darwin_to_nfsv4_flags[i].to;
- }
-
- /* map rights */
- darwin_ace_rights = ntohl(darwin_aces->darwin_ace_rights);
- for (i=0; darwin_to_nfsv4_rights[i].from != 0; i++) {
- if (darwin_ace_rights & darwin_to_nfsv4_rights[i].from)
- nfsv4_ace_rights |= darwin_to_nfsv4_rights[i].to;
- }
-
- LOG(log_debug9, logtype_afpd, "map_aces_darwin_to_solaris: ACE flags: Darwin:%08x -> NFSv4:%04x", darwin_ace_flags, nfsv4_ace_flags);
- LOG(log_debug9, logtype_afpd, "map_aces_darwin_to_solaris: ACE rights: Darwin:%08x -> NFSv4:%08x", darwin_ace_rights, nfsv4_ace_rights);
-
- nfsv4_aces->a_flags = nfsv4_ace_flags;
- nfsv4_aces->a_access_mask = nfsv4_ace_rights;
-
- mapped_aces++;
- darwin_aces++;
- nfsv4_aces++;
+ nfsv4_ace_flags = 0;
+ nfsv4_ace_rights = 0;
+
+ /* uid/gid first */
+ if ( (getnamefromuuid(darwin_aces->darwin_ace_uuid, &name, &uuidtype)) != 0)
+ return -1;
+ if (uuidtype == UUID_USER) {
+ pwd = getpwnam(name);
+ if (!pwd) {
+ LOG(log_error, logtype_afpd, "map_aces_darwin_to_solaris: getpwnam: %s", strerror(errno));
+ return -1;
+ }
+ nfsv4_aces->a_who = pwd->pw_uid;
+ } else { /* hopefully UUID_GROUP*/
+ grp = getgrnam(name);
+ if (!grp) {
+ LOG(log_error, logtype_afpd, "map_aces_darwin_to_solaris: getgrnam: %s", strerror(errno));
+ return -1;
+ }
+ nfsv4_aces->a_who = (uid_t)(grp->gr_gid);
+ nfsv4_ace_flags |= ACE_IDENTIFIER_GROUP;
+ }
+ free(name);
+ name = NULL;
+
+ /* now type: allow/deny */
+ darwin_ace_flags = ntohl(darwin_aces->darwin_ace_flags);
+ if (darwin_ace_flags & DARWIN_ACE_FLAGS_PERMIT)
+ nfsv4_aces->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
+ else if (darwin_ace_flags & DARWIN_ACE_FLAGS_DENY)
+ nfsv4_aces->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
+ else { /* unsupported type */
+ darwin_aces++;
+ continue;
+ }
+ /* map flags */
+ for(i=0; darwin_to_nfsv4_flags[i].from != 0; i++) {
+ if (darwin_ace_flags & darwin_to_nfsv4_flags[i].from)
+ nfsv4_ace_flags |= darwin_to_nfsv4_flags[i].to;
+ }
+
+ /* map rights */
+ darwin_ace_rights = ntohl(darwin_aces->darwin_ace_rights);
+ for (i=0; darwin_to_nfsv4_rights[i].from != 0; i++) {
+ if (darwin_ace_rights & darwin_to_nfsv4_rights[i].from)
+ nfsv4_ace_rights |= darwin_to_nfsv4_rights[i].to;
+ }
+
+ LOG(log_debug9, logtype_afpd, "map_aces_darwin_to_solaris: ACE flags: Darwin:%08x -> NFSv4:%04x", darwin_ace_flags, nfsv4_ace_flags);
+ LOG(log_debug9, logtype_afpd, "map_aces_darwin_to_solaris: ACE rights: Darwin:%08x -> NFSv4:%08x", darwin_ace_rights, nfsv4_ace_rights);
+
+ nfsv4_aces->a_flags = nfsv4_ace_flags;
+ nfsv4_aces->a_access_mask = nfsv4_ace_rights;
+
+ mapped_aces++;
+ darwin_aces++;
+ nfsv4_aces++;
- pwd = getpwnam(username);
- if (!pwd) {
- LOG(log_error, logtype_afpd, "check_access: getpwnam: %s", strerror(errno));
- ret = AFPERR_MISC;
- goto exit;
- }
- uid = pwd->pw_uid;
- pgid = pwd->pw_gid;
-
- /* If user is file/dir owner we must check the user trivial ACE */
- if (uid == st.st_uid) {
- LOG(log_debug, logtype_afpd, "check_access: user: %s is files owner. Must check trivial user ACE", username);
- check_user_trivace = 1;
- }
-
- /* Now check if requested user is files owning group. If yes we must check the group trivial ACE */
- if ( (check_group(username, uid, pgid, st.st_gid)) == 0) {
- LOG(log_debug, logtype_afpd, "check_access: user: %s is in group: %d. Must check trivial group ACE", username, st.st_gid);
- check_group_trivace = 1;
- }
+ pwd = getpwnam(username);
+ if (!pwd) {
+ LOG(log_error, logtype_afpd, "check_access: getpwnam: %s", strerror(errno));
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+ uid = pwd->pw_uid;
+ pgid = pwd->pw_gid;
+
+ /* If user is file/dir owner we must check the user trivial ACE */
+ if (uid == st.st_uid) {
+ LOG(log_debug, logtype_afpd, "check_access: user: %s is files owner. Must check trivial user ACE", username);
+ check_user_trivace = 1;
+ }
+
+ /* Now check if requested user is files owning group. If yes we must check the group trivial ACE */
+ if ( (check_group(username, uid, pgid, st.st_gid)) == 0) {
+ LOG(log_debug, logtype_afpd, "check_access: user: %s is in group: %d. Must check trivial group ACE", username, st.st_gid);
+ check_group_trivace = 1;
+ }
- who = aces[i].a_who;
- flags = aces[i].a_flags;
- type = aces[i].a_type;
- rights = aces[i].a_access_mask;
-
- if (flags & ACE_INHERIT_ONLY_ACE)
- continue;
-
- /* Check if its a group ACE and set checkgroup to 1 if yes */
- checkgroup = 0;
- if ( (flags & ACE_IDENTIFIER_GROUP) && !(flags & ACE_GROUP) ) {
- if ( (check_group(username, uid, pgid, who)) == 0)
- checkgroup = 1;
- else
- continue;
- }
-
- /* Now the tricky part: decide if ACE effects our user. I'll explain:
- if its a dedicated (non trivial) ACE for the user
- OR
- if its a ACE for a group we're member of
- OR
- if its a trivial ACE_OWNER ACE and requested UUID is the owner
- OR
- if its a trivial ACE_GROUP ACE and requested UUID is group
- OR
- if its a trivial ACE_EVERYONE ACE
- THEN
- process ACE */
- if (
- ( (who == uid) && !(flags & (ACE_TRIVIAL|ACE_IDENTIFIER_GROUP)) ) ||
- (checkgroup) ||
- ( (flags & ACE_OWNER) && check_user_trivace ) ||
- ( (flags & ACE_GROUP) && check_group_trivace ) ||
- ( flags & ACE_EVERYONE )
- ) {
- /* Found an applicable ACE */
- if (type == ACE_ACCESS_ALLOWED_ACE_TYPE)
- allowed_rights |= rights;
- else if (type == ACE_ACCESS_DENIED_ACE_TYPE)
- /* Only or to denied rights if not previously allowed !! */
- denied_rights |= ((!allowed_rights) & rights);
- }
+ who = aces[i].a_who;
+ flags = aces[i].a_flags;
+ type = aces[i].a_type;
+ rights = aces[i].a_access_mask;
+
+ if (flags & ACE_INHERIT_ONLY_ACE)
+ continue;
+
+ /* Check if its a group ACE and set checkgroup to 1 if yes */
+ checkgroup = 0;
+ if ( (flags & ACE_IDENTIFIER_GROUP) && !(flags & ACE_GROUP) ) {
+ if ( (check_group(username, uid, pgid, who)) == 0)
+ checkgroup = 1;
+ else
+ continue;
+ }
+
+ /* Now the tricky part: decide if ACE effects our user. I'll explain:
+ if its a dedicated (non trivial) ACE for the user
+ OR
+ if its a ACE for a group we're member of
+ OR
+ if its a trivial ACE_OWNER ACE and requested UUID is the owner
+ OR
+ if its a trivial ACE_GROUP ACE and requested UUID is group
+ OR
+ if its a trivial ACE_EVERYONE ACE
+ THEN
+ process ACE */
+ if (
+ ( (who == uid) && !(flags & (ACE_TRIVIAL|ACE_IDENTIFIER_GROUP)) ) ||
+ (checkgroup) ||
+ ( (flags & ACE_OWNER) && check_user_trivace ) ||
+ ( (flags & ACE_GROUP) && check_group_trivace ) ||
+ ( flags & ACE_EVERYONE )
+ ) {
+ /* Found an applicable ACE */
+ if (type == ACE_ACCESS_ALLOWED_ACE_TYPE)
+ allowed_rights |= rights;
+ else if (type == ACE_ACCESS_DENIED_ACE_TYPE)
+ /* Only or to denied rights if not previously allowed !! */
+ denied_rights |= ((!allowed_rights) & rights);
+ }
- LOG(log_debug, logtype_afpd, "afp_getacl: client requested files owner user UUID");
- if (NULL == (pw = getpwuid(s_path->st.st_uid)))
- return AFPERR_MISC;
- LOG(log_debug, logtype_afpd, "afp_getacl: got uid: %d, name: %s", s_path->st.st_uid, pw->pw_name);
- if ((ret = getuuidfromname(pw->pw_name, UUID_USER, rbuf)) != 0)
- return AFPERR_MISC;
- rbuf += UUID_BINSIZE;
- *rbuflen += UUID_BINSIZE;
- }
+ LOG(log_debug, logtype_afpd, "afp_getacl: client requested files owner user UUID");
+ if (NULL == (pw = getpwuid(s_path->st.st_uid)))
+ return AFPERR_MISC;
+ LOG(log_debug, logtype_afpd, "afp_getacl: got uid: %d, name: %s", s_path->st.st_uid, pw->pw_name);
+ if ((ret = getuuidfromname(pw->pw_name, UUID_USER, rbuf)) != 0)
+ return AFPERR_MISC;
+ rbuf += UUID_BINSIZE;
+ *rbuflen += UUID_BINSIZE;
+ }
- LOG(log_debug, logtype_afpd, "afp_getacl: client requested files owner group UUID");
- if (NULL == (gr = getgrgid(s_path->st.st_gid)))
- return AFPERR_MISC;
- LOG(log_debug, logtype_afpd, "afp_getacl: got gid: %d, name: %s", s_path->st.st_gid, gr->gr_name);
- if ((ret = getuuidfromname(gr->gr_name, UUID_GROUP, rbuf)) != 0)
- return AFPERR_MISC;
- rbuf += UUID_BINSIZE;
- *rbuflen += UUID_BINSIZE;
- }
+ LOG(log_debug, logtype_afpd, "afp_getacl: client requested files owner group UUID");
+ if (NULL == (gr = getgrgid(s_path->st.st_gid)))
+ return AFPERR_MISC;
+ LOG(log_debug, logtype_afpd, "afp_getacl: got gid: %d, name: %s", s_path->st.st_gid, gr->gr_name);
+ if ((ret = getuuidfromname(gr->gr_name, UUID_GROUP, rbuf)) != 0)
+ return AFPERR_MISC;
+ rbuf += UUID_BINSIZE;
+ *rbuflen += UUID_BINSIZE;
+ }
- LOG(log_debug, logtype_afpd, "afp_setacl: Change ACL request.");
-
- /* Check if its our job to preserve inherited ACEs */
- if (bitmap & kFileSec_Inherit)
- ret = set_acl_vfs(vol, s_path->u_name, 1, ibuf);
- else
- ret = set_acl_vfs(vol, s_path->u_name, 0, ibuf);
- if (ret == 0)
- ret = AFP_OK;
- else
- ret = AFPERR_MISC;
+ LOG(log_debug, logtype_afpd, "afp_setacl: Change ACL request.");
+
+ /* Check if its our job to preserve inherited ACEs */
+ if (bitmap & kFileSec_Inherit)
+ ret = set_acl_vfs(vol, s_path->u_name, 1, ibuf);
+ else
+ ret = set_acl_vfs(vol, s_path->u_name, 0, ibuf);
+ if (ret == 0)
+ ret = AFP_OK;
+ else
+ ret = AFPERR_MISC;
- if ((diracecount = get_nfsv4_acl(".", &diraces)) <= 0)
- goto cleanup;
- /* Remove any trivial ACE from "." */
- if ((diracecount = strip_trivial_aces(&diraces, diracecount)) <= 0)
- goto cleanup;
-
- /*
- Inherit to ".AppleDouble"
- */
-
- if ((adacecount = get_nfsv4_acl(".AppleDouble", &adaces)) <= 0)
- goto cleanup;
- /* Remove any non-trivial ACE from ".AppleDouble" */
- if ((adacecount = strip_nontrivial_aces(&adaces, adacecount)) <= 0)
- goto cleanup;
-
- /* Combine ACEs */
- if ((combinedaces = concat_aces(diraces, diracecount, adaces, adacecount)) == NULL)
- goto cleanup;
-
- /* Now set new acl */
- if ((acl(".AppleDouble", ACE_SETACL, diracecount + adacecount, combinedaces)) != 0)
- LOG(log_error, logtype_afpd, "addir_inherit_acl: acl: %s", strerror(errno));
-
- free(adaces);
- adaces = NULL;
- free(combinedaces);
- combinedaces = NULL;
-
- /*
- Inherit to ".AppleDouble/.Parent"
- */
-
- if ((adacecount = get_nfsv4_acl(".AppleDouble/.Parent", &adaces)) <= 0)
- goto cleanup;
- if ((adacecount = strip_nontrivial_aces(&adaces, adacecount)) <= 0)
- goto cleanup;
-
- /* Combine ACEs */
- if ((combinedaces = concat_aces(diraces, diracecount, adaces, adacecount)) == NULL)
- goto cleanup;
-
- /* Now set new acl */
- if ((acl(".AppleDouble/.Parent", ACE_SETACL, diracecount + adacecount, combinedaces)) != 0)
- LOG(log_error, logtype_afpd, "addir_inherit_acl: acl: %s", strerror(errno));
+ if ((diracecount = get_nfsv4_acl(".", &diraces)) <= 0)
+ goto cleanup;
+ /* Remove any trivial ACE from "." */
+ if ((diracecount = strip_trivial_aces(&diraces, diracecount)) <= 0)
+ goto cleanup;
+
+ /*
+ Inherit to ".AppleDouble"
+ */
+
+ if ((adacecount = get_nfsv4_acl(".AppleDouble", &adaces)) <= 0)
+ goto cleanup;
+ /* Remove any non-trivial ACE from ".AppleDouble" */
+ if ((adacecount = strip_nontrivial_aces(&adaces, adacecount)) <= 0)
+ goto cleanup;
+
+ /* Combine ACEs */
+ if ((combinedaces = concat_aces(diraces, diracecount, adaces, adacecount)) == NULL)
+ goto cleanup;
+
+ /* Now set new acl */
+ if ((acl(".AppleDouble", ACE_SETACL, diracecount + adacecount, combinedaces)) != 0)
+ LOG(log_error, logtype_afpd, "addir_inherit_acl: acl: %s", strerror(errno));
+
+ free(adaces);
+ adaces = NULL;
+ free(combinedaces);
+ combinedaces = NULL;
+
+ /*
+ Inherit to ".AppleDouble/.Parent"
+ */
+
+ if ((adacecount = get_nfsv4_acl(".AppleDouble/.Parent", &adaces)) <= 0)
+ goto cleanup;
+ if ((adacecount = strip_nontrivial_aces(&adaces, adacecount)) <= 0)
+ goto cleanup;
+
+ /* Combine ACEs */
+ if ((combinedaces = concat_aces(diraces, diracecount, adaces, adacecount)) == NULL)
+ goto cleanup;
+
+ /* Now set new acl */
+ if ((acl(".AppleDouble/.Parent", ACE_SETACL, diracecount + adacecount, combinedaces)) != 0)
+ LOG(log_error, logtype_afpd, "addir_inherit_acl: acl: %s", strerror(errno));