virtiofsd: prevent ".." escape in lo_do_readdir()
[qemu/ar7.git] / tools / virtiofsd / passthrough_ll.c
blobe3d65c36767b8814e084a84f786c13b322b1055d
1 /*
2 * FUSE: Filesystem in Userspace
3 * Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
5 * This program can be distributed under the terms of the GNU GPLv2.
6 * See the file COPYING.
7 */
9 /*
11 * This file system mirrors the existing file system hierarchy of the
12 * system, starting at the root file system. This is implemented by
13 * just "passing through" all requests to the corresponding user-space
14 * libc functions. In contrast to passthrough.c and passthrough_fh.c,
15 * this implementation uses the low-level API. Its performance should
16 * be the least bad among the three, but many operations are not
17 * implemented. In particular, it is not possible to remove files (or
18 * directories) because the code necessary to defer actual removal
19 * until the file is not opened anymore would make the example much
20 * more complicated.
22 * When writeback caching is enabled (-o writeback mount option), it
23 * is only possible to write to files for which the mounting user has
24 * read permissions. This is because the writeback cache requires the
25 * kernel to be able to issue read requests for all files (which the
26 * passthrough filesystem cannot satisfy if it can't read the file in
27 * the underlying filesystem).
29 * Compile with:
31 * gcc -Wall passthrough_ll.c `pkg-config fuse3 --cflags --libs` -o
32 * passthrough_ll
34 * ## Source code ##
35 * \include passthrough_ll.c
38 #include "qemu/osdep.h"
39 #include "fuse_virtio.h"
40 #include "fuse_lowlevel.h"
41 #include <assert.h>
42 #include <dirent.h>
43 #include <errno.h>
44 #include <inttypes.h>
45 #include <limits.h>
46 #include <pthread.h>
47 #include <stdbool.h>
48 #include <stddef.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #include <sys/file.h>
53 #include <sys/syscall.h>
54 #include <sys/xattr.h>
55 #include <unistd.h>
57 #include "passthrough_helpers.h"
59 struct lo_map_elem {
60 union {
61 struct lo_inode *inode;
62 struct lo_dirp *dirp;
63 int fd;
64 ssize_t freelist;
66 bool in_use;
69 /* Maps FUSE fh or ino values to internal objects */
70 struct lo_map {
71 struct lo_map_elem *elems;
72 size_t nelems;
73 ssize_t freelist;
76 struct lo_inode {
77 struct lo_inode *next; /* protected by lo->mutex */
78 struct lo_inode *prev; /* protected by lo->mutex */
79 int fd;
80 bool is_symlink;
81 ino_t ino;
82 dev_t dev;
83 uint64_t refcount; /* protected by lo->mutex */
84 fuse_ino_t fuse_ino;
87 struct lo_cred {
88 uid_t euid;
89 gid_t egid;
92 enum {
93 CACHE_NEVER,
94 CACHE_NORMAL,
95 CACHE_ALWAYS,
98 struct lo_data {
99 pthread_mutex_t mutex;
100 int debug;
101 int norace;
102 int writeback;
103 int flock;
104 int xattr;
105 const char *source;
106 double timeout;
107 int cache;
108 int timeout_set;
109 struct lo_inode root; /* protected by lo->mutex */
110 struct lo_map ino_map; /* protected by lo->mutex */
111 struct lo_map dirp_map; /* protected by lo->mutex */
112 struct lo_map fd_map; /* protected by lo->mutex */
115 static const struct fuse_opt lo_opts[] = {
116 { "writeback", offsetof(struct lo_data, writeback), 1 },
117 { "no_writeback", offsetof(struct lo_data, writeback), 0 },
118 { "source=%s", offsetof(struct lo_data, source), 0 },
119 { "flock", offsetof(struct lo_data, flock), 1 },
120 { "no_flock", offsetof(struct lo_data, flock), 0 },
121 { "xattr", offsetof(struct lo_data, xattr), 1 },
122 { "no_xattr", offsetof(struct lo_data, xattr), 0 },
123 { "timeout=%lf", offsetof(struct lo_data, timeout), 0 },
124 { "timeout=", offsetof(struct lo_data, timeout_set), 1 },
125 { "cache=never", offsetof(struct lo_data, cache), CACHE_NEVER },
126 { "cache=auto", offsetof(struct lo_data, cache), CACHE_NORMAL },
127 { "cache=always", offsetof(struct lo_data, cache), CACHE_ALWAYS },
128 { "norace", offsetof(struct lo_data, norace), 1 },
129 FUSE_OPT_END
132 static void unref_inode(struct lo_data *lo, struct lo_inode *inode, uint64_t n);
134 static struct lo_inode *lo_find(struct lo_data *lo, struct stat *st);
136 static int is_dot_or_dotdot(const char *name)
138 return name[0] == '.' &&
139 (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'));
142 /* Is `path` a single path component that is not "." or ".."? */
143 static int is_safe_path_component(const char *path)
145 if (strchr(path, '/')) {
146 return 0;
149 return !is_dot_or_dotdot(path);
152 static struct lo_data *lo_data(fuse_req_t req)
154 return (struct lo_data *)fuse_req_userdata(req);
157 static void lo_map_init(struct lo_map *map)
159 map->elems = NULL;
160 map->nelems = 0;
161 map->freelist = -1;
164 static void lo_map_destroy(struct lo_map *map)
166 free(map->elems);
169 static int lo_map_grow(struct lo_map *map, size_t new_nelems)
171 struct lo_map_elem *new_elems;
172 size_t i;
174 if (new_nelems <= map->nelems) {
175 return 1;
178 new_elems = realloc(map->elems, sizeof(map->elems[0]) * new_nelems);
179 if (!new_elems) {
180 return 0;
183 for (i = map->nelems; i < new_nelems; i++) {
184 new_elems[i].freelist = i + 1;
185 new_elems[i].in_use = false;
187 new_elems[new_nelems - 1].freelist = -1;
189 map->elems = new_elems;
190 map->freelist = map->nelems;
191 map->nelems = new_nelems;
192 return 1;
195 static struct lo_map_elem *lo_map_alloc_elem(struct lo_map *map)
197 struct lo_map_elem *elem;
199 if (map->freelist == -1 && !lo_map_grow(map, map->nelems + 256)) {
200 return NULL;
203 elem = &map->elems[map->freelist];
204 map->freelist = elem->freelist;
206 elem->in_use = true;
208 return elem;
211 static struct lo_map_elem *lo_map_reserve(struct lo_map *map, size_t key)
213 ssize_t *prev;
215 if (!lo_map_grow(map, key + 1)) {
216 return NULL;
219 for (prev = &map->freelist; *prev != -1;
220 prev = &map->elems[*prev].freelist) {
221 if (*prev == key) {
222 struct lo_map_elem *elem = &map->elems[key];
224 *prev = elem->freelist;
225 elem->in_use = true;
226 return elem;
229 return NULL;
232 static struct lo_map_elem *lo_map_get(struct lo_map *map, size_t key)
234 if (key >= map->nelems) {
235 return NULL;
237 if (!map->elems[key].in_use) {
238 return NULL;
240 return &map->elems[key];
243 static void lo_map_remove(struct lo_map *map, size_t key)
245 struct lo_map_elem *elem;
247 if (key >= map->nelems) {
248 return;
251 elem = &map->elems[key];
252 if (!elem->in_use) {
253 return;
256 elem->in_use = false;
258 elem->freelist = map->freelist;
259 map->freelist = key;
262 /* Assumes lo->mutex is held */
263 static ssize_t lo_add_fd_mapping(fuse_req_t req, int fd)
265 struct lo_map_elem *elem;
267 elem = lo_map_alloc_elem(&lo_data(req)->fd_map);
268 if (!elem) {
269 return -1;
272 elem->fd = fd;
273 return elem - lo_data(req)->fd_map.elems;
276 /* Assumes lo->mutex is held */
277 static ssize_t lo_add_dirp_mapping(fuse_req_t req, struct lo_dirp *dirp)
279 struct lo_map_elem *elem;
281 elem = lo_map_alloc_elem(&lo_data(req)->dirp_map);
282 if (!elem) {
283 return -1;
286 elem->dirp = dirp;
287 return elem - lo_data(req)->dirp_map.elems;
290 /* Assumes lo->mutex is held */
291 static ssize_t lo_add_inode_mapping(fuse_req_t req, struct lo_inode *inode)
293 struct lo_map_elem *elem;
295 elem = lo_map_alloc_elem(&lo_data(req)->ino_map);
296 if (!elem) {
297 return -1;
300 elem->inode = inode;
301 return elem - lo_data(req)->ino_map.elems;
304 static struct lo_inode *lo_inode(fuse_req_t req, fuse_ino_t ino)
306 struct lo_data *lo = lo_data(req);
307 struct lo_map_elem *elem;
309 pthread_mutex_lock(&lo->mutex);
310 elem = lo_map_get(&lo->ino_map, ino);
311 pthread_mutex_unlock(&lo->mutex);
313 if (!elem) {
314 return NULL;
317 return elem->inode;
320 static int lo_fd(fuse_req_t req, fuse_ino_t ino)
322 struct lo_inode *inode = lo_inode(req, ino);
323 return inode ? inode->fd : -1;
326 static bool lo_debug(fuse_req_t req)
328 return lo_data(req)->debug != 0;
331 static void lo_init(void *userdata, struct fuse_conn_info *conn)
333 struct lo_data *lo = (struct lo_data *)userdata;
335 if (conn->capable & FUSE_CAP_EXPORT_SUPPORT) {
336 conn->want |= FUSE_CAP_EXPORT_SUPPORT;
339 if (lo->writeback && conn->capable & FUSE_CAP_WRITEBACK_CACHE) {
340 if (lo->debug) {
341 fuse_log(FUSE_LOG_DEBUG, "lo_init: activating writeback\n");
343 conn->want |= FUSE_CAP_WRITEBACK_CACHE;
345 if (lo->flock && conn->capable & FUSE_CAP_FLOCK_LOCKS) {
346 if (lo->debug) {
347 fuse_log(FUSE_LOG_DEBUG, "lo_init: activating flock locks\n");
349 conn->want |= FUSE_CAP_FLOCK_LOCKS;
353 static void lo_getattr(fuse_req_t req, fuse_ino_t ino,
354 struct fuse_file_info *fi)
356 int res;
357 struct stat buf;
358 struct lo_data *lo = lo_data(req);
360 (void)fi;
362 res =
363 fstatat(lo_fd(req, ino), "", &buf, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW);
364 if (res == -1) {
365 return (void)fuse_reply_err(req, errno);
368 fuse_reply_attr(req, &buf, lo->timeout);
371 static int lo_parent_and_name(struct lo_data *lo, struct lo_inode *inode,
372 char path[PATH_MAX], struct lo_inode **parent)
374 char procname[64];
375 char *last;
376 struct stat stat;
377 struct lo_inode *p;
378 int retries = 2;
379 int res;
381 retry:
382 sprintf(procname, "/proc/self/fd/%i", inode->fd);
384 res = readlink(procname, path, PATH_MAX);
385 if (res < 0) {
386 fuse_log(FUSE_LOG_WARNING, "%s: readlink failed: %m\n", __func__);
387 goto fail_noretry;
390 if (res >= PATH_MAX) {
391 fuse_log(FUSE_LOG_WARNING, "%s: readlink overflowed\n", __func__);
392 goto fail_noretry;
394 path[res] = '\0';
396 last = strrchr(path, '/');
397 if (last == NULL) {
398 /* Shouldn't happen */
399 fuse_log(
400 FUSE_LOG_WARNING,
401 "%s: INTERNAL ERROR: bad path read from proc\n", __func__);
402 goto fail_noretry;
404 if (last == path) {
405 p = &lo->root;
406 pthread_mutex_lock(&lo->mutex);
407 p->refcount++;
408 pthread_mutex_unlock(&lo->mutex);
409 } else {
410 *last = '\0';
411 res = fstatat(AT_FDCWD, last == path ? "/" : path, &stat, 0);
412 if (res == -1) {
413 if (!retries) {
414 fuse_log(FUSE_LOG_WARNING,
415 "%s: failed to stat parent: %m\n", __func__);
417 goto fail;
419 p = lo_find(lo, &stat);
420 if (p == NULL) {
421 if (!retries) {
422 fuse_log(FUSE_LOG_WARNING,
423 "%s: failed to find parent\n", __func__);
425 goto fail;
428 last++;
429 res = fstatat(p->fd, last, &stat, AT_SYMLINK_NOFOLLOW);
430 if (res == -1) {
431 if (!retries) {
432 fuse_log(FUSE_LOG_WARNING,
433 "%s: failed to stat last\n", __func__);
435 goto fail_unref;
437 if (stat.st_dev != inode->dev || stat.st_ino != inode->ino) {
438 if (!retries) {
439 fuse_log(FUSE_LOG_WARNING,
440 "%s: failed to match last\n", __func__);
442 goto fail_unref;
444 *parent = p;
445 memmove(path, last, strlen(last) + 1);
447 return 0;
449 fail_unref:
450 unref_inode(lo, p, 1);
451 fail:
452 if (retries) {
453 retries--;
454 goto retry;
456 fail_noretry:
457 errno = EIO;
458 return -1;
461 static int utimensat_empty(struct lo_data *lo, struct lo_inode *inode,
462 const struct timespec *tv)
464 int res;
465 struct lo_inode *parent;
466 char path[PATH_MAX];
468 if (inode->is_symlink) {
469 res = utimensat(inode->fd, "", tv, AT_EMPTY_PATH);
470 if (res == -1 && errno == EINVAL) {
471 /* Sorry, no race free way to set times on symlink. */
472 if (lo->norace) {
473 errno = EPERM;
474 } else {
475 goto fallback;
478 return res;
480 sprintf(path, "/proc/self/fd/%i", inode->fd);
482 return utimensat(AT_FDCWD, path, tv, 0);
484 fallback:
485 res = lo_parent_and_name(lo, inode, path, &parent);
486 if (res != -1) {
487 res = utimensat(parent->fd, path, tv, AT_SYMLINK_NOFOLLOW);
488 unref_inode(lo, parent, 1);
491 return res;
494 static int lo_fi_fd(fuse_req_t req, struct fuse_file_info *fi)
496 struct lo_data *lo = lo_data(req);
497 struct lo_map_elem *elem;
499 pthread_mutex_lock(&lo->mutex);
500 elem = lo_map_get(&lo->fd_map, fi->fh);
501 pthread_mutex_unlock(&lo->mutex);
503 if (!elem) {
504 return -1;
507 return elem->fd;
510 static void lo_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
511 int valid, struct fuse_file_info *fi)
513 int saverr;
514 char procname[64];
515 struct lo_data *lo = lo_data(req);
516 struct lo_inode *inode;
517 int ifd;
518 int res;
519 int fd;
521 inode = lo_inode(req, ino);
522 if (!inode) {
523 fuse_reply_err(req, EBADF);
524 return;
527 ifd = inode->fd;
529 /* If fi->fh is invalid we'll report EBADF later */
530 if (fi) {
531 fd = lo_fi_fd(req, fi);
534 if (valid & FUSE_SET_ATTR_MODE) {
535 if (fi) {
536 res = fchmod(fd, attr->st_mode);
537 } else {
538 sprintf(procname, "/proc/self/fd/%i", ifd);
539 res = chmod(procname, attr->st_mode);
541 if (res == -1) {
542 goto out_err;
545 if (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID)) {
546 uid_t uid = (valid & FUSE_SET_ATTR_UID) ? attr->st_uid : (uid_t)-1;
547 gid_t gid = (valid & FUSE_SET_ATTR_GID) ? attr->st_gid : (gid_t)-1;
549 res = fchownat(ifd, "", uid, gid, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW);
550 if (res == -1) {
551 goto out_err;
554 if (valid & FUSE_SET_ATTR_SIZE) {
555 if (fi) {
556 res = ftruncate(fd, attr->st_size);
557 } else {
558 sprintf(procname, "/proc/self/fd/%i", ifd);
559 res = truncate(procname, attr->st_size);
561 if (res == -1) {
562 goto out_err;
565 if (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) {
566 struct timespec tv[2];
568 tv[0].tv_sec = 0;
569 tv[1].tv_sec = 0;
570 tv[0].tv_nsec = UTIME_OMIT;
571 tv[1].tv_nsec = UTIME_OMIT;
573 if (valid & FUSE_SET_ATTR_ATIME_NOW) {
574 tv[0].tv_nsec = UTIME_NOW;
575 } else if (valid & FUSE_SET_ATTR_ATIME) {
576 tv[0] = attr->st_atim;
579 if (valid & FUSE_SET_ATTR_MTIME_NOW) {
580 tv[1].tv_nsec = UTIME_NOW;
581 } else if (valid & FUSE_SET_ATTR_MTIME) {
582 tv[1] = attr->st_mtim;
585 if (fi) {
586 res = futimens(fd, tv);
587 } else {
588 res = utimensat_empty(lo, inode, tv);
590 if (res == -1) {
591 goto out_err;
595 return lo_getattr(req, ino, fi);
597 out_err:
598 saverr = errno;
599 fuse_reply_err(req, saverr);
602 static struct lo_inode *lo_find(struct lo_data *lo, struct stat *st)
604 struct lo_inode *p;
605 struct lo_inode *ret = NULL;
607 pthread_mutex_lock(&lo->mutex);
608 for (p = lo->root.next; p != &lo->root; p = p->next) {
609 if (p->ino == st->st_ino && p->dev == st->st_dev) {
610 assert(p->refcount > 0);
611 ret = p;
612 ret->refcount++;
613 break;
616 pthread_mutex_unlock(&lo->mutex);
617 return ret;
620 static int lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char *name,
621 struct fuse_entry_param *e)
623 int newfd;
624 int res;
625 int saverr;
626 struct lo_data *lo = lo_data(req);
627 struct lo_inode *inode, *dir = lo_inode(req, parent);
629 memset(e, 0, sizeof(*e));
630 e->attr_timeout = lo->timeout;
631 e->entry_timeout = lo->timeout;
633 /* Do not allow escaping root directory */
634 if (dir == &lo->root && strcmp(name, "..") == 0) {
635 name = ".";
638 newfd = openat(lo_fd(req, parent), name, O_PATH | O_NOFOLLOW);
639 if (newfd == -1) {
640 goto out_err;
643 res = fstatat(newfd, "", &e->attr, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW);
644 if (res == -1) {
645 goto out_err;
648 inode = lo_find(lo_data(req), &e->attr);
649 if (inode) {
650 close(newfd);
651 newfd = -1;
652 } else {
653 struct lo_inode *prev, *next;
655 saverr = ENOMEM;
656 inode = calloc(1, sizeof(struct lo_inode));
657 if (!inode) {
658 goto out_err;
661 inode->is_symlink = S_ISLNK(e->attr.st_mode);
662 inode->refcount = 1;
663 inode->fd = newfd;
664 inode->ino = e->attr.st_ino;
665 inode->dev = e->attr.st_dev;
667 pthread_mutex_lock(&lo->mutex);
668 inode->fuse_ino = lo_add_inode_mapping(req, inode);
669 prev = &lo->root;
670 next = prev->next;
671 next->prev = inode;
672 inode->next = next;
673 inode->prev = prev;
674 prev->next = inode;
675 pthread_mutex_unlock(&lo->mutex);
677 e->ino = inode->fuse_ino;
679 if (lo_debug(req)) {
680 fuse_log(FUSE_LOG_DEBUG, " %lli/%s -> %lli\n",
681 (unsigned long long)parent, name, (unsigned long long)e->ino);
684 return 0;
686 out_err:
687 saverr = errno;
688 if (newfd != -1) {
689 close(newfd);
691 return saverr;
694 static void lo_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
696 struct fuse_entry_param e;
697 int err;
699 if (lo_debug(req)) {
700 fuse_log(FUSE_LOG_DEBUG, "lo_lookup(parent=%" PRIu64 ", name=%s)\n",
701 parent, name);
705 * Don't use is_safe_path_component(), allow "." and ".." for NFS export
706 * support.
708 if (strchr(name, '/')) {
709 fuse_reply_err(req, EINVAL);
710 return;
713 err = lo_do_lookup(req, parent, name, &e);
714 if (err) {
715 fuse_reply_err(req, err);
716 } else {
717 fuse_reply_entry(req, &e);
722 * On some archs, setres*id is limited to 2^16 but they
723 * provide setres*id32 variants that allow 2^32.
724 * Others just let setres*id do 2^32 anyway.
726 #ifdef SYS_setresgid32
727 #define OURSYS_setresgid SYS_setresgid32
728 #else
729 #define OURSYS_setresgid SYS_setresgid
730 #endif
732 #ifdef SYS_setresuid32
733 #define OURSYS_setresuid SYS_setresuid32
734 #else
735 #define OURSYS_setresuid SYS_setresuid
736 #endif
739 * Change to uid/gid of caller so that file is created with
740 * ownership of caller.
741 * TODO: What about selinux context?
743 static int lo_change_cred(fuse_req_t req, struct lo_cred *old)
745 int res;
747 old->euid = geteuid();
748 old->egid = getegid();
750 res = syscall(OURSYS_setresgid, -1, fuse_req_ctx(req)->gid, -1);
751 if (res == -1) {
752 return errno;
755 res = syscall(OURSYS_setresuid, -1, fuse_req_ctx(req)->uid, -1);
756 if (res == -1) {
757 int errno_save = errno;
759 syscall(OURSYS_setresgid, -1, old->egid, -1);
760 return errno_save;
763 return 0;
766 /* Regain Privileges */
767 static void lo_restore_cred(struct lo_cred *old)
769 int res;
771 res = syscall(OURSYS_setresuid, -1, old->euid, -1);
772 if (res == -1) {
773 fuse_log(FUSE_LOG_ERR, "seteuid(%u): %m\n", old->euid);
774 exit(1);
777 res = syscall(OURSYS_setresgid, -1, old->egid, -1);
778 if (res == -1) {
779 fuse_log(FUSE_LOG_ERR, "setegid(%u): %m\n", old->egid);
780 exit(1);
784 static void lo_mknod_symlink(fuse_req_t req, fuse_ino_t parent,
785 const char *name, mode_t mode, dev_t rdev,
786 const char *link)
788 int res;
789 int saverr;
790 struct lo_inode *dir;
791 struct fuse_entry_param e;
792 struct lo_cred old = {};
794 if (!is_safe_path_component(name)) {
795 fuse_reply_err(req, EINVAL);
796 return;
799 dir = lo_inode(req, parent);
800 if (!dir) {
801 fuse_reply_err(req, EBADF);
802 return;
805 saverr = ENOMEM;
807 saverr = lo_change_cred(req, &old);
808 if (saverr) {
809 goto out;
812 res = mknod_wrapper(dir->fd, name, link, mode, rdev);
814 saverr = errno;
816 lo_restore_cred(&old);
818 if (res == -1) {
819 goto out;
822 saverr = lo_do_lookup(req, parent, name, &e);
823 if (saverr) {
824 goto out;
827 if (lo_debug(req)) {
828 fuse_log(FUSE_LOG_DEBUG, " %lli/%s -> %lli\n",
829 (unsigned long long)parent, name, (unsigned long long)e.ino);
832 fuse_reply_entry(req, &e);
833 return;
835 out:
836 fuse_reply_err(req, saverr);
839 static void lo_mknod(fuse_req_t req, fuse_ino_t parent, const char *name,
840 mode_t mode, dev_t rdev)
842 lo_mknod_symlink(req, parent, name, mode, rdev, NULL);
845 static void lo_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name,
846 mode_t mode)
848 lo_mknod_symlink(req, parent, name, S_IFDIR | mode, 0, NULL);
851 static void lo_symlink(fuse_req_t req, const char *link, fuse_ino_t parent,
852 const char *name)
854 lo_mknod_symlink(req, parent, name, S_IFLNK, 0, link);
857 static int linkat_empty_nofollow(struct lo_data *lo, struct lo_inode *inode,
858 int dfd, const char *name)
860 int res;
861 struct lo_inode *parent;
862 char path[PATH_MAX];
864 if (inode->is_symlink) {
865 res = linkat(inode->fd, "", dfd, name, AT_EMPTY_PATH);
866 if (res == -1 && (errno == ENOENT || errno == EINVAL)) {
867 /* Sorry, no race free way to hard-link a symlink. */
868 if (lo->norace) {
869 errno = EPERM;
870 } else {
871 goto fallback;
874 return res;
877 sprintf(path, "/proc/self/fd/%i", inode->fd);
879 return linkat(AT_FDCWD, path, dfd, name, AT_SYMLINK_FOLLOW);
881 fallback:
882 res = lo_parent_and_name(lo, inode, path, &parent);
883 if (res != -1) {
884 res = linkat(parent->fd, path, dfd, name, 0);
885 unref_inode(lo, parent, 1);
888 return res;
891 static void lo_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t parent,
892 const char *name)
894 int res;
895 struct lo_data *lo = lo_data(req);
896 struct lo_inode *inode;
897 struct fuse_entry_param e;
898 int saverr;
900 if (!is_safe_path_component(name)) {
901 fuse_reply_err(req, EINVAL);
902 return;
905 inode = lo_inode(req, ino);
906 if (!inode) {
907 fuse_reply_err(req, EBADF);
908 return;
911 memset(&e, 0, sizeof(struct fuse_entry_param));
912 e.attr_timeout = lo->timeout;
913 e.entry_timeout = lo->timeout;
915 res = linkat_empty_nofollow(lo, inode, lo_fd(req, parent), name);
916 if (res == -1) {
917 goto out_err;
920 res = fstatat(inode->fd, "", &e.attr, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW);
921 if (res == -1) {
922 goto out_err;
925 pthread_mutex_lock(&lo->mutex);
926 inode->refcount++;
927 pthread_mutex_unlock(&lo->mutex);
928 e.ino = inode->fuse_ino;
930 if (lo_debug(req)) {
931 fuse_log(FUSE_LOG_DEBUG, " %lli/%s -> %lli\n",
932 (unsigned long long)parent, name, (unsigned long long)e.ino);
935 fuse_reply_entry(req, &e);
936 return;
938 out_err:
939 saverr = errno;
940 fuse_reply_err(req, saverr);
943 static void lo_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name)
945 int res;
946 if (!is_safe_path_component(name)) {
947 fuse_reply_err(req, EINVAL);
948 return;
951 res = unlinkat(lo_fd(req, parent), name, AT_REMOVEDIR);
953 fuse_reply_err(req, res == -1 ? errno : 0);
956 static void lo_rename(fuse_req_t req, fuse_ino_t parent, const char *name,
957 fuse_ino_t newparent, const char *newname,
958 unsigned int flags)
960 int res;
962 if (!is_safe_path_component(name) || !is_safe_path_component(newname)) {
963 fuse_reply_err(req, EINVAL);
964 return;
967 if (flags) {
968 fuse_reply_err(req, EINVAL);
969 return;
972 res = renameat(lo_fd(req, parent), name, lo_fd(req, newparent), newname);
974 fuse_reply_err(req, res == -1 ? errno : 0);
977 static void lo_unlink(fuse_req_t req, fuse_ino_t parent, const char *name)
979 int res;
981 if (!is_safe_path_component(name)) {
982 fuse_reply_err(req, EINVAL);
983 return;
986 res = unlinkat(lo_fd(req, parent), name, 0);
988 fuse_reply_err(req, res == -1 ? errno : 0);
991 static void unref_inode(struct lo_data *lo, struct lo_inode *inode, uint64_t n)
993 if (!inode) {
994 return;
997 pthread_mutex_lock(&lo->mutex);
998 assert(inode->refcount >= n);
999 inode->refcount -= n;
1000 if (!inode->refcount) {
1001 struct lo_inode *prev, *next;
1003 prev = inode->prev;
1004 next = inode->next;
1005 next->prev = prev;
1006 prev->next = next;
1008 lo_map_remove(&lo->ino_map, inode->fuse_ino);
1009 pthread_mutex_unlock(&lo->mutex);
1010 close(inode->fd);
1011 free(inode);
1012 } else {
1013 pthread_mutex_unlock(&lo->mutex);
1017 static void lo_forget_one(fuse_req_t req, fuse_ino_t ino, uint64_t nlookup)
1019 struct lo_data *lo = lo_data(req);
1020 struct lo_inode *inode;
1022 inode = lo_inode(req, ino);
1023 if (!inode) {
1024 return;
1027 if (lo_debug(req)) {
1028 fuse_log(FUSE_LOG_DEBUG, " forget %lli %lli -%lli\n",
1029 (unsigned long long)ino, (unsigned long long)inode->refcount,
1030 (unsigned long long)nlookup);
1033 unref_inode(lo, inode, nlookup);
1036 static void lo_forget(fuse_req_t req, fuse_ino_t ino, uint64_t nlookup)
1038 lo_forget_one(req, ino, nlookup);
1039 fuse_reply_none(req);
1042 static void lo_forget_multi(fuse_req_t req, size_t count,
1043 struct fuse_forget_data *forgets)
1045 int i;
1047 for (i = 0; i < count; i++) {
1048 lo_forget_one(req, forgets[i].ino, forgets[i].nlookup);
1050 fuse_reply_none(req);
1053 static void lo_readlink(fuse_req_t req, fuse_ino_t ino)
1055 char buf[PATH_MAX + 1];
1056 int res;
1058 res = readlinkat(lo_fd(req, ino), "", buf, sizeof(buf));
1059 if (res == -1) {
1060 return (void)fuse_reply_err(req, errno);
1063 if (res == sizeof(buf)) {
1064 return (void)fuse_reply_err(req, ENAMETOOLONG);
1067 buf[res] = '\0';
1069 fuse_reply_readlink(req, buf);
1072 struct lo_dirp {
1073 DIR *dp;
1074 struct dirent *entry;
1075 off_t offset;
1078 static struct lo_dirp *lo_dirp(fuse_req_t req, struct fuse_file_info *fi)
1080 struct lo_data *lo = lo_data(req);
1081 struct lo_map_elem *elem;
1083 pthread_mutex_lock(&lo->mutex);
1084 elem = lo_map_get(&lo->dirp_map, fi->fh);
1085 pthread_mutex_unlock(&lo->mutex);
1086 if (!elem) {
1087 return NULL;
1090 return elem->dirp;
1093 static void lo_opendir(fuse_req_t req, fuse_ino_t ino,
1094 struct fuse_file_info *fi)
1096 int error = ENOMEM;
1097 struct lo_data *lo = lo_data(req);
1098 struct lo_dirp *d;
1099 int fd;
1100 ssize_t fh;
1102 d = calloc(1, sizeof(struct lo_dirp));
1103 if (d == NULL) {
1104 goto out_err;
1107 fd = openat(lo_fd(req, ino), ".", O_RDONLY);
1108 if (fd == -1) {
1109 goto out_errno;
1112 d->dp = fdopendir(fd);
1113 if (d->dp == NULL) {
1114 goto out_errno;
1117 d->offset = 0;
1118 d->entry = NULL;
1120 pthread_mutex_lock(&lo->mutex);
1121 fh = lo_add_dirp_mapping(req, d);
1122 pthread_mutex_unlock(&lo->mutex);
1123 if (fh == -1) {
1124 goto out_err;
1127 fi->fh = fh;
1128 if (lo->cache == CACHE_ALWAYS) {
1129 fi->keep_cache = 1;
1131 fuse_reply_open(req, fi);
1132 return;
1134 out_errno:
1135 error = errno;
1136 out_err:
1137 if (d) {
1138 if (d->dp) {
1139 closedir(d->dp);
1141 if (fd != -1) {
1142 close(fd);
1144 free(d);
1146 fuse_reply_err(req, error);
1149 static void lo_do_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
1150 off_t offset, struct fuse_file_info *fi, int plus)
1152 struct lo_data *lo = lo_data(req);
1153 struct lo_dirp *d;
1154 struct lo_inode *dinode;
1155 char *buf = NULL;
1156 char *p;
1157 size_t rem = size;
1158 int err = EBADF;
1160 dinode = lo_inode(req, ino);
1161 if (!dinode) {
1162 goto error;
1165 d = lo_dirp(req, fi);
1166 if (!d) {
1167 goto error;
1170 err = ENOMEM;
1171 buf = calloc(1, size);
1172 if (!buf) {
1173 goto error;
1175 p = buf;
1177 if (offset != d->offset) {
1178 seekdir(d->dp, offset);
1179 d->entry = NULL;
1180 d->offset = offset;
1182 while (1) {
1183 size_t entsize;
1184 off_t nextoff;
1185 const char *name;
1187 if (!d->entry) {
1188 errno = 0;
1189 d->entry = readdir(d->dp);
1190 if (!d->entry) {
1191 if (errno) { /* Error */
1192 err = errno;
1193 goto error;
1194 } else { /* End of stream */
1195 break;
1199 nextoff = d->entry->d_off;
1200 name = d->entry->d_name;
1202 fuse_ino_t entry_ino = 0;
1203 struct fuse_entry_param e = (struct fuse_entry_param){
1204 .attr.st_ino = d->entry->d_ino,
1205 .attr.st_mode = d->entry->d_type << 12,
1208 /* Hide root's parent directory */
1209 if (dinode == &lo->root && strcmp(name, "..") == 0) {
1210 e.attr.st_ino = lo->root.ino;
1211 e.attr.st_mode = DT_DIR << 12;
1214 if (plus) {
1215 if (!is_dot_or_dotdot(name)) {
1216 err = lo_do_lookup(req, ino, name, &e);
1217 if (err) {
1218 goto error;
1220 entry_ino = e.ino;
1223 entsize = fuse_add_direntry_plus(req, p, rem, name, &e, nextoff);
1224 } else {
1225 entsize = fuse_add_direntry(req, p, rem, name, &e.attr, nextoff);
1227 if (entsize > rem) {
1228 if (entry_ino != 0) {
1229 lo_forget_one(req, entry_ino, 1);
1231 break;
1234 p += entsize;
1235 rem -= entsize;
1237 d->entry = NULL;
1238 d->offset = nextoff;
1241 err = 0;
1242 error:
1244 * If there's an error, we can only signal it if we haven't stored
1245 * any entries yet - otherwise we'd end up with wrong lookup
1246 * counts for the entries that are already in the buffer. So we
1247 * return what we've collected until that point.
1249 if (err && rem == size) {
1250 fuse_reply_err(req, err);
1251 } else {
1252 fuse_reply_buf(req, buf, size - rem);
1254 free(buf);
1257 static void lo_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
1258 off_t offset, struct fuse_file_info *fi)
1260 lo_do_readdir(req, ino, size, offset, fi, 0);
1263 static void lo_readdirplus(fuse_req_t req, fuse_ino_t ino, size_t size,
1264 off_t offset, struct fuse_file_info *fi)
1266 lo_do_readdir(req, ino, size, offset, fi, 1);
1269 static void lo_releasedir(fuse_req_t req, fuse_ino_t ino,
1270 struct fuse_file_info *fi)
1272 struct lo_data *lo = lo_data(req);
1273 struct lo_dirp *d;
1275 (void)ino;
1277 d = lo_dirp(req, fi);
1278 if (!d) {
1279 fuse_reply_err(req, EBADF);
1280 return;
1283 pthread_mutex_lock(&lo->mutex);
1284 lo_map_remove(&lo->dirp_map, fi->fh);
1285 pthread_mutex_unlock(&lo->mutex);
1287 closedir(d->dp);
1288 free(d);
1289 fuse_reply_err(req, 0);
1292 static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name,
1293 mode_t mode, struct fuse_file_info *fi)
1295 int fd;
1296 struct lo_data *lo = lo_data(req);
1297 struct fuse_entry_param e;
1298 int err;
1299 struct lo_cred old = {};
1301 if (lo_debug(req)) {
1302 fuse_log(FUSE_LOG_DEBUG, "lo_create(parent=%" PRIu64 ", name=%s)\n",
1303 parent, name);
1306 if (!is_safe_path_component(name)) {
1307 fuse_reply_err(req, EINVAL);
1308 return;
1311 err = lo_change_cred(req, &old);
1312 if (err) {
1313 goto out;
1316 fd = openat(lo_fd(req, parent), name, (fi->flags | O_CREAT) & ~O_NOFOLLOW,
1317 mode);
1318 err = fd == -1 ? errno : 0;
1319 lo_restore_cred(&old);
1321 if (!err) {
1322 ssize_t fh;
1324 pthread_mutex_lock(&lo->mutex);
1325 fh = lo_add_fd_mapping(req, fd);
1326 pthread_mutex_unlock(&lo->mutex);
1327 if (fh == -1) {
1328 close(fd);
1329 fuse_reply_err(req, ENOMEM);
1330 return;
1333 fi->fh = fh;
1334 err = lo_do_lookup(req, parent, name, &e);
1336 if (lo->cache == CACHE_NEVER) {
1337 fi->direct_io = 1;
1338 } else if (lo->cache == CACHE_ALWAYS) {
1339 fi->keep_cache = 1;
1342 out:
1343 if (err) {
1344 fuse_reply_err(req, err);
1345 } else {
1346 fuse_reply_create(req, &e, fi);
1350 static void lo_fsyncdir(fuse_req_t req, fuse_ino_t ino, int datasync,
1351 struct fuse_file_info *fi)
1353 int res;
1354 struct lo_dirp *d;
1355 int fd;
1357 (void)ino;
1359 d = lo_dirp(req, fi);
1360 if (!d) {
1361 fuse_reply_err(req, EBADF);
1362 return;
1365 fd = dirfd(d->dp);
1366 if (datasync) {
1367 res = fdatasync(fd);
1368 } else {
1369 res = fsync(fd);
1371 fuse_reply_err(req, res == -1 ? errno : 0);
1374 static void lo_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
1376 int fd;
1377 ssize_t fh;
1378 char buf[64];
1379 struct lo_data *lo = lo_data(req);
1381 if (lo_debug(req)) {
1382 fuse_log(FUSE_LOG_DEBUG, "lo_open(ino=%" PRIu64 ", flags=%d)\n", ino,
1383 fi->flags);
1387 * With writeback cache, kernel may send read requests even
1388 * when userspace opened write-only
1390 if (lo->writeback && (fi->flags & O_ACCMODE) == O_WRONLY) {
1391 fi->flags &= ~O_ACCMODE;
1392 fi->flags |= O_RDWR;
1396 * With writeback cache, O_APPEND is handled by the kernel.
1397 * This breaks atomicity (since the file may change in the
1398 * underlying filesystem, so that the kernel's idea of the
1399 * end of the file isn't accurate anymore). In this example,
1400 * we just accept that. A more rigorous filesystem may want
1401 * to return an error here
1403 if (lo->writeback && (fi->flags & O_APPEND)) {
1404 fi->flags &= ~O_APPEND;
1407 sprintf(buf, "/proc/self/fd/%i", lo_fd(req, ino));
1408 fd = open(buf, fi->flags & ~O_NOFOLLOW);
1409 if (fd == -1) {
1410 return (void)fuse_reply_err(req, errno);
1413 pthread_mutex_lock(&lo->mutex);
1414 fh = lo_add_fd_mapping(req, fd);
1415 pthread_mutex_unlock(&lo->mutex);
1416 if (fh == -1) {
1417 close(fd);
1418 fuse_reply_err(req, ENOMEM);
1419 return;
1422 fi->fh = fh;
1423 if (lo->cache == CACHE_NEVER) {
1424 fi->direct_io = 1;
1425 } else if (lo->cache == CACHE_ALWAYS) {
1426 fi->keep_cache = 1;
1428 fuse_reply_open(req, fi);
1431 static void lo_release(fuse_req_t req, fuse_ino_t ino,
1432 struct fuse_file_info *fi)
1434 struct lo_data *lo = lo_data(req);
1435 int fd;
1437 (void)ino;
1439 fd = lo_fi_fd(req, fi);
1441 pthread_mutex_lock(&lo->mutex);
1442 lo_map_remove(&lo->fd_map, fi->fh);
1443 pthread_mutex_unlock(&lo->mutex);
1445 close(fd);
1446 fuse_reply_err(req, 0);
1449 static void lo_flush(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
1451 int res;
1452 (void)ino;
1453 res = close(dup(lo_fi_fd(req, fi)));
1454 fuse_reply_err(req, res == -1 ? errno : 0);
1457 static void lo_fsync(fuse_req_t req, fuse_ino_t ino, int datasync,
1458 struct fuse_file_info *fi)
1460 int res;
1461 (void)ino;
1462 int fd;
1463 char *buf;
1465 fuse_log(FUSE_LOG_DEBUG, "lo_fsync(ino=%" PRIu64 ", fi=0x%p)\n", ino,
1466 (void *)fi);
1468 if (!fi) {
1469 res = asprintf(&buf, "/proc/self/fd/%i", lo_fd(req, ino));
1470 if (res == -1) {
1471 return (void)fuse_reply_err(req, errno);
1474 fd = open(buf, O_RDWR);
1475 free(buf);
1476 if (fd == -1) {
1477 return (void)fuse_reply_err(req, errno);
1479 } else {
1480 fd = lo_fi_fd(req, fi);
1483 if (datasync) {
1484 res = fdatasync(fd);
1485 } else {
1486 res = fsync(fd);
1488 if (!fi) {
1489 close(fd);
1491 fuse_reply_err(req, res == -1 ? errno : 0);
1494 static void lo_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t offset,
1495 struct fuse_file_info *fi)
1497 struct fuse_bufvec buf = FUSE_BUFVEC_INIT(size);
1499 if (lo_debug(req)) {
1500 fuse_log(FUSE_LOG_DEBUG,
1501 "lo_read(ino=%" PRIu64 ", size=%zd, "
1502 "off=%lu)\n",
1503 ino, size, (unsigned long)offset);
1506 buf.buf[0].flags = FUSE_BUF_IS_FD | FUSE_BUF_FD_SEEK;
1507 buf.buf[0].fd = lo_fi_fd(req, fi);
1508 buf.buf[0].pos = offset;
1510 fuse_reply_data(req, &buf);
1513 static void lo_write_buf(fuse_req_t req, fuse_ino_t ino,
1514 struct fuse_bufvec *in_buf, off_t off,
1515 struct fuse_file_info *fi)
1517 (void)ino;
1518 ssize_t res;
1519 struct fuse_bufvec out_buf = FUSE_BUFVEC_INIT(fuse_buf_size(in_buf));
1521 out_buf.buf[0].flags = FUSE_BUF_IS_FD | FUSE_BUF_FD_SEEK;
1522 out_buf.buf[0].fd = lo_fi_fd(req, fi);
1523 out_buf.buf[0].pos = off;
1525 if (lo_debug(req)) {
1526 fuse_log(FUSE_LOG_DEBUG,
1527 "lo_write(ino=%" PRIu64 ", size=%zd, off=%lu)\n", ino,
1528 out_buf.buf[0].size, (unsigned long)off);
1531 res = fuse_buf_copy(&out_buf, in_buf);
1532 if (res < 0) {
1533 fuse_reply_err(req, -res);
1534 } else {
1535 fuse_reply_write(req, (size_t)res);
1539 static void lo_statfs(fuse_req_t req, fuse_ino_t ino)
1541 int res;
1542 struct statvfs stbuf;
1544 res = fstatvfs(lo_fd(req, ino), &stbuf);
1545 if (res == -1) {
1546 fuse_reply_err(req, errno);
1547 } else {
1548 fuse_reply_statfs(req, &stbuf);
1552 static void lo_fallocate(fuse_req_t req, fuse_ino_t ino, int mode, off_t offset,
1553 off_t length, struct fuse_file_info *fi)
1555 int err = EOPNOTSUPP;
1556 (void)ino;
1558 #ifdef CONFIG_FALLOCATE
1559 err = fallocate(lo_fi_fd(req, fi), mode, offset, length);
1560 if (err < 0) {
1561 err = errno;
1564 #elif defined(CONFIG_POSIX_FALLOCATE)
1565 if (mode) {
1566 fuse_reply_err(req, EOPNOTSUPP);
1567 return;
1570 err = posix_fallocate(lo_fi_fd(req, fi), offset, length);
1571 #endif
1573 fuse_reply_err(req, err);
1576 static void lo_flock(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi,
1577 int op)
1579 int res;
1580 (void)ino;
1582 res = flock(lo_fi_fd(req, fi), op);
1584 fuse_reply_err(req, res == -1 ? errno : 0);
1587 static void lo_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
1588 size_t size)
1590 char *value = NULL;
1591 char procname[64];
1592 struct lo_inode *inode;
1593 ssize_t ret;
1594 int saverr;
1596 inode = lo_inode(req, ino);
1597 if (!inode) {
1598 fuse_reply_err(req, EBADF);
1599 return;
1602 saverr = ENOSYS;
1603 if (!lo_data(req)->xattr) {
1604 goto out;
1607 if (lo_debug(req)) {
1608 fuse_log(FUSE_LOG_DEBUG,
1609 "lo_getxattr(ino=%" PRIu64 ", name=%s size=%zd)\n", ino, name,
1610 size);
1613 if (inode->is_symlink) {
1614 /* Sorry, no race free way to getxattr on symlink. */
1615 saverr = EPERM;
1616 goto out;
1619 sprintf(procname, "/proc/self/fd/%i", inode->fd);
1621 if (size) {
1622 value = malloc(size);
1623 if (!value) {
1624 goto out_err;
1627 ret = getxattr(procname, name, value, size);
1628 if (ret == -1) {
1629 goto out_err;
1631 saverr = 0;
1632 if (ret == 0) {
1633 goto out;
1636 fuse_reply_buf(req, value, ret);
1637 } else {
1638 ret = getxattr(procname, name, NULL, 0);
1639 if (ret == -1) {
1640 goto out_err;
1643 fuse_reply_xattr(req, ret);
1645 out_free:
1646 free(value);
1647 return;
1649 out_err:
1650 saverr = errno;
1651 out:
1652 fuse_reply_err(req, saverr);
1653 goto out_free;
1656 static void lo_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
1658 char *value = NULL;
1659 char procname[64];
1660 struct lo_inode *inode;
1661 ssize_t ret;
1662 int saverr;
1664 inode = lo_inode(req, ino);
1665 if (!inode) {
1666 fuse_reply_err(req, EBADF);
1667 return;
1670 saverr = ENOSYS;
1671 if (!lo_data(req)->xattr) {
1672 goto out;
1675 if (lo_debug(req)) {
1676 fuse_log(FUSE_LOG_DEBUG, "lo_listxattr(ino=%" PRIu64 ", size=%zd)\n",
1677 ino, size);
1680 if (inode->is_symlink) {
1681 /* Sorry, no race free way to listxattr on symlink. */
1682 saverr = EPERM;
1683 goto out;
1686 sprintf(procname, "/proc/self/fd/%i", inode->fd);
1688 if (size) {
1689 value = malloc(size);
1690 if (!value) {
1691 goto out_err;
1694 ret = listxattr(procname, value, size);
1695 if (ret == -1) {
1696 goto out_err;
1698 saverr = 0;
1699 if (ret == 0) {
1700 goto out;
1703 fuse_reply_buf(req, value, ret);
1704 } else {
1705 ret = listxattr(procname, NULL, 0);
1706 if (ret == -1) {
1707 goto out_err;
1710 fuse_reply_xattr(req, ret);
1712 out_free:
1713 free(value);
1714 return;
1716 out_err:
1717 saverr = errno;
1718 out:
1719 fuse_reply_err(req, saverr);
1720 goto out_free;
1723 static void lo_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
1724 const char *value, size_t size, int flags)
1726 char procname[64];
1727 struct lo_inode *inode;
1728 ssize_t ret;
1729 int saverr;
1731 inode = lo_inode(req, ino);
1732 if (!inode) {
1733 fuse_reply_err(req, EBADF);
1734 return;
1737 saverr = ENOSYS;
1738 if (!lo_data(req)->xattr) {
1739 goto out;
1742 if (lo_debug(req)) {
1743 fuse_log(FUSE_LOG_DEBUG,
1744 "lo_setxattr(ino=%" PRIu64 ", name=%s value=%s size=%zd)\n",
1745 ino, name, value, size);
1748 if (inode->is_symlink) {
1749 /* Sorry, no race free way to setxattr on symlink. */
1750 saverr = EPERM;
1751 goto out;
1754 sprintf(procname, "/proc/self/fd/%i", inode->fd);
1756 ret = setxattr(procname, name, value, size, flags);
1757 saverr = ret == -1 ? errno : 0;
1759 out:
1760 fuse_reply_err(req, saverr);
1763 static void lo_removexattr(fuse_req_t req, fuse_ino_t ino, const char *name)
1765 char procname[64];
1766 struct lo_inode *inode;
1767 ssize_t ret;
1768 int saverr;
1770 inode = lo_inode(req, ino);
1771 if (!inode) {
1772 fuse_reply_err(req, EBADF);
1773 return;
1776 saverr = ENOSYS;
1777 if (!lo_data(req)->xattr) {
1778 goto out;
1781 if (lo_debug(req)) {
1782 fuse_log(FUSE_LOG_DEBUG, "lo_removexattr(ino=%" PRIu64 ", name=%s)\n",
1783 ino, name);
1786 if (inode->is_symlink) {
1787 /* Sorry, no race free way to setxattr on symlink. */
1788 saverr = EPERM;
1789 goto out;
1792 sprintf(procname, "/proc/self/fd/%i", inode->fd);
1794 ret = removexattr(procname, name);
1795 saverr = ret == -1 ? errno : 0;
1797 out:
1798 fuse_reply_err(req, saverr);
1801 #ifdef HAVE_COPY_FILE_RANGE
1802 static void lo_copy_file_range(fuse_req_t req, fuse_ino_t ino_in, off_t off_in,
1803 struct fuse_file_info *fi_in, fuse_ino_t ino_out,
1804 off_t off_out, struct fuse_file_info *fi_out,
1805 size_t len, int flags)
1807 int in_fd, out_fd;
1808 ssize_t res;
1810 in_fd = lo_fi_fd(req, fi_in);
1811 out_fd = lo_fi_fd(req, fi_out);
1813 fuse_log(FUSE_LOG_DEBUG,
1814 "lo_copy_file_range(ino=%" PRIu64 "/fd=%d, "
1815 "off=%lu, ino=%" PRIu64 "/fd=%d, "
1816 "off=%lu, size=%zd, flags=0x%x)\n",
1817 ino_in, in_fd, off_in, ino_out, out_fd, off_out, len, flags);
1819 res = copy_file_range(in_fd, &off_in, out_fd, &off_out, len, flags);
1820 if (res < 0) {
1821 fuse_reply_err(req, -errno);
1822 } else {
1823 fuse_reply_write(req, res);
1826 #endif
1828 static void lo_lseek(fuse_req_t req, fuse_ino_t ino, off_t off, int whence,
1829 struct fuse_file_info *fi)
1831 off_t res;
1833 (void)ino;
1834 res = lseek(lo_fi_fd(req, fi), off, whence);
1835 if (res != -1) {
1836 fuse_reply_lseek(req, res);
1837 } else {
1838 fuse_reply_err(req, errno);
1842 static struct fuse_lowlevel_ops lo_oper = {
1843 .init = lo_init,
1844 .lookup = lo_lookup,
1845 .mkdir = lo_mkdir,
1846 .mknod = lo_mknod,
1847 .symlink = lo_symlink,
1848 .link = lo_link,
1849 .unlink = lo_unlink,
1850 .rmdir = lo_rmdir,
1851 .rename = lo_rename,
1852 .forget = lo_forget,
1853 .forget_multi = lo_forget_multi,
1854 .getattr = lo_getattr,
1855 .setattr = lo_setattr,
1856 .readlink = lo_readlink,
1857 .opendir = lo_opendir,
1858 .readdir = lo_readdir,
1859 .readdirplus = lo_readdirplus,
1860 .releasedir = lo_releasedir,
1861 .fsyncdir = lo_fsyncdir,
1862 .create = lo_create,
1863 .open = lo_open,
1864 .release = lo_release,
1865 .flush = lo_flush,
1866 .fsync = lo_fsync,
1867 .read = lo_read,
1868 .write_buf = lo_write_buf,
1869 .statfs = lo_statfs,
1870 .fallocate = lo_fallocate,
1871 .flock = lo_flock,
1872 .getxattr = lo_getxattr,
1873 .listxattr = lo_listxattr,
1874 .setxattr = lo_setxattr,
1875 .removexattr = lo_removexattr,
1876 #ifdef HAVE_COPY_FILE_RANGE
1877 .copy_file_range = lo_copy_file_range,
1878 #endif
1879 .lseek = lo_lseek,
1882 /* Print vhost-user.json backend program capabilities */
1883 static void print_capabilities(void)
1885 printf("{\n");
1886 printf(" \"type\": \"fs\"\n");
1887 printf("}\n");
1890 int main(int argc, char *argv[])
1892 struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
1893 struct fuse_session *se;
1894 struct fuse_cmdline_opts opts;
1895 struct lo_data lo = { .debug = 0, .writeback = 0 };
1896 struct lo_map_elem *root_elem;
1897 int ret = -1;
1899 /* Don't mask creation mode, kernel already did that */
1900 umask(0);
1902 pthread_mutex_init(&lo.mutex, NULL);
1903 lo.root.next = lo.root.prev = &lo.root;
1904 lo.root.fd = -1;
1905 lo.root.fuse_ino = FUSE_ROOT_ID;
1906 lo.cache = CACHE_NORMAL;
1909 * Set up the ino map like this:
1910 * [0] Reserved (will not be used)
1911 * [1] Root inode
1913 lo_map_init(&lo.ino_map);
1914 lo_map_reserve(&lo.ino_map, 0)->in_use = false;
1915 root_elem = lo_map_reserve(&lo.ino_map, lo.root.fuse_ino);
1916 root_elem->inode = &lo.root;
1918 lo_map_init(&lo.dirp_map);
1919 lo_map_init(&lo.fd_map);
1921 if (fuse_parse_cmdline(&args, &opts) != 0) {
1922 return 1;
1924 if (opts.show_help) {
1925 printf("usage: %s [options]\n\n", argv[0]);
1926 fuse_cmdline_help();
1927 printf(" -o source=PATH shared directory tree\n");
1928 fuse_lowlevel_help();
1929 ret = 0;
1930 goto err_out1;
1931 } else if (opts.show_version) {
1932 fuse_lowlevel_version();
1933 ret = 0;
1934 goto err_out1;
1935 } else if (opts.print_capabilities) {
1936 print_capabilities();
1937 ret = 0;
1938 goto err_out1;
1941 if (fuse_opt_parse(&args, &lo, lo_opts, NULL) == -1) {
1942 return 1;
1945 lo.debug = opts.debug;
1946 lo.root.refcount = 2;
1947 if (lo.source) {
1948 struct stat stat;
1949 int res;
1951 res = lstat(lo.source, &stat);
1952 if (res == -1) {
1953 fuse_log(FUSE_LOG_ERR, "failed to stat source (\"%s\"): %m\n",
1954 lo.source);
1955 exit(1);
1957 if (!S_ISDIR(stat.st_mode)) {
1958 fuse_log(FUSE_LOG_ERR, "source is not a directory\n");
1959 exit(1);
1962 } else {
1963 lo.source = "/";
1965 lo.root.is_symlink = false;
1966 if (!lo.timeout_set) {
1967 switch (lo.cache) {
1968 case CACHE_NEVER:
1969 lo.timeout = 0.0;
1970 break;
1972 case CACHE_NORMAL:
1973 lo.timeout = 1.0;
1974 break;
1976 case CACHE_ALWAYS:
1977 lo.timeout = 86400.0;
1978 break;
1980 } else if (lo.timeout < 0) {
1981 fuse_log(FUSE_LOG_ERR, "timeout is negative (%lf)\n", lo.timeout);
1982 exit(1);
1985 lo.root.fd = open(lo.source, O_PATH);
1986 if (lo.root.fd == -1) {
1987 fuse_log(FUSE_LOG_ERR, "open(\"%s\", O_PATH): %m\n", lo.source);
1988 exit(1);
1991 se = fuse_session_new(&args, &lo_oper, sizeof(lo_oper), &lo);
1992 if (se == NULL) {
1993 goto err_out1;
1996 if (fuse_set_signal_handlers(se) != 0) {
1997 goto err_out2;
2000 if (fuse_session_mount(se) != 0) {
2001 goto err_out3;
2004 fuse_daemonize(opts.foreground);
2006 /* Block until ctrl+c or fusermount -u */
2007 ret = virtio_loop(se);
2009 fuse_session_unmount(se);
2010 err_out3:
2011 fuse_remove_signal_handlers(se);
2012 err_out2:
2013 fuse_session_destroy(se);
2014 err_out1:
2015 fuse_opt_free_args(&args);
2017 lo_map_destroy(&lo.fd_map);
2018 lo_map_destroy(&lo.dirp_map);
2019 lo_map_destroy(&lo.ino_map);
2021 if (lo.root.fd >= 0) {
2022 close(lo.root.fd);
2025 return ret ? 1 : 0;