]> git.proxmox.com Git - qemu.git/blame - hw/9pfs/virtio-9p-local.c
hw/9pfs: Move fid pathname tracking to seperate data type.
[qemu.git] / hw / 9pfs / virtio-9p-local.c
CommitLineData
9f107513
AL
1/*
2 * Virtio 9p Posix callback
3 *
4 * Copyright IBM, Corp. 2010
5 *
6 * Authors:
7 * Anthony Liguori <aliguori@us.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 */
873c3213
SW
13
14#include "hw/virtio.h"
9f107513 15#include "virtio-9p.h"
fc22118d 16#include "virtio-9p-xattr.h"
c494dd6f 17#include <arpa/inet.h>
131dcb25
AL
18#include <pwd.h>
19#include <grp.h>
c494dd6f
AL
20#include <sys/socket.h>
21#include <sys/un.h>
758e8e38 22#include <attr/xattr.h>
131dcb25 23
1237ad76 24
2289be19 25static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
131dcb25 26{
1237ad76 27 int err;
faa44e3d 28 char buffer[PATH_MAX];
2289be19
AK
29 char *path = fs_path->data;
30
faa44e3d 31 err = lstat(rpath(fs_ctx, path, buffer), stbuf);
1237ad76
VJJ
32 if (err) {
33 return err;
34 }
35 if (fs_ctx->fs_sm == SM_MAPPED) {
36 /* Actual credentials are part of extended attrs */
37 uid_t tmp_uid;
38 gid_t tmp_gid;
39 mode_t tmp_mode;
40 dev_t tmp_dev;
faa44e3d 41 if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.uid", &tmp_uid,
1237ad76
VJJ
42 sizeof(uid_t)) > 0) {
43 stbuf->st_uid = tmp_uid;
44 }
faa44e3d 45 if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.gid", &tmp_gid,
1237ad76
VJJ
46 sizeof(gid_t)) > 0) {
47 stbuf->st_gid = tmp_gid;
48 }
faa44e3d
VJJ
49 if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.mode",
50 &tmp_mode, sizeof(mode_t)) > 0) {
1237ad76
VJJ
51 stbuf->st_mode = tmp_mode;
52 }
faa44e3d 53 if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.rdev", &tmp_dev,
1237ad76
VJJ
54 sizeof(dev_t)) > 0) {
55 stbuf->st_rdev = tmp_dev;
56 }
57 }
58 return err;
131dcb25
AL
59}
60
758e8e38 61static int local_set_xattr(const char *path, FsCred *credp)
131dcb25 62{
758e8e38 63 int err;
2289be19 64
758e8e38
VJJ
65 if (credp->fc_uid != -1) {
66 err = setxattr(path, "user.virtfs.uid", &credp->fc_uid, sizeof(uid_t),
67 0);
68 if (err) {
69 return err;
70 }
131dcb25 71 }
758e8e38
VJJ
72 if (credp->fc_gid != -1) {
73 err = setxattr(path, "user.virtfs.gid", &credp->fc_gid, sizeof(gid_t),
74 0);
75 if (err) {
76 return err;
77 }
131dcb25 78 }
758e8e38
VJJ
79 if (credp->fc_mode != -1) {
80 err = setxattr(path, "user.virtfs.mode", &credp->fc_mode,
81 sizeof(mode_t), 0);
82 if (err) {
83 return err;
84 }
131dcb25 85 }
758e8e38
VJJ
86 if (credp->fc_rdev != -1) {
87 err = setxattr(path, "user.virtfs.rdev", &credp->fc_rdev,
88 sizeof(dev_t), 0);
89 if (err) {
90 return err;
91 }
131dcb25 92 }
131dcb25
AL
93 return 0;
94}
95
4750a96f 96static int local_post_create_passthrough(FsContext *fs_ctx, const char *path,
2289be19 97 FsCred *credp)
4750a96f 98{
faa44e3d 99 char buffer[PATH_MAX];
2289be19 100
faa44e3d 101 if (chmod(rpath(fs_ctx, path, buffer), credp->fc_mode & 07777) < 0) {
4750a96f
VJJ
102 return -1;
103 }
faa44e3d
VJJ
104 if (lchown(rpath(fs_ctx, path, buffer), credp->fc_uid,
105 credp->fc_gid) < 0) {
12848bfc
AK
106 /*
107 * If we fail to change ownership and if we are
108 * using security model none. Ignore the error
109 */
110 if (fs_ctx->fs_sm != SM_NONE) {
111 return -1;
112 }
4750a96f
VJJ
113 }
114 return 0;
115}
116
2289be19
AK
117static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
118 char *buf, size_t bufsz)
131dcb25 119{
879c2813 120 ssize_t tsize = -1;
faa44e3d 121 char buffer[PATH_MAX];
2289be19
AK
122 char *path = fs_path->data;
123
879c2813
VJJ
124 if (fs_ctx->fs_sm == SM_MAPPED) {
125 int fd;
faa44e3d 126 fd = open(rpath(fs_ctx, path, buffer), O_RDONLY);
879c2813
VJJ
127 if (fd == -1) {
128 return -1;
129 }
130 do {
131 tsize = read(fd, (void *)buf, bufsz);
132 } while (tsize == -1 && errno == EINTR);
133 close(fd);
134 return tsize;
12848bfc
AK
135 } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
136 (fs_ctx->fs_sm == SM_NONE)) {
faa44e3d 137 tsize = readlink(rpath(fs_ctx, path, buffer), buf, bufsz);
879c2813
VJJ
138 }
139 return tsize;
131dcb25
AL
140}
141
142static int local_close(FsContext *ctx, int fd)
143{
144 return close(fd);
145}
146
147static int local_closedir(FsContext *ctx, DIR *dir)
148{
149 return closedir(dir);
150}
9f107513 151
2289be19 152static int local_open(FsContext *ctx, V9fsPath *fs_path, int flags)
a6568fe2 153{
faa44e3d 154 char buffer[PATH_MAX];
2289be19
AK
155 char *path = fs_path->data;
156
faa44e3d 157 return open(rpath(ctx, path, buffer), flags);
a6568fe2
AL
158}
159
2289be19 160static DIR *local_opendir(FsContext *ctx, V9fsPath *fs_path)
a6568fe2 161{
faa44e3d 162 char buffer[PATH_MAX];
2289be19
AK
163 char *path = fs_path->data;
164
faa44e3d 165 return opendir(rpath(ctx, path, buffer));
a6568fe2
AL
166}
167
a9231555
AL
168static void local_rewinddir(FsContext *ctx, DIR *dir)
169{
170 return rewinddir(dir);
171}
172
173static off_t local_telldir(FsContext *ctx, DIR *dir)
174{
175 return telldir(dir);
176}
177
5f524c1e 178static int local_readdir_r(FsContext *ctx, DIR *dir, struct dirent *entry,
2289be19 179 struct dirent **result)
a9231555 180{
5f524c1e 181 return readdir_r(dir, entry, result);
a9231555
AL
182}
183
184static void local_seekdir(FsContext *ctx, DIR *dir, off_t off)
185{
186 return seekdir(dir, off);
187}
188
56d15a53
SG
189static ssize_t local_preadv(FsContext *ctx, int fd, const struct iovec *iov,
190 int iovcnt, off_t offset)
a9231555 191{
56d15a53
SG
192#ifdef CONFIG_PREADV
193 return preadv(fd, iov, iovcnt, offset);
194#else
195 int err = lseek(fd, offset, SEEK_SET);
196 if (err == -1) {
197 return err;
198 } else {
199 return readv(fd, iov, iovcnt);
200 }
201#endif
a9231555
AL
202}
203
56d15a53 204static ssize_t local_pwritev(FsContext *ctx, int fd, const struct iovec *iov,
2289be19 205 int iovcnt, off_t offset)
8449360c 206{
56d15a53
SG
207#ifdef CONFIG_PREADV
208 return pwritev(fd, iov, iovcnt, offset);
209#else
210 int err = lseek(fd, offset, SEEK_SET);
211 if (err == -1) {
212 return err;
213 } else {
214 return writev(fd, iov, iovcnt);
215 }
216#endif
8449360c
AL
217}
218
2289be19 219static int local_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
c494dd6f 220{
faa44e3d 221 char buffer[PATH_MAX];
2289be19
AK
222 char *path = fs_path->data;
223
e95ead32 224 if (fs_ctx->fs_sm == SM_MAPPED) {
faa44e3d 225 return local_set_xattr(rpath(fs_ctx, path, buffer), credp);
12848bfc
AK
226 } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
227 (fs_ctx->fs_sm == SM_NONE)) {
faa44e3d 228 return chmod(rpath(fs_ctx, path, buffer), credp->fc_mode);
e95ead32
VJJ
229 }
230 return -1;
c494dd6f
AL
231}
232
2289be19
AK
233static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
234 const char *name, FsCred *credp)
c494dd6f 235{
2289be19 236 char *path;
1c293312
VJJ
237 int err = -1;
238 int serrno = 0;
2289be19 239 V9fsString fullname;
faa44e3d 240 char buffer[PATH_MAX];
1c293312 241
2289be19
AK
242 v9fs_string_init(&fullname);
243 v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
244 path = fullname.data;
245
1c293312
VJJ
246 /* Determine the security model */
247 if (fs_ctx->fs_sm == SM_MAPPED) {
faa44e3d
VJJ
248 err = mknod(rpath(fs_ctx, path, buffer),
249 SM_LOCAL_MODE_BITS|S_IFREG, 0);
1c293312 250 if (err == -1) {
2289be19 251 goto out;
1c293312 252 }
faa44e3d 253 local_set_xattr(rpath(fs_ctx, path, buffer), credp);
1c293312
VJJ
254 if (err == -1) {
255 serrno = errno;
256 goto err_end;
257 }
12848bfc
AK
258 } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
259 (fs_ctx->fs_sm == SM_NONE)) {
faa44e3d
VJJ
260 err = mknod(rpath(fs_ctx, path, buffer), credp->fc_mode,
261 credp->fc_rdev);
1c293312 262 if (err == -1) {
2289be19 263 goto out;
1c293312
VJJ
264 }
265 err = local_post_create_passthrough(fs_ctx, path, credp);
266 if (err == -1) {
267 serrno = errno;
268 goto err_end;
269 }
270 }
2289be19 271 goto out;
1c293312
VJJ
272
273err_end:
faa44e3d 274 remove(rpath(fs_ctx, path, buffer));
1c293312 275 errno = serrno;
2289be19
AK
276out:
277 v9fs_string_free(&fullname);
1c293312 278 return err;
c494dd6f
AL
279}
280
2289be19
AK
281static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
282 const char *name, FsCred *credp)
c494dd6f 283{
2289be19 284 char *path;
00ec5c37
VJJ
285 int err = -1;
286 int serrno = 0;
2289be19 287 V9fsString fullname;
faa44e3d 288 char buffer[PATH_MAX];
00ec5c37 289
2289be19
AK
290 v9fs_string_init(&fullname);
291 v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
292 path = fullname.data;
293
00ec5c37
VJJ
294 /* Determine the security model */
295 if (fs_ctx->fs_sm == SM_MAPPED) {
faa44e3d 296 err = mkdir(rpath(fs_ctx, path, buffer), SM_LOCAL_DIR_MODE_BITS);
00ec5c37 297 if (err == -1) {
2289be19 298 goto out;
00ec5c37
VJJ
299 }
300 credp->fc_mode = credp->fc_mode|S_IFDIR;
faa44e3d 301 err = local_set_xattr(rpath(fs_ctx, path, buffer), credp);
00ec5c37
VJJ
302 if (err == -1) {
303 serrno = errno;
304 goto err_end;
305 }
12848bfc
AK
306 } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
307 (fs_ctx->fs_sm == SM_NONE)) {
faa44e3d 308 err = mkdir(rpath(fs_ctx, path, buffer), credp->fc_mode);
00ec5c37 309 if (err == -1) {
2289be19 310 goto out;
00ec5c37
VJJ
311 }
312 err = local_post_create_passthrough(fs_ctx, path, credp);
313 if (err == -1) {
314 serrno = errno;
315 goto err_end;
316 }
317 }
2289be19 318 goto out;
00ec5c37
VJJ
319
320err_end:
faa44e3d 321 remove(rpath(fs_ctx, path, buffer));
00ec5c37 322 errno = serrno;
2289be19
AK
323out:
324 v9fs_string_free(&fullname);
00ec5c37 325 return err;
c494dd6f
AL
326}
327
1237ad76 328static int local_fstat(FsContext *fs_ctx, int fd, struct stat *stbuf)
c494dd6f 329{
1237ad76
VJJ
330 int err;
331 err = fstat(fd, stbuf);
332 if (err) {
333 return err;
334 }
335 if (fs_ctx->fs_sm == SM_MAPPED) {
336 /* Actual credentials are part of extended attrs */
337 uid_t tmp_uid;
338 gid_t tmp_gid;
339 mode_t tmp_mode;
340 dev_t tmp_dev;
341
342 if (fgetxattr(fd, "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) {
343 stbuf->st_uid = tmp_uid;
344 }
345 if (fgetxattr(fd, "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) {
346 stbuf->st_gid = tmp_gid;
347 }
348 if (fgetxattr(fd, "user.virtfs.mode", &tmp_mode, sizeof(mode_t)) > 0) {
349 stbuf->st_mode = tmp_mode;
350 }
351 if (fgetxattr(fd, "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) {
352 stbuf->st_rdev = tmp_dev;
353 }
354 }
355 return err;
c494dd6f
AL
356}
357
2289be19
AK
358static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
359 int flags, FsCred *credp)
c494dd6f 360{
2289be19 361 char *path;
4750a96f
VJJ
362 int fd = -1;
363 int err = -1;
364 int serrno = 0;
2289be19 365 V9fsString fullname;
faa44e3d 366 char buffer[PATH_MAX];
4750a96f 367
2289be19
AK
368 v9fs_string_init(&fullname);
369 v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
370 path = fullname.data;
371
4750a96f
VJJ
372 /* Determine the security model */
373 if (fs_ctx->fs_sm == SM_MAPPED) {
faa44e3d 374 fd = open(rpath(fs_ctx, path, buffer), flags, SM_LOCAL_MODE_BITS);
4750a96f 375 if (fd == -1) {
2289be19
AK
376 err = fd;
377 goto out;
4750a96f
VJJ
378 }
379 credp->fc_mode = credp->fc_mode|S_IFREG;
380 /* Set cleint credentials in xattr */
faa44e3d 381 err = local_set_xattr(rpath(fs_ctx, path, buffer), credp);
4750a96f
VJJ
382 if (err == -1) {
383 serrno = errno;
384 goto err_end;
385 }
12848bfc
AK
386 } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
387 (fs_ctx->fs_sm == SM_NONE)) {
faa44e3d 388 fd = open(rpath(fs_ctx, path, buffer), flags, credp->fc_mode);
4750a96f 389 if (fd == -1) {
2289be19
AK
390 err = fd;
391 goto out;
4750a96f
VJJ
392 }
393 err = local_post_create_passthrough(fs_ctx, path, credp);
394 if (err == -1) {
395 serrno = errno;
396 goto err_end;
397 }
398 }
2289be19
AK
399 err = fd;
400 goto out;
4750a96f
VJJ
401
402err_end:
403 close(fd);
faa44e3d 404 remove(rpath(fs_ctx, path, buffer));
4750a96f 405 errno = serrno;
2289be19
AK
406out:
407 v9fs_string_free(&fullname);
4750a96f 408 return err;
c494dd6f
AL
409}
410
758e8e38 411
879c2813 412static int local_symlink(FsContext *fs_ctx, const char *oldpath,
2289be19 413 V9fsPath *dir_path, const char *name, FsCred *credp)
c494dd6f 414{
879c2813
VJJ
415 int err = -1;
416 int serrno = 0;
2289be19
AK
417 char *newpath;
418 V9fsString fullname;
faa44e3d 419 char buffer[PATH_MAX];
879c2813 420
2289be19
AK
421 v9fs_string_init(&fullname);
422 v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
423 newpath = fullname.data;
424
879c2813
VJJ
425 /* Determine the security model */
426 if (fs_ctx->fs_sm == SM_MAPPED) {
427 int fd;
428 ssize_t oldpath_size, write_size;
faa44e3d 429 fd = open(rpath(fs_ctx, newpath, buffer), O_CREAT|O_EXCL|O_RDWR,
879c2813
VJJ
430 SM_LOCAL_MODE_BITS);
431 if (fd == -1) {
2289be19
AK
432 err = fd;
433 goto out;
879c2813
VJJ
434 }
435 /* Write the oldpath (target) to the file. */
f35bde2f 436 oldpath_size = strlen(oldpath);
879c2813
VJJ
437 do {
438 write_size = write(fd, (void *)oldpath, oldpath_size);
439 } while (write_size == -1 && errno == EINTR);
440
441 if (write_size != oldpath_size) {
442 serrno = errno;
443 close(fd);
444 err = -1;
445 goto err_end;
446 }
447 close(fd);
448 /* Set cleint credentials in symlink's xattr */
449 credp->fc_mode = credp->fc_mode|S_IFLNK;
faa44e3d 450 err = local_set_xattr(rpath(fs_ctx, newpath, buffer), credp);
879c2813
VJJ
451 if (err == -1) {
452 serrno = errno;
453 goto err_end;
454 }
12848bfc
AK
455 } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
456 (fs_ctx->fs_sm == SM_NONE)) {
faa44e3d 457 err = symlink(oldpath, rpath(fs_ctx, newpath, buffer));
879c2813 458 if (err) {
2289be19 459 goto out;
879c2813 460 }
faa44e3d 461 err = lchown(rpath(fs_ctx, newpath, buffer), credp->fc_uid,
2289be19 462 credp->fc_gid);
879c2813 463 if (err == -1) {
12848bfc
AK
464 /*
465 * If we fail to change ownership and if we are
466 * using security model none. Ignore the error
467 */
468 if (fs_ctx->fs_sm != SM_NONE) {
469 serrno = errno;
470 goto err_end;
471 } else
472 err = 0;
879c2813
VJJ
473 }
474 }
2289be19 475 goto out;
879c2813
VJJ
476
477err_end:
faa44e3d 478 remove(rpath(fs_ctx, newpath, buffer));
879c2813 479 errno = serrno;
2289be19
AK
480out:
481 v9fs_string_free(&fullname);
879c2813 482 return err;
c494dd6f
AL
483}
484
2289be19
AK
485static int local_link(FsContext *ctx, V9fsPath *oldpath,
486 V9fsPath *dirpath, const char *name)
c494dd6f 487{
2289be19
AK
488 int ret;
489 V9fsString newpath;
faa44e3d 490 char buffer[PATH_MAX], buffer1[PATH_MAX];
c494dd6f 491
2289be19
AK
492 v9fs_string_init(&newpath);
493 v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name);
494
495 ret = link(rpath(ctx, oldpath->data, buffer),
496 rpath(ctx, newpath.data, buffer1));
497 v9fs_string_free(&newpath);
498 return ret;
c494dd6f
AL
499}
500
2289be19 501static int local_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
8cf89e00 502{
faa44e3d 503 char buffer[PATH_MAX];
2289be19
AK
504 char *path = fs_path->data;
505
faa44e3d 506 return truncate(rpath(ctx, path, buffer), size);
8cf89e00
AL
507}
508
509static int local_rename(FsContext *ctx, const char *oldpath,
510 const char *newpath)
511{
faa44e3d 512 char buffer[PATH_MAX], buffer1[PATH_MAX];
8cf89e00 513
faa44e3d 514 return rename(rpath(ctx, oldpath, buffer), rpath(ctx, newpath, buffer1));
8cf89e00
AL
515}
516
2289be19 517static int local_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
8cf89e00 518{
faa44e3d 519 char buffer[PATH_MAX];
2289be19
AK
520 char *path = fs_path->data;
521
c79ce737
SK
522 if ((credp->fc_uid == -1 && credp->fc_gid == -1) ||
523 (fs_ctx->fs_sm == SM_PASSTHROUGH)) {
faa44e3d
VJJ
524 return lchown(rpath(fs_ctx, path, buffer), credp->fc_uid,
525 credp->fc_gid);
c79ce737 526 } else if (fs_ctx->fs_sm == SM_MAPPED) {
faa44e3d 527 return local_set_xattr(rpath(fs_ctx, path, buffer), credp);
12848bfc
AK
528 } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
529 (fs_ctx->fs_sm == SM_NONE)) {
faa44e3d
VJJ
530 return lchown(rpath(fs_ctx, path, buffer), credp->fc_uid,
531 credp->fc_gid);
f7613bee
VJJ
532 }
533 return -1;
8cf89e00
AL
534}
535
2289be19 536static int local_utimensat(FsContext *s, V9fsPath *fs_path,
38671423 537 const struct timespec *buf)
8cf89e00 538{
faa44e3d 539 char buffer[PATH_MAX];
2289be19
AK
540 char *path = fs_path->data;
541
faa44e3d 542 return qemu_utimensat(AT_FDCWD, rpath(s, path, buffer), buf,
2289be19 543 AT_SYMLINK_NOFOLLOW);
8cf89e00
AL
544}
545
5bae1900
AL
546static int local_remove(FsContext *ctx, const char *path)
547{
faa44e3d
VJJ
548 char buffer[PATH_MAX];
549 return remove(rpath(ctx, path, buffer));
5bae1900
AL
550}
551
49594973 552static int local_fsync(FsContext *ctx, int fd, int datasync)
8cf89e00 553{
49594973
VJJ
554 if (datasync) {
555 return qemu_fdatasync(fd);
556 } else {
557 return fsync(fd);
558 }
8cf89e00
AL
559}
560
2289be19 561static int local_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf)
be940c87 562{
faa44e3d 563 char buffer[PATH_MAX];
2289be19
AK
564 char *path = fs_path->data;
565
566 return statfs(rpath(s, path, buffer), stbuf);
be940c87
MK
567}
568
2289be19 569static ssize_t local_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
fa32ef88
AK
570 const char *name, void *value, size_t size)
571{
2289be19
AK
572 char *path = fs_path->data;
573
fc22118d 574 return v9fs_get_xattr(ctx, path, name, value, size);
fa32ef88
AK
575}
576
2289be19 577static ssize_t local_llistxattr(FsContext *ctx, V9fsPath *fs_path,
fa32ef88
AK
578 void *value, size_t size)
579{
2289be19
AK
580 char *path = fs_path->data;
581
fc22118d 582 return v9fs_list_xattr(ctx, path, value, size);
fa32ef88
AK
583}
584
2289be19 585static int local_lsetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name,
10b468bd
AK
586 void *value, size_t size, int flags)
587{
2289be19
AK
588 char *path = fs_path->data;
589
fc22118d 590 return v9fs_set_xattr(ctx, path, name, value, size, flags);
10b468bd
AK
591}
592
2289be19
AK
593static int local_lremovexattr(FsContext *ctx, V9fsPath *fs_path,
594 const char *name)
9ed3ef26 595{
2289be19
AK
596 char *path = fs_path->data;
597
fc22118d 598 return v9fs_remove_xattr(ctx, path, name);
9ed3ef26
AK
599}
600
2289be19
AK
601static int local_name_to_path(FsContext *ctx, V9fsPath *dir_path,
602 const char *name, V9fsPath *target)
603{
604 if (dir_path) {
605 v9fs_string_sprintf((V9fsString *)target, "%s/%s",
606 dir_path->data, name);
607 } else {
608 v9fs_string_sprintf((V9fsString *)target, "%s", name);
609 }
610 /* Bump the size for including terminating NULL */
611 target->size++;
612 return 0;
613}
614
615static int local_renameat(FsContext *ctx, V9fsPath *olddir,
616 const char *old_name, V9fsPath *newdir,
617 const char *new_name)
618{
619 int ret;
620 V9fsString old_full_name, new_full_name;
621
622 v9fs_string_init(&old_full_name);
623 v9fs_string_init(&new_full_name);
624
625 v9fs_string_sprintf(&old_full_name, "%s/%s", olddir->data, old_name);
626 v9fs_string_sprintf(&new_full_name, "%s/%s", newdir->data, new_name);
627
628 ret = local_rename(ctx, old_full_name.data, new_full_name.data);
629 v9fs_string_free(&old_full_name);
630 v9fs_string_free(&new_full_name);
631 return ret;
632}
633
634static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
635 const char *name, int flags)
636{
637 int ret;
638 V9fsString fullname;
639 char buffer[PATH_MAX];
640 v9fs_string_init(&fullname);
641
642 v9fs_string_sprintf(&fullname, "%s/%s", dir->data, name);
643 ret = remove(rpath(ctx, fullname.data, buffer));
644 v9fs_string_free(&fullname);
645
646 return ret;
647}
9ed3ef26 648
9f107513 649FileOperations local_ops = {
131dcb25 650 .lstat = local_lstat,
131dcb25
AL
651 .readlink = local_readlink,
652 .close = local_close,
653 .closedir = local_closedir,
a6568fe2
AL
654 .open = local_open,
655 .opendir = local_opendir,
a9231555
AL
656 .rewinddir = local_rewinddir,
657 .telldir = local_telldir,
5f524c1e 658 .readdir_r = local_readdir_r,
a9231555 659 .seekdir = local_seekdir,
56d15a53
SG
660 .preadv = local_preadv,
661 .pwritev = local_pwritev,
c494dd6f
AL
662 .chmod = local_chmod,
663 .mknod = local_mknod,
c494dd6f
AL
664 .mkdir = local_mkdir,
665 .fstat = local_fstat,
666 .open2 = local_open2,
667 .symlink = local_symlink,
668 .link = local_link,
8cf89e00
AL
669 .truncate = local_truncate,
670 .rename = local_rename,
671 .chown = local_chown,
74bc02b2 672 .utimensat = local_utimensat,
5bae1900 673 .remove = local_remove,
8cf89e00 674 .fsync = local_fsync,
be940c87 675 .statfs = local_statfs,
fa32ef88
AK
676 .lgetxattr = local_lgetxattr,
677 .llistxattr = local_llistxattr,
10b468bd 678 .lsetxattr = local_lsetxattr,
9ed3ef26 679 .lremovexattr = local_lremovexattr,
2289be19
AK
680 .name_to_path = local_name_to_path,
681 .renameat = local_renameat,
682 .unlinkat = local_unlinkat,
9f107513 683};