Linux Audio

Check our new training course

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