Released 2.9.3
[fuse.git] / lib / fuse.c
blob067d0dc3e73c04860fcf1b80321a2749ca518670
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 LGPLv2.
6 See the file COPYING.LIB
7 */
10 /* For pthread_rwlock_t */
11 #define _GNU_SOURCE
13 #include "config.h"
14 #include "fuse_i.h"
15 #include "fuse_lowlevel.h"
16 #include "fuse_opt.h"
17 #include "fuse_misc.h"
18 #include "fuse_common_compat.h"
19 #include "fuse_compat.h"
20 #include "fuse_kernel.h"
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <stddef.h>
26 #include <stdbool.h>
27 #include <unistd.h>
28 #include <time.h>
29 #include <fcntl.h>
30 #include <limits.h>
31 #include <errno.h>
32 #include <signal.h>
33 #include <dlfcn.h>
34 #include <assert.h>
35 #include <poll.h>
36 #include <sys/param.h>
37 #include <sys/uio.h>
38 #include <sys/time.h>
39 #include <sys/mman.h>
41 #define FUSE_NODE_SLAB 1
43 #ifndef MAP_ANONYMOUS
44 #undef FUSE_NODE_SLAB
45 #endif
47 #define FUSE_DEFAULT_INTR_SIGNAL SIGUSR1
49 #define FUSE_UNKNOWN_INO 0xffffffff
50 #define OFFSET_MAX 0x7fffffffffffffffLL
52 #define NODE_TABLE_MIN_SIZE 8192
54 struct fuse_config {
55 unsigned int uid;
56 unsigned int gid;
57 unsigned int umask;
58 double entry_timeout;
59 double negative_timeout;
60 double attr_timeout;
61 double ac_attr_timeout;
62 int ac_attr_timeout_set;
63 int remember;
64 int nopath;
65 int debug;
66 int hard_remove;
67 int use_ino;
68 int readdir_ino;
69 int set_mode;
70 int set_uid;
71 int set_gid;
72 int direct_io;
73 int kernel_cache;
74 int auto_cache;
75 int intr;
76 int intr_signal;
77 int help;
78 char *modules;
81 struct fuse_fs {
82 struct fuse_operations op;
83 struct fuse_module *m;
84 void *user_data;
85 int compat;
86 int debug;
89 struct fusemod_so {
90 void *handle;
91 int ctr;
94 struct lock_queue_element {
95 struct lock_queue_element *next;
96 pthread_cond_t cond;
97 fuse_ino_t nodeid1;
98 const char *name1;
99 char **path1;
100 struct node **wnode1;
101 fuse_ino_t nodeid2;
102 const char *name2;
103 char **path2;
104 struct node **wnode2;
105 int err;
106 bool first_locked : 1;
107 bool second_locked : 1;
108 bool done : 1;
111 struct node_table {
112 struct node **array;
113 size_t use;
114 size_t size;
115 size_t split;
118 #define container_of(ptr, type, member) ({ \
119 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
120 (type *)( (char *)__mptr - offsetof(type,member) );})
122 #define list_entry(ptr, type, member) \
123 container_of(ptr, type, member)
125 struct list_head {
126 struct list_head *next;
127 struct list_head *prev;
130 struct node_slab {
131 struct list_head list; /* must be the first member */
132 struct list_head freelist;
133 int used;
136 struct fuse {
137 struct fuse_session *se;
138 struct node_table name_table;
139 struct node_table id_table;
140 struct list_head lru_table;
141 fuse_ino_t ctr;
142 unsigned int generation;
143 unsigned int hidectr;
144 pthread_mutex_t lock;
145 struct fuse_config conf;
146 int intr_installed;
147 struct fuse_fs *fs;
148 int nullpath_ok;
149 int utime_omit_ok;
150 struct lock_queue_element *lockq;
151 int pagesize;
152 struct list_head partial_slabs;
153 struct list_head full_slabs;
154 pthread_t prune_thread;
157 struct lock {
158 int type;
159 off_t start;
160 off_t end;
161 pid_t pid;
162 uint64_t owner;
163 struct lock *next;
166 struct node {
167 struct node *name_next;
168 struct node *id_next;
169 fuse_ino_t nodeid;
170 unsigned int generation;
171 int refctr;
172 struct node *parent;
173 char *name;
174 uint64_t nlookup;
175 int open_count;
176 struct timespec stat_updated;
177 struct timespec mtime;
178 off_t size;
179 struct lock *locks;
180 unsigned int is_hidden : 1;
181 unsigned int cache_valid : 1;
182 int treelock;
183 char inline_name[32];
186 #define TREELOCK_WRITE -1
187 #define TREELOCK_WAIT_OFFSET INT_MIN
189 struct node_lru {
190 struct node node;
191 struct list_head lru;
192 struct timespec forget_time;
195 struct fuse_dh {
196 pthread_mutex_t lock;
197 struct fuse *fuse;
198 fuse_req_t req;
199 char *contents;
200 int allocated;
201 unsigned len;
202 unsigned size;
203 unsigned needlen;
204 int filled;
205 uint64_t fh;
206 int error;
207 fuse_ino_t nodeid;
210 /* old dir handle */
211 struct fuse_dirhandle {
212 fuse_fill_dir_t filler;
213 void *buf;
216 struct fuse_context_i {
217 struct fuse_context ctx;
218 fuse_req_t req;
221 static pthread_key_t fuse_context_key;
222 static pthread_mutex_t fuse_context_lock = PTHREAD_MUTEX_INITIALIZER;
223 static int fuse_context_ref;
224 static struct fusemod_so *fuse_current_so;
225 static struct fuse_module *fuse_modules;
227 static int fuse_load_so_name(const char *soname)
229 struct fusemod_so *so;
231 so = calloc(1, sizeof(struct fusemod_so));
232 if (!so) {
233 fprintf(stderr, "fuse: memory allocation failed\n");
234 return -1;
237 fuse_current_so = so;
238 so->handle = dlopen(soname, RTLD_NOW);
239 fuse_current_so = NULL;
240 if (!so->handle) {
241 fprintf(stderr, "fuse: %s\n", dlerror());
242 goto err;
244 if (!so->ctr) {
245 fprintf(stderr, "fuse: %s did not register any modules\n",
246 soname);
247 goto err;
249 return 0;
251 err:
252 if (so->handle)
253 dlclose(so->handle);
254 free(so);
255 return -1;
258 static int fuse_load_so_module(const char *module)
260 int res;
261 char *soname = malloc(strlen(module) + 64);
262 if (!soname) {
263 fprintf(stderr, "fuse: memory allocation failed\n");
264 return -1;
266 sprintf(soname, "libfusemod_%s.so", module);
267 res = fuse_load_so_name(soname);
268 free(soname);
269 return res;
272 static struct fuse_module *fuse_find_module(const char *module)
274 struct fuse_module *m;
275 for (m = fuse_modules; m; m = m->next) {
276 if (strcmp(module, m->name) == 0) {
277 m->ctr++;
278 break;
281 return m;
284 static struct fuse_module *fuse_get_module(const char *module)
286 struct fuse_module *m;
288 pthread_mutex_lock(&fuse_context_lock);
289 m = fuse_find_module(module);
290 if (!m) {
291 int err = fuse_load_so_module(module);
292 if (!err)
293 m = fuse_find_module(module);
295 pthread_mutex_unlock(&fuse_context_lock);
296 return m;
299 static void fuse_put_module(struct fuse_module *m)
301 pthread_mutex_lock(&fuse_context_lock);
302 assert(m->ctr > 0);
303 m->ctr--;
304 if (!m->ctr && m->so) {
305 struct fusemod_so *so = m->so;
306 assert(so->ctr > 0);
307 so->ctr--;
308 if (!so->ctr) {
309 struct fuse_module **mp;
310 for (mp = &fuse_modules; *mp;) {
311 if ((*mp)->so == so)
312 *mp = (*mp)->next;
313 else
314 mp = &(*mp)->next;
316 dlclose(so->handle);
317 free(so);
320 pthread_mutex_unlock(&fuse_context_lock);
323 static void init_list_head(struct list_head *list)
325 list->next = list;
326 list->prev = list;
329 static int list_empty(const struct list_head *head)
331 return head->next == head;
334 static void list_add(struct list_head *new, struct list_head *prev,
335 struct list_head *next)
337 next->prev = new;
338 new->next = next;
339 new->prev = prev;
340 prev->next = new;
343 static inline void list_add_head(struct list_head *new, struct list_head *head)
345 list_add(new, head, head->next);
348 static inline void list_add_tail(struct list_head *new, struct list_head *head)
350 list_add(new, head->prev, head);
353 static inline void list_del(struct list_head *entry)
355 struct list_head *prev = entry->prev;
356 struct list_head *next = entry->next;
358 next->prev = prev;
359 prev->next = next;
362 static inline int lru_enabled(struct fuse *f)
364 return f->conf.remember > 0;
367 static struct node_lru *node_lru(struct node *node)
369 return (struct node_lru *) node;
372 static size_t get_node_size(struct fuse *f)
374 if (lru_enabled(f))
375 return sizeof(struct node_lru);
376 else
377 return sizeof(struct node);
380 #ifdef FUSE_NODE_SLAB
381 static struct node_slab *list_to_slab(struct list_head *head)
383 return (struct node_slab *) head;
386 static struct node_slab *node_to_slab(struct fuse *f, struct node *node)
388 return (struct node_slab *) (((uintptr_t) node) & ~((uintptr_t) f->pagesize - 1));
391 static int alloc_slab(struct fuse *f)
393 void *mem;
394 struct node_slab *slab;
395 char *start;
396 size_t num;
397 size_t i;
398 size_t node_size = get_node_size(f);
400 mem = mmap(NULL, f->pagesize, PROT_READ | PROT_WRITE,
401 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
403 if (mem == MAP_FAILED)
404 return -1;
406 slab = mem;
407 init_list_head(&slab->freelist);
408 slab->used = 0;
409 num = (f->pagesize - sizeof(struct node_slab)) / node_size;
411 start = (char *) mem + f->pagesize - num * node_size;
412 for (i = 0; i < num; i++) {
413 struct list_head *n;
415 n = (struct list_head *) (start + i * node_size);
416 list_add_tail(n, &slab->freelist);
418 list_add_tail(&slab->list, &f->partial_slabs);
420 return 0;
423 static struct node *alloc_node(struct fuse *f)
425 struct node_slab *slab;
426 struct list_head *node;
428 if (list_empty(&f->partial_slabs)) {
429 int res = alloc_slab(f);
430 if (res != 0)
431 return NULL;
433 slab = list_to_slab(f->partial_slabs.next);
434 slab->used++;
435 node = slab->freelist.next;
436 list_del(node);
437 if (list_empty(&slab->freelist)) {
438 list_del(&slab->list);
439 list_add_tail(&slab->list, &f->full_slabs);
441 memset(node, 0, sizeof(struct node));
443 return (struct node *) node;
446 static void free_slab(struct fuse *f, struct node_slab *slab)
448 int res;
450 list_del(&slab->list);
451 res = munmap(slab, f->pagesize);
452 if (res == -1)
453 fprintf(stderr, "fuse warning: munmap(%p) failed\n", slab);
456 static void free_node_mem(struct fuse *f, struct node *node)
458 struct node_slab *slab = node_to_slab(f, node);
459 struct list_head *n = (struct list_head *) node;
461 slab->used--;
462 if (slab->used) {
463 if (list_empty(&slab->freelist)) {
464 list_del(&slab->list);
465 list_add_tail(&slab->list, &f->partial_slabs);
467 list_add_head(n, &slab->freelist);
468 } else {
469 free_slab(f, slab);
472 #else
473 static struct node *alloc_node(struct fuse *f)
475 return (struct node *) calloc(1, get_node_size(f));
478 static void free_node_mem(struct fuse *f, struct node *node)
480 (void) f;
481 free(node);
483 #endif
485 static size_t id_hash(struct fuse *f, fuse_ino_t ino)
487 uint64_t hash = ((uint32_t) ino * 2654435761U) % f->id_table.size;
488 uint64_t oldhash = hash % (f->id_table.size / 2);
490 if (oldhash >= f->id_table.split)
491 return oldhash;
492 else
493 return hash;
496 static struct node *get_node_nocheck(struct fuse *f, fuse_ino_t nodeid)
498 size_t hash = id_hash(f, nodeid);
499 struct node *node;
501 for (node = f->id_table.array[hash]; node != NULL; node = node->id_next)
502 if (node->nodeid == nodeid)
503 return node;
505 return NULL;
508 static struct node *get_node(struct fuse *f, fuse_ino_t nodeid)
510 struct node *node = get_node_nocheck(f, nodeid);
511 if (!node) {
512 fprintf(stderr, "fuse internal error: node %llu not found\n",
513 (unsigned long long) nodeid);
514 abort();
516 return node;
519 static void curr_time(struct timespec *now);
520 static double diff_timespec(const struct timespec *t1,
521 const struct timespec *t2);
523 static void remove_node_lru(struct node *node)
525 struct node_lru *lnode = node_lru(node);
526 list_del(&lnode->lru);
527 init_list_head(&lnode->lru);
530 static void set_forget_time(struct fuse *f, struct node *node)
532 struct node_lru *lnode = node_lru(node);
534 list_del(&lnode->lru);
535 list_add_tail(&lnode->lru, &f->lru_table);
536 curr_time(&lnode->forget_time);
539 static void free_node(struct fuse *f, struct node *node)
541 if (node->name != node->inline_name)
542 free(node->name);
543 free_node_mem(f, node);
546 static void node_table_reduce(struct node_table *t)
548 size_t newsize = t->size / 2;
549 void *newarray;
551 if (newsize < NODE_TABLE_MIN_SIZE)
552 return;
554 newarray = realloc(t->array, sizeof(struct node *) * newsize);
555 if (newarray != NULL)
556 t->array = newarray;
558 t->size = newsize;
559 t->split = t->size / 2;
562 static void remerge_id(struct fuse *f)
564 struct node_table *t = &f->id_table;
565 int iter;
567 if (t->split == 0)
568 node_table_reduce(t);
570 for (iter = 8; t->split > 0 && iter; iter--) {
571 struct node **upper;
573 t->split--;
574 upper = &t->array[t->split + t->size / 2];
575 if (*upper) {
576 struct node **nodep;
578 for (nodep = &t->array[t->split]; *nodep;
579 nodep = &(*nodep)->id_next);
581 *nodep = *upper;
582 *upper = NULL;
583 break;
588 static void unhash_id(struct fuse *f, struct node *node)
590 struct node **nodep = &f->id_table.array[id_hash(f, node->nodeid)];
592 for (; *nodep != NULL; nodep = &(*nodep)->id_next)
593 if (*nodep == node) {
594 *nodep = node->id_next;
595 f->id_table.use--;
597 if(f->id_table.use < f->id_table.size / 4)
598 remerge_id(f);
599 return;
603 static int node_table_resize(struct node_table *t)
605 size_t newsize = t->size * 2;
606 void *newarray;
608 newarray = realloc(t->array, sizeof(struct node *) * newsize);
609 if (newarray == NULL)
610 return -1;
612 t->array = newarray;
613 memset(t->array + t->size, 0, t->size * sizeof(struct node *));
614 t->size = newsize;
615 t->split = 0;
617 return 0;
620 static void rehash_id(struct fuse *f)
622 struct node_table *t = &f->id_table;
623 struct node **nodep;
624 struct node **next;
625 size_t hash;
627 if (t->split == t->size / 2)
628 return;
630 hash = t->split;
631 t->split++;
632 for (nodep = &t->array[hash]; *nodep != NULL; nodep = next) {
633 struct node *node = *nodep;
634 size_t newhash = id_hash(f, node->nodeid);
636 if (newhash != hash) {
637 next = nodep;
638 *nodep = node->id_next;
639 node->id_next = t->array[newhash];
640 t->array[newhash] = node;
641 } else {
642 next = &node->id_next;
645 if (t->split == t->size / 2)
646 node_table_resize(t);
649 static void hash_id(struct fuse *f, struct node *node)
651 size_t hash = id_hash(f, node->nodeid);
652 node->id_next = f->id_table.array[hash];
653 f->id_table.array[hash] = node;
654 f->id_table.use++;
656 if (f->id_table.use >= f->id_table.size / 2)
657 rehash_id(f);
660 static size_t name_hash(struct fuse *f, fuse_ino_t parent,
661 const char *name)
663 uint64_t hash = parent;
664 uint64_t oldhash;
666 for (; *name; name++)
667 hash = hash * 31 + (unsigned char) *name;
669 hash %= f->name_table.size;
670 oldhash = hash % (f->name_table.size / 2);
671 if (oldhash >= f->name_table.split)
672 return oldhash;
673 else
674 return hash;
677 static void unref_node(struct fuse *f, struct node *node);
679 static void remerge_name(struct fuse *f)
681 struct node_table *t = &f->name_table;
682 int iter;
684 if (t->split == 0)
685 node_table_reduce(t);
687 for (iter = 8; t->split > 0 && iter; iter--) {
688 struct node **upper;
690 t->split--;
691 upper = &t->array[t->split + t->size / 2];
692 if (*upper) {
693 struct node **nodep;
695 for (nodep = &t->array[t->split]; *nodep;
696 nodep = &(*nodep)->name_next);
698 *nodep = *upper;
699 *upper = NULL;
700 break;
705 static void unhash_name(struct fuse *f, struct node *node)
707 if (node->name) {
708 size_t hash = name_hash(f, node->parent->nodeid, node->name);
709 struct node **nodep = &f->name_table.array[hash];
711 for (; *nodep != NULL; nodep = &(*nodep)->name_next)
712 if (*nodep == node) {
713 *nodep = node->name_next;
714 node->name_next = NULL;
715 unref_node(f, node->parent);
716 if (node->name != node->inline_name)
717 free(node->name);
718 node->name = NULL;
719 node->parent = NULL;
720 f->name_table.use--;
722 if (f->name_table.use < f->name_table.size / 4)
723 remerge_name(f);
724 return;
726 fprintf(stderr,
727 "fuse internal error: unable to unhash node: %llu\n",
728 (unsigned long long) node->nodeid);
729 abort();
733 static void rehash_name(struct fuse *f)
735 struct node_table *t = &f->name_table;
736 struct node **nodep;
737 struct node **next;
738 size_t hash;
740 if (t->split == t->size / 2)
741 return;
743 hash = t->split;
744 t->split++;
745 for (nodep = &t->array[hash]; *nodep != NULL; nodep = next) {
746 struct node *node = *nodep;
747 size_t newhash = name_hash(f, node->parent->nodeid, node->name);
749 if (newhash != hash) {
750 next = nodep;
751 *nodep = node->name_next;
752 node->name_next = t->array[newhash];
753 t->array[newhash] = node;
754 } else {
755 next = &node->name_next;
758 if (t->split == t->size / 2)
759 node_table_resize(t);
762 static int hash_name(struct fuse *f, struct node *node, fuse_ino_t parentid,
763 const char *name)
765 size_t hash = name_hash(f, parentid, name);
766 struct node *parent = get_node(f, parentid);
767 if (strlen(name) < sizeof(node->inline_name)) {
768 strcpy(node->inline_name, name);
769 node->name = node->inline_name;
770 } else {
771 node->name = strdup(name);
772 if (node->name == NULL)
773 return -1;
776 parent->refctr ++;
777 node->parent = parent;
778 node->name_next = f->name_table.array[hash];
779 f->name_table.array[hash] = node;
780 f->name_table.use++;
782 if (f->name_table.use >= f->name_table.size / 2)
783 rehash_name(f);
785 return 0;
788 static void delete_node(struct fuse *f, struct node *node)
790 if (f->conf.debug)
791 fprintf(stderr, "DELETE: %llu\n",
792 (unsigned long long) node->nodeid);
794 assert(node->treelock == 0);
795 unhash_name(f, node);
796 if (lru_enabled(f))
797 remove_node_lru(node);
798 unhash_id(f, node);
799 free_node(f, node);
802 static void unref_node(struct fuse *f, struct node *node)
804 assert(node->refctr > 0);
805 node->refctr --;
806 if (!node->refctr)
807 delete_node(f, node);
810 static fuse_ino_t next_id(struct fuse *f)
812 do {
813 f->ctr = (f->ctr + 1) & 0xffffffff;
814 if (!f->ctr)
815 f->generation ++;
816 } while (f->ctr == 0 || f->ctr == FUSE_UNKNOWN_INO ||
817 get_node_nocheck(f, f->ctr) != NULL);
818 return f->ctr;
821 static struct node *lookup_node(struct fuse *f, fuse_ino_t parent,
822 const char *name)
824 size_t hash = name_hash(f, parent, name);
825 struct node *node;
827 for (node = f->name_table.array[hash]; node != NULL; node = node->name_next)
828 if (node->parent->nodeid == parent &&
829 strcmp(node->name, name) == 0)
830 return node;
832 return NULL;
835 static void inc_nlookup(struct node *node)
837 if (!node->nlookup)
838 node->refctr++;
839 node->nlookup++;
842 static struct node *find_node(struct fuse *f, fuse_ino_t parent,
843 const char *name)
845 struct node *node;
847 pthread_mutex_lock(&f->lock);
848 if (!name)
849 node = get_node(f, parent);
850 else
851 node = lookup_node(f, parent, name);
852 if (node == NULL) {
853 node = alloc_node(f);
854 if (node == NULL)
855 goto out_err;
857 node->nodeid = next_id(f);
858 node->generation = f->generation;
859 if (f->conf.remember)
860 inc_nlookup(node);
862 if (hash_name(f, node, parent, name) == -1) {
863 free_node(f, node);
864 node = NULL;
865 goto out_err;
867 hash_id(f, node);
868 if (lru_enabled(f)) {
869 struct node_lru *lnode = node_lru(node);
870 init_list_head(&lnode->lru);
872 } else if (lru_enabled(f) && node->nlookup == 1) {
873 remove_node_lru(node);
875 inc_nlookup(node);
876 out_err:
877 pthread_mutex_unlock(&f->lock);
878 return node;
881 static char *add_name(char **buf, unsigned *bufsize, char *s, const char *name)
883 size_t len = strlen(name);
885 if (s - len <= *buf) {
886 unsigned pathlen = *bufsize - (s - *buf);
887 unsigned newbufsize = *bufsize;
888 char *newbuf;
890 while (newbufsize < pathlen + len + 1) {
891 if (newbufsize >= 0x80000000)
892 newbufsize = 0xffffffff;
893 else
894 newbufsize *= 2;
897 newbuf = realloc(*buf, newbufsize);
898 if (newbuf == NULL)
899 return NULL;
901 *buf = newbuf;
902 s = newbuf + newbufsize - pathlen;
903 memmove(s, newbuf + *bufsize - pathlen, pathlen);
904 *bufsize = newbufsize;
906 s -= len;
907 strncpy(s, name, len);
908 s--;
909 *s = '/';
911 return s;
914 static void unlock_path(struct fuse *f, fuse_ino_t nodeid, struct node *wnode,
915 struct node *end)
917 struct node *node;
919 if (wnode) {
920 assert(wnode->treelock == TREELOCK_WRITE);
921 wnode->treelock = 0;
924 for (node = get_node(f, nodeid);
925 node != end && node->nodeid != FUSE_ROOT_ID; node = node->parent) {
926 assert(node->treelock != 0);
927 assert(node->treelock != TREELOCK_WAIT_OFFSET);
928 assert(node->treelock != TREELOCK_WRITE);
929 node->treelock--;
930 if (node->treelock == TREELOCK_WAIT_OFFSET)
931 node->treelock = 0;
935 static int try_get_path(struct fuse *f, fuse_ino_t nodeid, const char *name,
936 char **path, struct node **wnodep, bool need_lock)
938 unsigned bufsize = 256;
939 char *buf;
940 char *s;
941 struct node *node;
942 struct node *wnode = NULL;
943 int err;
945 *path = NULL;
947 err = -ENOMEM;
948 buf = malloc(bufsize);
949 if (buf == NULL)
950 goto out_err;
952 s = buf + bufsize - 1;
953 *s = '\0';
955 if (name != NULL) {
956 s = add_name(&buf, &bufsize, s, name);
957 err = -ENOMEM;
958 if (s == NULL)
959 goto out_free;
962 if (wnodep) {
963 assert(need_lock);
964 wnode = lookup_node(f, nodeid, name);
965 if (wnode) {
966 if (wnode->treelock != 0) {
967 if (wnode->treelock > 0)
968 wnode->treelock += TREELOCK_WAIT_OFFSET;
969 err = -EAGAIN;
970 goto out_free;
972 wnode->treelock = TREELOCK_WRITE;
976 for (node = get_node(f, nodeid); node->nodeid != FUSE_ROOT_ID;
977 node = node->parent) {
978 err = -ENOENT;
979 if (node->name == NULL || node->parent == NULL)
980 goto out_unlock;
982 err = -ENOMEM;
983 s = add_name(&buf, &bufsize, s, node->name);
984 if (s == NULL)
985 goto out_unlock;
987 if (need_lock) {
988 err = -EAGAIN;
989 if (node->treelock < 0)
990 goto out_unlock;
992 node->treelock++;
996 if (s[0])
997 memmove(buf, s, bufsize - (s - buf));
998 else
999 strcpy(buf, "/");
1001 *path = buf;
1002 if (wnodep)
1003 *wnodep = wnode;
1005 return 0;
1007 out_unlock:
1008 if (need_lock)
1009 unlock_path(f, nodeid, wnode, node);
1010 out_free:
1011 free(buf);
1013 out_err:
1014 return err;
1017 static void queue_element_unlock(struct fuse *f, struct lock_queue_element *qe)
1019 struct node *wnode;
1021 if (qe->first_locked) {
1022 wnode = qe->wnode1 ? *qe->wnode1 : NULL;
1023 unlock_path(f, qe->nodeid1, wnode, NULL);
1024 qe->first_locked = false;
1026 if (qe->second_locked) {
1027 wnode = qe->wnode2 ? *qe->wnode2 : NULL;
1028 unlock_path(f, qe->nodeid2, wnode, NULL);
1029 qe->second_locked = false;
1033 static void queue_element_wakeup(struct fuse *f, struct lock_queue_element *qe)
1035 int err;
1036 bool first = (qe == f->lockq);
1038 if (!qe->path1) {
1039 /* Just waiting for it to be unlocked */
1040 if (get_node(f, qe->nodeid1)->treelock == 0)
1041 pthread_cond_signal(&qe->cond);
1043 return;
1046 if (!qe->first_locked) {
1047 err = try_get_path(f, qe->nodeid1, qe->name1, qe->path1,
1048 qe->wnode1, true);
1049 if (!err)
1050 qe->first_locked = true;
1051 else if (err != -EAGAIN)
1052 goto err_unlock;
1054 if (!qe->second_locked && qe->path2) {
1055 err = try_get_path(f, qe->nodeid2, qe->name2, qe->path2,
1056 qe->wnode2, true);
1057 if (!err)
1058 qe->second_locked = true;
1059 else if (err != -EAGAIN)
1060 goto err_unlock;
1063 if (qe->first_locked && (qe->second_locked || !qe->path2)) {
1064 err = 0;
1065 goto done;
1069 * Only let the first element be partially locked otherwise there could
1070 * be a deadlock.
1072 * But do allow the first element to be partially locked to prevent
1073 * starvation.
1075 if (!first)
1076 queue_element_unlock(f, qe);
1078 /* keep trying */
1079 return;
1081 err_unlock:
1082 queue_element_unlock(f, qe);
1083 done:
1084 qe->err = err;
1085 qe->done = true;
1086 pthread_cond_signal(&qe->cond);
1089 static void wake_up_queued(struct fuse *f)
1091 struct lock_queue_element *qe;
1093 for (qe = f->lockq; qe != NULL; qe = qe->next)
1094 queue_element_wakeup(f, qe);
1097 static void debug_path(struct fuse *f, const char *msg, fuse_ino_t nodeid,
1098 const char *name, bool wr)
1100 if (f->conf.debug) {
1101 struct node *wnode = NULL;
1103 if (wr)
1104 wnode = lookup_node(f, nodeid, name);
1106 if (wnode)
1107 fprintf(stderr, "%s %li (w)\n", msg, wnode->nodeid);
1108 else
1109 fprintf(stderr, "%s %li\n", msg, nodeid);
1113 static void queue_path(struct fuse *f, struct lock_queue_element *qe)
1115 struct lock_queue_element **qp;
1117 qe->done = false;
1118 qe->first_locked = false;
1119 qe->second_locked = false;
1120 pthread_cond_init(&qe->cond, NULL);
1121 qe->next = NULL;
1122 for (qp = &f->lockq; *qp != NULL; qp = &(*qp)->next);
1123 *qp = qe;
1126 static void dequeue_path(struct fuse *f, struct lock_queue_element *qe)
1128 struct lock_queue_element **qp;
1130 pthread_cond_destroy(&qe->cond);
1131 for (qp = &f->lockq; *qp != qe; qp = &(*qp)->next);
1132 *qp = qe->next;
1135 static int wait_path(struct fuse *f, struct lock_queue_element *qe)
1137 queue_path(f, qe);
1139 do {
1140 pthread_cond_wait(&qe->cond, &f->lock);
1141 } while (!qe->done);
1143 dequeue_path(f, qe);
1145 return qe->err;
1148 static int get_path_common(struct fuse *f, fuse_ino_t nodeid, const char *name,
1149 char **path, struct node **wnode)
1151 int err;
1153 pthread_mutex_lock(&f->lock);
1154 err = try_get_path(f, nodeid, name, path, wnode, true);
1155 if (err == -EAGAIN) {
1156 struct lock_queue_element qe = {
1157 .nodeid1 = nodeid,
1158 .name1 = name,
1159 .path1 = path,
1160 .wnode1 = wnode,
1162 debug_path(f, "QUEUE PATH", nodeid, name, !!wnode);
1163 err = wait_path(f, &qe);
1164 debug_path(f, "DEQUEUE PATH", nodeid, name, !!wnode);
1166 pthread_mutex_unlock(&f->lock);
1168 return err;
1171 static int get_path(struct fuse *f, fuse_ino_t nodeid, char **path)
1173 return get_path_common(f, nodeid, NULL, path, NULL);
1176 static int get_path_nullok(struct fuse *f, fuse_ino_t nodeid, char **path)
1178 int err = 0;
1180 if (f->conf.nopath) {
1181 *path = NULL;
1182 } else {
1183 err = get_path_common(f, nodeid, NULL, path, NULL);
1184 if (err == -ENOENT && f->nullpath_ok)
1185 err = 0;
1188 return err;
1191 static int get_path_name(struct fuse *f, fuse_ino_t nodeid, const char *name,
1192 char **path)
1194 return get_path_common(f, nodeid, name, path, NULL);
1197 static int get_path_wrlock(struct fuse *f, fuse_ino_t nodeid, const char *name,
1198 char **path, struct node **wnode)
1200 return get_path_common(f, nodeid, name, path, wnode);
1203 static int try_get_path2(struct fuse *f, fuse_ino_t nodeid1, const char *name1,
1204 fuse_ino_t nodeid2, const char *name2,
1205 char **path1, char **path2,
1206 struct node **wnode1, struct node **wnode2)
1208 int err;
1210 /* FIXME: locking two paths needs deadlock checking */
1211 err = try_get_path(f, nodeid1, name1, path1, wnode1, true);
1212 if (!err) {
1213 err = try_get_path(f, nodeid2, name2, path2, wnode2, true);
1214 if (err) {
1215 struct node *wn1 = wnode1 ? *wnode1 : NULL;
1217 unlock_path(f, nodeid1, wn1, NULL);
1218 free(*path1);
1221 return err;
1224 static int get_path2(struct fuse *f, fuse_ino_t nodeid1, const char *name1,
1225 fuse_ino_t nodeid2, const char *name2,
1226 char **path1, char **path2,
1227 struct node **wnode1, struct node **wnode2)
1229 int err;
1231 pthread_mutex_lock(&f->lock);
1232 err = try_get_path2(f, nodeid1, name1, nodeid2, name2,
1233 path1, path2, wnode1, wnode2);
1234 if (err == -EAGAIN) {
1235 struct lock_queue_element qe = {
1236 .nodeid1 = nodeid1,
1237 .name1 = name1,
1238 .path1 = path1,
1239 .wnode1 = wnode1,
1240 .nodeid2 = nodeid2,
1241 .name2 = name2,
1242 .path2 = path2,
1243 .wnode2 = wnode2,
1246 debug_path(f, "QUEUE PATH1", nodeid1, name1, !!wnode1);
1247 debug_path(f, " PATH2", nodeid2, name2, !!wnode2);
1248 err = wait_path(f, &qe);
1249 debug_path(f, "DEQUEUE PATH1", nodeid1, name1, !!wnode1);
1250 debug_path(f, " PATH2", nodeid2, name2, !!wnode2);
1252 pthread_mutex_unlock(&f->lock);
1254 return err;
1257 static void free_path_wrlock(struct fuse *f, fuse_ino_t nodeid,
1258 struct node *wnode, char *path)
1260 pthread_mutex_lock(&f->lock);
1261 unlock_path(f, nodeid, wnode, NULL);
1262 if (f->lockq)
1263 wake_up_queued(f);
1264 pthread_mutex_unlock(&f->lock);
1265 free(path);
1268 static void free_path(struct fuse *f, fuse_ino_t nodeid, char *path)
1270 if (path)
1271 free_path_wrlock(f, nodeid, NULL, path);
1274 static void free_path2(struct fuse *f, fuse_ino_t nodeid1, fuse_ino_t nodeid2,
1275 struct node *wnode1, struct node *wnode2,
1276 char *path1, char *path2)
1278 pthread_mutex_lock(&f->lock);
1279 unlock_path(f, nodeid1, wnode1, NULL);
1280 unlock_path(f, nodeid2, wnode2, NULL);
1281 wake_up_queued(f);
1282 pthread_mutex_unlock(&f->lock);
1283 free(path1);
1284 free(path2);
1287 static void forget_node(struct fuse *f, fuse_ino_t nodeid, uint64_t nlookup)
1289 struct node *node;
1290 if (nodeid == FUSE_ROOT_ID)
1291 return;
1292 pthread_mutex_lock(&f->lock);
1293 node = get_node(f, nodeid);
1296 * Node may still be locked due to interrupt idiocy in open,
1297 * create and opendir
1299 while (node->nlookup == nlookup && node->treelock) {
1300 struct lock_queue_element qe = {
1301 .nodeid1 = nodeid,
1304 debug_path(f, "QUEUE PATH (forget)", nodeid, NULL, false);
1305 queue_path(f, &qe);
1307 do {
1308 pthread_cond_wait(&qe.cond, &f->lock);
1309 } while (node->nlookup == nlookup && node->treelock);
1311 dequeue_path(f, &qe);
1312 debug_path(f, "DEQUEUE_PATH (forget)", nodeid, NULL, false);
1315 assert(node->nlookup >= nlookup);
1316 node->nlookup -= nlookup;
1317 if (!node->nlookup) {
1318 unref_node(f, node);
1319 } else if (lru_enabled(f) && node->nlookup == 1) {
1320 set_forget_time(f, node);
1322 pthread_mutex_unlock(&f->lock);
1325 static void unlink_node(struct fuse *f, struct node *node)
1327 if (f->conf.remember) {
1328 assert(node->nlookup > 1);
1329 node->nlookup--;
1331 unhash_name(f, node);
1334 static void remove_node(struct fuse *f, fuse_ino_t dir, const char *name)
1336 struct node *node;
1338 pthread_mutex_lock(&f->lock);
1339 node = lookup_node(f, dir, name);
1340 if (node != NULL)
1341 unlink_node(f, node);
1342 pthread_mutex_unlock(&f->lock);
1345 static int rename_node(struct fuse *f, fuse_ino_t olddir, const char *oldname,
1346 fuse_ino_t newdir, const char *newname, int hide)
1348 struct node *node;
1349 struct node *newnode;
1350 int err = 0;
1352 pthread_mutex_lock(&f->lock);
1353 node = lookup_node(f, olddir, oldname);
1354 newnode = lookup_node(f, newdir, newname);
1355 if (node == NULL)
1356 goto out;
1358 if (newnode != NULL) {
1359 if (hide) {
1360 fprintf(stderr, "fuse: hidden file got created during hiding\n");
1361 err = -EBUSY;
1362 goto out;
1364 unlink_node(f, newnode);
1367 unhash_name(f, node);
1368 if (hash_name(f, node, newdir, newname) == -1) {
1369 err = -ENOMEM;
1370 goto out;
1373 if (hide)
1374 node->is_hidden = 1;
1376 out:
1377 pthread_mutex_unlock(&f->lock);
1378 return err;
1381 static void set_stat(struct fuse *f, fuse_ino_t nodeid, struct stat *stbuf)
1383 if (!f->conf.use_ino)
1384 stbuf->st_ino = nodeid;
1385 if (f->conf.set_mode)
1386 stbuf->st_mode = (stbuf->st_mode & S_IFMT) |
1387 (0777 & ~f->conf.umask);
1388 if (f->conf.set_uid)
1389 stbuf->st_uid = f->conf.uid;
1390 if (f->conf.set_gid)
1391 stbuf->st_gid = f->conf.gid;
1394 static struct fuse *req_fuse(fuse_req_t req)
1396 return (struct fuse *) fuse_req_userdata(req);
1399 static void fuse_intr_sighandler(int sig)
1401 (void) sig;
1402 /* Nothing to do */
1405 struct fuse_intr_data {
1406 pthread_t id;
1407 pthread_cond_t cond;
1408 int finished;
1411 static void fuse_interrupt(fuse_req_t req, void *d_)
1413 struct fuse_intr_data *d = d_;
1414 struct fuse *f = req_fuse(req);
1416 if (d->id == pthread_self())
1417 return;
1419 pthread_mutex_lock(&f->lock);
1420 while (!d->finished) {
1421 struct timeval now;
1422 struct timespec timeout;
1424 pthread_kill(d->id, f->conf.intr_signal);
1425 gettimeofday(&now, NULL);
1426 timeout.tv_sec = now.tv_sec + 1;
1427 timeout.tv_nsec = now.tv_usec * 1000;
1428 pthread_cond_timedwait(&d->cond, &f->lock, &timeout);
1430 pthread_mutex_unlock(&f->lock);
1433 static void fuse_do_finish_interrupt(struct fuse *f, fuse_req_t req,
1434 struct fuse_intr_data *d)
1436 pthread_mutex_lock(&f->lock);
1437 d->finished = 1;
1438 pthread_cond_broadcast(&d->cond);
1439 pthread_mutex_unlock(&f->lock);
1440 fuse_req_interrupt_func(req, NULL, NULL);
1441 pthread_cond_destroy(&d->cond);
1444 static void fuse_do_prepare_interrupt(fuse_req_t req, struct fuse_intr_data *d)
1446 d->id = pthread_self();
1447 pthread_cond_init(&d->cond, NULL);
1448 d->finished = 0;
1449 fuse_req_interrupt_func(req, fuse_interrupt, d);
1452 static inline void fuse_finish_interrupt(struct fuse *f, fuse_req_t req,
1453 struct fuse_intr_data *d)
1455 if (f->conf.intr)
1456 fuse_do_finish_interrupt(f, req, d);
1459 static inline void fuse_prepare_interrupt(struct fuse *f, fuse_req_t req,
1460 struct fuse_intr_data *d)
1462 if (f->conf.intr)
1463 fuse_do_prepare_interrupt(req, d);
1466 #if !defined(__FreeBSD__) && !defined(__NetBSD__)
1468 static int fuse_compat_open(struct fuse_fs *fs, const char *path,
1469 struct fuse_file_info *fi)
1471 int err;
1472 if (!fs->compat || fs->compat >= 25)
1473 err = fs->op.open(path, fi);
1474 else if (fs->compat == 22) {
1475 struct fuse_file_info_compat tmp;
1476 memcpy(&tmp, fi, sizeof(tmp));
1477 err = ((struct fuse_operations_compat22 *) &fs->op)->open(path,
1478 &tmp);
1479 memcpy(fi, &tmp, sizeof(tmp));
1480 fi->fh = tmp.fh;
1481 } else
1482 err = ((struct fuse_operations_compat2 *) &fs->op)
1483 ->open(path, fi->flags);
1484 return err;
1487 static int fuse_compat_release(struct fuse_fs *fs, const char *path,
1488 struct fuse_file_info *fi)
1490 if (!fs->compat || fs->compat >= 22)
1491 return fs->op.release(path, fi);
1492 else
1493 return ((struct fuse_operations_compat2 *) &fs->op)
1494 ->release(path, fi->flags);
1497 static int fuse_compat_opendir(struct fuse_fs *fs, const char *path,
1498 struct fuse_file_info *fi)
1500 if (!fs->compat || fs->compat >= 25)
1501 return fs->op.opendir(path, fi);
1502 else {
1503 int err;
1504 struct fuse_file_info_compat tmp;
1505 memcpy(&tmp, fi, sizeof(tmp));
1506 err = ((struct fuse_operations_compat22 *) &fs->op)
1507 ->opendir(path, &tmp);
1508 memcpy(fi, &tmp, sizeof(tmp));
1509 fi->fh = tmp.fh;
1510 return err;
1514 static void convert_statfs_compat(struct fuse_statfs_compat1 *compatbuf,
1515 struct statvfs *stbuf)
1517 stbuf->f_bsize = compatbuf->block_size;
1518 stbuf->f_blocks = compatbuf->blocks;
1519 stbuf->f_bfree = compatbuf->blocks_free;
1520 stbuf->f_bavail = compatbuf->blocks_free;
1521 stbuf->f_files = compatbuf->files;
1522 stbuf->f_ffree = compatbuf->files_free;
1523 stbuf->f_namemax = compatbuf->namelen;
1526 static void convert_statfs_old(struct statfs *oldbuf, struct statvfs *stbuf)
1528 stbuf->f_bsize = oldbuf->f_bsize;
1529 stbuf->f_blocks = oldbuf->f_blocks;
1530 stbuf->f_bfree = oldbuf->f_bfree;
1531 stbuf->f_bavail = oldbuf->f_bavail;
1532 stbuf->f_files = oldbuf->f_files;
1533 stbuf->f_ffree = oldbuf->f_ffree;
1534 stbuf->f_namemax = oldbuf->f_namelen;
1537 static int fuse_compat_statfs(struct fuse_fs *fs, const char *path,
1538 struct statvfs *buf)
1540 int err;
1542 if (!fs->compat || fs->compat >= 25) {
1543 err = fs->op.statfs(fs->compat == 25 ? "/" : path, buf);
1544 } else if (fs->compat > 11) {
1545 struct statfs oldbuf;
1546 err = ((struct fuse_operations_compat22 *) &fs->op)
1547 ->statfs("/", &oldbuf);
1548 if (!err)
1549 convert_statfs_old(&oldbuf, buf);
1550 } else {
1551 struct fuse_statfs_compat1 compatbuf;
1552 memset(&compatbuf, 0, sizeof(struct fuse_statfs_compat1));
1553 err = ((struct fuse_operations_compat1 *) &fs->op)
1554 ->statfs(&compatbuf);
1555 if (!err)
1556 convert_statfs_compat(&compatbuf, buf);
1558 return err;
1561 #else /* __FreeBSD__ || __NetBSD__ */
1563 static inline int fuse_compat_open(struct fuse_fs *fs, char *path,
1564 struct fuse_file_info *fi)
1566 return fs->op.open(path, fi);
1569 static inline int fuse_compat_release(struct fuse_fs *fs, const char *path,
1570 struct fuse_file_info *fi)
1572 return fs->op.release(path, fi);
1575 static inline int fuse_compat_opendir(struct fuse_fs *fs, const char *path,
1576 struct fuse_file_info *fi)
1578 return fs->op.opendir(path, fi);
1581 static inline int fuse_compat_statfs(struct fuse_fs *fs, const char *path,
1582 struct statvfs *buf)
1584 return fs->op.statfs(fs->compat == 25 ? "/" : path, buf);
1587 #endif /* __FreeBSD__ || __NetBSD__ */
1589 int fuse_fs_getattr(struct fuse_fs *fs, const char *path, struct stat *buf)
1591 fuse_get_context()->private_data = fs->user_data;
1592 if (fs->op.getattr) {
1593 if (fs->debug)
1594 fprintf(stderr, "getattr %s\n", path);
1596 return fs->op.getattr(path, buf);
1597 } else {
1598 return -ENOSYS;
1602 int fuse_fs_fgetattr(struct fuse_fs *fs, const char *path, struct stat *buf,
1603 struct fuse_file_info *fi)
1605 fuse_get_context()->private_data = fs->user_data;
1606 if (fs->op.fgetattr) {
1607 if (fs->debug)
1608 fprintf(stderr, "fgetattr[%llu] %s\n",
1609 (unsigned long long) fi->fh, path);
1611 return fs->op.fgetattr(path, buf, fi);
1612 } else if (path && fs->op.getattr) {
1613 if (fs->debug)
1614 fprintf(stderr, "getattr %s\n", path);
1616 return fs->op.getattr(path, buf);
1617 } else {
1618 return -ENOSYS;
1622 int fuse_fs_rename(struct fuse_fs *fs, const char *oldpath,
1623 const char *newpath)
1625 fuse_get_context()->private_data = fs->user_data;
1626 if (fs->op.rename) {
1627 if (fs->debug)
1628 fprintf(stderr, "rename %s %s\n", oldpath, newpath);
1630 return fs->op.rename(oldpath, newpath);
1631 } else {
1632 return -ENOSYS;
1636 int fuse_fs_unlink(struct fuse_fs *fs, const char *path)
1638 fuse_get_context()->private_data = fs->user_data;
1639 if (fs->op.unlink) {
1640 if (fs->debug)
1641 fprintf(stderr, "unlink %s\n", path);
1643 return fs->op.unlink(path);
1644 } else {
1645 return -ENOSYS;
1649 int fuse_fs_rmdir(struct fuse_fs *fs, const char *path)
1651 fuse_get_context()->private_data = fs->user_data;
1652 if (fs->op.rmdir) {
1653 if (fs->debug)
1654 fprintf(stderr, "rmdir %s\n", path);
1656 return fs->op.rmdir(path);
1657 } else {
1658 return -ENOSYS;
1662 int fuse_fs_symlink(struct fuse_fs *fs, const char *linkname, const char *path)
1664 fuse_get_context()->private_data = fs->user_data;
1665 if (fs->op.symlink) {
1666 if (fs->debug)
1667 fprintf(stderr, "symlink %s %s\n", linkname, path);
1669 return fs->op.symlink(linkname, path);
1670 } else {
1671 return -ENOSYS;
1675 int fuse_fs_link(struct fuse_fs *fs, const char *oldpath, const char *newpath)
1677 fuse_get_context()->private_data = fs->user_data;
1678 if (fs->op.link) {
1679 if (fs->debug)
1680 fprintf(stderr, "link %s %s\n", oldpath, newpath);
1682 return fs->op.link(oldpath, newpath);
1683 } else {
1684 return -ENOSYS;
1688 int fuse_fs_release(struct fuse_fs *fs, const char *path,
1689 struct fuse_file_info *fi)
1691 fuse_get_context()->private_data = fs->user_data;
1692 if (fs->op.release) {
1693 if (fs->debug)
1694 fprintf(stderr, "release%s[%llu] flags: 0x%x\n",
1695 fi->flush ? "+flush" : "",
1696 (unsigned long long) fi->fh, fi->flags);
1698 return fuse_compat_release(fs, path, fi);
1699 } else {
1700 return 0;
1704 int fuse_fs_opendir(struct fuse_fs *fs, const char *path,
1705 struct fuse_file_info *fi)
1707 fuse_get_context()->private_data = fs->user_data;
1708 if (fs->op.opendir) {
1709 int err;
1711 if (fs->debug)
1712 fprintf(stderr, "opendir flags: 0x%x %s\n", fi->flags,
1713 path);
1715 err = fuse_compat_opendir(fs, path, fi);
1717 if (fs->debug && !err)
1718 fprintf(stderr, " opendir[%lli] flags: 0x%x %s\n",
1719 (unsigned long long) fi->fh, fi->flags, path);
1721 return err;
1722 } else {
1723 return 0;
1727 int fuse_fs_open(struct fuse_fs *fs, const char *path,
1728 struct fuse_file_info *fi)
1730 fuse_get_context()->private_data = fs->user_data;
1731 if (fs->op.open) {
1732 int err;
1734 if (fs->debug)
1735 fprintf(stderr, "open flags: 0x%x %s\n", fi->flags,
1736 path);
1738 err = fuse_compat_open(fs, path, fi);
1740 if (fs->debug && !err)
1741 fprintf(stderr, " open[%lli] flags: 0x%x %s\n",
1742 (unsigned long long) fi->fh, fi->flags, path);
1744 return err;
1745 } else {
1746 return 0;
1750 static void fuse_free_buf(struct fuse_bufvec *buf)
1752 if (buf != NULL) {
1753 size_t i;
1755 for (i = 0; i < buf->count; i++)
1756 free(buf->buf[i].mem);
1757 free(buf);
1761 int fuse_fs_read_buf(struct fuse_fs *fs, const char *path,
1762 struct fuse_bufvec **bufp, size_t size, off_t off,
1763 struct fuse_file_info *fi)
1765 fuse_get_context()->private_data = fs->user_data;
1766 if (fs->op.read || fs->op.read_buf) {
1767 int res;
1769 if (fs->debug)
1770 fprintf(stderr,
1771 "read[%llu] %zu bytes from %llu flags: 0x%x\n",
1772 (unsigned long long) fi->fh,
1773 size, (unsigned long long) off, fi->flags);
1775 if (fs->op.read_buf) {
1776 res = fs->op.read_buf(path, bufp, size, off, fi);
1777 } else {
1778 struct fuse_bufvec *buf;
1779 void *mem;
1781 buf = malloc(sizeof(struct fuse_bufvec));
1782 if (buf == NULL)
1783 return -ENOMEM;
1785 mem = malloc(size);
1786 if (mem == NULL) {
1787 free(buf);
1788 return -ENOMEM;
1790 *buf = FUSE_BUFVEC_INIT(size);
1791 buf->buf[0].mem = mem;
1792 *bufp = buf;
1794 res = fs->op.read(path, mem, size, off, fi);
1795 if (res >= 0)
1796 buf->buf[0].size = res;
1799 if (fs->debug && res >= 0)
1800 fprintf(stderr, " read[%llu] %zu bytes from %llu\n",
1801 (unsigned long long) fi->fh,
1802 fuse_buf_size(*bufp),
1803 (unsigned long long) off);
1804 if (res >= 0 && fuse_buf_size(*bufp) > (int) size)
1805 fprintf(stderr, "fuse: read too many bytes\n");
1807 if (res < 0)
1808 return res;
1810 return 0;
1811 } else {
1812 return -ENOSYS;
1816 int fuse_fs_read(struct fuse_fs *fs, const char *path, char *mem, size_t size,
1817 off_t off, struct fuse_file_info *fi)
1819 int res;
1820 struct fuse_bufvec *buf = NULL;
1822 res = fuse_fs_read_buf(fs, path, &buf, size, off, fi);
1823 if (res == 0) {
1824 struct fuse_bufvec dst = FUSE_BUFVEC_INIT(size);
1826 dst.buf[0].mem = mem;
1827 res = fuse_buf_copy(&dst, buf, 0);
1829 fuse_free_buf(buf);
1831 return res;
1834 int fuse_fs_write_buf(struct fuse_fs *fs, const char *path,
1835 struct fuse_bufvec *buf, off_t off,
1836 struct fuse_file_info *fi)
1838 fuse_get_context()->private_data = fs->user_data;
1839 if (fs->op.write_buf || fs->op.write) {
1840 int res;
1841 size_t size = fuse_buf_size(buf);
1843 assert(buf->idx == 0 && buf->off == 0);
1844 if (fs->debug)
1845 fprintf(stderr,
1846 "write%s[%llu] %zu bytes to %llu flags: 0x%x\n",
1847 fi->writepage ? "page" : "",
1848 (unsigned long long) fi->fh,
1849 size,
1850 (unsigned long long) off,
1851 fi->flags);
1853 if (fs->op.write_buf) {
1854 res = fs->op.write_buf(path, buf, off, fi);
1855 } else {
1856 void *mem = NULL;
1857 struct fuse_buf *flatbuf;
1858 struct fuse_bufvec tmp = FUSE_BUFVEC_INIT(size);
1860 if (buf->count == 1 &&
1861 !(buf->buf[0].flags & FUSE_BUF_IS_FD)) {
1862 flatbuf = &buf->buf[0];
1863 } else {
1864 res = -ENOMEM;
1865 mem = malloc(size);
1866 if (mem == NULL)
1867 goto out;
1869 tmp.buf[0].mem = mem;
1870 res = fuse_buf_copy(&tmp, buf, 0);
1871 if (res <= 0)
1872 goto out_free;
1874 tmp.buf[0].size = res;
1875 flatbuf = &tmp.buf[0];
1878 res = fs->op.write(path, flatbuf->mem, flatbuf->size,
1879 off, fi);
1880 out_free:
1881 free(mem);
1883 out:
1884 if (fs->debug && res >= 0)
1885 fprintf(stderr, " write%s[%llu] %u bytes to %llu\n",
1886 fi->writepage ? "page" : "",
1887 (unsigned long long) fi->fh, res,
1888 (unsigned long long) off);
1889 if (res > (int) size)
1890 fprintf(stderr, "fuse: wrote too many bytes\n");
1892 return res;
1893 } else {
1894 return -ENOSYS;
1898 int fuse_fs_write(struct fuse_fs *fs, const char *path, const char *mem,
1899 size_t size, off_t off, struct fuse_file_info *fi)
1901 struct fuse_bufvec bufv = FUSE_BUFVEC_INIT(size);
1903 bufv.buf[0].mem = (void *) mem;
1905 return fuse_fs_write_buf(fs, path, &bufv, off, fi);
1908 int fuse_fs_fsync(struct fuse_fs *fs, const char *path, int datasync,
1909 struct fuse_file_info *fi)
1911 fuse_get_context()->private_data = fs->user_data;
1912 if (fs->op.fsync) {
1913 if (fs->debug)
1914 fprintf(stderr, "fsync[%llu] datasync: %i\n",
1915 (unsigned long long) fi->fh, datasync);
1917 return fs->op.fsync(path, datasync, fi);
1918 } else {
1919 return -ENOSYS;
1923 int fuse_fs_fsyncdir(struct fuse_fs *fs, const char *path, int datasync,
1924 struct fuse_file_info *fi)
1926 fuse_get_context()->private_data = fs->user_data;
1927 if (fs->op.fsyncdir) {
1928 if (fs->debug)
1929 fprintf(stderr, "fsyncdir[%llu] datasync: %i\n",
1930 (unsigned long long) fi->fh, datasync);
1932 return fs->op.fsyncdir(path, datasync, fi);
1933 } else {
1934 return -ENOSYS;
1938 int fuse_fs_flush(struct fuse_fs *fs, const char *path,
1939 struct fuse_file_info *fi)
1941 fuse_get_context()->private_data = fs->user_data;
1942 if (fs->op.flush) {
1943 if (fs->debug)
1944 fprintf(stderr, "flush[%llu]\n",
1945 (unsigned long long) fi->fh);
1947 return fs->op.flush(path, fi);
1948 } else {
1949 return -ENOSYS;
1953 int fuse_fs_statfs(struct fuse_fs *fs, const char *path, struct statvfs *buf)
1955 fuse_get_context()->private_data = fs->user_data;
1956 if (fs->op.statfs) {
1957 if (fs->debug)
1958 fprintf(stderr, "statfs %s\n", path);
1960 return fuse_compat_statfs(fs, path, buf);
1961 } else {
1962 buf->f_namemax = 255;
1963 buf->f_bsize = 512;
1964 return 0;
1968 int fuse_fs_releasedir(struct fuse_fs *fs, const char *path,
1969 struct fuse_file_info *fi)
1971 fuse_get_context()->private_data = fs->user_data;
1972 if (fs->op.releasedir) {
1973 if (fs->debug)
1974 fprintf(stderr, "releasedir[%llu] flags: 0x%x\n",
1975 (unsigned long long) fi->fh, fi->flags);
1977 return fs->op.releasedir(path, fi);
1978 } else {
1979 return 0;
1983 static int fill_dir_old(struct fuse_dirhandle *dh, const char *name, int type,
1984 ino_t ino)
1986 int res;
1987 struct stat stbuf;
1989 memset(&stbuf, 0, sizeof(stbuf));
1990 stbuf.st_mode = type << 12;
1991 stbuf.st_ino = ino;
1993 res = dh->filler(dh->buf, name, &stbuf, 0);
1994 return res ? -ENOMEM : 0;
1997 int fuse_fs_readdir(struct fuse_fs *fs, const char *path, void *buf,
1998 fuse_fill_dir_t filler, off_t off,
1999 struct fuse_file_info *fi)
2001 fuse_get_context()->private_data = fs->user_data;
2002 if (fs->op.readdir) {
2003 if (fs->debug)
2004 fprintf(stderr, "readdir[%llu] from %llu\n",
2005 (unsigned long long) fi->fh,
2006 (unsigned long long) off);
2008 return fs->op.readdir(path, buf, filler, off, fi);
2009 } else if (fs->op.getdir) {
2010 struct fuse_dirhandle dh;
2012 if (fs->debug)
2013 fprintf(stderr, "getdir[%llu]\n",
2014 (unsigned long long) fi->fh);
2016 dh.filler = filler;
2017 dh.buf = buf;
2018 return fs->op.getdir(path, &dh, fill_dir_old);
2019 } else {
2020 return -ENOSYS;
2024 int fuse_fs_create(struct fuse_fs *fs, const char *path, mode_t mode,
2025 struct fuse_file_info *fi)
2027 fuse_get_context()->private_data = fs->user_data;
2028 if (fs->op.create) {
2029 int err;
2031 if (fs->debug)
2032 fprintf(stderr,
2033 "create flags: 0x%x %s 0%o umask=0%03o\n",
2034 fi->flags, path, mode,
2035 fuse_get_context()->umask);
2037 err = fs->op.create(path, mode, fi);
2039 if (fs->debug && !err)
2040 fprintf(stderr, " create[%llu] flags: 0x%x %s\n",
2041 (unsigned long long) fi->fh, fi->flags, path);
2043 return err;
2044 } else {
2045 return -ENOSYS;
2049 int fuse_fs_lock(struct fuse_fs *fs, const char *path,
2050 struct fuse_file_info *fi, int cmd, struct flock *lock)
2052 fuse_get_context()->private_data = fs->user_data;
2053 if (fs->op.lock) {
2054 if (fs->debug)
2055 fprintf(stderr, "lock[%llu] %s %s start: %llu len: %llu pid: %llu\n",
2056 (unsigned long long) fi->fh,
2057 (cmd == F_GETLK ? "F_GETLK" :
2058 (cmd == F_SETLK ? "F_SETLK" :
2059 (cmd == F_SETLKW ? "F_SETLKW" : "???"))),
2060 (lock->l_type == F_RDLCK ? "F_RDLCK" :
2061 (lock->l_type == F_WRLCK ? "F_WRLCK" :
2062 (lock->l_type == F_UNLCK ? "F_UNLCK" :
2063 "???"))),
2064 (unsigned long long) lock->l_start,
2065 (unsigned long long) lock->l_len,
2066 (unsigned long long) lock->l_pid);
2068 return fs->op.lock(path, fi, cmd, lock);
2069 } else {
2070 return -ENOSYS;
2074 int fuse_fs_flock(struct fuse_fs *fs, const char *path,
2075 struct fuse_file_info *fi, int op)
2077 fuse_get_context()->private_data = fs->user_data;
2078 if (fs->op.flock) {
2079 if (fs->debug) {
2080 int xop = op & ~LOCK_NB;
2082 fprintf(stderr, "lock[%llu] %s%s\n",
2083 (unsigned long long) fi->fh,
2084 xop == LOCK_SH ? "LOCK_SH" :
2085 (xop == LOCK_EX ? "LOCK_EX" :
2086 (xop == LOCK_UN ? "LOCK_UN" : "???")),
2087 (op & LOCK_NB) ? "|LOCK_NB" : "");
2089 return fs->op.flock(path, fi, op);
2090 } else {
2091 return -ENOSYS;
2095 int fuse_fs_chown(struct fuse_fs *fs, const char *path, uid_t uid, gid_t gid)
2097 fuse_get_context()->private_data = fs->user_data;
2098 if (fs->op.chown) {
2099 if (fs->debug)
2100 fprintf(stderr, "chown %s %lu %lu\n", path,
2101 (unsigned long) uid, (unsigned long) gid);
2103 return fs->op.chown(path, uid, gid);
2104 } else {
2105 return -ENOSYS;
2109 int fuse_fs_truncate(struct fuse_fs *fs, const char *path, off_t size)
2111 fuse_get_context()->private_data = fs->user_data;
2112 if (fs->op.truncate) {
2113 if (fs->debug)
2114 fprintf(stderr, "truncate %s %llu\n", path,
2115 (unsigned long long) size);
2117 return fs->op.truncate(path, size);
2118 } else {
2119 return -ENOSYS;
2123 int fuse_fs_ftruncate(struct fuse_fs *fs, const char *path, off_t size,
2124 struct fuse_file_info *fi)
2126 fuse_get_context()->private_data = fs->user_data;
2127 if (fs->op.ftruncate) {
2128 if (fs->debug)
2129 fprintf(stderr, "ftruncate[%llu] %llu\n",
2130 (unsigned long long) fi->fh,
2131 (unsigned long long) size);
2133 return fs->op.ftruncate(path, size, fi);
2134 } else if (path && fs->op.truncate) {
2135 if (fs->debug)
2136 fprintf(stderr, "truncate %s %llu\n", path,
2137 (unsigned long long) size);
2139 return fs->op.truncate(path, size);
2140 } else {
2141 return -ENOSYS;
2145 int fuse_fs_utimens(struct fuse_fs *fs, const char *path,
2146 const struct timespec tv[2])
2148 fuse_get_context()->private_data = fs->user_data;
2149 if (fs->op.utimens) {
2150 if (fs->debug)
2151 fprintf(stderr, "utimens %s %li.%09lu %li.%09lu\n",
2152 path, tv[0].tv_sec, tv[0].tv_nsec,
2153 tv[1].tv_sec, tv[1].tv_nsec);
2155 return fs->op.utimens(path, tv);
2156 } else if(fs->op.utime) {
2157 struct utimbuf buf;
2159 if (fs->debug)
2160 fprintf(stderr, "utime %s %li %li\n", path,
2161 tv[0].tv_sec, tv[1].tv_sec);
2163 buf.actime = tv[0].tv_sec;
2164 buf.modtime = tv[1].tv_sec;
2165 return fs->op.utime(path, &buf);
2166 } else {
2167 return -ENOSYS;
2171 int fuse_fs_access(struct fuse_fs *fs, const char *path, int mask)
2173 fuse_get_context()->private_data = fs->user_data;
2174 if (fs->op.access) {
2175 if (fs->debug)
2176 fprintf(stderr, "access %s 0%o\n", path, mask);
2178 return fs->op.access(path, mask);
2179 } else {
2180 return -ENOSYS;
2184 int fuse_fs_readlink(struct fuse_fs *fs, const char *path, char *buf,
2185 size_t len)
2187 fuse_get_context()->private_data = fs->user_data;
2188 if (fs->op.readlink) {
2189 if (fs->debug)
2190 fprintf(stderr, "readlink %s %lu\n", path,
2191 (unsigned long) len);
2193 return fs->op.readlink(path, buf, len);
2194 } else {
2195 return -ENOSYS;
2199 int fuse_fs_mknod(struct fuse_fs *fs, const char *path, mode_t mode,
2200 dev_t rdev)
2202 fuse_get_context()->private_data = fs->user_data;
2203 if (fs->op.mknod) {
2204 if (fs->debug)
2205 fprintf(stderr, "mknod %s 0%o 0x%llx umask=0%03o\n",
2206 path, mode, (unsigned long long) rdev,
2207 fuse_get_context()->umask);
2209 return fs->op.mknod(path, mode, rdev);
2210 } else {
2211 return -ENOSYS;
2215 int fuse_fs_mkdir(struct fuse_fs *fs, const char *path, mode_t mode)
2217 fuse_get_context()->private_data = fs->user_data;
2218 if (fs->op.mkdir) {
2219 if (fs->debug)
2220 fprintf(stderr, "mkdir %s 0%o umask=0%03o\n",
2221 path, mode, fuse_get_context()->umask);
2223 return fs->op.mkdir(path, mode);
2224 } else {
2225 return -ENOSYS;
2229 int fuse_fs_setxattr(struct fuse_fs *fs, const char *path, const char *name,
2230 const char *value, size_t size, int flags)
2232 fuse_get_context()->private_data = fs->user_data;
2233 if (fs->op.setxattr) {
2234 if (fs->debug)
2235 fprintf(stderr, "setxattr %s %s %lu 0x%x\n",
2236 path, name, (unsigned long) size, flags);
2238 return fs->op.setxattr(path, name, value, size, flags);
2239 } else {
2240 return -ENOSYS;
2244 int fuse_fs_getxattr(struct fuse_fs *fs, const char *path, const char *name,
2245 char *value, size_t size)
2247 fuse_get_context()->private_data = fs->user_data;
2248 if (fs->op.getxattr) {
2249 if (fs->debug)
2250 fprintf(stderr, "getxattr %s %s %lu\n",
2251 path, name, (unsigned long) size);
2253 return fs->op.getxattr(path, name, value, size);
2254 } else {
2255 return -ENOSYS;
2259 int fuse_fs_listxattr(struct fuse_fs *fs, const char *path, char *list,
2260 size_t size)
2262 fuse_get_context()->private_data = fs->user_data;
2263 if (fs->op.listxattr) {
2264 if (fs->debug)
2265 fprintf(stderr, "listxattr %s %lu\n",
2266 path, (unsigned long) size);
2268 return fs->op.listxattr(path, list, size);
2269 } else {
2270 return -ENOSYS;
2274 int fuse_fs_bmap(struct fuse_fs *fs, const char *path, size_t blocksize,
2275 uint64_t *idx)
2277 fuse_get_context()->private_data = fs->user_data;
2278 if (fs->op.bmap) {
2279 if (fs->debug)
2280 fprintf(stderr, "bmap %s blocksize: %lu index: %llu\n",
2281 path, (unsigned long) blocksize,
2282 (unsigned long long) *idx);
2284 return fs->op.bmap(path, blocksize, idx);
2285 } else {
2286 return -ENOSYS;
2290 int fuse_fs_removexattr(struct fuse_fs *fs, const char *path, const char *name)
2292 fuse_get_context()->private_data = fs->user_data;
2293 if (fs->op.removexattr) {
2294 if (fs->debug)
2295 fprintf(stderr, "removexattr %s %s\n", path, name);
2297 return fs->op.removexattr(path, name);
2298 } else {
2299 return -ENOSYS;
2303 int fuse_fs_ioctl(struct fuse_fs *fs, const char *path, int cmd, void *arg,
2304 struct fuse_file_info *fi, unsigned int flags, void *data)
2306 fuse_get_context()->private_data = fs->user_data;
2307 if (fs->op.ioctl) {
2308 if (fs->debug)
2309 fprintf(stderr, "ioctl[%llu] 0x%x flags: 0x%x\n",
2310 (unsigned long long) fi->fh, cmd, flags);
2312 return fs->op.ioctl(path, cmd, arg, fi, flags, data);
2313 } else
2314 return -ENOSYS;
2317 int fuse_fs_poll(struct fuse_fs *fs, const char *path,
2318 struct fuse_file_info *fi, struct fuse_pollhandle *ph,
2319 unsigned *reventsp)
2321 fuse_get_context()->private_data = fs->user_data;
2322 if (fs->op.poll) {
2323 int res;
2325 if (fs->debug)
2326 fprintf(stderr, "poll[%llu] ph: %p\n",
2327 (unsigned long long) fi->fh, ph);
2329 res = fs->op.poll(path, fi, ph, reventsp);
2331 if (fs->debug && !res)
2332 fprintf(stderr, " poll[%llu] revents: 0x%x\n",
2333 (unsigned long long) fi->fh, *reventsp);
2335 return res;
2336 } else
2337 return -ENOSYS;
2340 int fuse_fs_fallocate(struct fuse_fs *fs, const char *path, int mode,
2341 off_t offset, off_t length, struct fuse_file_info *fi)
2343 fuse_get_context()->private_data = fs->user_data;
2344 if (fs->op.fallocate) {
2345 if (fs->debug)
2346 fprintf(stderr, "fallocate %s mode %x, offset: %llu, length: %llu\n",
2347 path,
2348 mode,
2349 (unsigned long long) offset,
2350 (unsigned long long) length);
2352 return fs->op.fallocate(path, mode, offset, length, fi);
2353 } else
2354 return -ENOSYS;
2357 static int is_open(struct fuse *f, fuse_ino_t dir, const char *name)
2359 struct node *node;
2360 int isopen = 0;
2361 pthread_mutex_lock(&f->lock);
2362 node = lookup_node(f, dir, name);
2363 if (node && node->open_count > 0)
2364 isopen = 1;
2365 pthread_mutex_unlock(&f->lock);
2366 return isopen;
2369 static char *hidden_name(struct fuse *f, fuse_ino_t dir, const char *oldname,
2370 char *newname, size_t bufsize)
2372 struct stat buf;
2373 struct node *node;
2374 struct node *newnode;
2375 char *newpath;
2376 int res;
2377 int failctr = 10;
2379 do {
2380 pthread_mutex_lock(&f->lock);
2381 node = lookup_node(f, dir, oldname);
2382 if (node == NULL) {
2383 pthread_mutex_unlock(&f->lock);
2384 return NULL;
2386 do {
2387 f->hidectr ++;
2388 snprintf(newname, bufsize, ".fuse_hidden%08x%08x",
2389 (unsigned int) node->nodeid, f->hidectr);
2390 newnode = lookup_node(f, dir, newname);
2391 } while(newnode);
2393 res = try_get_path(f, dir, newname, &newpath, NULL, false);
2394 pthread_mutex_unlock(&f->lock);
2395 if (res)
2396 break;
2398 res = fuse_fs_getattr(f->fs, newpath, &buf);
2399 if (res == -ENOENT)
2400 break;
2401 free(newpath);
2402 newpath = NULL;
2403 } while(res == 0 && --failctr);
2405 return newpath;
2408 static int hide_node(struct fuse *f, const char *oldpath,
2409 fuse_ino_t dir, const char *oldname)
2411 char newname[64];
2412 char *newpath;
2413 int err = -EBUSY;
2415 newpath = hidden_name(f, dir, oldname, newname, sizeof(newname));
2416 if (newpath) {
2417 err = fuse_fs_rename(f->fs, oldpath, newpath);
2418 if (!err)
2419 err = rename_node(f, dir, oldname, dir, newname, 1);
2420 free(newpath);
2422 return err;
2425 static int mtime_eq(const struct stat *stbuf, const struct timespec *ts)
2427 return stbuf->st_mtime == ts->tv_sec &&
2428 ST_MTIM_NSEC(stbuf) == ts->tv_nsec;
2431 #ifndef CLOCK_MONOTONIC
2432 #define CLOCK_MONOTONIC CLOCK_REALTIME
2433 #endif
2435 static void curr_time(struct timespec *now)
2437 static clockid_t clockid = CLOCK_MONOTONIC;
2438 int res = clock_gettime(clockid, now);
2439 if (res == -1 && errno == EINVAL) {
2440 clockid = CLOCK_REALTIME;
2441 res = clock_gettime(clockid, now);
2443 if (res == -1) {
2444 perror("fuse: clock_gettime");
2445 abort();
2449 static void update_stat(struct node *node, const struct stat *stbuf)
2451 if (node->cache_valid && (!mtime_eq(stbuf, &node->mtime) ||
2452 stbuf->st_size != node->size))
2453 node->cache_valid = 0;
2454 node->mtime.tv_sec = stbuf->st_mtime;
2455 node->mtime.tv_nsec = ST_MTIM_NSEC(stbuf);
2456 node->size = stbuf->st_size;
2457 curr_time(&node->stat_updated);
2460 static int lookup_path(struct fuse *f, fuse_ino_t nodeid,
2461 const char *name, const char *path,
2462 struct fuse_entry_param *e, struct fuse_file_info *fi)
2464 int res;
2466 memset(e, 0, sizeof(struct fuse_entry_param));
2467 if (fi)
2468 res = fuse_fs_fgetattr(f->fs, path, &e->attr, fi);
2469 else
2470 res = fuse_fs_getattr(f->fs, path, &e->attr);
2471 if (res == 0) {
2472 struct node *node;
2474 node = find_node(f, nodeid, name);
2475 if (node == NULL)
2476 res = -ENOMEM;
2477 else {
2478 e->ino = node->nodeid;
2479 e->generation = node->generation;
2480 e->entry_timeout = f->conf.entry_timeout;
2481 e->attr_timeout = f->conf.attr_timeout;
2482 if (f->conf.auto_cache) {
2483 pthread_mutex_lock(&f->lock);
2484 update_stat(node, &e->attr);
2485 pthread_mutex_unlock(&f->lock);
2487 set_stat(f, e->ino, &e->attr);
2488 if (f->conf.debug)
2489 fprintf(stderr, " NODEID: %lu\n",
2490 (unsigned long) e->ino);
2493 return res;
2496 static struct fuse_context_i *fuse_get_context_internal(void)
2498 struct fuse_context_i *c;
2500 c = (struct fuse_context_i *) pthread_getspecific(fuse_context_key);
2501 if (c == NULL) {
2502 c = (struct fuse_context_i *)
2503 calloc(1, sizeof(struct fuse_context_i));
2504 if (c == NULL) {
2505 /* This is hard to deal with properly, so just
2506 abort. If memory is so low that the
2507 context cannot be allocated, there's not
2508 much hope for the filesystem anyway */
2509 fprintf(stderr, "fuse: failed to allocate thread specific data\n");
2510 abort();
2512 pthread_setspecific(fuse_context_key, c);
2514 return c;
2517 static void fuse_freecontext(void *data)
2519 free(data);
2522 static int fuse_create_context_key(void)
2524 int err = 0;
2525 pthread_mutex_lock(&fuse_context_lock);
2526 if (!fuse_context_ref) {
2527 err = pthread_key_create(&fuse_context_key, fuse_freecontext);
2528 if (err) {
2529 fprintf(stderr, "fuse: failed to create thread specific key: %s\n",
2530 strerror(err));
2531 pthread_mutex_unlock(&fuse_context_lock);
2532 return -1;
2535 fuse_context_ref++;
2536 pthread_mutex_unlock(&fuse_context_lock);
2537 return 0;
2540 static void fuse_delete_context_key(void)
2542 pthread_mutex_lock(&fuse_context_lock);
2543 fuse_context_ref--;
2544 if (!fuse_context_ref) {
2545 free(pthread_getspecific(fuse_context_key));
2546 pthread_key_delete(fuse_context_key);
2548 pthread_mutex_unlock(&fuse_context_lock);
2551 static struct fuse *req_fuse_prepare(fuse_req_t req)
2553 struct fuse_context_i *c = fuse_get_context_internal();
2554 const struct fuse_ctx *ctx = fuse_req_ctx(req);
2555 c->req = req;
2556 c->ctx.fuse = req_fuse(req);
2557 c->ctx.uid = ctx->uid;
2558 c->ctx.gid = ctx->gid;
2559 c->ctx.pid = ctx->pid;
2560 c->ctx.umask = ctx->umask;
2561 return c->ctx.fuse;
2564 static inline void reply_err(fuse_req_t req, int err)
2566 /* fuse_reply_err() uses non-negated errno values */
2567 fuse_reply_err(req, -err);
2570 static void reply_entry(fuse_req_t req, const struct fuse_entry_param *e,
2571 int err)
2573 if (!err) {
2574 struct fuse *f = req_fuse(req);
2575 if (fuse_reply_entry(req, e) == -ENOENT) {
2576 /* Skip forget for negative result */
2577 if (e->ino != 0)
2578 forget_node(f, e->ino, 1);
2580 } else
2581 reply_err(req, err);
2584 void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn)
2586 fuse_get_context()->private_data = fs->user_data;
2587 if (!fs->op.write_buf)
2588 conn->want &= ~FUSE_CAP_SPLICE_READ;
2589 if (!fs->op.lock)
2590 conn->want &= ~FUSE_CAP_POSIX_LOCKS;
2591 if (!fs->op.flock)
2592 conn->want &= ~FUSE_CAP_FLOCK_LOCKS;
2593 if (fs->op.init)
2594 fs->user_data = fs->op.init(conn);
2597 static void fuse_lib_init(void *data, struct fuse_conn_info *conn)
2599 struct fuse *f = (struct fuse *) data;
2600 struct fuse_context_i *c = fuse_get_context_internal();
2602 memset(c, 0, sizeof(*c));
2603 c->ctx.fuse = f;
2604 conn->want |= FUSE_CAP_EXPORT_SUPPORT;
2605 fuse_fs_init(f->fs, conn);
2608 void fuse_fs_destroy(struct fuse_fs *fs)
2610 fuse_get_context()->private_data = fs->user_data;
2611 if (fs->op.destroy)
2612 fs->op.destroy(fs->user_data);
2613 if (fs->m)
2614 fuse_put_module(fs->m);
2615 free(fs);
2618 static void fuse_lib_destroy(void *data)
2620 struct fuse *f = (struct fuse *) data;
2621 struct fuse_context_i *c = fuse_get_context_internal();
2623 memset(c, 0, sizeof(*c));
2624 c->ctx.fuse = f;
2625 fuse_fs_destroy(f->fs);
2626 f->fs = NULL;
2629 static void fuse_lib_lookup(fuse_req_t req, fuse_ino_t parent,
2630 const char *name)
2632 struct fuse *f = req_fuse_prepare(req);
2633 struct fuse_entry_param e;
2634 char *path;
2635 int err;
2636 struct node *dot = NULL;
2638 if (name[0] == '.') {
2639 int len = strlen(name);
2641 if (len == 1 || (name[1] == '.' && len == 2)) {
2642 pthread_mutex_lock(&f->lock);
2643 if (len == 1) {
2644 if (f->conf.debug)
2645 fprintf(stderr, "LOOKUP-DOT\n");
2646 dot = get_node_nocheck(f, parent);
2647 if (dot == NULL) {
2648 pthread_mutex_unlock(&f->lock);
2649 reply_entry(req, &e, -ESTALE);
2650 return;
2652 dot->refctr++;
2653 } else {
2654 if (f->conf.debug)
2655 fprintf(stderr, "LOOKUP-DOTDOT\n");
2656 parent = get_node(f, parent)->parent->nodeid;
2658 pthread_mutex_unlock(&f->lock);
2659 name = NULL;
2663 err = get_path_name(f, parent, name, &path);
2664 if (!err) {
2665 struct fuse_intr_data d;
2666 if (f->conf.debug)
2667 fprintf(stderr, "LOOKUP %s\n", path);
2668 fuse_prepare_interrupt(f, req, &d);
2669 err = lookup_path(f, parent, name, path, &e, NULL);
2670 if (err == -ENOENT && f->conf.negative_timeout != 0.0) {
2671 e.ino = 0;
2672 e.entry_timeout = f->conf.negative_timeout;
2673 err = 0;
2675 fuse_finish_interrupt(f, req, &d);
2676 free_path(f, parent, path);
2678 if (dot) {
2679 pthread_mutex_lock(&f->lock);
2680 unref_node(f, dot);
2681 pthread_mutex_unlock(&f->lock);
2683 reply_entry(req, &e, err);
2686 static void do_forget(struct fuse *f, fuse_ino_t ino, uint64_t nlookup)
2688 if (f->conf.debug)
2689 fprintf(stderr, "FORGET %llu/%llu\n", (unsigned long long)ino,
2690 (unsigned long long) nlookup);
2691 forget_node(f, ino, nlookup);
2694 static void fuse_lib_forget(fuse_req_t req, fuse_ino_t ino,
2695 unsigned long nlookup)
2697 do_forget(req_fuse(req), ino, nlookup);
2698 fuse_reply_none(req);
2701 static void fuse_lib_forget_multi(fuse_req_t req, size_t count,
2702 struct fuse_forget_data *forgets)
2704 struct fuse *f = req_fuse(req);
2705 size_t i;
2707 for (i = 0; i < count; i++)
2708 do_forget(f, forgets[i].ino, forgets[i].nlookup);
2710 fuse_reply_none(req);
2714 static void fuse_lib_getattr(fuse_req_t req, fuse_ino_t ino,
2715 struct fuse_file_info *fi)
2717 struct fuse *f = req_fuse_prepare(req);
2718 struct stat buf;
2719 char *path;
2720 int err;
2722 memset(&buf, 0, sizeof(buf));
2724 if (fi != NULL && f->fs->op.fgetattr)
2725 err = get_path_nullok(f, ino, &path);
2726 else
2727 err = get_path(f, ino, &path);
2728 if (!err) {
2729 struct fuse_intr_data d;
2730 fuse_prepare_interrupt(f, req, &d);
2731 if (fi)
2732 err = fuse_fs_fgetattr(f->fs, path, &buf, fi);
2733 else
2734 err = fuse_fs_getattr(f->fs, path, &buf);
2735 fuse_finish_interrupt(f, req, &d);
2736 free_path(f, ino, path);
2738 if (!err) {
2739 struct node *node;
2741 pthread_mutex_lock(&f->lock);
2742 node = get_node(f, ino);
2743 if (node->is_hidden && buf.st_nlink > 0)
2744 buf.st_nlink--;
2745 if (f->conf.auto_cache)
2746 update_stat(node, &buf);
2747 pthread_mutex_unlock(&f->lock);
2748 set_stat(f, ino, &buf);
2749 fuse_reply_attr(req, &buf, f->conf.attr_timeout);
2750 } else
2751 reply_err(req, err);
2754 int fuse_fs_chmod(struct fuse_fs *fs, const char *path, mode_t mode)
2756 fuse_get_context()->private_data = fs->user_data;
2757 if (fs->op.chmod)
2758 return fs->op.chmod(path, mode);
2759 else
2760 return -ENOSYS;
2763 static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
2764 int valid, struct fuse_file_info *fi)
2766 struct fuse *f = req_fuse_prepare(req);
2767 struct stat buf;
2768 char *path;
2769 int err;
2771 if (valid == FUSE_SET_ATTR_SIZE && fi != NULL &&
2772 f->fs->op.ftruncate && f->fs->op.fgetattr)
2773 err = get_path_nullok(f, ino, &path);
2774 else
2775 err = get_path(f, ino, &path);
2776 if (!err) {
2777 struct fuse_intr_data d;
2778 fuse_prepare_interrupt(f, req, &d);
2779 err = 0;
2780 if (!err && (valid & FUSE_SET_ATTR_MODE))
2781 err = fuse_fs_chmod(f->fs, path, attr->st_mode);
2782 if (!err && (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID))) {
2783 uid_t uid = (valid & FUSE_SET_ATTR_UID) ?
2784 attr->st_uid : (uid_t) -1;
2785 gid_t gid = (valid & FUSE_SET_ATTR_GID) ?
2786 attr->st_gid : (gid_t) -1;
2787 err = fuse_fs_chown(f->fs, path, uid, gid);
2789 if (!err && (valid & FUSE_SET_ATTR_SIZE)) {
2790 if (fi)
2791 err = fuse_fs_ftruncate(f->fs, path,
2792 attr->st_size, fi);
2793 else
2794 err = fuse_fs_truncate(f->fs, path,
2795 attr->st_size);
2797 #ifdef HAVE_UTIMENSAT
2798 if (!err && f->utime_omit_ok &&
2799 (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME))) {
2800 struct timespec tv[2];
2802 tv[0].tv_sec = 0;
2803 tv[1].tv_sec = 0;
2804 tv[0].tv_nsec = UTIME_OMIT;
2805 tv[1].tv_nsec = UTIME_OMIT;
2807 if (valid & FUSE_SET_ATTR_ATIME_NOW)
2808 tv[0].tv_nsec = UTIME_NOW;
2809 else if (valid & FUSE_SET_ATTR_ATIME)
2810 tv[0] = attr->st_atim;
2812 if (valid & FUSE_SET_ATTR_MTIME_NOW)
2813 tv[1].tv_nsec = UTIME_NOW;
2814 else if (valid & FUSE_SET_ATTR_MTIME)
2815 tv[1] = attr->st_mtim;
2817 err = fuse_fs_utimens(f->fs, path, tv);
2818 } else
2819 #endif
2820 if (!err &&
2821 (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) ==
2822 (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) {
2823 struct timespec tv[2];
2824 tv[0].tv_sec = attr->st_atime;
2825 tv[0].tv_nsec = ST_ATIM_NSEC(attr);
2826 tv[1].tv_sec = attr->st_mtime;
2827 tv[1].tv_nsec = ST_MTIM_NSEC(attr);
2828 err = fuse_fs_utimens(f->fs, path, tv);
2830 if (!err) {
2831 if (fi)
2832 err = fuse_fs_fgetattr(f->fs, path, &buf, fi);
2833 else
2834 err = fuse_fs_getattr(f->fs, path, &buf);
2836 fuse_finish_interrupt(f, req, &d);
2837 free_path(f, ino, path);
2839 if (!err) {
2840 if (f->conf.auto_cache) {
2841 pthread_mutex_lock(&f->lock);
2842 update_stat(get_node(f, ino), &buf);
2843 pthread_mutex_unlock(&f->lock);
2845 set_stat(f, ino, &buf);
2846 fuse_reply_attr(req, &buf, f->conf.attr_timeout);
2847 } else
2848 reply_err(req, err);
2851 static void fuse_lib_access(fuse_req_t req, fuse_ino_t ino, int mask)
2853 struct fuse *f = req_fuse_prepare(req);
2854 char *path;
2855 int err;
2857 err = get_path(f, ino, &path);
2858 if (!err) {
2859 struct fuse_intr_data d;
2861 fuse_prepare_interrupt(f, req, &d);
2862 err = fuse_fs_access(f->fs, path, mask);
2863 fuse_finish_interrupt(f, req, &d);
2864 free_path(f, ino, path);
2866 reply_err(req, err);
2869 static void fuse_lib_readlink(fuse_req_t req, fuse_ino_t ino)
2871 struct fuse *f = req_fuse_prepare(req);
2872 char linkname[PATH_MAX + 1];
2873 char *path;
2874 int err;
2876 err = get_path(f, ino, &path);
2877 if (!err) {
2878 struct fuse_intr_data d;
2879 fuse_prepare_interrupt(f, req, &d);
2880 err = fuse_fs_readlink(f->fs, path, linkname, sizeof(linkname));
2881 fuse_finish_interrupt(f, req, &d);
2882 free_path(f, ino, path);
2884 if (!err) {
2885 linkname[PATH_MAX] = '\0';
2886 fuse_reply_readlink(req, linkname);
2887 } else
2888 reply_err(req, err);
2891 static void fuse_lib_mknod(fuse_req_t req, fuse_ino_t parent, const char *name,
2892 mode_t mode, dev_t rdev)
2894 struct fuse *f = req_fuse_prepare(req);
2895 struct fuse_entry_param e;
2896 char *path;
2897 int err;
2899 err = get_path_name(f, parent, name, &path);
2900 if (!err) {
2901 struct fuse_intr_data d;
2903 fuse_prepare_interrupt(f, req, &d);
2904 err = -ENOSYS;
2905 if (S_ISREG(mode)) {
2906 struct fuse_file_info fi;
2908 memset(&fi, 0, sizeof(fi));
2909 fi.flags = O_CREAT | O_EXCL | O_WRONLY;
2910 err = fuse_fs_create(f->fs, path, mode, &fi);
2911 if (!err) {
2912 err = lookup_path(f, parent, name, path, &e,
2913 &fi);
2914 fuse_fs_release(f->fs, path, &fi);
2917 if (err == -ENOSYS) {
2918 err = fuse_fs_mknod(f->fs, path, mode, rdev);
2919 if (!err)
2920 err = lookup_path(f, parent, name, path, &e,
2921 NULL);
2923 fuse_finish_interrupt(f, req, &d);
2924 free_path(f, parent, path);
2926 reply_entry(req, &e, err);
2929 static void fuse_lib_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name,
2930 mode_t mode)
2932 struct fuse *f = req_fuse_prepare(req);
2933 struct fuse_entry_param e;
2934 char *path;
2935 int err;
2937 err = get_path_name(f, parent, name, &path);
2938 if (!err) {
2939 struct fuse_intr_data d;
2941 fuse_prepare_interrupt(f, req, &d);
2942 err = fuse_fs_mkdir(f->fs, path, mode);
2943 if (!err)
2944 err = lookup_path(f, parent, name, path, &e, NULL);
2945 fuse_finish_interrupt(f, req, &d);
2946 free_path(f, parent, path);
2948 reply_entry(req, &e, err);
2951 static void fuse_lib_unlink(fuse_req_t req, fuse_ino_t parent,
2952 const char *name)
2954 struct fuse *f = req_fuse_prepare(req);
2955 struct node *wnode;
2956 char *path;
2957 int err;
2959 err = get_path_wrlock(f, parent, name, &path, &wnode);
2960 if (!err) {
2961 struct fuse_intr_data d;
2963 fuse_prepare_interrupt(f, req, &d);
2964 if (!f->conf.hard_remove && is_open(f, parent, name)) {
2965 err = hide_node(f, path, parent, name);
2966 } else {
2967 err = fuse_fs_unlink(f->fs, path);
2968 if (!err)
2969 remove_node(f, parent, name);
2971 fuse_finish_interrupt(f, req, &d);
2972 free_path_wrlock(f, parent, wnode, path);
2974 reply_err(req, err);
2977 static void fuse_lib_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name)
2979 struct fuse *f = req_fuse_prepare(req);
2980 struct node *wnode;
2981 char *path;
2982 int err;
2984 err = get_path_wrlock(f, parent, name, &path, &wnode);
2985 if (!err) {
2986 struct fuse_intr_data d;
2988 fuse_prepare_interrupt(f, req, &d);
2989 err = fuse_fs_rmdir(f->fs, path);
2990 fuse_finish_interrupt(f, req, &d);
2991 if (!err)
2992 remove_node(f, parent, name);
2993 free_path_wrlock(f, parent, wnode, path);
2995 reply_err(req, err);
2998 static void fuse_lib_symlink(fuse_req_t req, const char *linkname,
2999 fuse_ino_t parent, const char *name)
3001 struct fuse *f = req_fuse_prepare(req);
3002 struct fuse_entry_param e;
3003 char *path;
3004 int err;
3006 err = get_path_name(f, parent, name, &path);
3007 if (!err) {
3008 struct fuse_intr_data d;
3010 fuse_prepare_interrupt(f, req, &d);
3011 err = fuse_fs_symlink(f->fs, linkname, path);
3012 if (!err)
3013 err = lookup_path(f, parent, name, path, &e, NULL);
3014 fuse_finish_interrupt(f, req, &d);
3015 free_path(f, parent, path);
3017 reply_entry(req, &e, err);
3020 static void fuse_lib_rename(fuse_req_t req, fuse_ino_t olddir,
3021 const char *oldname, fuse_ino_t newdir,
3022 const char *newname)
3024 struct fuse *f = req_fuse_prepare(req);
3025 char *oldpath;
3026 char *newpath;
3027 struct node *wnode1;
3028 struct node *wnode2;
3029 int err;
3031 err = get_path2(f, olddir, oldname, newdir, newname,
3032 &oldpath, &newpath, &wnode1, &wnode2);
3033 if (!err) {
3034 struct fuse_intr_data d;
3035 err = 0;
3036 fuse_prepare_interrupt(f, req, &d);
3037 if (!f->conf.hard_remove && is_open(f, newdir, newname))
3038 err = hide_node(f, newpath, newdir, newname);
3039 if (!err) {
3040 err = fuse_fs_rename(f->fs, oldpath, newpath);
3041 if (!err)
3042 err = rename_node(f, olddir, oldname, newdir,
3043 newname, 0);
3045 fuse_finish_interrupt(f, req, &d);
3046 free_path2(f, olddir, newdir, wnode1, wnode2, oldpath, newpath);
3048 reply_err(req, err);
3051 static void fuse_lib_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent,
3052 const char *newname)
3054 struct fuse *f = req_fuse_prepare(req);
3055 struct fuse_entry_param e;
3056 char *oldpath;
3057 char *newpath;
3058 int err;
3060 err = get_path2(f, ino, NULL, newparent, newname,
3061 &oldpath, &newpath, NULL, NULL);
3062 if (!err) {
3063 struct fuse_intr_data d;
3065 fuse_prepare_interrupt(f, req, &d);
3066 err = fuse_fs_link(f->fs, oldpath, newpath);
3067 if (!err)
3068 err = lookup_path(f, newparent, newname, newpath,
3069 &e, NULL);
3070 fuse_finish_interrupt(f, req, &d);
3071 free_path2(f, ino, newparent, NULL, NULL, oldpath, newpath);
3073 reply_entry(req, &e, err);
3076 static void fuse_do_release(struct fuse *f, fuse_ino_t ino, const char *path,
3077 struct fuse_file_info *fi)
3079 struct node *node;
3080 int unlink_hidden = 0;
3081 const char *compatpath;
3083 if (path != NULL || f->nullpath_ok || f->conf.nopath)
3084 compatpath = path;
3085 else
3086 compatpath = "-";
3088 fuse_fs_release(f->fs, compatpath, fi);
3090 pthread_mutex_lock(&f->lock);
3091 node = get_node(f, ino);
3092 assert(node->open_count > 0);
3093 --node->open_count;
3094 if (node->is_hidden && !node->open_count) {
3095 unlink_hidden = 1;
3096 node->is_hidden = 0;
3098 pthread_mutex_unlock(&f->lock);
3100 if(unlink_hidden) {
3101 if (path) {
3102 fuse_fs_unlink(f->fs, path);
3103 } else if (f->conf.nopath) {
3104 char *unlinkpath;
3106 if (get_path(f, ino, &unlinkpath) == 0)
3107 fuse_fs_unlink(f->fs, unlinkpath);
3109 free_path(f, ino, unlinkpath);
3114 static void fuse_lib_create(fuse_req_t req, fuse_ino_t parent,
3115 const char *name, mode_t mode,
3116 struct fuse_file_info *fi)
3118 struct fuse *f = req_fuse_prepare(req);
3119 struct fuse_intr_data d;
3120 struct fuse_entry_param e;
3121 char *path;
3122 int err;
3124 err = get_path_name(f, parent, name, &path);
3125 if (!err) {
3126 fuse_prepare_interrupt(f, req, &d);
3127 err = fuse_fs_create(f->fs, path, mode, fi);
3128 if (!err) {
3129 err = lookup_path(f, parent, name, path, &e, fi);
3130 if (err)
3131 fuse_fs_release(f->fs, path, fi);
3132 else if (!S_ISREG(e.attr.st_mode)) {
3133 err = -EIO;
3134 fuse_fs_release(f->fs, path, fi);
3135 forget_node(f, e.ino, 1);
3136 } else {
3137 if (f->conf.direct_io)
3138 fi->direct_io = 1;
3139 if (f->conf.kernel_cache)
3140 fi->keep_cache = 1;
3144 fuse_finish_interrupt(f, req, &d);
3146 if (!err) {
3147 pthread_mutex_lock(&f->lock);
3148 get_node(f, e.ino)->open_count++;
3149 pthread_mutex_unlock(&f->lock);
3150 if (fuse_reply_create(req, &e, fi) == -ENOENT) {
3151 /* The open syscall was interrupted, so it
3152 must be cancelled */
3153 fuse_do_release(f, e.ino, path, fi);
3154 forget_node(f, e.ino, 1);
3156 } else {
3157 reply_err(req, err);
3160 free_path(f, parent, path);
3163 static double diff_timespec(const struct timespec *t1,
3164 const struct timespec *t2)
3166 return (t1->tv_sec - t2->tv_sec) +
3167 ((double) t1->tv_nsec - (double) t2->tv_nsec) / 1000000000.0;
3170 static void open_auto_cache(struct fuse *f, fuse_ino_t ino, const char *path,
3171 struct fuse_file_info *fi)
3173 struct node *node;
3175 pthread_mutex_lock(&f->lock);
3176 node = get_node(f, ino);
3177 if (node->cache_valid) {
3178 struct timespec now;
3180 curr_time(&now);
3181 if (diff_timespec(&now, &node->stat_updated) >
3182 f->conf.ac_attr_timeout) {
3183 struct stat stbuf;
3184 int err;
3185 pthread_mutex_unlock(&f->lock);
3186 err = fuse_fs_fgetattr(f->fs, path, &stbuf, fi);
3187 pthread_mutex_lock(&f->lock);
3188 if (!err)
3189 update_stat(node, &stbuf);
3190 else
3191 node->cache_valid = 0;
3194 if (node->cache_valid)
3195 fi->keep_cache = 1;
3197 node->cache_valid = 1;
3198 pthread_mutex_unlock(&f->lock);
3201 static void fuse_lib_open(fuse_req_t req, fuse_ino_t ino,
3202 struct fuse_file_info *fi)
3204 struct fuse *f = req_fuse_prepare(req);
3205 struct fuse_intr_data d;
3206 char *path;
3207 int err;
3209 err = get_path(f, ino, &path);
3210 if (!err) {
3211 fuse_prepare_interrupt(f, req, &d);
3212 err = fuse_fs_open(f->fs, path, fi);
3213 if (!err) {
3214 if (f->conf.direct_io)
3215 fi->direct_io = 1;
3216 if (f->conf.kernel_cache)
3217 fi->keep_cache = 1;
3219 if (f->conf.auto_cache)
3220 open_auto_cache(f, ino, path, fi);
3222 fuse_finish_interrupt(f, req, &d);
3224 if (!err) {
3225 pthread_mutex_lock(&f->lock);
3226 get_node(f, ino)->open_count++;
3227 pthread_mutex_unlock(&f->lock);
3228 if (fuse_reply_open(req, fi) == -ENOENT) {
3229 /* The open syscall was interrupted, so it
3230 must be cancelled */
3231 fuse_do_release(f, ino, path, fi);
3233 } else
3234 reply_err(req, err);
3236 free_path(f, ino, path);
3239 static void fuse_lib_read(fuse_req_t req, fuse_ino_t ino, size_t size,
3240 off_t off, struct fuse_file_info *fi)
3242 struct fuse *f = req_fuse_prepare(req);
3243 struct fuse_bufvec *buf = NULL;
3244 char *path;
3245 int res;
3247 res = get_path_nullok(f, ino, &path);
3248 if (res == 0) {
3249 struct fuse_intr_data d;
3251 fuse_prepare_interrupt(f, req, &d);
3252 res = fuse_fs_read_buf(f->fs, path, &buf, size, off, fi);
3253 fuse_finish_interrupt(f, req, &d);
3254 free_path(f, ino, path);
3257 if (res == 0)
3258 fuse_reply_data(req, buf, FUSE_BUF_SPLICE_MOVE);
3259 else
3260 reply_err(req, res);
3262 fuse_free_buf(buf);
3265 static void fuse_lib_write_buf(fuse_req_t req, fuse_ino_t ino,
3266 struct fuse_bufvec *buf, off_t off,
3267 struct fuse_file_info *fi)
3269 struct fuse *f = req_fuse_prepare(req);
3270 char *path;
3271 int res;
3273 res = get_path_nullok(f, ino, &path);
3274 if (res == 0) {
3275 struct fuse_intr_data d;
3277 fuse_prepare_interrupt(f, req, &d);
3278 res = fuse_fs_write_buf(f->fs, path, buf, off, fi);
3279 fuse_finish_interrupt(f, req, &d);
3280 free_path(f, ino, path);
3283 if (res >= 0)
3284 fuse_reply_write(req, res);
3285 else
3286 reply_err(req, res);
3289 static void fuse_lib_fsync(fuse_req_t req, fuse_ino_t ino, int datasync,
3290 struct fuse_file_info *fi)
3292 struct fuse *f = req_fuse_prepare(req);
3293 char *path;
3294 int err;
3296 err = get_path_nullok(f, ino, &path);
3297 if (!err) {
3298 struct fuse_intr_data d;
3300 fuse_prepare_interrupt(f, req, &d);
3301 err = fuse_fs_fsync(f->fs, path, datasync, fi);
3302 fuse_finish_interrupt(f, req, &d);
3303 free_path(f, ino, path);
3305 reply_err(req, err);
3308 static struct fuse_dh *get_dirhandle(const struct fuse_file_info *llfi,
3309 struct fuse_file_info *fi)
3311 struct fuse_dh *dh = (struct fuse_dh *) (uintptr_t) llfi->fh;
3312 memset(fi, 0, sizeof(struct fuse_file_info));
3313 fi->fh = dh->fh;
3314 fi->fh_old = dh->fh;
3315 return dh;
3318 static void fuse_lib_opendir(fuse_req_t req, fuse_ino_t ino,
3319 struct fuse_file_info *llfi)
3321 struct fuse *f = req_fuse_prepare(req);
3322 struct fuse_intr_data d;
3323 struct fuse_dh *dh;
3324 struct fuse_file_info fi;
3325 char *path;
3326 int err;
3328 dh = (struct fuse_dh *) malloc(sizeof(struct fuse_dh));
3329 if (dh == NULL) {
3330 reply_err(req, -ENOMEM);
3331 return;
3333 memset(dh, 0, sizeof(struct fuse_dh));
3334 dh->fuse = f;
3335 dh->contents = NULL;
3336 dh->len = 0;
3337 dh->filled = 0;
3338 dh->nodeid = ino;
3339 fuse_mutex_init(&dh->lock);
3341 llfi->fh = (uintptr_t) dh;
3343 memset(&fi, 0, sizeof(fi));
3344 fi.flags = llfi->flags;
3346 err = get_path(f, ino, &path);
3347 if (!err) {
3348 fuse_prepare_interrupt(f, req, &d);
3349 err = fuse_fs_opendir(f->fs, path, &fi);
3350 fuse_finish_interrupt(f, req, &d);
3351 dh->fh = fi.fh;
3353 if (!err) {
3354 if (fuse_reply_open(req, llfi) == -ENOENT) {
3355 /* The opendir syscall was interrupted, so it
3356 must be cancelled */
3357 fuse_fs_releasedir(f->fs, path, &fi);
3358 pthread_mutex_destroy(&dh->lock);
3359 free(dh);
3361 } else {
3362 reply_err(req, err);
3363 pthread_mutex_destroy(&dh->lock);
3364 free(dh);
3366 free_path(f, ino, path);
3369 static int extend_contents(struct fuse_dh *dh, unsigned minsize)
3371 if (minsize > dh->size) {
3372 char *newptr;
3373 unsigned newsize = dh->size;
3374 if (!newsize)
3375 newsize = 1024;
3376 while (newsize < minsize) {
3377 if (newsize >= 0x80000000)
3378 newsize = 0xffffffff;
3379 else
3380 newsize *= 2;
3383 newptr = (char *) realloc(dh->contents, newsize);
3384 if (!newptr) {
3385 dh->error = -ENOMEM;
3386 return -1;
3388 dh->contents = newptr;
3389 dh->size = newsize;
3391 return 0;
3394 static int fill_dir(void *dh_, const char *name, const struct stat *statp,
3395 off_t off)
3397 struct fuse_dh *dh = (struct fuse_dh *) dh_;
3398 struct stat stbuf;
3399 size_t newlen;
3401 if (statp)
3402 stbuf = *statp;
3403 else {
3404 memset(&stbuf, 0, sizeof(stbuf));
3405 stbuf.st_ino = FUSE_UNKNOWN_INO;
3408 if (!dh->fuse->conf.use_ino) {
3409 stbuf.st_ino = FUSE_UNKNOWN_INO;
3410 if (dh->fuse->conf.readdir_ino) {
3411 struct node *node;
3412 pthread_mutex_lock(&dh->fuse->lock);
3413 node = lookup_node(dh->fuse, dh->nodeid, name);
3414 if (node)
3415 stbuf.st_ino = (ino_t) node->nodeid;
3416 pthread_mutex_unlock(&dh->fuse->lock);
3420 if (off) {
3421 if (extend_contents(dh, dh->needlen) == -1)
3422 return 1;
3424 dh->filled = 0;
3425 newlen = dh->len +
3426 fuse_add_direntry(dh->req, dh->contents + dh->len,
3427 dh->needlen - dh->len, name,
3428 &stbuf, off);
3429 if (newlen > dh->needlen)
3430 return 1;
3431 } else {
3432 newlen = dh->len +
3433 fuse_add_direntry(dh->req, NULL, 0, name, NULL, 0);
3434 if (extend_contents(dh, newlen) == -1)
3435 return 1;
3437 fuse_add_direntry(dh->req, dh->contents + dh->len,
3438 dh->size - dh->len, name, &stbuf, newlen);
3440 dh->len = newlen;
3441 return 0;
3444 static int readdir_fill(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
3445 size_t size, off_t off, struct fuse_dh *dh,
3446 struct fuse_file_info *fi)
3448 char *path;
3449 int err;
3451 if (f->fs->op.readdir)
3452 err = get_path_nullok(f, ino, &path);
3453 else
3454 err = get_path(f, ino, &path);
3455 if (!err) {
3456 struct fuse_intr_data d;
3458 dh->len = 0;
3459 dh->error = 0;
3460 dh->needlen = size;
3461 dh->filled = 1;
3462 dh->req = req;
3463 fuse_prepare_interrupt(f, req, &d);
3464 err = fuse_fs_readdir(f->fs, path, dh, fill_dir, off, fi);
3465 fuse_finish_interrupt(f, req, &d);
3466 dh->req = NULL;
3467 if (!err)
3468 err = dh->error;
3469 if (err)
3470 dh->filled = 0;
3471 free_path(f, ino, path);
3473 return err;
3476 static void fuse_lib_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
3477 off_t off, struct fuse_file_info *llfi)
3479 struct fuse *f = req_fuse_prepare(req);
3480 struct fuse_file_info fi;
3481 struct fuse_dh *dh = get_dirhandle(llfi, &fi);
3483 pthread_mutex_lock(&dh->lock);
3484 /* According to SUS, directory contents need to be refreshed on
3485 rewinddir() */
3486 if (!off)
3487 dh->filled = 0;
3489 if (!dh->filled) {
3490 int err = readdir_fill(f, req, ino, size, off, dh, &fi);
3491 if (err) {
3492 reply_err(req, err);
3493 goto out;
3496 if (dh->filled) {
3497 if (off < dh->len) {
3498 if (off + size > dh->len)
3499 size = dh->len - off;
3500 } else
3501 size = 0;
3502 } else {
3503 size = dh->len;
3504 off = 0;
3506 fuse_reply_buf(req, dh->contents + off, size);
3507 out:
3508 pthread_mutex_unlock(&dh->lock);
3511 static void fuse_lib_releasedir(fuse_req_t req, fuse_ino_t ino,
3512 struct fuse_file_info *llfi)
3514 struct fuse *f = req_fuse_prepare(req);
3515 struct fuse_intr_data d;
3516 struct fuse_file_info fi;
3517 struct fuse_dh *dh = get_dirhandle(llfi, &fi);
3518 char *path;
3519 const char *compatpath;
3521 get_path_nullok(f, ino, &path);
3522 if (path != NULL || f->nullpath_ok || f->conf.nopath)
3523 compatpath = path;
3524 else
3525 compatpath = "-";
3527 fuse_prepare_interrupt(f, req, &d);
3528 fuse_fs_releasedir(f->fs, compatpath, &fi);
3529 fuse_finish_interrupt(f, req, &d);
3530 free_path(f, ino, path);
3532 pthread_mutex_lock(&dh->lock);
3533 pthread_mutex_unlock(&dh->lock);
3534 pthread_mutex_destroy(&dh->lock);
3535 free(dh->contents);
3536 free(dh);
3537 reply_err(req, 0);
3540 static void fuse_lib_fsyncdir(fuse_req_t req, fuse_ino_t ino, int datasync,
3541 struct fuse_file_info *llfi)
3543 struct fuse *f = req_fuse_prepare(req);
3544 struct fuse_file_info fi;
3545 char *path;
3546 int err;
3548 get_dirhandle(llfi, &fi);
3550 err = get_path_nullok(f, ino, &path);
3551 if (!err) {
3552 struct fuse_intr_data d;
3553 fuse_prepare_interrupt(f, req, &d);
3554 err = fuse_fs_fsyncdir(f->fs, path, datasync, &fi);
3555 fuse_finish_interrupt(f, req, &d);
3556 free_path(f, ino, path);
3558 reply_err(req, err);
3561 static void fuse_lib_statfs(fuse_req_t req, fuse_ino_t ino)
3563 struct fuse *f = req_fuse_prepare(req);
3564 struct statvfs buf;
3565 char *path = NULL;
3566 int err = 0;
3568 memset(&buf, 0, sizeof(buf));
3569 if (ino)
3570 err = get_path(f, ino, &path);
3572 if (!err) {
3573 struct fuse_intr_data d;
3574 fuse_prepare_interrupt(f, req, &d);
3575 err = fuse_fs_statfs(f->fs, path ? path : "/", &buf);
3576 fuse_finish_interrupt(f, req, &d);
3577 free_path(f, ino, path);
3580 if (!err)
3581 fuse_reply_statfs(req, &buf);
3582 else
3583 reply_err(req, err);
3586 static void fuse_lib_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
3587 const char *value, size_t size, int flags)
3589 struct fuse *f = req_fuse_prepare(req);
3590 char *path;
3591 int err;
3593 err = get_path(f, ino, &path);
3594 if (!err) {
3595 struct fuse_intr_data d;
3596 fuse_prepare_interrupt(f, req, &d);
3597 err = fuse_fs_setxattr(f->fs, path, name, value, size, flags);
3598 fuse_finish_interrupt(f, req, &d);
3599 free_path(f, ino, path);
3601 reply_err(req, err);
3604 static int common_getxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
3605 const char *name, char *value, size_t size)
3607 int err;
3608 char *path;
3610 err = get_path(f, ino, &path);
3611 if (!err) {
3612 struct fuse_intr_data d;
3613 fuse_prepare_interrupt(f, req, &d);
3614 err = fuse_fs_getxattr(f->fs, path, name, value, size);
3615 fuse_finish_interrupt(f, req, &d);
3616 free_path(f, ino, path);
3618 return err;
3621 static void fuse_lib_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
3622 size_t size)
3624 struct fuse *f = req_fuse_prepare(req);
3625 int res;
3627 if (size) {
3628 char *value = (char *) malloc(size);
3629 if (value == NULL) {
3630 reply_err(req, -ENOMEM);
3631 return;
3633 res = common_getxattr(f, req, ino, name, value, size);
3634 if (res > 0)
3635 fuse_reply_buf(req, value, res);
3636 else
3637 reply_err(req, res);
3638 free(value);
3639 } else {
3640 res = common_getxattr(f, req, ino, name, NULL, 0);
3641 if (res >= 0)
3642 fuse_reply_xattr(req, res);
3643 else
3644 reply_err(req, res);
3648 static int common_listxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
3649 char *list, size_t size)
3651 char *path;
3652 int err;
3654 err = get_path(f, ino, &path);
3655 if (!err) {
3656 struct fuse_intr_data d;
3657 fuse_prepare_interrupt(f, req, &d);
3658 err = fuse_fs_listxattr(f->fs, path, list, size);
3659 fuse_finish_interrupt(f, req, &d);
3660 free_path(f, ino, path);
3662 return err;
3665 static void fuse_lib_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
3667 struct fuse *f = req_fuse_prepare(req);
3668 int res;
3670 if (size) {
3671 char *list = (char *) malloc(size);
3672 if (list == NULL) {
3673 reply_err(req, -ENOMEM);
3674 return;
3676 res = common_listxattr(f, req, ino, list, size);
3677 if (res > 0)
3678 fuse_reply_buf(req, list, res);
3679 else
3680 reply_err(req, res);
3681 free(list);
3682 } else {
3683 res = common_listxattr(f, req, ino, NULL, 0);
3684 if (res >= 0)
3685 fuse_reply_xattr(req, res);
3686 else
3687 reply_err(req, res);
3691 static void fuse_lib_removexattr(fuse_req_t req, fuse_ino_t ino,
3692 const char *name)
3694 struct fuse *f = req_fuse_prepare(req);
3695 char *path;
3696 int err;
3698 err = get_path(f, ino, &path);
3699 if (!err) {
3700 struct fuse_intr_data d;
3701 fuse_prepare_interrupt(f, req, &d);
3702 err = fuse_fs_removexattr(f->fs, path, name);
3703 fuse_finish_interrupt(f, req, &d);
3704 free_path(f, ino, path);
3706 reply_err(req, err);
3709 static struct lock *locks_conflict(struct node *node, const struct lock *lock)
3711 struct lock *l;
3713 for (l = node->locks; l; l = l->next)
3714 if (l->owner != lock->owner &&
3715 lock->start <= l->end && l->start <= lock->end &&
3716 (l->type == F_WRLCK || lock->type == F_WRLCK))
3717 break;
3719 return l;
3722 static void delete_lock(struct lock **lockp)
3724 struct lock *l = *lockp;
3725 *lockp = l->next;
3726 free(l);
3729 static void insert_lock(struct lock **pos, struct lock *lock)
3731 lock->next = *pos;
3732 *pos = lock;
3735 static int locks_insert(struct node *node, struct lock *lock)
3737 struct lock **lp;
3738 struct lock *newl1 = NULL;
3739 struct lock *newl2 = NULL;
3741 if (lock->type != F_UNLCK || lock->start != 0 ||
3742 lock->end != OFFSET_MAX) {
3743 newl1 = malloc(sizeof(struct lock));
3744 newl2 = malloc(sizeof(struct lock));
3746 if (!newl1 || !newl2) {
3747 free(newl1);
3748 free(newl2);
3749 return -ENOLCK;
3753 for (lp = &node->locks; *lp;) {
3754 struct lock *l = *lp;
3755 if (l->owner != lock->owner)
3756 goto skip;
3758 if (lock->type == l->type) {
3759 if (l->end < lock->start - 1)
3760 goto skip;
3761 if (lock->end < l->start - 1)
3762 break;
3763 if (l->start <= lock->start && lock->end <= l->end)
3764 goto out;
3765 if (l->start < lock->start)
3766 lock->start = l->start;
3767 if (lock->end < l->end)
3768 lock->end = l->end;
3769 goto delete;
3770 } else {
3771 if (l->end < lock->start)
3772 goto skip;
3773 if (lock->end < l->start)
3774 break;
3775 if (lock->start <= l->start && l->end <= lock->end)
3776 goto delete;
3777 if (l->end <= lock->end) {
3778 l->end = lock->start - 1;
3779 goto skip;
3781 if (lock->start <= l->start) {
3782 l->start = lock->end + 1;
3783 break;
3785 *newl2 = *l;
3786 newl2->start = lock->end + 1;
3787 l->end = lock->start - 1;
3788 insert_lock(&l->next, newl2);
3789 newl2 = NULL;
3791 skip:
3792 lp = &l->next;
3793 continue;
3795 delete:
3796 delete_lock(lp);
3798 if (lock->type != F_UNLCK) {
3799 *newl1 = *lock;
3800 insert_lock(lp, newl1);
3801 newl1 = NULL;
3803 out:
3804 free(newl1);
3805 free(newl2);
3806 return 0;
3809 static void flock_to_lock(struct flock *flock, struct lock *lock)
3811 memset(lock, 0, sizeof(struct lock));
3812 lock->type = flock->l_type;
3813 lock->start = flock->l_start;
3814 lock->end =
3815 flock->l_len ? flock->l_start + flock->l_len - 1 : OFFSET_MAX;
3816 lock->pid = flock->l_pid;
3819 static void lock_to_flock(struct lock *lock, struct flock *flock)
3821 flock->l_type = lock->type;
3822 flock->l_start = lock->start;
3823 flock->l_len =
3824 (lock->end == OFFSET_MAX) ? 0 : lock->end - lock->start + 1;
3825 flock->l_pid = lock->pid;
3828 static int fuse_flush_common(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
3829 const char *path, struct fuse_file_info *fi)
3831 struct fuse_intr_data d;
3832 struct flock lock;
3833 struct lock l;
3834 int err;
3835 int errlock;
3837 fuse_prepare_interrupt(f, req, &d);
3838 memset(&lock, 0, sizeof(lock));
3839 lock.l_type = F_UNLCK;
3840 lock.l_whence = SEEK_SET;
3841 err = fuse_fs_flush(f->fs, path, fi);
3842 errlock = fuse_fs_lock(f->fs, path, fi, F_SETLK, &lock);
3843 fuse_finish_interrupt(f, req, &d);
3845 if (errlock != -ENOSYS) {
3846 flock_to_lock(&lock, &l);
3847 l.owner = fi->lock_owner;
3848 pthread_mutex_lock(&f->lock);
3849 locks_insert(get_node(f, ino), &l);
3850 pthread_mutex_unlock(&f->lock);
3852 /* if op.lock() is defined FLUSH is needed regardless
3853 of op.flush() */
3854 if (err == -ENOSYS)
3855 err = 0;
3857 return err;
3860 static void fuse_lib_release(fuse_req_t req, fuse_ino_t ino,
3861 struct fuse_file_info *fi)
3863 struct fuse *f = req_fuse_prepare(req);
3864 struct fuse_intr_data d;
3865 char *path;
3866 int err = 0;
3868 get_path_nullok(f, ino, &path);
3869 if (fi->flush) {
3870 err = fuse_flush_common(f, req, ino, path, fi);
3871 if (err == -ENOSYS)
3872 err = 0;
3875 fuse_prepare_interrupt(f, req, &d);
3876 fuse_do_release(f, ino, path, fi);
3877 fuse_finish_interrupt(f, req, &d);
3878 free_path(f, ino, path);
3880 reply_err(req, err);
3883 static void fuse_lib_flush(fuse_req_t req, fuse_ino_t ino,
3884 struct fuse_file_info *fi)
3886 struct fuse *f = req_fuse_prepare(req);
3887 char *path;
3888 int err;
3890 get_path_nullok(f, ino, &path);
3891 err = fuse_flush_common(f, req, ino, path, fi);
3892 free_path(f, ino, path);
3894 reply_err(req, err);
3897 static int fuse_lock_common(fuse_req_t req, fuse_ino_t ino,
3898 struct fuse_file_info *fi, struct flock *lock,
3899 int cmd)
3901 struct fuse *f = req_fuse_prepare(req);
3902 char *path;
3903 int err;
3905 err = get_path_nullok(f, ino, &path);
3906 if (!err) {
3907 struct fuse_intr_data d;
3908 fuse_prepare_interrupt(f, req, &d);
3909 err = fuse_fs_lock(f->fs, path, fi, cmd, lock);
3910 fuse_finish_interrupt(f, req, &d);
3911 free_path(f, ino, path);
3913 return err;
3916 static void fuse_lib_getlk(fuse_req_t req, fuse_ino_t ino,
3917 struct fuse_file_info *fi, struct flock *lock)
3919 int err;
3920 struct lock l;
3921 struct lock *conflict;
3922 struct fuse *f = req_fuse(req);
3924 flock_to_lock(lock, &l);
3925 l.owner = fi->lock_owner;
3926 pthread_mutex_lock(&f->lock);
3927 conflict = locks_conflict(get_node(f, ino), &l);
3928 if (conflict)
3929 lock_to_flock(conflict, lock);
3930 pthread_mutex_unlock(&f->lock);
3931 if (!conflict)
3932 err = fuse_lock_common(req, ino, fi, lock, F_GETLK);
3933 else
3934 err = 0;
3936 if (!err)
3937 fuse_reply_lock(req, lock);
3938 else
3939 reply_err(req, err);
3942 static void fuse_lib_setlk(fuse_req_t req, fuse_ino_t ino,
3943 struct fuse_file_info *fi, struct flock *lock,
3944 int sleep)
3946 int err = fuse_lock_common(req, ino, fi, lock,
3947 sleep ? F_SETLKW : F_SETLK);
3948 if (!err) {
3949 struct fuse *f = req_fuse(req);
3950 struct lock l;
3951 flock_to_lock(lock, &l);
3952 l.owner = fi->lock_owner;
3953 pthread_mutex_lock(&f->lock);
3954 locks_insert(get_node(f, ino), &l);
3955 pthread_mutex_unlock(&f->lock);
3957 reply_err(req, err);
3960 static void fuse_lib_flock(fuse_req_t req, fuse_ino_t ino,
3961 struct fuse_file_info *fi, int op)
3963 struct fuse *f = req_fuse_prepare(req);
3964 char *path;
3965 int err;
3967 err = get_path_nullok(f, ino, &path);
3968 if (err == 0) {
3969 struct fuse_intr_data d;
3970 fuse_prepare_interrupt(f, req, &d);
3971 err = fuse_fs_flock(f->fs, path, fi, op);
3972 fuse_finish_interrupt(f, req, &d);
3973 free_path(f, ino, path);
3975 reply_err(req, err);
3978 static void fuse_lib_bmap(fuse_req_t req, fuse_ino_t ino, size_t blocksize,
3979 uint64_t idx)
3981 struct fuse *f = req_fuse_prepare(req);
3982 struct fuse_intr_data d;
3983 char *path;
3984 int err;
3986 err = get_path(f, ino, &path);
3987 if (!err) {
3988 fuse_prepare_interrupt(f, req, &d);
3989 err = fuse_fs_bmap(f->fs, path, blocksize, &idx);
3990 fuse_finish_interrupt(f, req, &d);
3991 free_path(f, ino, path);
3993 if (!err)
3994 fuse_reply_bmap(req, idx);
3995 else
3996 reply_err(req, err);
3999 static void fuse_lib_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg,
4000 struct fuse_file_info *fi, unsigned int flags,
4001 const void *in_buf, size_t in_bufsz,
4002 size_t out_bufsz)
4004 struct fuse *f = req_fuse_prepare(req);
4005 struct fuse_intr_data d;
4006 char *path, *out_buf = NULL;
4007 int err;
4009 err = -EPERM;
4010 if (flags & FUSE_IOCTL_UNRESTRICTED)
4011 goto err;
4013 if (out_bufsz) {
4014 err = -ENOMEM;
4015 out_buf = malloc(out_bufsz);
4016 if (!out_buf)
4017 goto err;
4020 assert(!in_bufsz || !out_bufsz || in_bufsz == out_bufsz);
4021 if (out_buf)
4022 memcpy(out_buf, in_buf, in_bufsz);
4024 err = get_path_nullok(f, ino, &path);
4025 if (err)
4026 goto err;
4028 fuse_prepare_interrupt(f, req, &d);
4030 err = fuse_fs_ioctl(f->fs, path, cmd, arg, fi, flags,
4031 out_buf ?: (void *)in_buf);
4033 fuse_finish_interrupt(f, req, &d);
4034 free_path(f, ino, path);
4036 fuse_reply_ioctl(req, err, out_buf, out_bufsz);
4037 goto out;
4038 err:
4039 reply_err(req, err);
4040 out:
4041 free(out_buf);
4044 static void fuse_lib_poll(fuse_req_t req, fuse_ino_t ino,
4045 struct fuse_file_info *fi, struct fuse_pollhandle *ph)
4047 struct fuse *f = req_fuse_prepare(req);
4048 struct fuse_intr_data d;
4049 char *path;
4050 int err;
4051 unsigned revents = 0;
4053 err = get_path_nullok(f, ino, &path);
4054 if (!err) {
4055 fuse_prepare_interrupt(f, req, &d);
4056 err = fuse_fs_poll(f->fs, path, fi, ph, &revents);
4057 fuse_finish_interrupt(f, req, &d);
4058 free_path(f, ino, path);
4060 if (!err)
4061 fuse_reply_poll(req, revents);
4062 else
4063 reply_err(req, err);
4066 static void fuse_lib_fallocate(fuse_req_t req, fuse_ino_t ino, int mode,
4067 off_t offset, off_t length, struct fuse_file_info *fi)
4069 struct fuse *f = req_fuse_prepare(req);
4070 struct fuse_intr_data d;
4071 char *path;
4072 int err;
4074 err = get_path_nullok(f, ino, &path);
4075 if (!err) {
4076 fuse_prepare_interrupt(f, req, &d);
4077 err = fuse_fs_fallocate(f->fs, path, mode, offset, length, fi);
4078 fuse_finish_interrupt(f, req, &d);
4079 free_path(f, ino, path);
4081 reply_err(req, err);
4084 static int clean_delay(struct fuse *f)
4087 * This is calculating the delay between clean runs. To
4088 * reduce the number of cleans we are doing them 10 times
4089 * within the remember window.
4091 int min_sleep = 60;
4092 int max_sleep = 3600;
4093 int sleep_time = f->conf.remember / 10;
4095 if (sleep_time > max_sleep)
4096 return max_sleep;
4097 if (sleep_time < min_sleep)
4098 return min_sleep;
4099 return sleep_time;
4102 int fuse_clean_cache(struct fuse *f)
4104 struct node_lru *lnode;
4105 struct list_head *curr, *next;
4106 struct node *node;
4107 struct timespec now;
4109 pthread_mutex_lock(&f->lock);
4111 curr_time(&now);
4113 for (curr = f->lru_table.next; curr != &f->lru_table; curr = next) {
4114 double age;
4116 next = curr->next;
4117 lnode = list_entry(curr, struct node_lru, lru);
4118 node = &lnode->node;
4120 age = diff_timespec(&now, &lnode->forget_time);
4121 if (age <= f->conf.remember)
4122 break;
4124 assert(node->nlookup == 1);
4126 /* Don't forget active directories */
4127 if (node->refctr > 1)
4128 continue;
4130 node->nlookup = 0;
4131 unhash_name(f, node);
4132 unref_node(f, node);
4134 pthread_mutex_unlock(&f->lock);
4136 return clean_delay(f);
4139 static struct fuse_lowlevel_ops fuse_path_ops = {
4140 .init = fuse_lib_init,
4141 .destroy = fuse_lib_destroy,
4142 .lookup = fuse_lib_lookup,
4143 .forget = fuse_lib_forget,
4144 .forget_multi = fuse_lib_forget_multi,
4145 .getattr = fuse_lib_getattr,
4146 .setattr = fuse_lib_setattr,
4147 .access = fuse_lib_access,
4148 .readlink = fuse_lib_readlink,
4149 .mknod = fuse_lib_mknod,
4150 .mkdir = fuse_lib_mkdir,
4151 .unlink = fuse_lib_unlink,
4152 .rmdir = fuse_lib_rmdir,
4153 .symlink = fuse_lib_symlink,
4154 .rename = fuse_lib_rename,
4155 .link = fuse_lib_link,
4156 .create = fuse_lib_create,
4157 .open = fuse_lib_open,
4158 .read = fuse_lib_read,
4159 .write_buf = fuse_lib_write_buf,
4160 .flush = fuse_lib_flush,
4161 .release = fuse_lib_release,
4162 .fsync = fuse_lib_fsync,
4163 .opendir = fuse_lib_opendir,
4164 .readdir = fuse_lib_readdir,
4165 .releasedir = fuse_lib_releasedir,
4166 .fsyncdir = fuse_lib_fsyncdir,
4167 .statfs = fuse_lib_statfs,
4168 .setxattr = fuse_lib_setxattr,
4169 .getxattr = fuse_lib_getxattr,
4170 .listxattr = fuse_lib_listxattr,
4171 .removexattr = fuse_lib_removexattr,
4172 .getlk = fuse_lib_getlk,
4173 .setlk = fuse_lib_setlk,
4174 .flock = fuse_lib_flock,
4175 .bmap = fuse_lib_bmap,
4176 .ioctl = fuse_lib_ioctl,
4177 .poll = fuse_lib_poll,
4178 .fallocate = fuse_lib_fallocate,
4181 int fuse_notify_poll(struct fuse_pollhandle *ph)
4183 return fuse_lowlevel_notify_poll(ph);
4186 static void free_cmd(struct fuse_cmd *cmd)
4188 free(cmd->buf);
4189 free(cmd);
4192 void fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd)
4194 fuse_session_process(f->se, cmd->buf, cmd->buflen, cmd->ch);
4195 free_cmd(cmd);
4198 int fuse_exited(struct fuse *f)
4200 return fuse_session_exited(f->se);
4203 struct fuse_session *fuse_get_session(struct fuse *f)
4205 return f->se;
4208 static struct fuse_cmd *fuse_alloc_cmd(size_t bufsize)
4210 struct fuse_cmd *cmd = (struct fuse_cmd *) malloc(sizeof(*cmd));
4211 if (cmd == NULL) {
4212 fprintf(stderr, "fuse: failed to allocate cmd\n");
4213 return NULL;
4215 cmd->buf = (char *) malloc(bufsize);
4216 if (cmd->buf == NULL) {
4217 fprintf(stderr, "fuse: failed to allocate read buffer\n");
4218 free(cmd);
4219 return NULL;
4221 return cmd;
4224 struct fuse_cmd *fuse_read_cmd(struct fuse *f)
4226 struct fuse_chan *ch = fuse_session_next_chan(f->se, NULL);
4227 size_t bufsize = fuse_chan_bufsize(ch);
4228 struct fuse_cmd *cmd = fuse_alloc_cmd(bufsize);
4229 if (cmd != NULL) {
4230 int res = fuse_chan_recv(&ch, cmd->buf, bufsize);
4231 if (res <= 0) {
4232 free_cmd(cmd);
4233 if (res < 0 && res != -EINTR && res != -EAGAIN)
4234 fuse_exit(f);
4235 return NULL;
4237 cmd->buflen = res;
4238 cmd->ch = ch;
4240 return cmd;
4243 static int fuse_session_loop_remember(struct fuse *f)
4245 struct fuse_session *se = f->se;
4246 int res = 0;
4247 struct timespec now;
4248 time_t next_clean;
4249 struct fuse_chan *ch = fuse_session_next_chan(se, NULL);
4250 size_t bufsize = fuse_chan_bufsize(ch);
4251 char *buf = (char *) malloc(bufsize);
4252 struct pollfd fds = {
4253 .fd = fuse_chan_fd(ch),
4254 .events = POLLIN
4257 if (!buf) {
4258 fprintf(stderr, "fuse: failed to allocate read buffer\n");
4259 return -1;
4262 curr_time(&now);
4263 next_clean = now.tv_sec;
4264 while (!fuse_session_exited(se)) {
4265 struct fuse_chan *tmpch = ch;
4266 struct fuse_buf fbuf = {
4267 .mem = buf,
4268 .size = bufsize,
4270 unsigned timeout;
4272 curr_time(&now);
4273 if (now.tv_sec < next_clean)
4274 timeout = next_clean - now.tv_sec;
4275 else
4276 timeout = 0;
4278 res = poll(&fds, 1, timeout * 1000);
4279 if (res == -1) {
4280 if (errno == -EINTR)
4281 continue;
4282 else
4283 break;
4284 } else if (res > 0) {
4285 res = fuse_session_receive_buf(se, &fbuf, &tmpch);
4287 if (res == -EINTR)
4288 continue;
4289 if (res <= 0)
4290 break;
4292 fuse_session_process_buf(se, &fbuf, tmpch);
4293 } else {
4294 timeout = fuse_clean_cache(f);
4295 curr_time(&now);
4296 next_clean = now.tv_sec + timeout;
4300 free(buf);
4301 fuse_session_reset(se);
4302 return res < 0 ? -1 : 0;
4305 int fuse_loop(struct fuse *f)
4307 if (!f)
4308 return -1;
4310 if (lru_enabled(f))
4311 return fuse_session_loop_remember(f);
4313 return fuse_session_loop(f->se);
4316 int fuse_invalidate(struct fuse *f, const char *path)
4318 (void) f;
4319 (void) path;
4320 return -EINVAL;
4323 void fuse_exit(struct fuse *f)
4325 fuse_session_exit(f->se);
4328 struct fuse_context *fuse_get_context(void)
4330 return &fuse_get_context_internal()->ctx;
4334 * The size of fuse_context got extended, so need to be careful about
4335 * incompatibility (i.e. a new binary cannot work with an old
4336 * library).
4338 struct fuse_context *fuse_get_context_compat22(void);
4339 struct fuse_context *fuse_get_context_compat22(void)
4341 return &fuse_get_context_internal()->ctx;
4343 FUSE_SYMVER(".symver fuse_get_context_compat22,fuse_get_context@FUSE_2.2");
4345 int fuse_getgroups(int size, gid_t list[])
4347 fuse_req_t req = fuse_get_context_internal()->req;
4348 return fuse_req_getgroups(req, size, list);
4351 int fuse_interrupted(void)
4353 return fuse_req_interrupted(fuse_get_context_internal()->req);
4356 void fuse_set_getcontext_func(struct fuse_context *(*func)(void))
4358 (void) func;
4359 /* no-op */
4362 enum {
4363 KEY_HELP,
4366 #define FUSE_LIB_OPT(t, p, v) { t, offsetof(struct fuse_config, p), v }
4368 static const struct fuse_opt fuse_lib_opts[] = {
4369 FUSE_OPT_KEY("-h", KEY_HELP),
4370 FUSE_OPT_KEY("--help", KEY_HELP),
4371 FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP),
4372 FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP),
4373 FUSE_LIB_OPT("debug", debug, 1),
4374 FUSE_LIB_OPT("-d", debug, 1),
4375 FUSE_LIB_OPT("hard_remove", hard_remove, 1),
4376 FUSE_LIB_OPT("use_ino", use_ino, 1),
4377 FUSE_LIB_OPT("readdir_ino", readdir_ino, 1),
4378 FUSE_LIB_OPT("direct_io", direct_io, 1),
4379 FUSE_LIB_OPT("kernel_cache", kernel_cache, 1),
4380 FUSE_LIB_OPT("auto_cache", auto_cache, 1),
4381 FUSE_LIB_OPT("noauto_cache", auto_cache, 0),
4382 FUSE_LIB_OPT("umask=", set_mode, 1),
4383 FUSE_LIB_OPT("umask=%o", umask, 0),
4384 FUSE_LIB_OPT("uid=", set_uid, 1),
4385 FUSE_LIB_OPT("uid=%d", uid, 0),
4386 FUSE_LIB_OPT("gid=", set_gid, 1),
4387 FUSE_LIB_OPT("gid=%d", gid, 0),
4388 FUSE_LIB_OPT("entry_timeout=%lf", entry_timeout, 0),
4389 FUSE_LIB_OPT("attr_timeout=%lf", attr_timeout, 0),
4390 FUSE_LIB_OPT("ac_attr_timeout=%lf", ac_attr_timeout, 0),
4391 FUSE_LIB_OPT("ac_attr_timeout=", ac_attr_timeout_set, 1),
4392 FUSE_LIB_OPT("negative_timeout=%lf", negative_timeout, 0),
4393 FUSE_LIB_OPT("noforget", remember, -1),
4394 FUSE_LIB_OPT("remember=%u", remember, 0),
4395 FUSE_LIB_OPT("nopath", nopath, 1),
4396 FUSE_LIB_OPT("intr", intr, 1),
4397 FUSE_LIB_OPT("intr_signal=%d", intr_signal, 0),
4398 FUSE_LIB_OPT("modules=%s", modules, 0),
4399 FUSE_OPT_END
4402 static void fuse_lib_help(void)
4404 fprintf(stderr,
4405 " -o hard_remove immediate removal (don't hide files)\n"
4406 " -o use_ino let filesystem set inode numbers\n"
4407 " -o readdir_ino try to fill in d_ino in readdir\n"
4408 " -o direct_io use direct I/O\n"
4409 " -o kernel_cache cache files in kernel\n"
4410 " -o [no]auto_cache enable caching based on modification times (off)\n"
4411 " -o umask=M set file permissions (octal)\n"
4412 " -o uid=N set file owner\n"
4413 " -o gid=N set file group\n"
4414 " -o entry_timeout=T cache timeout for names (1.0s)\n"
4415 " -o negative_timeout=T cache timeout for deleted names (0.0s)\n"
4416 " -o attr_timeout=T cache timeout for attributes (1.0s)\n"
4417 " -o ac_attr_timeout=T auto cache timeout for attributes (attr_timeout)\n"
4418 " -o noforget never forget cached inodes\n"
4419 " -o remember=T remember cached inodes for T seconds (0s)\n"
4420 " -o nopath don't supply path if not necessary\n"
4421 " -o intr allow requests to be interrupted\n"
4422 " -o intr_signal=NUM signal to send on interrupt (%i)\n"
4423 " -o modules=M1[:M2...] names of modules to push onto filesystem stack\n"
4424 "\n", FUSE_DEFAULT_INTR_SIGNAL);
4427 static void fuse_lib_help_modules(void)
4429 struct fuse_module *m;
4430 fprintf(stderr, "\nModule options:\n");
4431 pthread_mutex_lock(&fuse_context_lock);
4432 for (m = fuse_modules; m; m = m->next) {
4433 struct fuse_fs *fs = NULL;
4434 struct fuse_fs *newfs;
4435 struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
4436 if (fuse_opt_add_arg(&args, "") != -1 &&
4437 fuse_opt_add_arg(&args, "-h") != -1) {
4438 fprintf(stderr, "\n[%s]\n", m->name);
4439 newfs = m->factory(&args, &fs);
4440 assert(newfs == NULL);
4442 fuse_opt_free_args(&args);
4444 pthread_mutex_unlock(&fuse_context_lock);
4447 static int fuse_lib_opt_proc(void *data, const char *arg, int key,
4448 struct fuse_args *outargs)
4450 (void) arg; (void) outargs;
4452 if (key == KEY_HELP) {
4453 struct fuse_config *conf = (struct fuse_config *) data;
4454 fuse_lib_help();
4455 conf->help = 1;
4458 return 1;
4461 int fuse_is_lib_option(const char *opt)
4463 return fuse_lowlevel_is_lib_option(opt) ||
4464 fuse_opt_match(fuse_lib_opts, opt);
4467 static int fuse_init_intr_signal(int signum, int *installed)
4469 struct sigaction old_sa;
4471 if (sigaction(signum, NULL, &old_sa) == -1) {
4472 perror("fuse: cannot get old signal handler");
4473 return -1;
4476 if (old_sa.sa_handler == SIG_DFL) {
4477 struct sigaction sa;
4479 memset(&sa, 0, sizeof(struct sigaction));
4480 sa.sa_handler = fuse_intr_sighandler;
4481 sigemptyset(&sa.sa_mask);
4483 if (sigaction(signum, &sa, NULL) == -1) {
4484 perror("fuse: cannot set interrupt signal handler");
4485 return -1;
4487 *installed = 1;
4489 return 0;
4492 static void fuse_restore_intr_signal(int signum)
4494 struct sigaction sa;
4496 memset(&sa, 0, sizeof(struct sigaction));
4497 sa.sa_handler = SIG_DFL;
4498 sigaction(signum, &sa, NULL);
4502 static int fuse_push_module(struct fuse *f, const char *module,
4503 struct fuse_args *args)
4505 struct fuse_fs *fs[2] = { f->fs, NULL };
4506 struct fuse_fs *newfs;
4507 struct fuse_module *m = fuse_get_module(module);
4509 if (!m)
4510 return -1;
4512 newfs = m->factory(args, fs);
4513 if (!newfs) {
4514 fuse_put_module(m);
4515 return -1;
4517 newfs->m = m;
4518 f->fs = newfs;
4519 f->nullpath_ok = newfs->op.flag_nullpath_ok && f->nullpath_ok;
4520 f->conf.nopath = newfs->op.flag_nopath && f->conf.nopath;
4521 f->utime_omit_ok = newfs->op.flag_utime_omit_ok && f->utime_omit_ok;
4522 return 0;
4525 struct fuse_fs *fuse_fs_new(const struct fuse_operations *op, size_t op_size,
4526 void *user_data)
4528 struct fuse_fs *fs;
4530 if (sizeof(struct fuse_operations) < op_size) {
4531 fprintf(stderr, "fuse: warning: library too old, some operations may not not work\n");
4532 op_size = sizeof(struct fuse_operations);
4535 fs = (struct fuse_fs *) calloc(1, sizeof(struct fuse_fs));
4536 if (!fs) {
4537 fprintf(stderr, "fuse: failed to allocate fuse_fs object\n");
4538 return NULL;
4541 fs->user_data = user_data;
4542 if (op)
4543 memcpy(&fs->op, op, op_size);
4544 return fs;
4547 static int node_table_init(struct node_table *t)
4549 t->size = NODE_TABLE_MIN_SIZE;
4550 t->array = (struct node **) calloc(1, sizeof(struct node *) * t->size);
4551 if (t->array == NULL) {
4552 fprintf(stderr, "fuse: memory allocation failed\n");
4553 return -1;
4555 t->use = 0;
4556 t->split = 0;
4558 return 0;
4561 static void *fuse_prune_nodes(void *fuse)
4563 struct fuse *f = fuse;
4564 int sleep_time;
4566 while(1) {
4567 sleep_time = fuse_clean_cache(f);
4568 sleep(sleep_time);
4570 return NULL;
4573 int fuse_start_cleanup_thread(struct fuse *f)
4575 if (lru_enabled(f))
4576 return fuse_start_thread(&f->prune_thread, fuse_prune_nodes, f);
4578 return 0;
4581 void fuse_stop_cleanup_thread(struct fuse *f)
4583 if (lru_enabled(f)) {
4584 pthread_mutex_lock(&f->lock);
4585 pthread_cancel(f->prune_thread);
4586 pthread_mutex_unlock(&f->lock);
4587 pthread_join(f->prune_thread, NULL);
4591 struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args,
4592 const struct fuse_operations *op,
4593 size_t op_size, void *user_data, int compat)
4595 struct fuse *f;
4596 struct node *root;
4597 struct fuse_fs *fs;
4598 struct fuse_lowlevel_ops llop = fuse_path_ops;
4600 if (fuse_create_context_key() == -1)
4601 goto out;
4603 f = (struct fuse *) calloc(1, sizeof(struct fuse));
4604 if (f == NULL) {
4605 fprintf(stderr, "fuse: failed to allocate fuse object\n");
4606 goto out_delete_context_key;
4609 fs = fuse_fs_new(op, op_size, user_data);
4610 if (!fs)
4611 goto out_free;
4613 fs->compat = compat;
4614 f->fs = fs;
4615 f->nullpath_ok = fs->op.flag_nullpath_ok;
4616 f->conf.nopath = fs->op.flag_nopath;
4617 f->utime_omit_ok = fs->op.flag_utime_omit_ok;
4619 /* Oh f**k, this is ugly! */
4620 if (!fs->op.lock) {
4621 llop.getlk = NULL;
4622 llop.setlk = NULL;
4625 f->conf.entry_timeout = 1.0;
4626 f->conf.attr_timeout = 1.0;
4627 f->conf.negative_timeout = 0.0;
4628 f->conf.intr_signal = FUSE_DEFAULT_INTR_SIGNAL;
4630 f->pagesize = getpagesize();
4631 init_list_head(&f->partial_slabs);
4632 init_list_head(&f->full_slabs);
4633 init_list_head(&f->lru_table);
4635 if (fuse_opt_parse(args, &f->conf, fuse_lib_opts,
4636 fuse_lib_opt_proc) == -1)
4637 goto out_free_fs;
4639 if (f->conf.modules) {
4640 char *module;
4641 char *next;
4643 for (module = f->conf.modules; module; module = next) {
4644 char *p;
4645 for (p = module; *p && *p != ':'; p++);
4646 next = *p ? p + 1 : NULL;
4647 *p = '\0';
4648 if (module[0] &&
4649 fuse_push_module(f, module, args) == -1)
4650 goto out_free_fs;
4654 if (!f->conf.ac_attr_timeout_set)
4655 f->conf.ac_attr_timeout = f->conf.attr_timeout;
4657 #if defined(__FreeBSD__) || defined(__NetBSD__)
4659 * In FreeBSD, we always use these settings as inode numbers
4660 * are needed to make getcwd(3) work.
4662 f->conf.readdir_ino = 1;
4663 #endif
4665 if (compat && compat <= 25) {
4666 if (fuse_sync_compat_args(args) == -1)
4667 goto out_free_fs;
4670 f->se = fuse_lowlevel_new_common(args, &llop, sizeof(llop), f);
4671 if (f->se == NULL) {
4672 if (f->conf.help)
4673 fuse_lib_help_modules();
4674 goto out_free_fs;
4677 fuse_session_add_chan(f->se, ch);
4679 if (f->conf.debug) {
4680 fprintf(stderr, "nullpath_ok: %i\n", f->nullpath_ok);
4681 fprintf(stderr, "nopath: %i\n", f->conf.nopath);
4682 fprintf(stderr, "utime_omit_ok: %i\n", f->utime_omit_ok);
4685 /* Trace topmost layer by default */
4686 f->fs->debug = f->conf.debug;
4687 f->ctr = 0;
4688 f->generation = 0;
4689 if (node_table_init(&f->name_table) == -1)
4690 goto out_free_session;
4692 if (node_table_init(&f->id_table) == -1)
4693 goto out_free_name_table;
4695 fuse_mutex_init(&f->lock);
4697 root = alloc_node(f);
4698 if (root == NULL) {
4699 fprintf(stderr, "fuse: memory allocation failed\n");
4700 goto out_free_id_table;
4702 if (lru_enabled(f)) {
4703 struct node_lru *lnode = node_lru(root);
4704 init_list_head(&lnode->lru);
4707 strcpy(root->inline_name, "/");
4708 root->name = root->inline_name;
4710 if (f->conf.intr &&
4711 fuse_init_intr_signal(f->conf.intr_signal,
4712 &f->intr_installed) == -1)
4713 goto out_free_root;
4715 root->parent = NULL;
4716 root->nodeid = FUSE_ROOT_ID;
4717 inc_nlookup(root);
4718 hash_id(f, root);
4720 return f;
4722 out_free_root:
4723 free(root);
4724 out_free_id_table:
4725 free(f->id_table.array);
4726 out_free_name_table:
4727 free(f->name_table.array);
4728 out_free_session:
4729 fuse_session_destroy(f->se);
4730 out_free_fs:
4731 /* Horrible compatibility hack to stop the destructor from being
4732 called on the filesystem without init being called first */
4733 fs->op.destroy = NULL;
4734 fuse_fs_destroy(f->fs);
4735 free(f->conf.modules);
4736 out_free:
4737 free(f);
4738 out_delete_context_key:
4739 fuse_delete_context_key();
4740 out:
4741 return NULL;
4744 struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args,
4745 const struct fuse_operations *op, size_t op_size,
4746 void *user_data)
4748 return fuse_new_common(ch, args, op, op_size, user_data, 0);
4751 void fuse_destroy(struct fuse *f)
4753 size_t i;
4755 if (f->conf.intr && f->intr_installed)
4756 fuse_restore_intr_signal(f->conf.intr_signal);
4758 if (f->fs) {
4759 struct fuse_context_i *c = fuse_get_context_internal();
4761 memset(c, 0, sizeof(*c));
4762 c->ctx.fuse = f;
4764 for (i = 0; i < f->id_table.size; i++) {
4765 struct node *node;
4767 for (node = f->id_table.array[i]; node != NULL;
4768 node = node->id_next) {
4769 if (node->is_hidden) {
4770 char *path;
4771 if (try_get_path(f, node->nodeid, NULL, &path, NULL, false) == 0) {
4772 fuse_fs_unlink(f->fs, path);
4773 free(path);
4779 for (i = 0; i < f->id_table.size; i++) {
4780 struct node *node;
4781 struct node *next;
4783 for (node = f->id_table.array[i]; node != NULL; node = next) {
4784 next = node->id_next;
4785 free_node(f, node);
4786 f->id_table.use--;
4789 assert(list_empty(&f->partial_slabs));
4790 assert(list_empty(&f->full_slabs));
4792 free(f->id_table.array);
4793 free(f->name_table.array);
4794 pthread_mutex_destroy(&f->lock);
4795 fuse_session_destroy(f->se);
4796 free(f->conf.modules);
4797 free(f);
4798 fuse_delete_context_key();
4801 static struct fuse *fuse_new_common_compat25(int fd, struct fuse_args *args,
4802 const struct fuse_operations *op,
4803 size_t op_size, int compat)
4805 struct fuse *f = NULL;
4806 struct fuse_chan *ch = fuse_kern_chan_new(fd);
4808 if (ch)
4809 f = fuse_new_common(ch, args, op, op_size, NULL, compat);
4811 return f;
4814 /* called with fuse_context_lock held or during initialization (before
4815 main() has been called) */
4816 void fuse_register_module(struct fuse_module *mod)
4818 mod->ctr = 0;
4819 mod->so = fuse_current_so;
4820 if (mod->so)
4821 mod->so->ctr++;
4822 mod->next = fuse_modules;
4823 fuse_modules = mod;
4826 #if !defined(__FreeBSD__) && !defined(__NetBSD__)
4828 static struct fuse *fuse_new_common_compat(int fd, const char *opts,
4829 const struct fuse_operations *op,
4830 size_t op_size, int compat)
4832 struct fuse *f;
4833 struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
4835 if (fuse_opt_add_arg(&args, "") == -1)
4836 return NULL;
4837 if (opts &&
4838 (fuse_opt_add_arg(&args, "-o") == -1 ||
4839 fuse_opt_add_arg(&args, opts) == -1)) {
4840 fuse_opt_free_args(&args);
4841 return NULL;
4843 f = fuse_new_common_compat25(fd, &args, op, op_size, compat);
4844 fuse_opt_free_args(&args);
4846 return f;
4849 struct fuse *fuse_new_compat22(int fd, const char *opts,
4850 const struct fuse_operations_compat22 *op,
4851 size_t op_size)
4853 return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op,
4854 op_size, 22);
4857 struct fuse *fuse_new_compat2(int fd, const char *opts,
4858 const struct fuse_operations_compat2 *op)
4860 return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op,
4861 sizeof(struct fuse_operations_compat2),
4862 21);
4865 struct fuse *fuse_new_compat1(int fd, int flags,
4866 const struct fuse_operations_compat1 *op)
4868 const char *opts = NULL;
4869 if (flags & FUSE_DEBUG_COMPAT1)
4870 opts = "debug";
4871 return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op,
4872 sizeof(struct fuse_operations_compat1),
4873 11);
4876 FUSE_SYMVER(".symver fuse_exited,__fuse_exited@");
4877 FUSE_SYMVER(".symver fuse_process_cmd,__fuse_process_cmd@");
4878 FUSE_SYMVER(".symver fuse_read_cmd,__fuse_read_cmd@");
4879 FUSE_SYMVER(".symver fuse_set_getcontext_func,__fuse_set_getcontext_func@");
4880 FUSE_SYMVER(".symver fuse_new_compat2,fuse_new@");
4881 FUSE_SYMVER(".symver fuse_new_compat22,fuse_new@FUSE_2.2");
4883 #endif /* __FreeBSD__ || __NetBSD__ */
4885 struct fuse *fuse_new_compat25(int fd, struct fuse_args *args,
4886 const struct fuse_operations_compat25 *op,
4887 size_t op_size)
4889 return fuse_new_common_compat25(fd, args, (struct fuse_operations *) op,
4890 op_size, 25);
4893 FUSE_SYMVER(".symver fuse_new_compat25,fuse_new@FUSE_2.5");