]>
Commit | Line | Data |
---|---|---|
fc22118d AK |
1 | /* |
2 | * Virtio 9p xattr callback | |
3 | * | |
4 | * Copyright IBM, Corp. 2010 | |
5 | * | |
6 | * Authors: | |
7 | * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | |
8 | * | |
9 | * This work is licensed under the terms of the GNU GPL, version 2. See | |
10 | * the COPYING file in the top-level directory. | |
11 | * | |
12 | */ | |
13 | ||
0d09e41a | 14 | #include "hw/virtio/virtio.h" |
fc22118d | 15 | #include "virtio-9p.h" |
353ac78d | 16 | #include "fsdev/file-op-9p.h" |
fc22118d AK |
17 | #include "virtio-9p-xattr.h" |
18 | ||
19 | ||
20 | static XattrOperations *get_xattr_operations(XattrOperations **h, | |
21 | const char *name) | |
22 | { | |
23 | XattrOperations *xops; | |
24 | for (xops = *(h)++; xops != NULL; xops = *(h)++) { | |
25 | if (!strncmp(name, xops->name, strlen(xops->name))) { | |
26 | return xops; | |
27 | } | |
28 | } | |
29 | return NULL; | |
30 | } | |
31 | ||
32 | ssize_t v9fs_get_xattr(FsContext *ctx, const char *path, | |
33 | const char *name, void *value, size_t size) | |
34 | { | |
35 | XattrOperations *xops = get_xattr_operations(ctx->xops, name); | |
36 | if (xops) { | |
37 | return xops->getxattr(ctx, path, name, value, size); | |
38 | } | |
8af00205 | 39 | errno = EOPNOTSUPP; |
fc22118d AK |
40 | return -1; |
41 | } | |
42 | ||
43 | ssize_t pt_listxattr(FsContext *ctx, const char *path, | |
44 | char *name, void *value, size_t size) | |
45 | { | |
46 | int name_size = strlen(name) + 1; | |
47 | if (!value) { | |
48 | return name_size; | |
49 | } | |
50 | ||
51 | if (size < name_size) { | |
52 | errno = ERANGE; | |
53 | return -1; | |
54 | } | |
55 | ||
9238c209 JM |
56 | /* no need for strncpy: name_size is strlen(name)+1 */ |
57 | memcpy(value, name, name_size); | |
fc22118d AK |
58 | return name_size; |
59 | } | |
60 | ||
61 | ||
62 | /* | |
63 | * Get the list and pass to each layer to find out whether | |
64 | * to send the data or not | |
65 | */ | |
66 | ssize_t v9fs_list_xattr(FsContext *ctx, const char *path, | |
67 | void *value, size_t vsize) | |
68 | { | |
69 | ssize_t size = 0; | |
faa44e3d | 70 | char buffer[PATH_MAX]; |
fc22118d AK |
71 | void *ovalue = value; |
72 | XattrOperations *xops; | |
73 | char *orig_value, *orig_value_start; | |
74 | ssize_t xattr_len, parsed_len = 0, attr_len; | |
75 | ||
76 | /* Get the actual len */ | |
faa44e3d | 77 | xattr_len = llistxattr(rpath(ctx, path, buffer), value, 0); |
0562c674 KK |
78 | if (xattr_len <= 0) { |
79 | return xattr_len; | |
80 | } | |
fc22118d AK |
81 | |
82 | /* Now fetch the xattr and find the actual size */ | |
7267c094 | 83 | orig_value = g_malloc(xattr_len); |
faa44e3d | 84 | xattr_len = llistxattr(rpath(ctx, path, buffer), orig_value, xattr_len); |
fc22118d AK |
85 | |
86 | /* store the orig pointer */ | |
87 | orig_value_start = orig_value; | |
88 | while (xattr_len > parsed_len) { | |
89 | xops = get_xattr_operations(ctx->xops, orig_value); | |
90 | if (!xops) { | |
91 | goto next_entry; | |
92 | } | |
93 | ||
94 | if (!value) { | |
95 | size += xops->listxattr(ctx, path, orig_value, value, vsize); | |
96 | } else { | |
97 | size = xops->listxattr(ctx, path, orig_value, value, vsize); | |
98 | if (size < 0) { | |
99 | goto err_out; | |
100 | } | |
101 | value += size; | |
102 | vsize -= size; | |
103 | } | |
104 | next_entry: | |
105 | /* Got the next entry */ | |
106 | attr_len = strlen(orig_value) + 1; | |
107 | parsed_len += attr_len; | |
108 | orig_value += attr_len; | |
109 | } | |
110 | if (value) { | |
111 | size = value - ovalue; | |
112 | } | |
113 | ||
114 | err_out: | |
7267c094 | 115 | g_free(orig_value_start); |
fc22118d AK |
116 | return size; |
117 | } | |
118 | ||
119 | int v9fs_set_xattr(FsContext *ctx, const char *path, const char *name, | |
120 | void *value, size_t size, int flags) | |
121 | { | |
122 | XattrOperations *xops = get_xattr_operations(ctx->xops, name); | |
123 | if (xops) { | |
124 | return xops->setxattr(ctx, path, name, value, size, flags); | |
125 | } | |
8af00205 | 126 | errno = EOPNOTSUPP; |
fc22118d AK |
127 | return -1; |
128 | ||
129 | } | |
130 | ||
131 | int v9fs_remove_xattr(FsContext *ctx, | |
132 | const char *path, const char *name) | |
133 | { | |
134 | XattrOperations *xops = get_xattr_operations(ctx->xops, name); | |
135 | if (xops) { | |
136 | return xops->removexattr(ctx, path, name); | |
137 | } | |
8af00205 | 138 | errno = EOPNOTSUPP; |
fc22118d AK |
139 | return -1; |
140 | ||
141 | } | |
142 | ||
143 | XattrOperations *mapped_xattr_ops[] = { | |
144 | &mapped_user_xattr, | |
70fc55eb AK |
145 | &mapped_pacl_xattr, |
146 | &mapped_dacl_xattr, | |
fc22118d AK |
147 | NULL, |
148 | }; | |
149 | ||
150 | XattrOperations *passthrough_xattr_ops[] = { | |
151 | &passthrough_user_xattr, | |
70fc55eb | 152 | &passthrough_acl_xattr, |
fc22118d AK |
153 | NULL, |
154 | }; | |
155 | ||
156 | /* for .user none model should be same as passthrough */ | |
157 | XattrOperations *none_xattr_ops[] = { | |
158 | &passthrough_user_xattr, | |
70fc55eb | 159 | &none_acl_xattr, |
fc22118d AK |
160 | NULL, |
161 | }; |