Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.5.6.
  1/*
  2 * FUSE: Filesystem in Userspace
  3 * Copyright (C) 2001-2016  Miklos Szeredi <miklos@szeredi.hu>
  4 *
  5 * This program can be distributed under the terms of the GNU GPL.
  6 * See the file COPYING.
  7 */
  8
  9#include "fuse_i.h"
 10
 11#include <linux/xattr.h>
 12#include <linux/posix_acl_xattr.h>
 13
 14int fuse_setxattr(struct inode *inode, const char *name, const void *value,
 15		  size_t size, int flags, unsigned int extra_flags)
 16{
 17	struct fuse_mount *fm = get_fuse_mount(inode);
 18	FUSE_ARGS(args);
 19	struct fuse_setxattr_in inarg;
 20	int err;
 21
 22	if (fm->fc->no_setxattr)
 23		return -EOPNOTSUPP;
 24
 25	memset(&inarg, 0, sizeof(inarg));
 26	inarg.size = size;
 27	inarg.flags = flags;
 28	inarg.setxattr_flags = extra_flags;
 29
 30	args.opcode = FUSE_SETXATTR;
 31	args.nodeid = get_node_id(inode);
 32	args.in_numargs = 3;
 33	args.in_args[0].size = fm->fc->setxattr_ext ?
 34		sizeof(inarg) : FUSE_COMPAT_SETXATTR_IN_SIZE;
 35	args.in_args[0].value = &inarg;
 36	args.in_args[1].size = strlen(name) + 1;
 37	args.in_args[1].value = name;
 38	args.in_args[2].size = size;
 39	args.in_args[2].value = value;
 40	err = fuse_simple_request(fm, &args);
 41	if (err == -ENOSYS) {
 42		fm->fc->no_setxattr = 1;
 43		err = -EOPNOTSUPP;
 44	}
 45	if (!err) {
 46		fuse_invalidate_attr(inode);
 47		fuse_update_ctime(inode);
 48	}
 49	return err;
 50}
 51
 52ssize_t fuse_getxattr(struct inode *inode, const char *name, void *value,
 53		      size_t size)
 54{
 55	struct fuse_mount *fm = get_fuse_mount(inode);
 56	FUSE_ARGS(args);
 57	struct fuse_getxattr_in inarg;
 58	struct fuse_getxattr_out outarg;
 59	ssize_t ret;
 60
 61	if (fm->fc->no_getxattr)
 62		return -EOPNOTSUPP;
 63
 64	memset(&inarg, 0, sizeof(inarg));
 65	inarg.size = size;
 66	args.opcode = FUSE_GETXATTR;
 67	args.nodeid = get_node_id(inode);
 68	args.in_numargs = 2;
 69	args.in_args[0].size = sizeof(inarg);
 70	args.in_args[0].value = &inarg;
 71	args.in_args[1].size = strlen(name) + 1;
 72	args.in_args[1].value = name;
 73	/* This is really two different operations rolled into one */
 74	args.out_numargs = 1;
 75	if (size) {
 76		args.out_argvar = true;
 77		args.out_args[0].size = size;
 78		args.out_args[0].value = value;
 79	} else {
 80		args.out_args[0].size = sizeof(outarg);
 81		args.out_args[0].value = &outarg;
 82	}
 83	ret = fuse_simple_request(fm, &args);
 84	if (!ret && !size)
 85		ret = min_t(ssize_t, outarg.size, XATTR_SIZE_MAX);
 86	if (ret == -ENOSYS) {
 87		fm->fc->no_getxattr = 1;
 88		ret = -EOPNOTSUPP;
 89	}
 90	return ret;
 91}
 92
 93static int fuse_verify_xattr_list(char *list, size_t size)
 94{
 95	size_t origsize = size;
 96
 97	while (size) {
 98		size_t thislen = strnlen(list, size);
 99
100		if (!thislen || thislen == size)
101			return -EIO;
102
103		size -= thislen + 1;
104		list += thislen + 1;
105	}
106
107	return origsize;
108}
109
110ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
111{
112	struct inode *inode = d_inode(entry);
113	struct fuse_mount *fm = get_fuse_mount(inode);
114	FUSE_ARGS(args);
115	struct fuse_getxattr_in inarg;
116	struct fuse_getxattr_out outarg;
117	ssize_t ret;
118
119	if (fuse_is_bad(inode))
120		return -EIO;
121
122	if (!fuse_allow_current_process(fm->fc))
123		return -EACCES;
124
125	if (fm->fc->no_listxattr)
126		return -EOPNOTSUPP;
127
128	memset(&inarg, 0, sizeof(inarg));
129	inarg.size = size;
130	args.opcode = FUSE_LISTXATTR;
131	args.nodeid = get_node_id(inode);
132	args.in_numargs = 1;
133	args.in_args[0].size = sizeof(inarg);
134	args.in_args[0].value = &inarg;
135	/* This is really two different operations rolled into one */
136	args.out_numargs = 1;
137	if (size) {
138		args.out_argvar = true;
139		args.out_args[0].size = size;
140		args.out_args[0].value = list;
141	} else {
142		args.out_args[0].size = sizeof(outarg);
143		args.out_args[0].value = &outarg;
144	}
145	ret = fuse_simple_request(fm, &args);
146	if (!ret && !size)
147		ret = min_t(ssize_t, outarg.size, XATTR_LIST_MAX);
148	if (ret > 0 && size)
149		ret = fuse_verify_xattr_list(list, ret);
150	if (ret == -ENOSYS) {
151		fm->fc->no_listxattr = 1;
152		ret = -EOPNOTSUPP;
153	}
154	return ret;
155}
156
157int fuse_removexattr(struct inode *inode, const char *name)
158{
159	struct fuse_mount *fm = get_fuse_mount(inode);
160	FUSE_ARGS(args);
161	int err;
162
163	if (fm->fc->no_removexattr)
164		return -EOPNOTSUPP;
165
166	args.opcode = FUSE_REMOVEXATTR;
167	args.nodeid = get_node_id(inode);
168	args.in_numargs = 1;
169	args.in_args[0].size = strlen(name) + 1;
170	args.in_args[0].value = name;
171	err = fuse_simple_request(fm, &args);
172	if (err == -ENOSYS) {
173		fm->fc->no_removexattr = 1;
174		err = -EOPNOTSUPP;
175	}
176	if (!err) {
177		fuse_invalidate_attr(inode);
178		fuse_update_ctime(inode);
179	}
180	return err;
181}
182
183static int fuse_xattr_get(const struct xattr_handler *handler,
184			 struct dentry *dentry, struct inode *inode,
185			 const char *name, void *value, size_t size)
186{
187	if (fuse_is_bad(inode))
188		return -EIO;
189
190	return fuse_getxattr(inode, name, value, size);
191}
192
193static int fuse_xattr_set(const struct xattr_handler *handler,
194			  struct user_namespace *mnt_userns,
195			  struct dentry *dentry, struct inode *inode,
196			  const char *name, const void *value, size_t size,
197			  int flags)
198{
199	if (fuse_is_bad(inode))
200		return -EIO;
201
202	if (!value)
203		return fuse_removexattr(inode, name);
204
205	return fuse_setxattr(inode, name, value, size, flags, 0);
206}
207
208static bool no_xattr_list(struct dentry *dentry)
209{
210	return false;
211}
212
213static int no_xattr_get(const struct xattr_handler *handler,
214			struct dentry *dentry, struct inode *inode,
215			const char *name, void *value, size_t size)
216{
217	return -EOPNOTSUPP;
218}
219
220static int no_xattr_set(const struct xattr_handler *handler,
221			struct user_namespace *mnt_userns,
222			struct dentry *dentry, struct inode *nodee,
223			const char *name, const void *value,
224			size_t size, int flags)
225{
226	return -EOPNOTSUPP;
227}
228
229static const struct xattr_handler fuse_xattr_handler = {
230	.prefix = "",
231	.get    = fuse_xattr_get,
232	.set    = fuse_xattr_set,
233};
234
235const struct xattr_handler *fuse_xattr_handlers[] = {
236	&fuse_xattr_handler,
237	NULL
238};
239
240const struct xattr_handler *fuse_acl_xattr_handlers[] = {
241	&posix_acl_access_xattr_handler,
242	&posix_acl_default_xattr_handler,
243	&fuse_xattr_handler,
244	NULL
245};
246
247static const struct xattr_handler fuse_no_acl_access_xattr_handler = {
248	.name  = XATTR_NAME_POSIX_ACL_ACCESS,
249	.flags = ACL_TYPE_ACCESS,
250	.list  = no_xattr_list,
251	.get   = no_xattr_get,
252	.set   = no_xattr_set,
253};
254
255static const struct xattr_handler fuse_no_acl_default_xattr_handler = {
256	.name  = XATTR_NAME_POSIX_ACL_DEFAULT,
257	.flags = ACL_TYPE_ACCESS,
258	.list  = no_xattr_list,
259	.get   = no_xattr_get,
260	.set   = no_xattr_set,
261};
262
263const struct xattr_handler *fuse_no_acl_xattr_handlers[] = {
264	&fuse_no_acl_access_xattr_handler,
265	&fuse_no_acl_default_xattr_handler,
266	&fuse_xattr_handler,
267	NULL
268};