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>
12 #include <linux/posix_acl_xattr.h>
14 int fuse_setxattr(struct inode
*inode
, const char *name
, const void *value
,
15 size_t size
, int flags
)
17 struct fuse_conn
*fc
= get_fuse_conn(inode
);
19 struct fuse_setxattr_in inarg
;
25 memset(&inarg
, 0, sizeof(inarg
));
28 args
.in
.h
.opcode
= FUSE_SETXATTR
;
29 args
.in
.h
.nodeid
= get_node_id(inode
);
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
);
43 fuse_invalidate_attr(inode
);
44 fuse_update_ctime(inode
);
49 ssize_t
fuse_getxattr(struct inode
*inode
, const char *name
, void *value
,
52 struct fuse_conn
*fc
= get_fuse_conn(inode
);
54 struct fuse_getxattr_in inarg
;
55 struct fuse_getxattr_out outarg
;
61 memset(&inarg
, 0, sizeof(inarg
));
63 args
.in
.h
.opcode
= FUSE_GETXATTR
;
64 args
.in
.h
.nodeid
= get_node_id(inode
);
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 */
74 args
.out
.args
[0].size
= size
;
75 args
.out
.args
[0].value
= value
;
77 args
.out
.args
[0].size
= sizeof(outarg
);
78 args
.out
.args
[0].value
= &outarg
;
80 ret
= fuse_simple_request(fc
, &args
);
82 ret
= min_t(ssize_t
, outarg
.size
, XATTR_SIZE_MAX
);
90 static int fuse_verify_xattr_list(char *list
, size_t size
)
92 size_t origsize
= size
;
95 size_t thislen
= strnlen(list
, size
);
97 if (!thislen
|| thislen
== size
)
107 ssize_t
fuse_listxattr(struct dentry
*entry
, char *list
, size_t size
)
109 struct inode
*inode
= d_inode(entry
);
110 struct fuse_conn
*fc
= get_fuse_conn(inode
);
112 struct fuse_getxattr_in inarg
;
113 struct fuse_getxattr_out outarg
;
116 if (!fuse_allow_current_process(fc
))
119 if (fc
->no_listxattr
)
122 memset(&inarg
, 0, sizeof(inarg
));
124 args
.in
.h
.opcode
= FUSE_LISTXATTR
;
125 args
.in
.h
.nodeid
= get_node_id(inode
);
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;
133 args
.out
.args
[0].size
= size
;
134 args
.out
.args
[0].value
= list
;
136 args
.out
.args
[0].size
= sizeof(outarg
);
137 args
.out
.args
[0].value
= &outarg
;
139 ret
= fuse_simple_request(fc
, &args
);
141 ret
= min_t(ssize_t
, outarg
.size
, XATTR_LIST_MAX
);
143 ret
= fuse_verify_xattr_list(list
, ret
);
144 if (ret
== -ENOSYS
) {
145 fc
->no_listxattr
= 1;
151 int fuse_removexattr(struct inode
*inode
, const char *name
)
153 struct fuse_conn
*fc
= get_fuse_conn(inode
);
157 if (fc
->no_removexattr
)
160 args
.in
.h
.opcode
= FUSE_REMOVEXATTR
;
161 args
.in
.h
.nodeid
= get_node_id(inode
);
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;
171 fuse_invalidate_attr(inode
);
172 fuse_update_ctime(inode
);
177 static 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
)
181 return fuse_getxattr(inode
, name
, value
, size
);
184 static 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
,
190 return fuse_removexattr(inode
, name
);
192 return fuse_setxattr(inode
, name
, value
, size
, flags
);
195 static const struct xattr_handler fuse_xattr_handler
= {
197 .get
= fuse_xattr_get
,
198 .set
= fuse_xattr_set
,
201 const struct xattr_handler
*fuse_xattr_handlers
[] = {
206 const struct xattr_handler
*fuse_acl_xattr_handlers
[] = {
207 &posix_acl_access_xattr_handler
,
208 &posix_acl_default_xattr_handler
,