4 * Copyright IBM, Corp. 2010
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
14 #include "qemu/osdep.h"
16 #include "fsdev/file-op-9p.h"
22 static XattrOperations *get_xattr_operations(XattrOperations **h,
25 XattrOperations *xops;
26 for (xops = *(h)++; xops != NULL; xops = *(h)++) {
27 if (!strncmp(name, xops->name, strlen(xops->name))) {
34 ssize_t v9fs_get_xattr(FsContext *ctx, const char *path,
35 const char *name, void *value, size_t size)
37 XattrOperations *xops = get_xattr_operations(ctx->xops, name);
39 return xops->getxattr(ctx, path, name, value, size);
45 ssize_t pt_listxattr(FsContext *ctx, const char *path,
46 char *name, void *value, size_t size)
48 int name_size = strlen(name) + 1;
53 if (size < name_size) {
58 /* no need for strncpy: name_size is strlen(name)+1 */
59 memcpy(value, name, name_size);
63 static ssize_t flistxattrat_nofollow(int dirfd, const char *filename,
64 char *list, size_t size)
66 char *proc_path = g_strdup_printf("/proc/self/fd/%d/%s", dirfd, filename);
69 ret = llistxattr(proc_path, list, size);
75 * Get the list and pass to each layer to find out whether
76 * to send the data or not
78 ssize_t v9fs_list_xattr(FsContext *ctx, const char *path,
79 void *value, size_t vsize)
83 XattrOperations *xops;
84 char *orig_value, *orig_value_start;
85 ssize_t xattr_len, parsed_len = 0, attr_len;
89 /* Get the actual len */
90 dirpath = g_path_get_dirname(path);
91 dirfd = local_opendir_nofollow(ctx, dirpath);
97 name = g_path_get_basename(path);
98 xattr_len = flistxattrat_nofollow(dirfd, name, value, 0);
101 close_preserve_errno(dirfd);
105 /* Now fetch the xattr and find the actual size */
106 orig_value = g_malloc(xattr_len);
107 xattr_len = flistxattrat_nofollow(dirfd, name, orig_value, xattr_len);
109 close_preserve_errno(dirfd);
115 /* store the orig pointer */
116 orig_value_start = orig_value;
117 while (xattr_len > parsed_len) {
118 xops = get_xattr_operations(ctx->xops, orig_value);
124 size += xops->listxattr(ctx, path, orig_value, value, vsize);
126 size = xops->listxattr(ctx, path, orig_value, value, vsize);
134 /* Got the next entry */
135 attr_len = strlen(orig_value) + 1;
136 parsed_len += attr_len;
137 orig_value += attr_len;
140 size = value - ovalue;
144 g_free(orig_value_start);
148 int v9fs_set_xattr(FsContext *ctx, const char *path, const char *name,
149 void *value, size_t size, int flags)
151 XattrOperations *xops = get_xattr_operations(ctx->xops, name);
153 return xops->setxattr(ctx, path, name, value, size, flags);
160 int v9fs_remove_xattr(FsContext *ctx,
161 const char *path, const char *name)
163 XattrOperations *xops = get_xattr_operations(ctx->xops, name);
165 return xops->removexattr(ctx, path, name);
172 ssize_t local_getxattr_nofollow(FsContext *ctx, const char *path,
173 const char *name, void *value, size_t size)
175 char *dirpath = g_path_get_dirname(path);
176 char *filename = g_path_get_basename(path);
180 dirfd = local_opendir_nofollow(ctx, dirpath);
185 ret = fgetxattrat_nofollow(dirfd, filename, name, value, size);
186 close_preserve_errno(dirfd);
193 ssize_t pt_getxattr(FsContext *ctx, const char *path, const char *name,
194 void *value, size_t size)
196 return local_getxattr_nofollow(ctx, path, name, value, size);
199 int fsetxattrat_nofollow(int dirfd, const char *filename, const char *name,
200 void *value, size_t size, int flags)
202 char *proc_path = g_strdup_printf("/proc/self/fd/%d/%s", dirfd, filename);
205 ret = lsetxattr(proc_path, name, value, size, flags);
210 ssize_t local_setxattr_nofollow(FsContext *ctx, const char *path,
211 const char *name, void *value, size_t size,
214 char *dirpath = g_path_get_dirname(path);
215 char *filename = g_path_get_basename(path);
219 dirfd = local_opendir_nofollow(ctx, dirpath);
224 ret = fsetxattrat_nofollow(dirfd, filename, name, value, size, flags);
225 close_preserve_errno(dirfd);
232 int pt_setxattr(FsContext *ctx, const char *path, const char *name, void *value,
233 size_t size, int flags)
235 return local_setxattr_nofollow(ctx, path, name, value, size, flags);
238 static ssize_t fremovexattrat_nofollow(int dirfd, const char *filename,
241 char *proc_path = g_strdup_printf("/proc/self/fd/%d/%s", dirfd, filename);
244 ret = lremovexattr(proc_path, name);
249 ssize_t local_removexattr_nofollow(FsContext *ctx, const char *path,
252 char *dirpath = g_path_get_dirname(path);
253 char *filename = g_path_get_basename(path);
257 dirfd = local_opendir_nofollow(ctx, dirpath);
262 ret = fremovexattrat_nofollow(dirfd, filename, name);
263 close_preserve_errno(dirfd);
270 int pt_removexattr(FsContext *ctx, const char *path, const char *name)
272 return local_removexattr_nofollow(ctx, path, name);
275 ssize_t notsup_getxattr(FsContext *ctx, const char *path, const char *name,
276 void *value, size_t size)
282 int notsup_setxattr(FsContext *ctx, const char *path, const char *name,
283 void *value, size_t size, int flags)
289 ssize_t notsup_listxattr(FsContext *ctx, const char *path, char *name,
290 void *value, size_t size)
295 int notsup_removexattr(FsContext *ctx, const char *path, const char *name)
301 XattrOperations *mapped_xattr_ops[] = {
308 XattrOperations *passthrough_xattr_ops[] = {
309 &passthrough_user_xattr,
310 &passthrough_acl_xattr,
314 /* for .user none model should be same as passthrough */
315 XattrOperations *none_xattr_ops[] = {
316 &passthrough_user_xattr,