STATIC int linvfs_removexattr( struct dentry *dentry, const char *name) { int error; int xflags = 0; char *p = (char *)name; struct inode *inode = dentry->d_inode; vnode_t *vp = LINVFS_GET_VP(inode); if (strncmp(name, xfs_namespaces[SYSTEM_NAMES].name, xfs_namespaces[SYSTEM_NAMES].namelen) == 0) { error = -ENOATTR; p += xfs_namespaces[SYSTEM_NAMES].namelen; if (strcmp(p, POSIXACL_ACCESS) == 0) error = xfs_acl_vremove(vp, _ACL_TYPE_ACCESS); else if (strcmp(p, POSIXACL_DEFAULT) == 0) error = xfs_acl_vremove(vp, _ACL_TYPE_DEFAULT); else if (strcmp(p, POSIXCAP) == 0) error = xfs_cap_vremove(vp); return error; } if (strncmp(name, xfs_namespaces[ROOT_NAMES].name, xfs_namespaces[ROOT_NAMES].namelen) == 0) { if (!capable(CAP_SYS_ADMIN)) return -EPERM; xflags |= ATTR_ROOT; p += xfs_namespaces[ROOT_NAMES].namelen; VOP_ATTR_REMOVE(vp, p, xflags, NULL, error); return -error; } if (strncmp(name, xfs_namespaces[USER_NAMES].name, xfs_namespaces[USER_NAMES].namelen) == 0) { p += xfs_namespaces[USER_NAMES].namelen; if (!capable_user_xattr(inode)) return -EPERM; VOP_ATTR_REMOVE(vp, p, xflags, NULL, error); return -error; } return -ENOATTR; }
int xfs_acl_vset( xfs_vnode_t *vp, void *acl, size_t size, int kind) { posix_acl_xattr_header *ext_acl = acl; xfs_acl_t *xfs_acl; int error; int basicperms = 0; /* more than std unix perms? */ if (!acl) return -EINVAL; if (!(_ACL_ALLOC(xfs_acl))) return -ENOMEM; error = posix_acl_xattr_to_xfs(ext_acl, size, xfs_acl); if (error) { _ACL_FREE(xfs_acl); return -error; } if (!xfs_acl->acl_cnt) { _ACL_FREE(xfs_acl); return 0; } VN_HOLD(vp); error = xfs_acl_allow_set(vp, kind); if (error) goto out; /* Incoming ACL exists, set file mode based on its value */ if (kind == _ACL_TYPE_ACCESS) xfs_acl_setmode(vp, xfs_acl, &basicperms); /* * If we have more than std unix permissions, set up the actual attr. * Otherwise, delete any existing attr. This prevents us from * having actual attrs for permissions that can be stored in the * standard permission bits. */ if (!basicperms) { xfs_acl_set_attr(vp, xfs_acl, kind, &error); } else { xfs_acl_vremove(vp, _ACL_TYPE_ACCESS); } out: VN_RELE(vp); _ACL_FREE(xfs_acl); return -error; }