2 * FUSE: Filesystem in Userspace
3 * Copyright (C) 2001-2016 Miklos Szeredi <miklos@szeredi.hu>
5 * This program can be distributed under the terms of the GNU GPL.
6 * See the file COPYING.
11 #include <linux/xattr.h>
13 static int fuse_setxattr(struct inode *inode, const char *name,
14 const void *value, size_t size, int flags)
16 struct fuse_conn *fc = get_fuse_conn(inode);
18 struct fuse_setxattr_in inarg;
24 memset(&inarg, 0, sizeof(inarg));
27 args.in.h.opcode = FUSE_SETXATTR;
28 args.in.h.nodeid = get_node_id(inode);
30 args.in.args[0].size = sizeof(inarg);
31 args.in.args[0].value = &inarg;
32 args.in.args[1].size = strlen(name) + 1;
33 args.in.args[1].value = name;
34 args.in.args[2].size = size;
35 args.in.args[2].value = value;
36 err = fuse_simple_request(fc, &args);
42 fuse_invalidate_attr(inode);
43 fuse_update_ctime(inode);
48 static ssize_t fuse_getxattr(struct inode *inode, const char *name,
49 void *value, size_t size)
51 struct fuse_conn *fc = get_fuse_conn(inode);
53 struct fuse_getxattr_in inarg;
54 struct fuse_getxattr_out outarg;
60 memset(&inarg, 0, sizeof(inarg));
62 args.in.h.opcode = FUSE_GETXATTR;
63 args.in.h.nodeid = get_node_id(inode);
65 args.in.args[0].size = sizeof(inarg);
66 args.in.args[0].value = &inarg;
67 args.in.args[1].size = strlen(name) + 1;
68 args.in.args[1].value = name;
69 /* This is really two different operations rolled into one */
73 args.out.args[0].size = size;
74 args.out.args[0].value = value;
76 args.out.args[0].size = sizeof(outarg);
77 args.out.args[0].value = &outarg;
79 ret = fuse_simple_request(fc, &args);
89 static int fuse_verify_xattr_list(char *list, size_t size)
91 size_t origsize = size;
94 size_t thislen = strnlen(list, size);
96 if (!thislen || thislen == size)
106 ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
108 struct inode *inode = d_inode(entry);
109 struct fuse_conn *fc = get_fuse_conn(inode);
111 struct fuse_getxattr_in inarg;
112 struct fuse_getxattr_out outarg;
115 if (!fuse_allow_current_process(fc))
118 if (fc->no_listxattr)
121 memset(&inarg, 0, sizeof(inarg));
123 args.in.h.opcode = FUSE_LISTXATTR;
124 args.in.h.nodeid = get_node_id(inode);
126 args.in.args[0].size = sizeof(inarg);
127 args.in.args[0].value = &inarg;
128 /* This is really two different operations rolled into one */
129 args.out.numargs = 1;
132 args.out.args[0].size = size;
133 args.out.args[0].value = list;
135 args.out.args[0].size = sizeof(outarg);
136 args.out.args[0].value = &outarg;
138 ret = fuse_simple_request(fc, &args);
142 ret = fuse_verify_xattr_list(list, ret);
143 if (ret == -ENOSYS) {
144 fc->no_listxattr = 1;
150 static int fuse_removexattr(struct inode *inode, const char *name)
152 struct fuse_conn *fc = get_fuse_conn(inode);
156 if (fc->no_removexattr)
159 args.in.h.opcode = FUSE_REMOVEXATTR;
160 args.in.h.nodeid = get_node_id(inode);
162 args.in.args[0].size = strlen(name) + 1;
163 args.in.args[0].value = name;
164 err = fuse_simple_request(fc, &args);
165 if (err == -ENOSYS) {
166 fc->no_removexattr = 1;
170 fuse_invalidate_attr(inode);
171 fuse_update_ctime(inode);
176 static int fuse_xattr_get(const struct xattr_handler *handler,
177 struct dentry *dentry, struct inode *inode,
178 const char *name, void *value, size_t size)
180 return fuse_getxattr(inode, name, value, size);
183 static int fuse_xattr_set(const struct xattr_handler *handler,
184 struct dentry *dentry, struct inode *inode,
185 const char *name, const void *value, size_t size,
189 return fuse_removexattr(inode, name);
191 return fuse_setxattr(inode, name, value, size, flags);
194 static const struct xattr_handler fuse_xattr_handler = {
196 .get = fuse_xattr_get,
197 .set = fuse_xattr_set,
200 const struct xattr_handler *fuse_xattr_handlers[] = {