ssize_t nfs3_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size) { struct inode *inode = dentry->d_inode; struct posix_acl *acl; int type, error = 0; if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0) type = ACL_TYPE_ACCESS; else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0) type = ACL_TYPE_DEFAULT; else return -EOPNOTSUPP; acl = nfs3_proc_getacl(inode, type); if (IS_ERR(acl)) return PTR_ERR(acl); else if (acl) { if (type == ACL_TYPE_ACCESS && acl->a_count == 0) error = -ENODATA; else error = posix_acl_to_xattr(acl, buffer, size); posix_acl_release(acl); } else error = -ENODATA; return error; }
int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode, mode_t mode) { struct posix_acl *dfacl, *acl; int error = 0; dfacl = nfs3_proc_getacl(dir, ACL_TYPE_DEFAULT); if (IS_ERR(dfacl)) { error = PTR_ERR(dfacl); return (error == -EOPNOTSUPP) ? 0 : error; } if (!dfacl) return 0; acl = posix_acl_clone(dfacl, GFP_KERNEL); error = -ENOMEM; if (!acl) goto out_release_dfacl; error = posix_acl_create_masq(acl, &mode); if (error < 0) goto out_release_acl; error = nfs3_proc_setacls(inode, acl, S_ISDIR(inode->i_mode) ? dfacl : NULL); out_release_acl: posix_acl_release(acl); out_release_dfacl: posix_acl_release(dfacl); return error; }
int nfs3_proc_setacl(struct inode *inode, int type, struct posix_acl *acl) { struct posix_acl *alloc = NULL, *dfacl = NULL; int status; if (S_ISDIR(inode->i_mode)) { switch(type) { case ACL_TYPE_ACCESS: alloc = dfacl = nfs3_proc_getacl(inode, ACL_TYPE_DEFAULT); if (IS_ERR(alloc)) goto fail; break; case ACL_TYPE_DEFAULT: dfacl = acl; alloc = acl = nfs3_proc_getacl(inode, ACL_TYPE_ACCESS); if (IS_ERR(alloc)) goto fail; break; default: return -EINVAL; } } else if (type != ACL_TYPE_ACCESS) return -EINVAL; if (acl == NULL) { alloc = acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL); if (IS_ERR(alloc)) goto fail; } status = nfs3_proc_setacls(inode, acl, dfacl); posix_acl_release(alloc); return status; fail: return PTR_ERR(alloc); }
ssize_t nfs3_listxattr(struct dentry *dentry, char *buffer, size_t size) { struct inode *inode = dentry->d_inode; struct posix_acl *acl; int pos=0, len=0; # define output(s) do { \ if (pos + sizeof(s) <= size) { \ memcpy(buffer + pos, s, sizeof(s)); \ pos += sizeof(s); \ } \ len += sizeof(s); \ } while(0) acl = nfs3_proc_getacl(inode, ACL_TYPE_ACCESS); if (IS_ERR(acl)) return PTR_ERR(acl); if (acl) { output("system.posix_acl_access"); posix_acl_release(acl); } if (S_ISDIR(inode->i_mode)) { acl = nfs3_proc_getacl(inode, ACL_TYPE_DEFAULT); if (IS_ERR(acl)) return PTR_ERR(acl); if (acl) { output("system.posix_acl_default"); posix_acl_release(acl); } } # undef output if (!buffer || len <= size) return len; return -ERANGE; }