4 * Copyright IBM, Corp. 2010
7 * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
15 * Not so fast! You might want to read the 9p developer docs first:
16 * https://wiki.qemu.org/Documentation/9p
19 #include "qemu/osdep.h"
21 #include "fsdev/file-op-9p.h"
27 static XattrOperations
*get_xattr_operations(XattrOperations
**h
,
30 XattrOperations
*xops
;
31 for (xops
= *(h
)++; xops
!= NULL
; xops
= *(h
)++) {
32 if (!strncmp(name
, xops
->name
, strlen(xops
->name
))) {
39 ssize_t
v9fs_get_xattr(FsContext
*ctx
, const char *path
,
40 const char *name
, void *value
, size_t size
)
42 XattrOperations
*xops
= get_xattr_operations(ctx
->xops
, name
);
44 return xops
->getxattr(ctx
, path
, name
, value
, size
);
50 ssize_t
pt_listxattr(FsContext
*ctx
, const char *path
,
51 char *name
, void *value
, size_t size
)
53 int name_size
= strlen(name
) + 1;
58 if (size
< name_size
) {
63 /* no need for strncpy: name_size is strlen(name)+1 */
64 memcpy(value
, name
, name_size
);
69 * Get the list and pass to each layer to find out whether
70 * to send the data or not
72 ssize_t
v9fs_list_xattr(FsContext
*ctx
, const char *path
,
73 void *value
, size_t vsize
)
77 XattrOperations
*xops
;
78 char *orig_value
, *orig_value_start
;
79 ssize_t xattr_len
, parsed_len
= 0, attr_len
;
83 /* Get the actual len */
84 dirpath
= g_path_get_dirname(path
);
85 dirfd
= local_opendir_nofollow(ctx
, dirpath
);
91 name
= g_path_get_basename(path
);
92 xattr_len
= flistxattrat_nofollow(dirfd
, name
, value
, 0);
95 close_preserve_errno(dirfd
);
99 /* Now fetch the xattr and find the actual size */
100 orig_value
= g_malloc(xattr_len
);
101 xattr_len
= flistxattrat_nofollow(dirfd
, name
, orig_value
, xattr_len
);
103 close_preserve_errno(dirfd
);
109 /* store the orig pointer */
110 orig_value_start
= orig_value
;
111 while (xattr_len
> parsed_len
) {
112 xops
= get_xattr_operations(ctx
->xops
, orig_value
);
118 size
+= xops
->listxattr(ctx
, path
, orig_value
, value
, vsize
);
120 size
= xops
->listxattr(ctx
, path
, orig_value
, value
, vsize
);
128 /* Got the next entry */
129 attr_len
= strlen(orig_value
) + 1;
130 parsed_len
+= attr_len
;
131 orig_value
+= attr_len
;
134 size
= value
- ovalue
;
138 g_free(orig_value_start
);
142 int v9fs_set_xattr(FsContext
*ctx
, const char *path
, const char *name
,
143 void *value
, size_t size
, int flags
)
145 XattrOperations
*xops
= get_xattr_operations(ctx
->xops
, name
);
147 return xops
->setxattr(ctx
, path
, name
, value
, size
, flags
);
154 int v9fs_remove_xattr(FsContext
*ctx
,
155 const char *path
, const char *name
)
157 XattrOperations
*xops
= get_xattr_operations(ctx
->xops
, name
);
159 return xops
->removexattr(ctx
, path
, name
);
166 ssize_t
local_getxattr_nofollow(FsContext
*ctx
, const char *path
,
167 const char *name
, void *value
, size_t size
)
169 char *dirpath
= g_path_get_dirname(path
);
170 char *filename
= g_path_get_basename(path
);
174 dirfd
= local_opendir_nofollow(ctx
, dirpath
);
179 ret
= fgetxattrat_nofollow(dirfd
, filename
, name
, value
, size
);
180 close_preserve_errno(dirfd
);
187 ssize_t
pt_getxattr(FsContext
*ctx
, const char *path
, const char *name
,
188 void *value
, size_t size
)
190 return local_getxattr_nofollow(ctx
, path
, name
, value
, size
);
193 ssize_t
local_setxattr_nofollow(FsContext
*ctx
, const char *path
,
194 const char *name
, void *value
, size_t size
,
197 char *dirpath
= g_path_get_dirname(path
);
198 char *filename
= g_path_get_basename(path
);
202 dirfd
= local_opendir_nofollow(ctx
, dirpath
);
207 ret
= fsetxattrat_nofollow(dirfd
, filename
, name
, value
, size
, flags
);
208 close_preserve_errno(dirfd
);
215 int pt_setxattr(FsContext
*ctx
, const char *path
, const char *name
, void *value
,
216 size_t size
, int flags
)
218 return local_setxattr_nofollow(ctx
, path
, name
, value
, size
, flags
);
221 ssize_t
local_removexattr_nofollow(FsContext
*ctx
, const char *path
,
224 char *dirpath
= g_path_get_dirname(path
);
225 char *filename
= g_path_get_basename(path
);
229 dirfd
= local_opendir_nofollow(ctx
, dirpath
);
234 ret
= fremovexattrat_nofollow(dirfd
, filename
, name
);
235 close_preserve_errno(dirfd
);
242 int pt_removexattr(FsContext
*ctx
, const char *path
, const char *name
)
244 return local_removexattr_nofollow(ctx
, path
, name
);
247 ssize_t
notsup_getxattr(FsContext
*ctx
, const char *path
, const char *name
,
248 void *value
, size_t size
)
254 int notsup_setxattr(FsContext
*ctx
, const char *path
, const char *name
,
255 void *value
, size_t size
, int flags
)
261 ssize_t
notsup_listxattr(FsContext
*ctx
, const char *path
, char *name
,
262 void *value
, size_t size
)
267 int notsup_removexattr(FsContext
*ctx
, const char *path
, const char *name
)
273 XattrOperations
*mapped_xattr_ops
[] = {
280 XattrOperations
*passthrough_xattr_ops
[] = {
281 &passthrough_user_xattr
,
282 &passthrough_acl_xattr
,
286 /* for .user none model should be same as passthrough */
287 XattrOperations
*none_xattr_ops
[] = {
288 &passthrough_user_xattr
,