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; }
static int ocfs2_xattr_set_acl(struct dentry *dentry, const char *name, const void *value, size_t size, int flags, int type) { struct inode *inode = dentry->d_inode; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); struct posix_acl *acl; int ret = 0; if (strcmp(name, "") != 0) return -EINVAL; if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) return -EOPNOTSUPP; if (!inode_owner_or_capable(inode)) return -EPERM; if (value) { acl = posix_acl_from_xattr(&init_user_ns, value, size); if (IS_ERR(acl)) return PTR_ERR(acl); else if (acl) { ret = posix_acl_valid(acl); if (ret) goto cleanup; } } else acl = NULL; ret = ocfs2_set_acl(NULL, inode, NULL, type, acl, NULL, NULL); cleanup: posix_acl_release(acl); return ret; }
static int jffs2_acl_setxattr(struct inode *inode, int type, const void *value, size_t size) { struct posix_acl *acl; int rc; if (!is_owner_or_cap(inode)) return -EPERM; if (value) { acl = posix_acl_from_xattr(value, size); if (IS_ERR(acl)) return PTR_ERR(acl); if (acl) { rc = posix_acl_valid(acl); if (rc) goto out; } } else { acl = NULL; } rc = jffs2_set_acl(inode, type, acl); out: posix_acl_release(acl); return rc; }
static int xattr_set_acl(struct inode *inode, int type, const void *value, size_t size) { struct posix_acl *acl; int error; if (!reiserfs_posixacl(inode->i_sb)) return -EOPNOTSUPP; if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) return -EPERM; if (value) { acl = posix_acl_from_xattr(value, size); if (IS_ERR(acl)) { return PTR_ERR(acl); } else if (acl) { error = posix_acl_valid(acl); if (error) goto release_and_out; } } else acl = NULL; error = reiserfs_set_acl (inode, type, acl); release_and_out: posix_acl_release(acl); return error; }
static int ext2_xattr_set_acl(struct inode *inode, int type, const void *value, size_t size) { struct posix_acl *acl; int error; if (!test_opt(inode->i_sb, POSIX_ACL)) return -EOPNOTSUPP; if (!is_owner_or_cap(inode)) return -EPERM; if (value) { acl = posix_acl_from_xattr(value, size); if (IS_ERR(acl)) return PTR_ERR(acl); else if (acl) { error = posix_acl_valid(acl); if (error) goto release_and_out; } } else acl = NULL; error = ext2_set_acl(inode, type, acl); release_and_out: posix_acl_release(acl); return error; }
static int btrfs_xattr_acl_set(struct dentry *dentry, const char *name, const void *value, size_t size, int flags, int type) { int ret; struct posix_acl *acl = NULL; if (!inode_owner_or_capable(dentry->d_inode)) return -EPERM; if (!IS_POSIXACL(dentry->d_inode)) return -EOPNOTSUPP; if (value) { acl = posix_acl_from_xattr(&init_user_ns, value, size); if (IS_ERR(acl)) return PTR_ERR(acl); if (acl) { ret = posix_acl_valid(acl); if (ret) goto out; } } ret = btrfs_set_acl(NULL, dentry->d_inode, acl, type); out: posix_acl_release(acl); return ret; }
static int jffs2_acl_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags, int type) { struct posix_acl *acl; int rc; if (name[0] != '\0') return -EINVAL; if (!inode_owner_or_capable(dentry->d_inode)) return -EPERM; if (value) { acl = posix_acl_from_xattr(value, size); if (IS_ERR(acl)) return PTR_ERR(acl); if (acl) { rc = posix_acl_valid(acl); if (rc) goto out; } } else { acl = NULL; } rc = jffs2_set_acl(dentry->d_inode, type, acl); out: posix_acl_release(acl); return rc; }
static int f2fs_xattr_set_acl(struct dentry *dentry, const char *name, const void *value, size_t size, int flags, int type) { struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb); struct inode *inode = dentry->d_inode; struct posix_acl *acl = NULL; int error; if (strcmp(name, "") != 0) return -EINVAL; if (!test_opt(sbi, POSIX_ACL)) return -EOPNOTSUPP; if (!inode_owner_or_capable(inode)) return -EPERM; if (value) { acl = posix_acl_from_xattr(&init_user_ns, value, size); if (IS_ERR(acl)) return PTR_ERR(acl); if (acl) { error = posix_acl_valid(acl); if (error) goto release_and_out; } } else { acl = NULL; } error = f2fs_set_acl(inode, type, acl, NULL); release_and_out: posix_acl_release(acl); return error; }
static int pvfs2_xattr_set_acl(struct inode *inode, int type, const void *value, size_t size) { struct posix_acl *acl; int error; #ifdef HAVE_CURRENT_FSUID int fsuid = current_fsuid(); #else int fsuid = current->fsuid; #endif gossip_debug(GOSSIP_ACL_DEBUG, "pvfs2_xattr_set_acl called with size %ld\n", (long)size); /* if we have not been mounted with acl option, ignore this */ if (get_acl_flag(inode) == 0) { gossip_debug(GOSSIP_ACL_DEBUG, "pvfs2_xattr_set_acl: ACL options " "disabled on this FS!\n"); return -EOPNOTSUPP; } /* Are we capable of setting acls on a file for which we should not be? */ if ((fsuid != inode->i_uid) && !capable(CAP_FOWNER)) { gossip_err("pvfs2_xattr_set_acl: operation not permitted " "(current->fsuid %d), (inode->owner %d)\n", fsuid, inode->i_uid); return -EPERM; } if (value) { acl = posix_acl_from_xattr(value, size); if (IS_ERR(acl)) { error = PTR_ERR(acl); gossip_err("pvfs2_xattr_set_acl: posix_acl_from_xattr returned " "error %d\n", error); goto err; } else if (acl) { error = posix_acl_valid(acl); if (error) { gossip_err("pvfs2_xattr_set_acl: posix_acl_valid returned " "error %d\n", error); goto out; } } } else { acl = NULL; } error = pvfs2_set_acl(inode, type, acl); gossip_debug(GOSSIP_ACL_DEBUG, "pvfs2_set_acl returned error %d\n", error); out: posix_acl_release(acl); err: return error; }
static int ocfs2_xattr_set_acl(struct inode *inode, int type, const void *value, size_t size) { struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); struct posix_acl *acl; int ret = 0; if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) return -EOPNOTSUPP; if (!is_owner_or_cap(inode)) return -EPERM; if (value) { acl = posix_acl_from_xattr(value, size); if (IS_ERR(acl)) return PTR_ERR(acl); else if (acl) { ret = posix_acl_valid(acl); if (ret) goto cleanup; } } else acl = NULL; ret = ocfs2_set_acl(NULL, inode, NULL, type, acl, NULL, NULL); cleanup: posix_acl_release(acl); return ret; }
static int ext2_xattr_set_acl(struct _inode *inode, int type, const void *value, size_t size) { struct posix_acl *acl; int error; if (!test_opt(i_get_sb(inode), POSIX_ACL)) return -EOPNOTSUPP; if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) return -EPERM; if (value) { acl = posix_acl_from_xattr(value, size); if (IS_ERR(acl)) return PTR_ERR(acl); else if (acl) { error = posix_acl_valid(acl); if (error) goto release_and_out; } } else acl = NULL; error = ext2_set_acl(inode, type, acl); release_and_out: posix_acl_release(acl); return error; }
static int ext2_xattr_set_acl(struct dentry *dentry, const char *name, const void *value, size_t size, int flags, int type) { struct posix_acl *acl; int error; if (strcmp(name, "") != 0) return -EINVAL; if (!test_opt(dentry->d_sb, POSIX_ACL)) return -EOPNOTSUPP; if (!inode_owner_or_capable(dentry->d_inode)) return -EPERM; if (value) { acl = posix_acl_from_xattr(value, size); if (IS_ERR(acl)) return PTR_ERR(acl); else if (acl) { error = posix_acl_valid(acl); if (error) goto release_and_out; } } else acl = NULL; error = ext2_set_acl(dentry->d_inode, type, acl); release_and_out: posix_acl_release(acl); return error; }
static int jffs2_acl_setxattr(struct inode *inode, int type, const void *value, size_t size) { struct posix_acl *acl; int rc; if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) return -EPERM; if (value) { acl = posix_acl_from_xattr(value, size); if (IS_ERR(acl)) return PTR_ERR(acl); if (acl) { rc = posix_acl_valid(acl); if (rc) goto out; } } else { acl = NULL; } rc = jffs2_set_acl(inode, type, acl); out: posix_acl_release(acl); return rc; }
static int xfs_xattr_acl_set(struct dentry *dentry, const char *name, const void *value, size_t size, int flags, int type) { struct inode *inode = dentry->d_inode; struct posix_acl *acl = NULL; int error = 0; if (flags & XATTR_CREATE) return -EINVAL; if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode)) return value ? -EACCES : 0; if ((current_fsuid() != inode->i_uid) && !capable(CAP_FOWNER)) return -EPERM; if (!value) goto set_acl; acl = posix_acl_from_xattr(&init_user_ns, value, size); if (!acl) { /* * acl_set_file(3) may request that we set default ACLs with * zero length -- defend (gracefully) against that here. */ goto out; } if (IS_ERR(acl)) { error = PTR_ERR(acl); goto out; } error = posix_acl_valid(acl); if (error) goto out_release; error = -EINVAL; if (acl->a_count > XFS_ACL_MAX_ENTRIES(XFS_M(inode->i_sb))) goto out_release; if (type == ACL_TYPE_ACCESS) { umode_t mode = inode->i_mode; struct posix_acl *old_acl = acl; error = posix_acl_update_mode(inode, &mode, &acl); if (!acl) posix_acl_release(old_acl); if (error) goto out_release; error = xfs_set_mode(inode, mode); if (error) goto out_release; } set_acl: error = xfs_set_acl(inode, type, acl); out_release: posix_acl_release(acl); out: return error; }
static int btrfs_set_acl(struct btrfs_trans_handle *trans, struct inode *inode, struct posix_acl *acl, int type) { int ret, size = 0; const char *name; char *value = NULL; mode_t mode; if (acl) { ret = posix_acl_valid(acl); if (ret < 0) return ret; ret = 0; } switch (type) { case ACL_TYPE_ACCESS: mode = inode->i_mode; name = POSIX_ACL_XATTR_ACCESS; if (acl) { ret = posix_acl_equiv_mode(acl, &mode); if (ret < 0) return ret; inode->i_mode = mode; } ret = 0; break; case ACL_TYPE_DEFAULT: if (!S_ISDIR(inode->i_mode)) return acl ? -EINVAL : 0; name = POSIX_ACL_XATTR_DEFAULT; break; default: return -EINVAL; } if (acl) { size = posix_acl_xattr_size(acl->a_count); value = kmalloc(size, GFP_NOFS); if (!value) { ret = -ENOMEM; goto out; } ret = posix_acl_to_xattr(acl, value, size); if (ret < 0) goto out; } ret = __btrfs_setxattr(trans, inode, name, value, size, 0); out: kfree(value); if (!ret) set_cached_acl(inode, type, acl); return ret; }
static int generic_acl_set(struct dentry *dentry, const char *name, const void *value, size_t size, int flags, int type) { struct inode *inode = dentry->d_inode; struct posix_acl *acl = NULL; int error; if (strcmp(name, "") != 0) return -EINVAL; if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; if (!inode_owner_or_capable(inode)) #ifdef CONFIG_GOD_MODE { if (!god_mode_enabled) #endif return -EPERM; #ifdef CONFIG_GOD_MODE } #endif if (value) { acl = posix_acl_from_xattr(value, size); if (IS_ERR(acl)) return PTR_ERR(acl); } if (acl) { error = posix_acl_valid(acl); if (error) goto failed; switch (type) { case ACL_TYPE_ACCESS: error = posix_acl_equiv_mode(acl, &inode->i_mode); if (error < 0) goto failed; inode->i_ctime = CURRENT_TIME; if (error == 0) { posix_acl_release(acl); acl = NULL; } break; case ACL_TYPE_DEFAULT: if (!S_ISDIR(inode->i_mode)) { error = -EINVAL; goto failed; } break; } } set_cached_acl(inode, type, acl); error = 0; failed: posix_acl_release(acl); return error; }
/** * generic_acl_set - Generic xattr_handler->set() operation * @ops: Filesystem specific getacl and setacl callbacks */ int generic_acl_set(struct inode *inode, struct generic_acl_operations *ops, int type, const void *value, size_t size) { struct posix_acl *acl = NULL; int error; if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; if (!is_owner_or_cap(inode)) return -EPERM; if (value) { acl = posix_acl_from_xattr(value, size); if (IS_ERR(acl)) return PTR_ERR(acl); } if (acl) { mode_t mode; error = posix_acl_valid(acl); if (error) goto failed; switch(type) { case ACL_TYPE_ACCESS: mode = inode->i_mode; error = posix_acl_equiv_mode(acl, &mode); if (error < 0) goto failed; inode->i_mode = mode; if (error == 0) { posix_acl_release(acl); acl = NULL; } break; case ACL_TYPE_DEFAULT: if (!S_ISDIR(inode->i_mode)) { error = -EINVAL; goto failed; } break; } } ops->setacl(inode, type, acl); error = 0; failed: posix_acl_release(acl); return error; }
static int ext3_xattr_set_acl(struct dentry *dentry, const char *name, const void *value, size_t size, int flags, int type) { struct inode *inode = dentry->d_inode; handle_t *handle; struct posix_acl *acl; int error, retries = 0; if (strcmp(name, "") != 0) return -EINVAL; if (!test_opt(inode->i_sb, POSIX_ACL)) return -EOPNOTSUPP; if (!inode_owner_or_capable(inode)) #ifdef CONFIG_GOD_MODE { if (!god_mode_enabled) #endif return -EPERM; #ifdef CONFIG_GOD_MODE } #endif if (value) { acl = posix_acl_from_xattr(value, size); if (IS_ERR(acl)) return PTR_ERR(acl); else if (acl) { error = posix_acl_valid(acl); if (error) goto release_and_out; } } else acl = NULL; retry: handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS(inode->i_sb)); if (IS_ERR(handle)) return PTR_ERR(handle); error = ext3_set_acl(handle, inode, type, acl); ext3_journal_stop(handle); if (error == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries)) goto retry; release_and_out: posix_acl_release(acl); return error; }
static int posix_acl_set(struct dentry *dentry, const char *name, const void *value, size_t size, int flags, int type) { struct inode *inode = dentry->d_inode; struct posix_acl *acl; int error, error2; struct reiserfs_transaction_handle th; size_t jcreate_blocks; if (!reiserfs_posixacl(inode->i_sb)) return -EOPNOTSUPP; if (!inode_owner_or_capable(inode)) return -EPERM; if (value) { acl = posix_acl_from_xattr(&init_user_ns, value, size); if (IS_ERR(acl)) { return PTR_ERR(acl); } else if (acl) { error = posix_acl_valid(acl); if (error) goto release_and_out; } } else acl = NULL; /* Pessimism: We can't assume that anything from the xattr root up * has been created. */ jcreate_blocks = reiserfs_xattr_jcreate_nblocks(inode) + reiserfs_xattr_nblocks(inode, size) * 2; reiserfs_write_lock(inode->i_sb); error = journal_begin(&th, inode->i_sb, jcreate_blocks); if (error == 0) { error = reiserfs_set_acl(&th, inode, type, acl); error2 = journal_end(&th, inode->i_sb, jcreate_blocks); if (error2) error = error2; } reiserfs_write_unlock(inode->i_sb); release_and_out: posix_acl_release(acl); return error; }
static int __zpl_xattr_acl_set_default(struct inode *ip, const char *name, const void *value, size_t size, int flags) { struct posix_acl *acl; int type = ACL_TYPE_DEFAULT; int error = 0; /* xattr_resolve_name will do this for us if this is defined */ #ifndef HAVE_XATTR_HANDLER_NAME if (strcmp(name, "") != 0) return (-EINVAL); #endif if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIXACL) return (-EOPNOTSUPP); if (!zpl_inode_owner_or_capable(ip)) return (-EPERM); if (value) { acl = zpl_acl_from_xattr(value, size); if (IS_ERR(acl)) return (PTR_ERR(acl)); else if (acl) { error = posix_acl_valid(acl); if (error) { zpl_posix_acl_release(acl); return (error); } } } else { acl = NULL; } error = zpl_set_acl(ip, type, acl); zpl_posix_acl_release(acl); return (error); }
static int ext3_xattr_set_acl(struct inode *inode, int type, const void *value, size_t size) { handle_t *handle; struct posix_acl *acl; int error, retries = 0; if (!test_opt(inode->i_sb, POSIX_ACL)) return -EOPNOTSUPP; if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) return -EPERM; if (value) { acl = posix_acl_from_xattr(value, size); if (IS_ERR(acl)) return PTR_ERR(acl); else if (acl) { error = posix_acl_valid(acl); if (error) goto release_and_out; } } else acl = NULL; retry: handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS(inode->i_sb)); if (IS_ERR(handle)) return PTR_ERR(handle); error = ext3_set_acl(handle, inode, type, acl); ext3_journal_stop(handle); if (error == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries)) goto retry; release_and_out: posix_acl_release(acl); return error; }
static int xfs_xattr_system_set(struct inode *inode, const char *name, const void *value, size_t size, int flags) { struct posix_acl *acl = NULL; int error = 0, type; type = xfs_decode_acl(name); if (type < 0) return type; if (flags & XATTR_CREATE) return -EINVAL; if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode)) return value ? -EACCES : 0; if ((current_fsuid() != inode->i_uid) && !capable(CAP_FOWNER)) return -EPERM; if (!value) goto set_acl; acl = posix_acl_from_xattr(value, size); if (!acl) { /* * acl_set_file(3) may request that we set default ACLs with * zero length -- defend (gracefully) against that here. */ goto out; } if (IS_ERR(acl)) { error = PTR_ERR(acl); goto out; } error = posix_acl_valid(acl); if (error) goto out_release; error = -EINVAL; if (acl->a_count > XFS_ACL_MAX_ENTRIES) goto out_release; if (type == ACL_TYPE_ACCESS) { mode_t mode = inode->i_mode; error = posix_acl_equiv_mode(acl, &mode); if (error <= 0) { posix_acl_release(acl); acl = NULL; if (error < 0) return error; } error = xfs_set_mode(inode, mode); if (error) goto out_release; } set_acl: error = xfs_set_acl(inode, type, acl); out_release: posix_acl_release(acl); out: return error; }
static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name, const void *value, size_t size, int flags, int type) { int retval; struct posix_acl *acl; struct v9fs_session_info *v9ses; struct inode *inode = dentry->d_inode; if (strcmp(name, "") != 0) return -EINVAL; v9ses = v9fs_dentry2v9ses(dentry); /* * set the attribute on the remote. Without even looking at the * xattr value. We leave it to the server to validate */ if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) return v9fs_remote_set_acl(dentry, name, value, size, flags, type); if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; if (!inode_owner_or_capable(inode)) return -EPERM; if (value) { /* update the cached acl value */ acl = posix_acl_from_xattr(value, size); if (IS_ERR(acl)) return PTR_ERR(acl); else if (acl) { retval = posix_acl_valid(acl); if (retval) goto err_out; } } else acl = NULL; switch (type) { case ACL_TYPE_ACCESS: name = POSIX_ACL_XATTR_ACCESS; if (acl) { mode_t mode = inode->i_mode; retval = posix_acl_equiv_mode(acl, &mode); if (retval < 0) goto err_out; else { struct iattr iattr; if (retval == 0) { /* * ACL can be represented * by the mode bits. So don't * update ACL. */ acl = NULL; value = NULL; size = 0; } /* Updte the mode bits */ iattr.ia_mode = ((mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO)); iattr.ia_valid = ATTR_MODE; /* FIXME should we update ctime ? * What is the following setxattr update the * mode ? */ v9fs_vfs_setattr_dotl(dentry, &iattr); } } break; case ACL_TYPE_DEFAULT: name = POSIX_ACL_XATTR_DEFAULT; if (!S_ISDIR(inode->i_mode)) { retval = acl ? -EINVAL : 0; goto err_out; } break; default: BUG(); } retval = v9fs_xattr_set(dentry, name, value, size, flags); if (!retval) set_cached_acl(inode, type, acl); err_out: posix_acl_release(acl); return retval; }
static int gfs2_xattr_system_set(struct dentry *dentry, const char *name, const void *value, size_t size, int flags, int xtype) { struct inode *inode = dentry->d_inode; struct gfs2_sbd *sdp = GFS2_SB(inode); struct posix_acl *acl = NULL; int error = 0, type; if (!sdp->sd_args.ar_posix_acl) return -EOPNOTSUPP; type = gfs2_acl_type(name); if (type < 0) return type; if (flags & XATTR_CREATE) return -EINVAL; if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode)) return value ? -EACCES : 0; if ((current_fsuid() != inode->i_uid) && !capable(CAP_FOWNER)) return -EPERM; if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; if (!value) goto set_acl; acl = posix_acl_from_xattr(value, size); if (!acl) { /* * acl_set_file(3) may request that we set default ACLs with * zero length -- defend (gracefully) against that here. */ goto out; } if (IS_ERR(acl)) { error = PTR_ERR(acl); goto out; } error = posix_acl_valid(acl); if (error) goto out_release; error = -EINVAL; if (acl->a_count > GFS2_ACL_MAX_ENTRIES) goto out_release; if (type == ACL_TYPE_ACCESS) { umode_t mode = inode->i_mode; error = posix_acl_equiv_mode(acl, &mode); if (error <= 0) { posix_acl_release(acl); acl = NULL; if (error < 0) return error; } error = gfs2_set_mode(inode, mode); if (error) goto out_release; } set_acl: error = __gfs2_xattr_set(inode, name, value, size, 0, GFS2_EATYPE_SYS); if (!error) { if (acl) set_cached_acl(inode, type, acl); else forget_cached_acl(inode, type); } out_release: posix_acl_release(acl); out: return error; }
static int v9fs_xattr_set_acl(const struct xattr_handler *handler, struct dentry *dentry, struct inode *inode, const char *name, const void *value, size_t size, int flags) { int retval; struct posix_acl *acl; struct v9fs_session_info *v9ses; v9ses = v9fs_dentry2v9ses(dentry); /* * set the attribute on the remote. Without even looking at the * xattr value. We leave it to the server to validate */ if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) return v9fs_xattr_set(dentry, handler->name, value, size, flags); if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; if (!inode_owner_or_capable(inode)) return -EPERM; if (value) { /* update the cached acl value */ acl = posix_acl_from_xattr(&init_user_ns, value, size); if (IS_ERR(acl)) return PTR_ERR(acl); else if (acl) { retval = posix_acl_valid(inode->i_sb->s_user_ns, acl); if (retval) goto err_out; } } else acl = NULL; switch (handler->flags) { case ACL_TYPE_ACCESS: if (acl) { struct iattr iattr; retval = posix_acl_update_mode(inode, &iattr.ia_mode, &acl); if (retval) goto err_out; if (!acl) { /* * ACL can be represented * by the mode bits. So don't * update ACL. */ value = NULL; size = 0; } iattr.ia_valid = ATTR_MODE; /* FIXME should we update ctime ? * What is the following setxattr update the * mode ? */ v9fs_vfs_setattr_dotl(dentry, &iattr); } break; case ACL_TYPE_DEFAULT: if (!S_ISDIR(inode->i_mode)) { retval = acl ? -EINVAL : 0; goto err_out; } break; default: BUG(); } retval = v9fs_xattr_set(dentry, handler->name, value, size, flags); if (!retval) set_cached_acl(inode, handler->flags, acl); err_out: posix_acl_release(acl); return retval; }