blob: 9ae69dd8dbc8526cab1f75592a5db7d307e30d60 [file] [log] [blame]
Aneesh Kumar K.Vfc221182010-10-18 15:28:16 +05301/*
Wei Liu267ae092015-11-18 18:31:52 +00002 * 9p xattr callback
Aneesh Kumar K.Vfc221182010-10-18 15:28:16 +05303 *
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
Christian Schoenebeck6f569082021-05-06 15:12:23 +020014/*
15 * Not so fast! You might want to read the 9p developer docs first:
16 * https://wiki.qemu.org/Documentation/9p
17 */
18
Peter Maydellfbc04122016-01-26 18:17:10 +000019#include "qemu/osdep.h"
Wei Liuebe74f82016-01-07 18:18:02 +000020#include "9p.h"
Aneesh Kumar K.V353ac782011-01-28 18:09:08 +053021#include "fsdev/file-op-9p.h"
Wei Liu267ae092015-11-18 18:31:52 +000022#include "9p-xattr.h"
Greg Kurz56ad3e52017-02-26 23:42:26 +010023#include "9p-util.h"
24#include "9p-local.h"
Aneesh Kumar K.Vfc221182010-10-18 15:28:16 +053025
26
27static XattrOperations *get_xattr_operations(XattrOperations **h,
28 const char *name)
29{
30 XattrOperations *xops;
31 for (xops = *(h)++; xops != NULL; xops = *(h)++) {
32 if (!strncmp(name, xops->name, strlen(xops->name))) {
33 return xops;
34 }
35 }
36 return NULL;
37}
38
39ssize_t v9fs_get_xattr(FsContext *ctx, const char *path,
40 const char *name, void *value, size_t size)
41{
42 XattrOperations *xops = get_xattr_operations(ctx->xops, name);
43 if (xops) {
44 return xops->getxattr(ctx, path, name, value, size);
45 }
Daniel P. Berrange8af00202013-10-01 12:28:17 +010046 errno = EOPNOTSUPP;
Aneesh Kumar K.Vfc221182010-10-18 15:28:16 +053047 return -1;
48}
49
50ssize_t pt_listxattr(FsContext *ctx, const char *path,
51 char *name, void *value, size_t size)
52{
53 int name_size = strlen(name) + 1;
54 if (!value) {
55 return name_size;
56 }
57
58 if (size < name_size) {
59 errno = ERANGE;
60 return -1;
61 }
62
Jim Meyering9238c202012-10-04 13:09:56 +020063 /* no need for strncpy: name_size is strlen(name)+1 */
64 memcpy(value, name, name_size);
Aneesh Kumar K.Vfc221182010-10-18 15:28:16 +053065 return name_size;
66}
67
Aneesh Kumar K.Vfc221182010-10-18 15:28:16 +053068/*
69 * Get the list and pass to each layer to find out whether
70 * to send the data or not
71 */
72ssize_t v9fs_list_xattr(FsContext *ctx, const char *path,
73 void *value, size_t vsize)
74{
75 ssize_t size = 0;
76 void *ovalue = value;
77 XattrOperations *xops;
78 char *orig_value, *orig_value_start;
79 ssize_t xattr_len, parsed_len = 0, attr_len;
Greg Kurz55079042017-02-26 23:42:34 +010080 char *dirpath, *name;
81 int dirfd;
Aneesh Kumar K.Vfc221182010-10-18 15:28:16 +053082
83 /* Get the actual len */
Greg Kurz55079042017-02-26 23:42:34 +010084 dirpath = g_path_get_dirname(path);
85 dirfd = local_opendir_nofollow(ctx, dirpath);
86 g_free(dirpath);
87 if (dirfd == -1) {
88 return -1;
89 }
90
91 name = g_path_get_basename(path);
92 xattr_len = flistxattrat_nofollow(dirfd, name, value, 0);
Kusanagi Kouichi0562c672010-10-30 11:52:39 +090093 if (xattr_len <= 0) {
Greg Kurz55079042017-02-26 23:42:34 +010094 g_free(name);
95 close_preserve_errno(dirfd);
Kusanagi Kouichi0562c672010-10-30 11:52:39 +090096 return xattr_len;
97 }
Aneesh Kumar K.Vfc221182010-10-18 15:28:16 +053098
99 /* Now fetch the xattr and find the actual size */
Anthony Liguori7267c092011-08-20 22:09:37 -0500100 orig_value = g_malloc(xattr_len);
Greg Kurz55079042017-02-26 23:42:34 +0100101 xattr_len = flistxattrat_nofollow(dirfd, name, orig_value, xattr_len);
102 g_free(name);
103 close_preserve_errno(dirfd);
104 if (xattr_len < 0) {
Li Qiang4ffcdef2017-04-07 03:48:52 -0700105 g_free(orig_value);
Greg Kurz55079042017-02-26 23:42:34 +0100106 return -1;
107 }
Aneesh Kumar K.Vfc221182010-10-18 15:28:16 +0530108
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);
113 if (!xops) {
114 goto next_entry;
115 }
116
117 if (!value) {
118 size += xops->listxattr(ctx, path, orig_value, value, vsize);
119 } else {
120 size = xops->listxattr(ctx, path, orig_value, value, vsize);
121 if (size < 0) {
122 goto err_out;
123 }
124 value += size;
125 vsize -= size;
126 }
127next_entry:
128 /* Got the next entry */
129 attr_len = strlen(orig_value) + 1;
130 parsed_len += attr_len;
131 orig_value += attr_len;
132 }
133 if (value) {
134 size = value - ovalue;
135 }
136
137err_out:
Anthony Liguori7267c092011-08-20 22:09:37 -0500138 g_free(orig_value_start);
Aneesh Kumar K.Vfc221182010-10-18 15:28:16 +0530139 return size;
140}
141
142int v9fs_set_xattr(FsContext *ctx, const char *path, const char *name,
143 void *value, size_t size, int flags)
144{
145 XattrOperations *xops = get_xattr_operations(ctx->xops, name);
146 if (xops) {
147 return xops->setxattr(ctx, path, name, value, size, flags);
148 }
Daniel P. Berrange8af00202013-10-01 12:28:17 +0100149 errno = EOPNOTSUPP;
Aneesh Kumar K.Vfc221182010-10-18 15:28:16 +0530150 return -1;
151
152}
153
154int v9fs_remove_xattr(FsContext *ctx,
155 const char *path, const char *name)
156{
157 XattrOperations *xops = get_xattr_operations(ctx->xops, name);
158 if (xops) {
159 return xops->removexattr(ctx, path, name);
160 }
Daniel P. Berrange8af00202013-10-01 12:28:17 +0100161 errno = EOPNOTSUPP;
Aneesh Kumar K.Vfc221182010-10-18 15:28:16 +0530162 return -1;
163
164}
165
Greg Kurz56ad3e52017-02-26 23:42:26 +0100166ssize_t local_getxattr_nofollow(FsContext *ctx, const char *path,
167 const char *name, void *value, size_t size)
168{
169 char *dirpath = g_path_get_dirname(path);
170 char *filename = g_path_get_basename(path);
171 int dirfd;
172 ssize_t ret = -1;
173
174 dirfd = local_opendir_nofollow(ctx, dirpath);
175 if (dirfd == -1) {
176 goto out;
177 }
178
179 ret = fgetxattrat_nofollow(dirfd, filename, name, value, size);
180 close_preserve_errno(dirfd);
181out:
182 g_free(dirpath);
183 g_free(filename);
184 return ret;
185}
186
Greg Kurz56fc4942017-02-26 23:41:40 +0100187ssize_t pt_getxattr(FsContext *ctx, const char *path, const char *name,
188 void *value, size_t size)
189{
Greg Kurz56ad3e52017-02-26 23:42:26 +0100190 return local_getxattr_nofollow(ctx, path, name, value, size);
Greg Kurz56fc4942017-02-26 23:41:40 +0100191}
192
Greg Kurz3e36aba2017-02-26 23:42:43 +0100193ssize_t local_setxattr_nofollow(FsContext *ctx, const char *path,
194 const char *name, void *value, size_t size,
195 int flags)
196{
197 char *dirpath = g_path_get_dirname(path);
198 char *filename = g_path_get_basename(path);
199 int dirfd;
200 ssize_t ret = -1;
201
202 dirfd = local_opendir_nofollow(ctx, dirpath);
203 if (dirfd == -1) {
204 goto out;
205 }
206
207 ret = fsetxattrat_nofollow(dirfd, filename, name, value, size, flags);
208 close_preserve_errno(dirfd);
209out:
210 g_free(dirpath);
211 g_free(filename);
212 return ret;
213}
214
Greg Kurz56fc4942017-02-26 23:41:40 +0100215int pt_setxattr(FsContext *ctx, const char *path, const char *name, void *value,
216 size_t size, int flags)
217{
Greg Kurz3e36aba2017-02-26 23:42:43 +0100218 return local_setxattr_nofollow(ctx, path, name, value, size, flags);
Greg Kurz56fc4942017-02-26 23:41:40 +0100219}
220
Greg Kurz72f0d0b2017-02-26 23:42:51 +0100221ssize_t local_removexattr_nofollow(FsContext *ctx, const char *path,
222 const char *name)
223{
224 char *dirpath = g_path_get_dirname(path);
225 char *filename = g_path_get_basename(path);
226 int dirfd;
227 ssize_t ret = -1;
228
229 dirfd = local_opendir_nofollow(ctx, dirpath);
230 if (dirfd == -1) {
231 goto out;
232 }
233
234 ret = fremovexattrat_nofollow(dirfd, filename, name);
235 close_preserve_errno(dirfd);
236out:
237 g_free(dirpath);
238 g_free(filename);
239 return ret;
240}
241
242int pt_removexattr(FsContext *ctx, const char *path, const char *name)
243{
244 return local_removexattr_nofollow(ctx, path, name);
245}
246
Greg Kurz56fc4942017-02-26 23:41:40 +0100247ssize_t notsup_getxattr(FsContext *ctx, const char *path, const char *name,
248 void *value, size_t size)
249{
250 errno = ENOTSUP;
251 return -1;
252}
253
254int notsup_setxattr(FsContext *ctx, const char *path, const char *name,
255 void *value, size_t size, int flags)
256{
257 errno = ENOTSUP;
258 return -1;
259}
260
261ssize_t notsup_listxattr(FsContext *ctx, const char *path, char *name,
262 void *value, size_t size)
263{
264 return 0;
265}
266
267int notsup_removexattr(FsContext *ctx, const char *path, const char *name)
268{
269 errno = ENOTSUP;
270 return -1;
271}
272
Aneesh Kumar K.Vfc221182010-10-18 15:28:16 +0530273XattrOperations *mapped_xattr_ops[] = {
274 &mapped_user_xattr,
Aneesh Kumar K.V70fc55e2010-10-18 15:28:16 +0530275 &mapped_pacl_xattr,
276 &mapped_dacl_xattr,
Aneesh Kumar K.Vfc221182010-10-18 15:28:16 +0530277 NULL,
278};
279
280XattrOperations *passthrough_xattr_ops[] = {
281 &passthrough_user_xattr,
Aneesh Kumar K.V70fc55e2010-10-18 15:28:16 +0530282 &passthrough_acl_xattr,
Aneesh Kumar K.Vfc221182010-10-18 15:28:16 +0530283 NULL,
284};
285
286/* for .user none model should be same as passthrough */
287XattrOperations *none_xattr_ops[] = {
288 &passthrough_user_xattr,
Aneesh Kumar K.V70fc55e2010-10-18 15:28:16 +0530289 &none_acl_xattr,
Aneesh Kumar K.Vfc221182010-10-18 15:28:16 +0530290 NULL,
291};