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; }
/* * Called under i_mutex */ int reiserfs_acl_chmod(struct inode *inode) { if (IS_PRIVATE(inode)) return 0; if (get_inode_sd_version(inode) == STAT_DATA_V1 || !reiserfs_posixacl(inode->i_sb)) return 0; return posix_acl_chmod(inode, inode->i_mode); }
static int posix_acl_default_list (struct inode *inode, const char *name, int namelen, char *out) { int len = namelen; if (!reiserfs_posixacl (inode->i_sb)) return 0; if (out) memcpy (out, name, len); return len; }
static size_t posix_acl_default_list(struct dentry *dentry, char *list, size_t list_size, const char *name, size_t name_len, int type) { const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT); if (!reiserfs_posixacl(dentry->d_sb)) return 0; if (list && size <= list_size) memcpy(list, POSIX_ACL_XATTR_DEFAULT, size); return size; }
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; }
/* Looks up and caches the result of the default ACL. * We do this so that we don't need to carry the xattr_sem into * reiserfs_new_inode if we don't need to */ int reiserfs_cache_default_acl(struct inode *inode) { int ret = 0; if (reiserfs_posixacl(inode->i_sb) && !is_reiserfs_priv_object(inode)) { struct posix_acl *acl; reiserfs_read_lock_xattr_i(inode); reiserfs_read_lock_xattrs(inode->i_sb); acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT); reiserfs_read_unlock_xattrs(inode->i_sb); reiserfs_read_unlock_xattr_i(inode); ret = (acl && !IS_ERR(acl)); if (ret) posix_acl_release(acl); } return ret; }
int reiserfs_acl_chmod(struct inode *inode) { struct posix_acl *acl, *clone; int error; if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; if (get_inode_sd_version(inode) == STAT_DATA_V1 || !reiserfs_posixacl(inode->i_sb)) { return 0; } reiserfs_write_unlock(inode->i_sb); acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); reiserfs_write_lock(inode->i_sb); if (!acl) return 0; if (IS_ERR(acl)) return PTR_ERR(acl); clone = posix_acl_clone(acl, GFP_NOFS); posix_acl_release(acl); if (!clone) return -ENOMEM; error = posix_acl_chmod_masq(clone, inode->i_mode); if (!error) { struct reiserfs_transaction_handle th; size_t size = reiserfs_xattr_nblocks(inode, reiserfs_acl_size(clone->a_count)); int depth; depth = reiserfs_write_lock_once(inode->i_sb); error = journal_begin(&th, inode->i_sb, size * 2); if (!error) { int error2; error = reiserfs_set_acl(&th, inode, ACL_TYPE_ACCESS, clone); error2 = journal_end(&th, inode->i_sb, size * 2); if (error2) error = error2; } reiserfs_write_unlock_once(inode->i_sb, depth); } posix_acl_release(clone); return error; }
int reiserfs_acl_chmod (struct inode *inode) { struct posix_acl *acl, *clone; int error; if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; if (get_inode_sd_version (inode) == STAT_DATA_V1 || !reiserfs_posixacl(inode->i_sb)) { return 0; } reiserfs_read_lock_xattrs (inode->i_sb); acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); reiserfs_read_unlock_xattrs (inode->i_sb); if (!acl) return 0; if (IS_ERR(acl)) return PTR_ERR(acl); clone = posix_acl_clone(acl, GFP_NOFS); posix_acl_release(acl); if (!clone) return -ENOMEM; error = posix_acl_chmod_masq(clone, inode->i_mode); if (!error) { int lock = !has_xattr_dir (inode); reiserfs_write_lock_xattr_i (inode); if (lock) reiserfs_write_lock_xattrs (inode->i_sb); else reiserfs_read_lock_xattrs (inode->i_sb); error = reiserfs_set_acl(inode, ACL_TYPE_ACCESS, clone); if (lock) reiserfs_write_unlock_xattrs (inode->i_sb); else reiserfs_read_unlock_xattrs (inode->i_sb); reiserfs_write_unlock_xattr_i (inode); } posix_acl_release(clone); return error; }
/* We need to take a copy of the mount flags since things like * MS_RDONLY don't get set until *after* we're called. * mount_flags != mount_options */ int reiserfs_xattr_init(struct super_block *s, int mount_flags) { int err = 0; struct dentry *privroot = REISERFS_SB(s)->priv_root; err = xattr_mount_check(s); if (err) goto error; if (!privroot->d_inode && !(mount_flags & MS_RDONLY)) { reiserfs_mutex_lock_safe(&s->s_root->d_inode->i_mutex, s); err = create_privroot(REISERFS_SB(s)->priv_root); mutex_unlock(&s->s_root->d_inode->i_mutex); } if (privroot->d_inode) { s->s_xattr = reiserfs_xattr_handlers; reiserfs_mutex_lock_safe(&privroot->d_inode->i_mutex, s); if (!REISERFS_SB(s)->xattr_root) { struct dentry *dentry; dentry = lookup_one_len(XAROOT_NAME, privroot, strlen(XAROOT_NAME)); if (!IS_ERR(dentry)) REISERFS_SB(s)->xattr_root = dentry; else err = PTR_ERR(dentry); } mutex_unlock(&privroot->d_inode->i_mutex); } error: if (err) { clear_bit(REISERFS_XATTRS_USER, &(REISERFS_SB(s)->s_mount_opt)); clear_bit(REISERFS_POSIXACL, &(REISERFS_SB(s)->s_mount_opt)); } /* The super_block MS_POSIXACL must mirror the (no)acl mount option. */ if (reiserfs_posixacl(s)) s->s_flags |= MS_POSIXACL; else s->s_flags &= ~MS_POSIXACL; return err; }
static int xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size) { struct posix_acl *acl; int error; if (!reiserfs_posixacl(inode->i_sb)) return -EOPNOTSUPP; acl = reiserfs_get_acl (inode, type); if (IS_ERR(acl)) return PTR_ERR(acl); if (acl == NULL) return -ENODATA; error = posix_acl_to_xattr(acl, buffer, size); posix_acl_release(acl); return error; }
static int posix_acl_get(struct dentry *dentry, const char *name, void *buffer, size_t size, int type) { struct posix_acl *acl; int error; if (!reiserfs_posixacl(dentry->d_sb)) return -EOPNOTSUPP; acl = reiserfs_get_acl(dentry->d_inode, type); if (IS_ERR(acl)) return PTR_ERR(acl); if (acl == NULL) return -ENODATA; error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size); posix_acl_release(acl); return error; }