⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xattr.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
      out_dir:	fput(fp);      out:	attrs->ia_valid = ia_valid;	return err;}/* Actual operations that are exported to VFS-land *//* * Inode operation getxattr() * Preliminary locking: we down dentry->d_inode->i_mutex */ssize_treiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer,		  size_t size){	struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix(name);	int err;	if (!xah || !reiserfs_xattrs(dentry->d_sb) ||	    get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)		return -EOPNOTSUPP;	reiserfs_read_lock_xattr_i(dentry->d_inode);	reiserfs_read_lock_xattrs(dentry->d_sb);	err = xah->get(dentry->d_inode, name, buffer, size);	reiserfs_read_unlock_xattrs(dentry->d_sb);	reiserfs_read_unlock_xattr_i(dentry->d_inode);	return err;}/* * Inode operation setxattr() * * dentry->d_inode->i_mutex down */intreiserfs_setxattr(struct dentry *dentry, const char *name, const void *value,		  size_t size, int flags){	struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix(name);	int err;	int lock;	if (!xah || !reiserfs_xattrs(dentry->d_sb) ||	    get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)		return -EOPNOTSUPP;	reiserfs_write_lock_xattr_i(dentry->d_inode);	lock = !has_xattr_dir(dentry->d_inode);	if (lock)		reiserfs_write_lock_xattrs(dentry->d_sb);	else		reiserfs_read_lock_xattrs(dentry->d_sb);	err = xah->set(dentry->d_inode, name, value, size, flags);	if (lock)		reiserfs_write_unlock_xattrs(dentry->d_sb);	else		reiserfs_read_unlock_xattrs(dentry->d_sb);	reiserfs_write_unlock_xattr_i(dentry->d_inode);	return err;}/* * Inode operation removexattr() * * dentry->d_inode->i_mutex down */int reiserfs_removexattr(struct dentry *dentry, const char *name){	int err;	struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix(name);	if (!xah || !reiserfs_xattrs(dentry->d_sb) ||	    get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)		return -EOPNOTSUPP;	reiserfs_write_lock_xattr_i(dentry->d_inode);	reiserfs_read_lock_xattrs(dentry->d_sb);	/* Deletion pre-operation */	if (xah->del) {		err = xah->del(dentry->d_inode, name);		if (err)			goto out;	}	err = reiserfs_xattr_del(dentry->d_inode, name);	dentry->d_inode->i_ctime = CURRENT_TIME_SEC;	mark_inode_dirty(dentry->d_inode);      out:	reiserfs_read_unlock_xattrs(dentry->d_sb);	reiserfs_write_unlock_xattr_i(dentry->d_inode);	return err;}/* This is what filldir will use: * r_pos will always contain the amount of space required for the entire * list. If r_pos becomes larger than r_size, we need more space and we * return an error indicating this. If r_pos is less than r_size, then we've * filled the buffer successfully and we return success */struct reiserfs_listxattr_buf {	int r_pos;	int r_size;	char *r_buf;	struct inode *r_inode;};static intreiserfs_listxattr_filler(void *buf, const char *name, int namelen,			  loff_t offset, u64 ino, unsigned int d_type){	struct reiserfs_listxattr_buf *b = (struct reiserfs_listxattr_buf *)buf;	int len = 0;	if (name[0] != '.'	    || (namelen != 1 && (name[1] != '.' || namelen != 2))) {		struct reiserfs_xattr_handler *xah =		    find_xattr_handler_prefix(name);		if (!xah)			return 0;	/* Unsupported xattr name, skip it */		/* We call ->list() twice because the operation isn't required to just		 * return the name back - we want to make sure we have enough space */		len += xah->list(b->r_inode, name, namelen, NULL);		if (len) {			if (b->r_pos + len + 1 <= b->r_size) {				char *p = b->r_buf + b->r_pos;				p += xah->list(b->r_inode, name, namelen, p);				*p++ = '\0';			}			b->r_pos += len + 1;		}	}	return 0;}/* * Inode operation listxattr() * * Preliminary locking: we down dentry->d_inode->i_mutex */ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size){	struct file *fp;	struct dentry *dir;	int err = 0;	struct reiserfs_listxattr_buf buf;	if (!dentry->d_inode)		return -EINVAL;	if (!reiserfs_xattrs(dentry->d_sb) ||	    get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)		return -EOPNOTSUPP;	reiserfs_read_lock_xattr_i(dentry->d_inode);	reiserfs_read_lock_xattrs(dentry->d_sb);	dir = open_xa_dir(dentry->d_inode, FL_READONLY);	reiserfs_read_unlock_xattrs(dentry->d_sb);	if (IS_ERR(dir)) {		err = PTR_ERR(dir);		if (err == -ENODATA)			err = 0;	/* Not an error if there aren't any xattrs */		goto out;	}	fp = dentry_open(dir, NULL, O_RDWR);	if (IS_ERR(fp)) {		err = PTR_ERR(fp);		/* dentry_open dputs the dentry if it fails */		goto out;	}	buf.r_buf = buffer;	buf.r_size = buffer ? size : 0;	buf.r_pos = 0;	buf.r_inode = dentry->d_inode;	REISERFS_I(dentry->d_inode)->i_flags |= i_has_xattr_dir;	err = xattr_readdir(fp, reiserfs_listxattr_filler, &buf);	if (err)		goto out_dir;	if (buf.r_pos > buf.r_size && buffer != NULL)		err = -ERANGE;	else		err = buf.r_pos;      out_dir:	fput(fp);      out:	reiserfs_read_unlock_xattr_i(dentry->d_inode);	return err;}/* This is the implementation for the xattr plugin infrastructure */static struct list_head xattr_handlers = LIST_HEAD_INIT(xattr_handlers);static DEFINE_RWLOCK(handler_lock);static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char								*prefix){	struct reiserfs_xattr_handler *xah = NULL;	struct list_head *p;	read_lock(&handler_lock);	list_for_each(p, &xattr_handlers) {		xah = list_entry(p, struct reiserfs_xattr_handler, handlers);		if (strncmp(xah->prefix, prefix, strlen(xah->prefix)) == 0)			break;		xah = NULL;	}	read_unlock(&handler_lock);	return xah;}static void __unregister_handlers(void){	struct reiserfs_xattr_handler *xah;	struct list_head *p, *tmp;	list_for_each_safe(p, tmp, &xattr_handlers) {		xah = list_entry(p, struct reiserfs_xattr_handler, handlers);		if (xah->exit)			xah->exit();		list_del_init(p);	}	INIT_LIST_HEAD(&xattr_handlers);}int __init reiserfs_xattr_register_handlers(void){	int err = 0;	struct reiserfs_xattr_handler *xah;	struct list_head *p;	write_lock(&handler_lock);	/* If we're already initialized, nothing to do */	if (!list_empty(&xattr_handlers)) {		write_unlock(&handler_lock);		return 0;	}	/* Add the handlers */	list_add_tail(&user_handler.handlers, &xattr_handlers);	list_add_tail(&trusted_handler.handlers, &xattr_handlers);#ifdef CONFIG_REISERFS_FS_SECURITY	list_add_tail(&security_handler.handlers, &xattr_handlers);#endif#ifdef CONFIG_REISERFS_FS_POSIX_ACL	list_add_tail(&posix_acl_access_handler.handlers, &xattr_handlers);	list_add_tail(&posix_acl_default_handler.handlers, &xattr_handlers);#endif	/* Run initializers, if available */	list_for_each(p, &xattr_handlers) {		xah = list_entry(p, struct reiserfs_xattr_handler, handlers);		if (xah->init) {			err = xah->init();			if (err) {				list_del_init(p);				break;			}		}	}	/* Clean up other handlers, if any failed */	if (err)		__unregister_handlers();	write_unlock(&handler_lock);	return err;}void reiserfs_xattr_unregister_handlers(void){	write_lock(&handler_lock);	__unregister_handlers();	write_unlock(&handler_lock);}/* This will catch lookups from the fs root to .reiserfs_priv */static intxattr_lookup_poison(struct dentry *dentry, struct qstr *q1, struct qstr *name){	struct dentry *priv_root = REISERFS_SB(dentry->d_sb)->priv_root;	if (name->len == priv_root->d_name.len &&	    name->hash == priv_root->d_name.hash &&	    !memcmp(name->name, priv_root->d_name.name, name->len)) {		return -ENOENT;	} else if (q1->len == name->len &&		   !memcmp(q1->name, name->name, name->len))		return 0;	return 1;}static struct dentry_operations xattr_lookup_poison_ops = {	.d_compare = xattr_lookup_poison,};/* 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;	/* We need generation numbers to ensure that the oid mapping is correct	 * v3.5 filesystems don't have them. */	if (!old_format_only(s)) {		set_bit(REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt));	} else if (reiserfs_xattrs_optional(s)) {		/* Old format filesystem, but optional xattrs have been enabled		 * at mount time. Error out. */		reiserfs_warning(s, "xattrs/ACLs not supported on pre v3.6 "				 "format filesystem. Failing mount.");		err = -EOPNOTSUPP;		goto error;	} else {		/* Old format filesystem, but no optional xattrs have been enabled. This		 * means we silently disable xattrs on the filesystem. */		clear_bit(REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt));	}	/* If we don't have the privroot located yet - go find it */	if (reiserfs_xattrs(s) && !REISERFS_SB(s)->priv_root) {		struct dentry *dentry;		dentry = lookup_one_len(PRIVROOT_NAME, s->s_root,					strlen(PRIVROOT_NAME));		if (!IS_ERR(dentry)) {			if (!(mount_flags & MS_RDONLY) && !dentry->d_inode) {				struct inode *inode = dentry->d_parent->d_inode;				mutex_lock_nested(&inode->i_mutex,						  I_MUTEX_XATTR);				err = inode->i_op->mkdir(inode, dentry, 0700);				mutex_unlock(&inode->i_mutex);				if (err) {					dput(dentry);					dentry = NULL;				}				if (dentry && dentry->d_inode)					reiserfs_warning(s,							 "Created %s on %s - reserved for "							 "xattr storage.",							 PRIVROOT_NAME,							 reiserfs_bdevname							 (inode->i_sb));			} else if (!dentry->d_inode) {				dput(dentry);				dentry = NULL;			}		} else			err = PTR_ERR(dentry);		if (!err && dentry) {			s->s_root->d_op = &xattr_lookup_poison_ops;			reiserfs_mark_inode_private(dentry->d_inode);			REISERFS_SB(s)->priv_root = dentry;		} else if (!(mount_flags & MS_RDONLY)) {	/* xattrs are unavailable */			/* If we're read-only it just means that the dir hasn't been			 * created. Not an error -- just no xattrs on the fs. We'll			 * check again if we go read-write */			reiserfs_warning(s, "xattrs/ACLs enabled and couldn't "					 "find/create .reiserfs_priv. Failing mount.");			err = -EOPNOTSUPP;		}	}      error:	/* This is only nonzero if there was an error initializing the xattr	 * directory or if there is a condition where we don't support them. */	if (err) {		clear_bit(REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt));		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. */	s->s_flags = s->s_flags & ~MS_POSIXACL;	if (reiserfs_posixacl(s))		s->s_flags |= MS_POSIXACL;	return err;}static int reiserfs_check_acl(struct inode *inode, int mask){	struct posix_acl *acl;	int error = -EAGAIN; /* do regular unix permission checks by default */	reiserfs_read_lock_xattr_i(inode);	reiserfs_read_lock_xattrs(inode->i_sb);	acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);	reiserfs_read_unlock_xattrs(inode->i_sb);	reiserfs_read_unlock_xattr_i(inode);	if (acl) {		if (!IS_ERR(acl)) {			error = posix_acl_permission(inode, acl, mask);			posix_acl_release(acl);		} else if (PTR_ERR(acl) != -ENODATA)			error = PTR_ERR(acl);	}	return error;}int reiserfs_permission(struct inode *inode, int mask, struct nameidata *nd){	/*	 * We don't do permission checks on the internal objects.	 * Permissions are determined by the "owning" object.	 */	if (is_reiserfs_priv_object(inode))		return 0;	/*	 * Stat data v1 doesn't support ACLs.	 */	if (get_inode_sd_version(inode) == STAT_DATA_V1)		return generic_permission(inode, mask, NULL);	else		return generic_permission(inode, mask, reiserfs_check_acl);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -