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
[] = {