struct nfs4_acl * nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl, unsigned int flags) { struct nfs4_acl *acl; int size = 0; if (pacl) { if (posix_acl_valid(pacl) < 0) return ERR_PTR(-EINVAL); size += 2*pacl->a_count; } if (dpacl) { if (posix_acl_valid(dpacl) < 0) return ERR_PTR(-EINVAL); size += 2*dpacl->a_count; } /* Allocate for worst case: one (deny, allow) pair each: */ acl = nfs4_acl_new(size); if (acl == NULL) return ERR_PTR(-ENOMEM); if (pacl) _posix_to_nfsv4_one(pacl, acl, flags & ~NFS4_ACL_TYPE_DEFAULT); if (dpacl) _posix_to_nfsv4_one(dpacl, acl, flags | NFS4_ACL_TYPE_DEFAULT); return acl; }
int nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_acl **acl) { struct inode *inode = dentry->d_inode; int error = 0; struct posix_acl *pacl = NULL, *dpacl = NULL; unsigned int flags = 0; int size = 0; pacl = get_acl(inode, ACL_TYPE_ACCESS); if (!pacl) { pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL); if (IS_ERR(pacl)) return PTR_ERR(pacl); /* allocate for worst case: one (deny, allow) pair each: */ size += 2 * pacl->a_count; } if (S_ISDIR(inode->i_mode)) { flags = NFS4_ACL_DIR; dpacl = get_acl(inode, ACL_TYPE_DEFAULT); if (dpacl) size += 2 * dpacl->a_count; } else { dpacl = NULL; } *acl = nfs4_acl_new(size); if (*acl == NULL) { error = -ENOMEM; goto out; } if (pacl) _posix_to_nfsv4_one(pacl, *acl, flags & ~NFS4_ACL_TYPE_DEFAULT); if (dpacl) _posix_to_nfsv4_one(dpacl, *acl, flags | NFS4_ACL_TYPE_DEFAULT); out: posix_acl_release(pacl); posix_acl_release(dpacl); return error; }