Fix missing config.h in buffer.c
[fuse.git] / lib / fuse.c
blob2907cfea5b8742e190ab67bbff6f3fc54553a968
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 <unistd.h>
27 #include <time.h>
28 #include <fcntl.h>
29 #include <limits.h>
30 #include <errno.h>
31 #include <signal.h>
32 #include <dlfcn.h>
33 #include <assert.h>
34 #include <poll.h>
35 #include <sys/param.h>
36 #include <sys/uio.h>
37 #include <sys/time.h>
38 #include <sys/mman.h>
40 #define FUSE_NODE_SLAB 1
42 #ifndef MAP_ANONYMOUS
43 #undef FUSE_NODE_SLAB
44 #endif
46 #define FUSE_DEFAULT_INTR_SIGNAL SIGUSR1
48 #define FUSE_UNKNOWN_INO 0xffffffff
49 #define OFFSET_MAX 0x7fffffffffffffffLL
51 #define NODE_TABLE_MIN_SIZE 8192
53 struct fuse_config {
54 unsigned int uid;
55 unsigned int gid;
56 unsigned int umask;
57 double entry_timeout;
58 double negative_timeout;
59 double attr_timeout;
60 double ac_attr_timeout;
61 int ac_attr_timeout_set;
62 int remember;
63 int nopath;
64 int debug;
65 int hard_remove;
66 int use_ino;
67 int readdir_ino;
68 int set_mode;
69 int set_uid;
70 int set_gid;
71 int direct_io;
72 int kernel_cache;
73 int auto_cache;
74 int intr;
75 int intr_signal;
76 int help;
77 char *modules;
80 struct fuse_fs {
81 struct fuse_operations op;
82 struct fuse_module *m;
83 void *user_data;
84 int compat;
85 int debug;
88 struct fusemod_so {
89 void *handle;
90 int ctr;
93 struct lock_queue_element {
94 struct lock_queue_element *next;
95 pthread_cond_t cond;
98 struct node_table {
99 struct node **array;
100 size_t use;
101 size_t size;
102 size_t split;
105 #define container_of(ptr, type, member) ({ \
106 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
107 (type *)( (char *)__mptr - offsetof(type,member) );})
109 #define list_entry(ptr, type, member) \
110 container_of(ptr, type, member)
112 struct list_head {
113 struct list_head *next;
114 struct list_head *prev;
117 struct node_slab {
118 struct list_head list; /* must be the first member */
119 struct list_head freelist;
120 int used;
123 struct fuse {
124 struct fuse_session *se;
125 struct node_table name_table;
126 struct node_table id_table;
127 struct list_head lru_table;
128 fuse_ino_t ctr;
129 unsigned int generation;
130 unsigned int hidectr;
131 pthread_mutex_t lock;
132 struct fuse_config conf;
133 int intr_installed;
134 struct fuse_fs *fs;
135 int nullpath_ok;
136 int utime_omit_ok;
137 int curr_ticket;
138 struct lock_queue_element *lockq;
139 int pagesize;
140 struct list_head partial_slabs;
141 struct list_head full_slabs;
142 pthread_t prune_thread;
145 struct lock {
146 int type;
147 off_t start;
148 off_t end;
149 pid_t pid;
150 uint64_t owner;
151 struct lock *next;
154 struct node {
155 struct node *name_next;
156 struct node *id_next;
157 fuse_ino_t nodeid;
158 unsigned int generation;
159 int refctr;
160 struct node *parent;
161 char *name;
162 uint64_t nlookup;
163 int open_count;
164 struct timespec stat_updated;
165 struct timespec mtime;
166 off_t size;
167 struct lock *locks;
168 unsigned int is_hidden : 1;
169 unsigned int cache_valid : 1;
170 int treelock;
171 int ticket;
172 char inline_name[32];
175 struct node_lru {
176 struct node node;
177 struct list_head lru;
178 struct timespec forget_time;
181 struct fuse_dh {
182 pthread_mutex_t lock;
183 struct fuse *fuse;
184 fuse_req_t req;
185 char *contents;
186 int allocated;
187 unsigned len;
188 unsigned size;
189 unsigned needlen;
190 int filled;
191 uint64_t fh;
192 int error;
193 fuse_ino_t nodeid;
196 /* old dir handle */
197 struct fuse_dirhandle {
198 fuse_fill_dir_t filler;
199 void *buf;
202 struct fuse_context_i {
203 struct fuse_context ctx;
204 fuse_req_t req;
207 static pthread_key_t fuse_context_key;
208 static pthread_mutex_t fuse_context_lock = PTHREAD_MUTEX_INITIALIZER;
209 static int fuse_context_ref;
210 static struct fusemod_so *fuse_current_so;
211 static struct fuse_module *fuse_modules;
213 static int fuse_load_so_name(const char *soname)
215 struct fusemod_so *so;
217 so = calloc(1, sizeof(struct fusemod_so));
218 if (!so) {
219 fprintf(stderr, "fuse: memory allocation failed\n");
220 return -1;
223 fuse_current_so = so;
224 so->handle = dlopen(soname, RTLD_NOW);
225 fuse_current_so = NULL;
226 if (!so->handle) {
227 fprintf(stderr, "fuse: %s\n", dlerror());
228 goto err;
230 if (!so->ctr) {
231 fprintf(stderr, "fuse: %s did not register any modules\n",
232 soname);
233 goto err;
235 return 0;
237 err:
238 if (so->handle)
239 dlclose(so->handle);
240 free(so);
241 return -1;
244 static int fuse_load_so_module(const char *module)
246 int res;
247 char *soname = malloc(strlen(module) + 64);
248 if (!soname) {
249 fprintf(stderr, "fuse: memory allocation failed\n");
250 return -1;
252 sprintf(soname, "libfusemod_%s.so", module);
253 res = fuse_load_so_name(soname);
254 free(soname);
255 return res;
258 static struct fuse_module *fuse_find_module(const char *module)
260 struct fuse_module *m;
261 for (m = fuse_modules; m; m = m->next) {
262 if (strcmp(module, m->name) == 0) {
263 m->ctr++;
264 break;
267 return m;
270 static struct fuse_module *fuse_get_module(const char *module)
272 struct fuse_module *m;
274 pthread_mutex_lock(&fuse_context_lock);
275 m = fuse_find_module(module);
276 if (!m) {
277 int err = fuse_load_so_module(module);
278 if (!err)
279 m = fuse_find_module(module);
281 pthread_mutex_unlock(&fuse_context_lock);
282 return m;
285 static void fuse_put_module(struct fuse_module *m)
287 pthread_mutex_lock(&fuse_context_lock);
288 assert(m->ctr > 0);
289 m->ctr--;
290 if (!m->ctr && m->so) {
291 struct fusemod_so *so = m->so;
292 assert(so->ctr > 0);
293 so->ctr--;
294 if (!so->ctr) {
295 struct fuse_module **mp;
296 for (mp = &fuse_modules; *mp;) {
297 if ((*mp)->so == so)
298 *mp = (*mp)->next;
299 else
300 mp = &(*mp)->next;
302 dlclose(so->handle);
303 free(so);
306 pthread_mutex_unlock(&fuse_context_lock);
309 static void init_list_head(struct list_head *list)
311 list->next = list;
312 list->prev = list;
315 static int list_empty(const struct list_head *head)
317 return head->next == head;
320 static void list_add(struct list_head *new, struct list_head *prev,
321 struct list_head *next)
323 next->prev = new;
324 new->next = next;
325 new->prev = prev;
326 prev->next = new;
329 static inline void list_add_head(struct list_head *new, struct list_head *head)
331 list_add(new, head, head->next);
334 static inline void list_add_tail(struct list_head *new, struct list_head *head)
336 list_add(new, head->prev, head);
339 static inline void list_del(struct list_head *entry)
341 struct list_head *prev = entry->prev;
342 struct list_head *next = entry->next;
344 next->prev = prev;
345 prev->next = next;
348 static inline int lru_enabled(struct fuse *f)
350 return f->conf.remember > 0;
353 static struct node_lru *node_lru(struct node *node)
355 return (struct node_lru *) node;
358 static size_t get_node_size(struct fuse *f)
360 if (lru_enabled(f))
361 return sizeof(struct node_lru);
362 else
363 return sizeof(struct node);
366 #ifdef FUSE_NODE_SLAB
367 static struct node_slab *list_to_slab(struct list_head *head)
369 return (struct node_slab *) head;
372 static struct node_slab *node_to_slab(struct fuse *f, struct node *node)
374 return (struct node_slab *) (((uintptr_t) node) & ~((uintptr_t) f->pagesize - 1));
377 static int alloc_slab(struct fuse *f)
379 void *mem;
380 struct node_slab *slab;
381 char *start;
382 size_t num;
383 size_t i;
384 size_t node_size = get_node_size(f);
386 mem = mmap(NULL, f->pagesize, PROT_READ | PROT_WRITE,
387 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
389 if (mem == MAP_FAILED)
390 return -1;
392 slab = mem;
393 init_list_head(&slab->freelist);
394 slab->used = 0;
395 num = (f->pagesize - sizeof(struct node_slab)) / node_size;
397 start = (char *) mem + f->pagesize - num * node_size;
398 for (i = 0; i < num; i++) {
399 struct list_head *n;
401 n = (struct list_head *) (start + i * node_size);
402 list_add_tail(n, &slab->freelist);
404 list_add_tail(&slab->list, &f->partial_slabs);
406 return 0;
409 static struct node *alloc_node(struct fuse *f)
411 struct node_slab *slab;
412 struct list_head *node;
414 if (list_empty(&f->partial_slabs)) {
415 int res = alloc_slab(f);
416 if (res != 0)
417 return NULL;
419 slab = list_to_slab(f->partial_slabs.next);
420 slab->used++;
421 node = slab->freelist.next;
422 list_del(node);
423 if (list_empty(&slab->freelist)) {
424 list_del(&slab->list);
425 list_add_tail(&slab->list, &f->full_slabs);
427 memset(node, 0, sizeof(struct node));
429 return (struct node *) node;
432 static void free_slab(struct fuse *f, struct node_slab *slab)
434 int res;
436 list_del(&slab->list);
437 res = munmap(slab, f->pagesize);
438 if (res == -1)
439 fprintf(stderr, "fuse warning: munmap(%p) failed\n", slab);
442 static void free_node_mem(struct fuse *f, struct node *node)
444 struct node_slab *slab = node_to_slab(f, node);
445 struct list_head *n = (struct list_head *) node;
447 slab->used--;
448 if (slab->used) {
449 if (list_empty(&slab->freelist)) {
450 list_del(&slab->list);
451 list_add_tail(&slab->list, &f->partial_slabs);
453 list_add_head(n, &slab->freelist);
454 } else {
455 free_slab(f, slab);
458 #else
459 static struct node *alloc_node(struct fuse *f)
461 return (struct node *) calloc(1, get_node_size(f));
464 static void free_node_mem(struct fuse *f, struct node *node)
466 (void) f;
467 free(node);
469 #endif
471 static size_t id_hash(struct fuse *f, fuse_ino_t ino)
473 uint64_t hash = ((uint32_t) ino * 2654435761U) % f->id_table.size;
474 uint64_t oldhash = hash % (f->id_table.size / 2);
476 if (oldhash >= f->id_table.split)
477 return oldhash;
478 else
479 return hash;
482 static struct node *get_node_nocheck(struct fuse *f, fuse_ino_t nodeid)
484 size_t hash = id_hash(f, nodeid);
485 struct node *node;
487 for (node = f->id_table.array[hash]; node != NULL; node = node->id_next)
488 if (node->nodeid == nodeid)
489 return node;
491 return NULL;
494 static struct node *get_node(struct fuse *f, fuse_ino_t nodeid)
496 struct node *node = get_node_nocheck(f, nodeid);
497 if (!node) {
498 fprintf(stderr, "fuse internal error: node %llu not found\n",
499 (unsigned long long) nodeid);
500 abort();
502 return node;
505 static void curr_time(struct timespec *now);
506 static double diff_timespec(const struct timespec *t1,
507 const struct timespec *t2);
509 static void remove_node_lru(struct node *node)
511 struct node_lru *lnode = node_lru(node);
512 list_del(&lnode->lru);
513 init_list_head(&lnode->lru);
516 static void set_forget_time(struct fuse *f, struct node *node)
518 struct node_lru *lnode = node_lru(node);
520 list_del(&lnode->lru);
521 list_add_tail(&lnode->lru, &f->lru_table);
522 curr_time(&lnode->forget_time);
525 static void free_node(struct fuse *f, struct node *node)
527 if (node->name != node->inline_name)
528 free(node->name);
529 free_node_mem(f, node);
532 static void node_table_reduce(struct node_table *t)
534 size_t newsize = t->size / 2;
535 void *newarray;
537 if (newsize < NODE_TABLE_MIN_SIZE)
538 return;
540 newarray = realloc(t->array, sizeof(struct node *) * newsize);
541 if (newarray != NULL)
542 t->array = newarray;
544 t->size = newsize;
545 t->split = t->size / 2;
548 static void remerge_id(struct fuse *f)
550 struct node_table *t = &f->id_table;
551 int iter;
553 if (t->split == 0)
554 node_table_reduce(t);
556 for (iter = 8; t->split > 0 && iter; iter--) {
557 struct node **upper;
559 t->split--;
560 upper = &t->array[t->split + t->size / 2];
561 if (*upper) {
562 struct node **nodep;
564 for (nodep = &t->array[t->split]; *nodep;
565 nodep = &(*nodep)->id_next);
567 *nodep = *upper;
568 *upper = NULL;
569 break;
574 static void unhash_id(struct fuse *f, struct node *node)
576 struct node **nodep = &f->id_table.array[id_hash(f, node->nodeid)];
578 for (; *nodep != NULL; nodep = &(*nodep)->id_next)
579 if (*nodep == node) {
580 *nodep = node->id_next;
581 f->id_table.use--;
583 if(f->id_table.use < f->id_table.size / 4)
584 remerge_id(f);
585 return;
589 static int node_table_resize(struct node_table *t)
591 size_t newsize = t->size * 2;
592 void *newarray;
594 newarray = realloc(t->array, sizeof(struct node *) * newsize);
595 if (newarray == NULL)
596 return -1;
598 t->array = newarray;
599 memset(t->array + t->size, 0, t->size * sizeof(struct node *));
600 t->size = newsize;
601 t->split = 0;
603 return 0;
606 static void rehash_id(struct fuse *f)
608 struct node_table *t = &f->id_table;
609 struct node **nodep;
610 struct node **next;
611 size_t hash;
613 if (t->split == t->size / 2)
614 return;
616 hash = t->split;
617 t->split++;
618 for (nodep = &t->array[hash]; *nodep != NULL; nodep = next) {
619 struct node *node = *nodep;
620 size_t newhash = id_hash(f, node->nodeid);
622 if (newhash != hash) {
623 next = nodep;
624 *nodep = node->id_next;
625 node->id_next = t->array[newhash];
626 t->array[newhash] = node;
627 } else {
628 next = &node->id_next;
631 if (t->split == t->size / 2)
632 node_table_resize(t);
635 static void hash_id(struct fuse *f, struct node *node)
637 size_t hash = id_hash(f, node->nodeid);
638 node->id_next = f->id_table.array[hash];
639 f->id_table.array[hash] = node;
640 f->id_table.use++;
642 if (f->id_table.use >= f->id_table.size / 2)
643 rehash_id(f);
646 static size_t name_hash(struct fuse *f, fuse_ino_t parent,
647 const char *name)
649 uint64_t hash = parent;
650 uint64_t oldhash;
652 for (; *name; name++)
653 hash = hash * 31 + (unsigned char) *name;
655 hash %= f->name_table.size;
656 oldhash = hash % (f->name_table.size / 2);
657 if (oldhash >= f->name_table.split)
658 return oldhash;
659 else
660 return hash;
663 static void unref_node(struct fuse *f, struct node *node);
665 static void remerge_name(struct fuse *f)
667 struct node_table *t = &f->name_table;
668 int iter;
670 if (t->split == 0)
671 node_table_reduce(t);
673 for (iter = 8; t->split > 0 && iter; iter--) {
674 struct node **upper;
676 t->split--;
677 upper = &t->array[t->split + t->size / 2];
678 if (*upper) {
679 struct node **nodep;
681 for (nodep = &t->array[t->split]; *nodep;
682 nodep = &(*nodep)->name_next);
684 *nodep = *upper;
685 *upper = NULL;
686 break;
691 static void unhash_name(struct fuse *f, struct node *node)
693 if (node->name) {
694 size_t hash = name_hash(f, node->parent->nodeid, node->name);
695 struct node **nodep = &f->name_table.array[hash];
697 for (; *nodep != NULL; nodep = &(*nodep)->name_next)
698 if (*nodep == node) {
699 *nodep = node->name_next;
700 node->name_next = NULL;
701 unref_node(f, node->parent);
702 if (node->name != node->inline_name)
703 free(node->name);
704 node->name = NULL;
705 node->parent = NULL;
706 f->name_table.use--;
708 if (f->name_table.use < f->name_table.size / 4)
709 remerge_name(f);
710 return;
712 fprintf(stderr,
713 "fuse internal error: unable to unhash node: %llu\n",
714 (unsigned long long) node->nodeid);
715 abort();
719 static void rehash_name(struct fuse *f)
721 struct node_table *t = &f->name_table;
722 struct node **nodep;
723 struct node **next;
724 size_t hash;
726 if (t->split == t->size / 2)
727 return;
729 hash = t->split;
730 t->split++;
731 for (nodep = &t->array[hash]; *nodep != NULL; nodep = next) {
732 struct node *node = *nodep;
733 size_t newhash = name_hash(f, node->parent->nodeid, node->name);
735 if (newhash != hash) {
736 next = nodep;
737 *nodep = node->name_next;
738 node->name_next = t->array[newhash];
739 t->array[newhash] = node;
740 } else {
741 next = &node->name_next;
744 if (t->split == t->size / 2)
745 node_table_resize(t);
748 static int hash_name(struct fuse *f, struct node *node, fuse_ino_t parentid,
749 const char *name)
751 size_t hash = name_hash(f, parentid, name);
752 struct node *parent = get_node(f, parentid);
753 if (strlen(name) < sizeof(node->inline_name)) {
754 strcpy(node->inline_name, name);
755 node->name = node->inline_name;
756 } else {
757 node->name = strdup(name);
758 if (node->name == NULL)
759 return -1;
762 parent->refctr ++;
763 node->parent = parent;
764 node->name_next = f->name_table.array[hash];
765 f->name_table.array[hash] = node;
766 f->name_table.use++;
768 if (f->name_table.use >= f->name_table.size / 2)
769 rehash_name(f);
771 return 0;
774 static void delete_node(struct fuse *f, struct node *node)
776 if (f->conf.debug)
777 fprintf(stderr, "DELETE: %llu\n",
778 (unsigned long long) node->nodeid);
780 assert(node->treelock == 0);
781 unhash_name(f, node);
782 if (lru_enabled(f))
783 remove_node_lru(node);
784 unhash_id(f, node);
785 free_node(f, node);
788 static void unref_node(struct fuse *f, struct node *node)
790 assert(node->refctr > 0);
791 node->refctr --;
792 if (!node->refctr)
793 delete_node(f, node);
796 static fuse_ino_t next_id(struct fuse *f)
798 do {
799 f->ctr = (f->ctr + 1) & 0xffffffff;
800 if (!f->ctr)
801 f->generation ++;
802 } while (f->ctr == 0 || f->ctr == FUSE_UNKNOWN_INO ||
803 get_node_nocheck(f, f->ctr) != NULL);
804 return f->ctr;
807 static struct node *lookup_node(struct fuse *f, fuse_ino_t parent,
808 const char *name)
810 size_t hash = name_hash(f, parent, name);
811 struct node *node;
813 for (node = f->name_table.array[hash]; node != NULL; node = node->name_next)
814 if (node->parent->nodeid == parent &&
815 strcmp(node->name, name) == 0)
816 return node;
818 return NULL;
821 static void inc_nlookup(struct node *node)
823 if (!node->nlookup)
824 node->refctr++;
825 node->nlookup++;
828 static struct node *find_node(struct fuse *f, fuse_ino_t parent,
829 const char *name)
831 struct node *node;
833 pthread_mutex_lock(&f->lock);
834 if (!name)
835 node = get_node(f, parent);
836 else
837 node = lookup_node(f, parent, name);
838 if (node == NULL) {
839 node = alloc_node(f);
840 if (node == NULL)
841 goto out_err;
843 node->nodeid = next_id(f);
844 node->generation = f->generation;
845 if (f->conf.remember)
846 inc_nlookup(node);
848 if (hash_name(f, node, parent, name) == -1) {
849 free_node(f, node);
850 node = NULL;
851 goto out_err;
853 hash_id(f, node);
854 if (lru_enabled(f)) {
855 struct node_lru *lnode = node_lru(node);
856 init_list_head(&lnode->lru);
858 } else if (lru_enabled(f) && node->nlookup == 1) {
859 remove_node_lru(node);
861 inc_nlookup(node);
862 out_err:
863 pthread_mutex_unlock(&f->lock);
864 return node;
867 static char *add_name(char **buf, unsigned *bufsize, char *s, const char *name)
869 size_t len = strlen(name);
871 if (s - len <= *buf) {
872 unsigned pathlen = *bufsize - (s - *buf);
873 unsigned newbufsize = *bufsize;
874 char *newbuf;
876 while (newbufsize < pathlen + len + 1) {
877 if (newbufsize >= 0x80000000)
878 newbufsize = 0xffffffff;
879 else
880 newbufsize *= 2;
883 newbuf = realloc(*buf, newbufsize);
884 if (newbuf == NULL)
885 return NULL;
887 *buf = newbuf;
888 s = newbuf + newbufsize - pathlen;
889 memmove(s, newbuf + *bufsize - pathlen, pathlen);
890 *bufsize = newbufsize;
892 s -= len;
893 strncpy(s, name, len);
894 s--;
895 *s = '/';
897 return s;
900 static void unlock_path(struct fuse *f, fuse_ino_t nodeid, struct node *wnode,
901 struct node *end, int ticket)
903 struct node *node;
905 if (wnode) {
906 assert(wnode->treelock == -1);
907 wnode->treelock = 0;
908 if (!wnode->ticket)
909 wnode->ticket = ticket;
912 for (node = get_node(f, nodeid);
913 node != end && node->nodeid != FUSE_ROOT_ID; node = node->parent) {
914 assert(node->treelock > 0);
915 node->treelock--;
916 if (!node->ticket)
917 node->ticket = ticket;
921 static void release_tickets(struct fuse *f, fuse_ino_t nodeid,
922 struct node *wnode, int ticket)
924 struct node *node;
926 if (wnode) {
927 if (wnode->ticket != ticket)
928 return;
930 wnode->ticket = 0;
933 for (node = get_node(f, nodeid);
934 node->nodeid != FUSE_ROOT_ID; node = node->parent) {
935 if (node->ticket != ticket)
936 return;
937 node->ticket = 0;
941 static int try_get_path(struct fuse *f, fuse_ino_t nodeid, const char *name,
942 char **path, struct node **wnodep, int ticket)
944 unsigned bufsize = 256;
945 char *buf;
946 char *s;
947 struct node *node;
948 struct node *wnode = NULL;
949 int err;
951 *path = NULL;
953 err = -ENOMEM;
954 buf = malloc(bufsize);
955 if (buf == NULL)
956 goto out_err;
958 s = buf + bufsize - 1;
959 *s = '\0';
961 if (name != NULL) {
962 s = add_name(&buf, &bufsize, s, name);
963 err = -ENOMEM;
964 if (s == NULL)
965 goto out_free;
968 if (wnodep) {
969 assert(ticket);
970 wnode = lookup_node(f, nodeid, name);
971 if (wnode) {
972 if (wnode->treelock != 0 ||
973 (wnode->ticket && wnode->ticket != ticket)) {
974 if (!wnode->ticket)
975 wnode->ticket = ticket;
976 err = -EAGAIN;
977 goto out_free;
979 wnode->treelock = -1;
980 wnode->ticket = 0;
984 for (node = get_node(f, nodeid); node->nodeid != FUSE_ROOT_ID;
985 node = node->parent) {
986 err = -ENOENT;
987 if (node->name == NULL || node->parent == NULL)
988 goto out_unlock;
990 err = -ENOMEM;
991 s = add_name(&buf, &bufsize, s, node->name);
992 if (s == NULL)
993 goto out_unlock;
995 if (ticket) {
996 err = -EAGAIN;
997 if (node->treelock == -1 ||
998 (node->ticket && node->ticket != ticket))
999 goto out_unlock;
1001 node->treelock++;
1002 node->ticket = 0;
1006 if (s[0])
1007 memmove(buf, s, bufsize - (s - buf));
1008 else
1009 strcpy(buf, "/");
1011 *path = buf;
1012 if (wnodep)
1013 *wnodep = wnode;
1015 return 0;
1017 out_unlock:
1018 if (ticket)
1019 unlock_path(f, nodeid, wnode, node, ticket);
1020 out_free:
1021 free(buf);
1023 out_err:
1024 if (ticket && err != -EAGAIN)
1025 release_tickets(f, nodeid, wnode, ticket);
1027 return err;
1030 static void wake_up_first(struct fuse *f)
1032 if (f->lockq)
1033 pthread_cond_signal(&f->lockq->cond);
1036 static void wake_up_next(struct lock_queue_element *qe)
1038 if (qe->next)
1039 pthread_cond_signal(&qe->next->cond);
1042 static int get_ticket(struct fuse *f)
1044 do f->curr_ticket++;
1045 while (f->curr_ticket == 0);
1047 return f->curr_ticket;
1050 static void debug_path(struct fuse *f, const char *msg, fuse_ino_t nodeid,
1051 const char *name, int wr)
1053 if (f->conf.debug) {
1054 struct node *wnode = NULL;
1056 if (wr)
1057 wnode = lookup_node(f, nodeid, name);
1059 if (wnode)
1060 fprintf(stderr, "%s %li (w)\n", msg, wnode->nodeid);
1061 else
1062 fprintf(stderr, "%s %li\n", msg, nodeid);
1066 static void queue_path(struct fuse *f, struct lock_queue_element *qe,
1067 fuse_ino_t nodeid, const char *name, int wr)
1069 struct lock_queue_element **qp;
1071 debug_path(f, "QUEUE PATH", nodeid, name, wr);
1072 pthread_cond_init(&qe->cond, NULL);
1073 qe->next = NULL;
1074 for (qp = &f->lockq; *qp != NULL; qp = &(*qp)->next);
1075 *qp = qe;
1078 static void dequeue_path(struct fuse *f, struct lock_queue_element *qe,
1079 fuse_ino_t nodeid, const char *name, int wr)
1081 struct lock_queue_element **qp;
1083 debug_path(f, "DEQUEUE PATH", nodeid, name, wr);
1084 pthread_cond_destroy(&qe->cond);
1085 for (qp = &f->lockq; *qp != qe; qp = &(*qp)->next);
1086 *qp = qe->next;
1089 static void wait_on_path(struct fuse *f, struct lock_queue_element *qe,
1090 fuse_ino_t nodeid, const char *name, int wr)
1092 debug_path(f, "WAIT ON PATH", nodeid, name, wr);
1093 pthread_cond_wait(&qe->cond, &f->lock);
1096 static int get_path_common(struct fuse *f, fuse_ino_t nodeid, const char *name,
1097 char **path, struct node **wnode)
1099 int err;
1100 int ticket;
1102 pthread_mutex_lock(&f->lock);
1103 ticket = get_ticket(f);
1104 err = try_get_path(f, nodeid, name, path, wnode, ticket);
1105 if (err == -EAGAIN) {
1106 struct lock_queue_element qe;
1108 queue_path(f, &qe, nodeid, name, !!wnode);
1109 do {
1110 wait_on_path(f, &qe, nodeid, name, !!wnode);
1111 err = try_get_path(f, nodeid, name, path, wnode,
1112 ticket);
1113 wake_up_next(&qe);
1114 } while (err == -EAGAIN);
1115 dequeue_path(f, &qe, nodeid, name, !!wnode);
1117 pthread_mutex_unlock(&f->lock);
1119 return err;
1122 static int get_path(struct fuse *f, fuse_ino_t nodeid, char **path)
1124 return get_path_common(f, nodeid, NULL, path, NULL);
1127 static int get_path_nullok(struct fuse *f, fuse_ino_t nodeid, char **path)
1129 int err = 0;
1131 if (f->conf.nopath) {
1132 *path = NULL;
1133 } else {
1134 err = get_path_common(f, nodeid, NULL, path, NULL);
1135 if (err == -ENOENT && f->nullpath_ok)
1136 err = 0;
1139 return err;
1142 static int get_path_name(struct fuse *f, fuse_ino_t nodeid, const char *name,
1143 char **path)
1145 return get_path_common(f, nodeid, name, path, NULL);
1148 static int get_path_wrlock(struct fuse *f, fuse_ino_t nodeid, const char *name,
1149 char **path, struct node **wnode)
1151 return get_path_common(f, nodeid, name, path, wnode);
1154 static int try_get_path2(struct fuse *f, fuse_ino_t nodeid1, const char *name1,
1155 fuse_ino_t nodeid2, const char *name2,
1156 char **path1, char **path2,
1157 struct node **wnode1, struct node **wnode2,
1158 int ticket)
1160 int err;
1162 /* FIXME: locking two paths needs deadlock checking */
1163 err = try_get_path(f, nodeid1, name1, path1, wnode1, ticket);
1164 if (!err) {
1165 err = try_get_path(f, nodeid2, name2, path2, wnode2, ticket);
1166 if (err) {
1167 struct node *wn1 = wnode1 ? *wnode1 : NULL;
1169 unlock_path(f, nodeid1, wn1, NULL, ticket);
1170 free(*path1);
1171 if (ticket && err != -EAGAIN)
1172 release_tickets(f, nodeid1, wn1, ticket);
1175 return err;
1178 static int get_path2(struct fuse *f, fuse_ino_t nodeid1, const char *name1,
1179 fuse_ino_t nodeid2, const char *name2,
1180 char **path1, char **path2,
1181 struct node **wnode1, struct node **wnode2)
1183 int err;
1184 int ticket;
1186 pthread_mutex_lock(&f->lock);
1187 ticket = get_ticket(f);
1188 err = try_get_path2(f, nodeid1, name1, nodeid2, name2,
1189 path1, path2, wnode1, wnode2, ticket);
1190 if (err == -EAGAIN) {
1191 struct lock_queue_element qe;
1193 queue_path(f, &qe, nodeid1, name1, !!wnode1);
1194 debug_path(f, " path2", nodeid2, name2, !!wnode2);
1195 do {
1196 wait_on_path(f, &qe, nodeid1, name1, !!wnode1);
1197 debug_path(f, " path2", nodeid2, name2, !!wnode2);
1198 err = try_get_path2(f, nodeid1, name1, nodeid2, name2,
1199 path1, path2, wnode1, wnode2,
1200 ticket);
1201 wake_up_next(&qe);
1202 } while (err == -EAGAIN);
1203 dequeue_path(f, &qe, nodeid1, name1, !!wnode1);
1204 debug_path(f, " path2", nodeid2, name2, !!wnode2);
1206 pthread_mutex_unlock(&f->lock);
1208 return err;
1211 static void free_path_wrlock(struct fuse *f, fuse_ino_t nodeid,
1212 struct node *wnode, char *path)
1214 pthread_mutex_lock(&f->lock);
1215 unlock_path(f, nodeid, wnode, NULL, 0);
1216 wake_up_first(f);
1217 pthread_mutex_unlock(&f->lock);
1218 free(path);
1221 static void free_path(struct fuse *f, fuse_ino_t nodeid, char *path)
1223 if (path)
1224 free_path_wrlock(f, nodeid, NULL, path);
1227 static void free_path2(struct fuse *f, fuse_ino_t nodeid1, fuse_ino_t nodeid2,
1228 struct node *wnode1, struct node *wnode2,
1229 char *path1, char *path2)
1231 pthread_mutex_lock(&f->lock);
1232 unlock_path(f, nodeid1, wnode1, NULL, 0);
1233 unlock_path(f, nodeid2, wnode2, NULL, 0);
1234 wake_up_first(f);
1235 pthread_mutex_unlock(&f->lock);
1236 free(path1);
1237 free(path2);
1240 static void forget_node(struct fuse *f, fuse_ino_t nodeid, uint64_t nlookup)
1242 struct node *node;
1243 if (nodeid == FUSE_ROOT_ID)
1244 return;
1245 pthread_mutex_lock(&f->lock);
1246 node = get_node(f, nodeid);
1249 * Node may still be locked due to interrupt idiocy in open,
1250 * create and opendir
1252 while (node->nlookup == nlookup && node->treelock) {
1253 struct lock_queue_element qe;
1255 queue_path(f, &qe, node->nodeid, NULL, 0);
1256 do {
1257 wait_on_path(f, &qe, node->nodeid, NULL, 0);
1258 wake_up_next(&qe);
1260 } while (node->nlookup == nlookup && node->treelock);
1261 dequeue_path(f, &qe, node->nodeid, NULL, 0);
1264 assert(node->nlookup >= nlookup);
1265 node->nlookup -= nlookup;
1266 if (!node->nlookup) {
1267 unref_node(f, node);
1268 } else if (lru_enabled(f) && node->nlookup == 1) {
1269 set_forget_time(f, node);
1271 pthread_mutex_unlock(&f->lock);
1274 static void unlink_node(struct fuse *f, struct node *node)
1276 if (f->conf.remember) {
1277 assert(node->nlookup > 1);
1278 node->nlookup--;
1280 unhash_name(f, node);
1283 static void remove_node(struct fuse *f, fuse_ino_t dir, const char *name)
1285 struct node *node;
1287 pthread_mutex_lock(&f->lock);
1288 node = lookup_node(f, dir, name);
1289 if (node != NULL)
1290 unlink_node(f, node);
1291 pthread_mutex_unlock(&f->lock);
1294 static int rename_node(struct fuse *f, fuse_ino_t olddir, const char *oldname,
1295 fuse_ino_t newdir, const char *newname, int hide)
1297 struct node *node;
1298 struct node *newnode;
1299 int err = 0;
1301 pthread_mutex_lock(&f->lock);
1302 node = lookup_node(f, olddir, oldname);
1303 newnode = lookup_node(f, newdir, newname);
1304 if (node == NULL)
1305 goto out;
1307 if (newnode != NULL) {
1308 if (hide) {
1309 fprintf(stderr, "fuse: hidden file got created during hiding\n");
1310 err = -EBUSY;
1311 goto out;
1313 unlink_node(f, newnode);
1316 unhash_name(f, node);
1317 if (hash_name(f, node, newdir, newname) == -1) {
1318 err = -ENOMEM;
1319 goto out;
1322 if (hide)
1323 node->is_hidden = 1;
1325 out:
1326 pthread_mutex_unlock(&f->lock);
1327 return err;
1330 static void set_stat(struct fuse *f, fuse_ino_t nodeid, struct stat *stbuf)
1332 if (!f->conf.use_ino)
1333 stbuf->st_ino = nodeid;
1334 if (f->conf.set_mode)
1335 stbuf->st_mode = (stbuf->st_mode & S_IFMT) |
1336 (0777 & ~f->conf.umask);
1337 if (f->conf.set_uid)
1338 stbuf->st_uid = f->conf.uid;
1339 if (f->conf.set_gid)
1340 stbuf->st_gid = f->conf.gid;
1343 static struct fuse *req_fuse(fuse_req_t req)
1345 return (struct fuse *) fuse_req_userdata(req);
1348 static void fuse_intr_sighandler(int sig)
1350 (void) sig;
1351 /* Nothing to do */
1354 struct fuse_intr_data {
1355 pthread_t id;
1356 pthread_cond_t cond;
1357 int finished;
1360 static void fuse_interrupt(fuse_req_t req, void *d_)
1362 struct fuse_intr_data *d = d_;
1363 struct fuse *f = req_fuse(req);
1365 if (d->id == pthread_self())
1366 return;
1368 pthread_mutex_lock(&f->lock);
1369 while (!d->finished) {
1370 struct timeval now;
1371 struct timespec timeout;
1373 pthread_kill(d->id, f->conf.intr_signal);
1374 gettimeofday(&now, NULL);
1375 timeout.tv_sec = now.tv_sec + 1;
1376 timeout.tv_nsec = now.tv_usec * 1000;
1377 pthread_cond_timedwait(&d->cond, &f->lock, &timeout);
1379 pthread_mutex_unlock(&f->lock);
1382 static void fuse_do_finish_interrupt(struct fuse *f, fuse_req_t req,
1383 struct fuse_intr_data *d)
1385 pthread_mutex_lock(&f->lock);
1386 d->finished = 1;
1387 pthread_cond_broadcast(&d->cond);
1388 pthread_mutex_unlock(&f->lock);
1389 fuse_req_interrupt_func(req, NULL, NULL);
1390 pthread_cond_destroy(&d->cond);
1393 static void fuse_do_prepare_interrupt(fuse_req_t req, struct fuse_intr_data *d)
1395 d->id = pthread_self();
1396 pthread_cond_init(&d->cond, NULL);
1397 d->finished = 0;
1398 fuse_req_interrupt_func(req, fuse_interrupt, d);
1401 static inline void fuse_finish_interrupt(struct fuse *f, fuse_req_t req,
1402 struct fuse_intr_data *d)
1404 if (f->conf.intr)
1405 fuse_do_finish_interrupt(f, req, d);
1408 static inline void fuse_prepare_interrupt(struct fuse *f, fuse_req_t req,
1409 struct fuse_intr_data *d)
1411 if (f->conf.intr)
1412 fuse_do_prepare_interrupt(req, d);
1415 #if !defined(__FreeBSD__) && !defined(__NetBSD__)
1417 static int fuse_compat_open(struct fuse_fs *fs, const char *path,
1418 struct fuse_file_info *fi)
1420 int err;
1421 if (!fs->compat || fs->compat >= 25)
1422 err = fs->op.open(path, fi);
1423 else if (fs->compat == 22) {
1424 struct fuse_file_info_compat tmp;
1425 memcpy(&tmp, fi, sizeof(tmp));
1426 err = ((struct fuse_operations_compat22 *) &fs->op)->open(path,
1427 &tmp);
1428 memcpy(fi, &tmp, sizeof(tmp));
1429 fi->fh = tmp.fh;
1430 } else
1431 err = ((struct fuse_operations_compat2 *) &fs->op)
1432 ->open(path, fi->flags);
1433 return err;
1436 static int fuse_compat_release(struct fuse_fs *fs, const char *path,
1437 struct fuse_file_info *fi)
1439 if (!fs->compat || fs->compat >= 22)
1440 return fs->op.release(path, fi);
1441 else
1442 return ((struct fuse_operations_compat2 *) &fs->op)
1443 ->release(path, fi->flags);
1446 static int fuse_compat_opendir(struct fuse_fs *fs, const char *path,
1447 struct fuse_file_info *fi)
1449 if (!fs->compat || fs->compat >= 25)
1450 return fs->op.opendir(path, fi);
1451 else {
1452 int err;
1453 struct fuse_file_info_compat tmp;
1454 memcpy(&tmp, fi, sizeof(tmp));
1455 err = ((struct fuse_operations_compat22 *) &fs->op)
1456 ->opendir(path, &tmp);
1457 memcpy(fi, &tmp, sizeof(tmp));
1458 fi->fh = tmp.fh;
1459 return err;
1463 static void convert_statfs_compat(struct fuse_statfs_compat1 *compatbuf,
1464 struct statvfs *stbuf)
1466 stbuf->f_bsize = compatbuf->block_size;
1467 stbuf->f_blocks = compatbuf->blocks;
1468 stbuf->f_bfree = compatbuf->blocks_free;
1469 stbuf->f_bavail = compatbuf->blocks_free;
1470 stbuf->f_files = compatbuf->files;
1471 stbuf->f_ffree = compatbuf->files_free;
1472 stbuf->f_namemax = compatbuf->namelen;
1475 static void convert_statfs_old(struct statfs *oldbuf, struct statvfs *stbuf)
1477 stbuf->f_bsize = oldbuf->f_bsize;
1478 stbuf->f_blocks = oldbuf->f_blocks;
1479 stbuf->f_bfree = oldbuf->f_bfree;
1480 stbuf->f_bavail = oldbuf->f_bavail;
1481 stbuf->f_files = oldbuf->f_files;
1482 stbuf->f_ffree = oldbuf->f_ffree;
1483 stbuf->f_namemax = oldbuf->f_namelen;
1486 static int fuse_compat_statfs(struct fuse_fs *fs, const char *path,
1487 struct statvfs *buf)
1489 int err;
1491 if (!fs->compat || fs->compat >= 25) {
1492 err = fs->op.statfs(fs->compat == 25 ? "/" : path, buf);
1493 } else if (fs->compat > 11) {
1494 struct statfs oldbuf;
1495 err = ((struct fuse_operations_compat22 *) &fs->op)
1496 ->statfs("/", &oldbuf);
1497 if (!err)
1498 convert_statfs_old(&oldbuf, buf);
1499 } else {
1500 struct fuse_statfs_compat1 compatbuf;
1501 memset(&compatbuf, 0, sizeof(struct fuse_statfs_compat1));
1502 err = ((struct fuse_operations_compat1 *) &fs->op)
1503 ->statfs(&compatbuf);
1504 if (!err)
1505 convert_statfs_compat(&compatbuf, buf);
1507 return err;
1510 #else /* __FreeBSD__ || __NetBSD__ */
1512 static inline int fuse_compat_open(struct fuse_fs *fs, char *path,
1513 struct fuse_file_info *fi)
1515 return fs->op.open(path, fi);
1518 static inline int fuse_compat_release(struct fuse_fs *fs, const char *path,
1519 struct fuse_file_info *fi)
1521 return fs->op.release(path, fi);
1524 static inline int fuse_compat_opendir(struct fuse_fs *fs, const char *path,
1525 struct fuse_file_info *fi)
1527 return fs->op.opendir(path, fi);
1530 static inline int fuse_compat_statfs(struct fuse_fs *fs, const char *path,
1531 struct statvfs *buf)
1533 return fs->op.statfs(fs->compat == 25 ? "/" : path, buf);
1536 #endif /* __FreeBSD__ || __NetBSD__ */
1538 int fuse_fs_getattr(struct fuse_fs *fs, const char *path, struct stat *buf)
1540 fuse_get_context()->private_data = fs->user_data;
1541 if (fs->op.getattr) {
1542 if (fs->debug)
1543 fprintf(stderr, "getattr %s\n", path);
1545 return fs->op.getattr(path, buf);
1546 } else {
1547 return -ENOSYS;
1551 int fuse_fs_fgetattr(struct fuse_fs *fs, const char *path, struct stat *buf,
1552 struct fuse_file_info *fi)
1554 fuse_get_context()->private_data = fs->user_data;
1555 if (fs->op.fgetattr) {
1556 if (fs->debug)
1557 fprintf(stderr, "fgetattr[%llu] %s\n",
1558 (unsigned long long) fi->fh, path);
1560 return fs->op.fgetattr(path, buf, fi);
1561 } else if (path && fs->op.getattr) {
1562 if (fs->debug)
1563 fprintf(stderr, "getattr %s\n", path);
1565 return fs->op.getattr(path, buf);
1566 } else {
1567 return -ENOSYS;
1571 int fuse_fs_rename(struct fuse_fs *fs, const char *oldpath,
1572 const char *newpath)
1574 fuse_get_context()->private_data = fs->user_data;
1575 if (fs->op.rename) {
1576 if (fs->debug)
1577 fprintf(stderr, "rename %s %s\n", oldpath, newpath);
1579 return fs->op.rename(oldpath, newpath);
1580 } else {
1581 return -ENOSYS;
1585 int fuse_fs_unlink(struct fuse_fs *fs, const char *path)
1587 fuse_get_context()->private_data = fs->user_data;
1588 if (fs->op.unlink) {
1589 if (fs->debug)
1590 fprintf(stderr, "unlink %s\n", path);
1592 return fs->op.unlink(path);
1593 } else {
1594 return -ENOSYS;
1598 int fuse_fs_rmdir(struct fuse_fs *fs, const char *path)
1600 fuse_get_context()->private_data = fs->user_data;
1601 if (fs->op.rmdir) {
1602 if (fs->debug)
1603 fprintf(stderr, "rmdir %s\n", path);
1605 return fs->op.rmdir(path);
1606 } else {
1607 return -ENOSYS;
1611 int fuse_fs_symlink(struct fuse_fs *fs, const char *linkname, const char *path)
1613 fuse_get_context()->private_data = fs->user_data;
1614 if (fs->op.symlink) {
1615 if (fs->debug)
1616 fprintf(stderr, "symlink %s %s\n", linkname, path);
1618 return fs->op.symlink(linkname, path);
1619 } else {
1620 return -ENOSYS;
1624 int fuse_fs_link(struct fuse_fs *fs, const char *oldpath, const char *newpath)
1626 fuse_get_context()->private_data = fs->user_data;
1627 if (fs->op.link) {
1628 if (fs->debug)
1629 fprintf(stderr, "link %s %s\n", oldpath, newpath);
1631 return fs->op.link(oldpath, newpath);
1632 } else {
1633 return -ENOSYS;
1637 int fuse_fs_release(struct fuse_fs *fs, const char *path,
1638 struct fuse_file_info *fi)
1640 fuse_get_context()->private_data = fs->user_data;
1641 if (fs->op.release) {
1642 if (fs->debug)
1643 fprintf(stderr, "release%s[%llu] flags: 0x%x\n",
1644 fi->flush ? "+flush" : "",
1645 (unsigned long long) fi->fh, fi->flags);
1647 return fuse_compat_release(fs, path, fi);
1648 } else {
1649 return 0;
1653 int fuse_fs_opendir(struct fuse_fs *fs, const char *path,
1654 struct fuse_file_info *fi)
1656 fuse_get_context()->private_data = fs->user_data;
1657 if (fs->op.opendir) {
1658 int err;
1660 if (fs->debug)
1661 fprintf(stderr, "opendir flags: 0x%x %s\n", fi->flags,
1662 path);
1664 err = fuse_compat_opendir(fs, path, fi);
1666 if (fs->debug && !err)
1667 fprintf(stderr, " opendir[%lli] flags: 0x%x %s\n",
1668 (unsigned long long) fi->fh, fi->flags, path);
1670 return err;
1671 } else {
1672 return 0;
1676 int fuse_fs_open(struct fuse_fs *fs, const char *path,
1677 struct fuse_file_info *fi)
1679 fuse_get_context()->private_data = fs->user_data;
1680 if (fs->op.open) {
1681 int err;
1683 if (fs->debug)
1684 fprintf(stderr, "open flags: 0x%x %s\n", fi->flags,
1685 path);
1687 err = fuse_compat_open(fs, path, fi);
1689 if (fs->debug && !err)
1690 fprintf(stderr, " open[%lli] flags: 0x%x %s\n",
1691 (unsigned long long) fi->fh, fi->flags, path);
1693 return err;
1694 } else {
1695 return 0;
1699 static void fuse_free_buf(struct fuse_bufvec *buf)
1701 if (buf != NULL) {
1702 size_t i;
1704 for (i = 0; i < buf->count; i++)
1705 free(buf->buf[i].mem);
1706 free(buf);
1710 int fuse_fs_read_buf(struct fuse_fs *fs, const char *path,
1711 struct fuse_bufvec **bufp, size_t size, off_t off,
1712 struct fuse_file_info *fi)
1714 fuse_get_context()->private_data = fs->user_data;
1715 if (fs->op.read || fs->op.read_buf) {
1716 int res;
1718 if (fs->debug)
1719 fprintf(stderr,
1720 "read[%llu] %zu bytes from %llu flags: 0x%x\n",
1721 (unsigned long long) fi->fh,
1722 size, (unsigned long long) off, fi->flags);
1724 if (fs->op.read_buf) {
1725 res = fs->op.read_buf(path, bufp, size, off, fi);
1726 } else {
1727 struct fuse_bufvec *buf;
1728 void *mem;
1730 buf = malloc(sizeof(struct fuse_bufvec));
1731 if (buf == NULL)
1732 return -ENOMEM;
1734 mem = malloc(size);
1735 if (mem == NULL) {
1736 free(buf);
1737 return -ENOMEM;
1739 *buf = FUSE_BUFVEC_INIT(size);
1740 buf->buf[0].mem = mem;
1741 *bufp = buf;
1743 res = fs->op.read(path, mem, size, off, fi);
1744 if (res >= 0)
1745 buf->buf[0].size = res;
1748 if (fs->debug && res >= 0)
1749 fprintf(stderr, " read[%llu] %zu bytes from %llu\n",
1750 (unsigned long long) fi->fh,
1751 fuse_buf_size(*bufp),
1752 (unsigned long long) off);
1753 if (res >= 0 && fuse_buf_size(*bufp) > (int) size)
1754 fprintf(stderr, "fuse: read too many bytes\n");
1756 if (res < 0)
1757 return res;
1759 return 0;
1760 } else {
1761 return -ENOSYS;
1765 int fuse_fs_read(struct fuse_fs *fs, const char *path, char *mem, size_t size,
1766 off_t off, struct fuse_file_info *fi)
1768 int res;
1769 struct fuse_bufvec *buf = NULL;
1771 res = fuse_fs_read_buf(fs, path, &buf, size, off, fi);
1772 if (res == 0) {
1773 struct fuse_bufvec dst = FUSE_BUFVEC_INIT(size);
1775 dst.buf[0].mem = mem;
1776 res = fuse_buf_copy(&dst, buf, 0);
1778 fuse_free_buf(buf);
1780 return res;
1783 int fuse_fs_write_buf(struct fuse_fs *fs, const char *path,
1784 struct fuse_bufvec *buf, off_t off,
1785 struct fuse_file_info *fi)
1787 fuse_get_context()->private_data = fs->user_data;
1788 if (fs->op.write_buf || fs->op.write) {
1789 int res;
1790 size_t size = fuse_buf_size(buf);
1792 assert(buf->idx == 0 && buf->off == 0);
1793 if (fs->debug)
1794 fprintf(stderr,
1795 "write%s[%llu] %zu bytes to %llu flags: 0x%x\n",
1796 fi->writepage ? "page" : "",
1797 (unsigned long long) fi->fh,
1798 size,
1799 (unsigned long long) off,
1800 fi->flags);
1802 if (fs->op.write_buf) {
1803 res = fs->op.write_buf(path, buf, off, fi);
1804 } else {
1805 void *mem = NULL;
1806 struct fuse_buf *flatbuf;
1807 struct fuse_bufvec tmp = FUSE_BUFVEC_INIT(size);
1809 if (buf->count == 1 &&
1810 !(buf->buf[0].flags & FUSE_BUF_IS_FD)) {
1811 flatbuf = &buf->buf[0];
1812 } else {
1813 res = -ENOMEM;
1814 mem = malloc(size);
1815 if (mem == NULL)
1816 goto out;
1818 tmp.buf[0].mem = mem;
1819 res = fuse_buf_copy(&tmp, buf, 0);
1820 if (res <= 0)
1821 goto out_free;
1823 tmp.buf[0].size = res;
1824 flatbuf = &tmp.buf[0];
1827 res = fs->op.write(path, flatbuf->mem, flatbuf->size,
1828 off, fi);
1829 out_free:
1830 free(mem);
1832 out:
1833 if (fs->debug && res >= 0)
1834 fprintf(stderr, " write%s[%llu] %u bytes to %llu\n",
1835 fi->writepage ? "page" : "",
1836 (unsigned long long) fi->fh, res,
1837 (unsigned long long) off);
1838 if (res > (int) size)
1839 fprintf(stderr, "fuse: wrote too many bytes\n");
1841 return res;
1842 } else {
1843 return -ENOSYS;
1847 int fuse_fs_write(struct fuse_fs *fs, const char *path, const char *mem,
1848 size_t size, off_t off, struct fuse_file_info *fi)
1850 struct fuse_bufvec bufv = FUSE_BUFVEC_INIT(size);
1852 bufv.buf[0].mem = (void *) mem;
1854 return fuse_fs_write_buf(fs, path, &bufv, off, fi);
1857 int fuse_fs_fsync(struct fuse_fs *fs, const char *path, int datasync,
1858 struct fuse_file_info *fi)
1860 fuse_get_context()->private_data = fs->user_data;
1861 if (fs->op.fsync) {
1862 if (fs->debug)
1863 fprintf(stderr, "fsync[%llu] datasync: %i\n",
1864 (unsigned long long) fi->fh, datasync);
1866 return fs->op.fsync(path, datasync, fi);
1867 } else {
1868 return -ENOSYS;
1872 int fuse_fs_fsyncdir(struct fuse_fs *fs, const char *path, int datasync,
1873 struct fuse_file_info *fi)
1875 fuse_get_context()->private_data = fs->user_data;
1876 if (fs->op.fsyncdir) {
1877 if (fs->debug)
1878 fprintf(stderr, "fsyncdir[%llu] datasync: %i\n",
1879 (unsigned long long) fi->fh, datasync);
1881 return fs->op.fsyncdir(path, datasync, fi);
1882 } else {
1883 return -ENOSYS;
1887 int fuse_fs_flush(struct fuse_fs *fs, const char *path,
1888 struct fuse_file_info *fi)
1890 fuse_get_context()->private_data = fs->user_data;
1891 if (fs->op.flush) {
1892 if (fs->debug)
1893 fprintf(stderr, "flush[%llu]\n",
1894 (unsigned long long) fi->fh);
1896 return fs->op.flush(path, fi);
1897 } else {
1898 return -ENOSYS;
1902 int fuse_fs_statfs(struct fuse_fs *fs, const char *path, struct statvfs *buf)
1904 fuse_get_context()->private_data = fs->user_data;
1905 if (fs->op.statfs) {
1906 if (fs->debug)
1907 fprintf(stderr, "statfs %s\n", path);
1909 return fuse_compat_statfs(fs, path, buf);
1910 } else {
1911 buf->f_namemax = 255;
1912 buf->f_bsize = 512;
1913 return 0;
1917 int fuse_fs_releasedir(struct fuse_fs *fs, const char *path,
1918 struct fuse_file_info *fi)
1920 fuse_get_context()->private_data = fs->user_data;
1921 if (fs->op.releasedir) {
1922 if (fs->debug)
1923 fprintf(stderr, "releasedir[%llu] flags: 0x%x\n",
1924 (unsigned long long) fi->fh, fi->flags);
1926 return fs->op.releasedir(path, fi);
1927 } else {
1928 return 0;
1932 static int fill_dir_old(struct fuse_dirhandle *dh, const char *name, int type,
1933 ino_t ino)
1935 int res;
1936 struct stat stbuf;
1938 memset(&stbuf, 0, sizeof(stbuf));
1939 stbuf.st_mode = type << 12;
1940 stbuf.st_ino = ino;
1942 res = dh->filler(dh->buf, name, &stbuf, 0);
1943 return res ? -ENOMEM : 0;
1946 int fuse_fs_readdir(struct fuse_fs *fs, const char *path, void *buf,
1947 fuse_fill_dir_t filler, off_t off,
1948 struct fuse_file_info *fi)
1950 fuse_get_context()->private_data = fs->user_data;
1951 if (fs->op.readdir) {
1952 if (fs->debug)
1953 fprintf(stderr, "readdir[%llu] from %llu\n",
1954 (unsigned long long) fi->fh,
1955 (unsigned long long) off);
1957 return fs->op.readdir(path, buf, filler, off, fi);
1958 } else if (fs->op.getdir) {
1959 struct fuse_dirhandle dh;
1961 if (fs->debug)
1962 fprintf(stderr, "getdir[%llu]\n",
1963 (unsigned long long) fi->fh);
1965 dh.filler = filler;
1966 dh.buf = buf;
1967 return fs->op.getdir(path, &dh, fill_dir_old);
1968 } else {
1969 return -ENOSYS;
1973 int fuse_fs_create(struct fuse_fs *fs, const char *path, mode_t mode,
1974 struct fuse_file_info *fi)
1976 fuse_get_context()->private_data = fs->user_data;
1977 if (fs->op.create) {
1978 int err;
1980 if (fs->debug)
1981 fprintf(stderr,
1982 "create flags: 0x%x %s 0%o umask=0%03o\n",
1983 fi->flags, path, mode,
1984 fuse_get_context()->umask);
1986 err = fs->op.create(path, mode, fi);
1988 if (fs->debug && !err)
1989 fprintf(stderr, " create[%llu] flags: 0x%x %s\n",
1990 (unsigned long long) fi->fh, fi->flags, path);
1992 return err;
1993 } else {
1994 return -ENOSYS;
1998 int fuse_fs_lock(struct fuse_fs *fs, const char *path,
1999 struct fuse_file_info *fi, int cmd, struct flock *lock)
2001 fuse_get_context()->private_data = fs->user_data;
2002 if (fs->op.lock) {
2003 if (fs->debug)
2004 fprintf(stderr, "lock[%llu] %s %s start: %llu len: %llu pid: %llu\n",
2005 (unsigned long long) fi->fh,
2006 (cmd == F_GETLK ? "F_GETLK" :
2007 (cmd == F_SETLK ? "F_SETLK" :
2008 (cmd == F_SETLKW ? "F_SETLKW" : "???"))),
2009 (lock->l_type == F_RDLCK ? "F_RDLCK" :
2010 (lock->l_type == F_WRLCK ? "F_WRLCK" :
2011 (lock->l_type == F_UNLCK ? "F_UNLCK" :
2012 "???"))),
2013 (unsigned long long) lock->l_start,
2014 (unsigned long long) lock->l_len,
2015 (unsigned long long) lock->l_pid);
2017 return fs->op.lock(path, fi, cmd, lock);
2018 } else {
2019 return -ENOSYS;
2023 int fuse_fs_flock(struct fuse_fs *fs, const char *path,
2024 struct fuse_file_info *fi, int op)
2026 fuse_get_context()->private_data = fs->user_data;
2027 if (fs->op.flock) {
2028 if (fs->debug) {
2029 int xop = op & ~LOCK_NB;
2031 fprintf(stderr, "lock[%llu] %s%s\n",
2032 (unsigned long long) fi->fh,
2033 xop == LOCK_SH ? "LOCK_SH" :
2034 (xop == LOCK_EX ? "LOCK_EX" :
2035 (xop == LOCK_UN ? "LOCK_UN" : "???")),
2036 (op & LOCK_NB) ? "|LOCK_NB" : "");
2038 return fs->op.flock(path, fi, op);
2039 } else {
2040 return -ENOSYS;
2044 int fuse_fs_chown(struct fuse_fs *fs, const char *path, uid_t uid, gid_t gid)
2046 fuse_get_context()->private_data = fs->user_data;
2047 if (fs->op.chown) {
2048 if (fs->debug)
2049 fprintf(stderr, "chown %s %lu %lu\n", path,
2050 (unsigned long) uid, (unsigned long) gid);
2052 return fs->op.chown(path, uid, gid);
2053 } else {
2054 return -ENOSYS;
2058 int fuse_fs_truncate(struct fuse_fs *fs, const char *path, off_t size)
2060 fuse_get_context()->private_data = fs->user_data;
2061 if (fs->op.truncate) {
2062 if (fs->debug)
2063 fprintf(stderr, "truncate %s %llu\n", path,
2064 (unsigned long long) size);
2066 return fs->op.truncate(path, size);
2067 } else {
2068 return -ENOSYS;
2072 int fuse_fs_ftruncate(struct fuse_fs *fs, const char *path, off_t size,
2073 struct fuse_file_info *fi)
2075 fuse_get_context()->private_data = fs->user_data;
2076 if (fs->op.ftruncate) {
2077 if (fs->debug)
2078 fprintf(stderr, "ftruncate[%llu] %llu\n",
2079 (unsigned long long) fi->fh,
2080 (unsigned long long) size);
2082 return fs->op.ftruncate(path, size, fi);
2083 } else if (path && fs->op.truncate) {
2084 if (fs->debug)
2085 fprintf(stderr, "truncate %s %llu\n", path,
2086 (unsigned long long) size);
2088 return fs->op.truncate(path, size);
2089 } else {
2090 return -ENOSYS;
2094 int fuse_fs_utimens(struct fuse_fs *fs, const char *path,
2095 const struct timespec tv[2])
2097 fuse_get_context()->private_data = fs->user_data;
2098 if (fs->op.utimens) {
2099 if (fs->debug)
2100 fprintf(stderr, "utimens %s %li.%09lu %li.%09lu\n",
2101 path, tv[0].tv_sec, tv[0].tv_nsec,
2102 tv[1].tv_sec, tv[1].tv_nsec);
2104 return fs->op.utimens(path, tv);
2105 } else if(fs->op.utime) {
2106 struct utimbuf buf;
2108 if (fs->debug)
2109 fprintf(stderr, "utime %s %li %li\n", path,
2110 tv[0].tv_sec, tv[1].tv_sec);
2112 buf.actime = tv[0].tv_sec;
2113 buf.modtime = tv[1].tv_sec;
2114 return fs->op.utime(path, &buf);
2115 } else {
2116 return -ENOSYS;
2120 int fuse_fs_access(struct fuse_fs *fs, const char *path, int mask)
2122 fuse_get_context()->private_data = fs->user_data;
2123 if (fs->op.access) {
2124 if (fs->debug)
2125 fprintf(stderr, "access %s 0%o\n", path, mask);
2127 return fs->op.access(path, mask);
2128 } else {
2129 return -ENOSYS;
2133 int fuse_fs_readlink(struct fuse_fs *fs, const char *path, char *buf,
2134 size_t len)
2136 fuse_get_context()->private_data = fs->user_data;
2137 if (fs->op.readlink) {
2138 if (fs->debug)
2139 fprintf(stderr, "readlink %s %lu\n", path,
2140 (unsigned long) len);
2142 return fs->op.readlink(path, buf, len);
2143 } else {
2144 return -ENOSYS;
2148 int fuse_fs_mknod(struct fuse_fs *fs, const char *path, mode_t mode,
2149 dev_t rdev)
2151 fuse_get_context()->private_data = fs->user_data;
2152 if (fs->op.mknod) {
2153 if (fs->debug)
2154 fprintf(stderr, "mknod %s 0%o 0x%llx umask=0%03o\n",
2155 path, mode, (unsigned long long) rdev,
2156 fuse_get_context()->umask);
2158 return fs->op.mknod(path, mode, rdev);
2159 } else {
2160 return -ENOSYS;
2164 int fuse_fs_mkdir(struct fuse_fs *fs, const char *path, mode_t mode)
2166 fuse_get_context()->private_data = fs->user_data;
2167 if (fs->op.mkdir) {
2168 if (fs->debug)
2169 fprintf(stderr, "mkdir %s 0%o umask=0%03o\n",
2170 path, mode, fuse_get_context()->umask);
2172 return fs->op.mkdir(path, mode);
2173 } else {
2174 return -ENOSYS;
2178 int fuse_fs_setxattr(struct fuse_fs *fs, const char *path, const char *name,
2179 const char *value, size_t size, int flags)
2181 fuse_get_context()->private_data = fs->user_data;
2182 if (fs->op.setxattr) {
2183 if (fs->debug)
2184 fprintf(stderr, "setxattr %s %s %lu 0x%x\n",
2185 path, name, (unsigned long) size, flags);
2187 return fs->op.setxattr(path, name, value, size, flags);
2188 } else {
2189 return -ENOSYS;
2193 int fuse_fs_getxattr(struct fuse_fs *fs, const char *path, const char *name,
2194 char *value, size_t size)
2196 fuse_get_context()->private_data = fs->user_data;
2197 if (fs->op.getxattr) {
2198 if (fs->debug)
2199 fprintf(stderr, "getxattr %s %s %lu\n",
2200 path, name, (unsigned long) size);
2202 return fs->op.getxattr(path, name, value, size);
2203 } else {
2204 return -ENOSYS;
2208 int fuse_fs_listxattr(struct fuse_fs *fs, const char *path, char *list,
2209 size_t size)
2211 fuse_get_context()->private_data = fs->user_data;
2212 if (fs->op.listxattr) {
2213 if (fs->debug)
2214 fprintf(stderr, "listxattr %s %lu\n",
2215 path, (unsigned long) size);
2217 return fs->op.listxattr(path, list, size);
2218 } else {
2219 return -ENOSYS;
2223 int fuse_fs_bmap(struct fuse_fs *fs, const char *path, size_t blocksize,
2224 uint64_t *idx)
2226 fuse_get_context()->private_data = fs->user_data;
2227 if (fs->op.bmap) {
2228 if (fs->debug)
2229 fprintf(stderr, "bmap %s blocksize: %lu index: %llu\n",
2230 path, (unsigned long) blocksize,
2231 (unsigned long long) *idx);
2233 return fs->op.bmap(path, blocksize, idx);
2234 } else {
2235 return -ENOSYS;
2239 int fuse_fs_removexattr(struct fuse_fs *fs, const char *path, const char *name)
2241 fuse_get_context()->private_data = fs->user_data;
2242 if (fs->op.removexattr) {
2243 if (fs->debug)
2244 fprintf(stderr, "removexattr %s %s\n", path, name);
2246 return fs->op.removexattr(path, name);
2247 } else {
2248 return -ENOSYS;
2252 int fuse_fs_ioctl(struct fuse_fs *fs, const char *path, int cmd, void *arg,
2253 struct fuse_file_info *fi, unsigned int flags, void *data)
2255 fuse_get_context()->private_data = fs->user_data;
2256 if (fs->op.ioctl) {
2257 if (fs->debug)
2258 fprintf(stderr, "ioctl[%llu] 0x%x flags: 0x%x\n",
2259 (unsigned long long) fi->fh, cmd, flags);
2261 return fs->op.ioctl(path, cmd, arg, fi, flags, data);
2262 } else
2263 return -ENOSYS;
2266 int fuse_fs_poll(struct fuse_fs *fs, const char *path,
2267 struct fuse_file_info *fi, struct fuse_pollhandle *ph,
2268 unsigned *reventsp)
2270 fuse_get_context()->private_data = fs->user_data;
2271 if (fs->op.poll) {
2272 int res;
2274 if (fs->debug)
2275 fprintf(stderr, "poll[%llu] ph: %p\n",
2276 (unsigned long long) fi->fh, ph);
2278 res = fs->op.poll(path, fi, ph, reventsp);
2280 if (fs->debug && !res)
2281 fprintf(stderr, " poll[%llu] revents: 0x%x\n",
2282 (unsigned long long) fi->fh, *reventsp);
2284 return res;
2285 } else
2286 return -ENOSYS;
2289 int fuse_fs_fallocate(struct fuse_fs *fs, const char *path, int mode,
2290 off_t offset, off_t length, struct fuse_file_info *fi)
2292 fuse_get_context()->private_data = fs->user_data;
2293 if (fs->op.fallocate) {
2294 if (fs->debug)
2295 fprintf(stderr, "fallocate %s mode %x, offset: %llu, length: %llu\n",
2296 path,
2297 mode,
2298 (unsigned long long) offset,
2299 (unsigned long long) length);
2301 return fs->op.fallocate(path, mode, offset, length, fi);
2302 } else
2303 return -ENOSYS;
2306 static int is_open(struct fuse *f, fuse_ino_t dir, const char *name)
2308 struct node *node;
2309 int isopen = 0;
2310 pthread_mutex_lock(&f->lock);
2311 node = lookup_node(f, dir, name);
2312 if (node && node->open_count > 0)
2313 isopen = 1;
2314 pthread_mutex_unlock(&f->lock);
2315 return isopen;
2318 static char *hidden_name(struct fuse *f, fuse_ino_t dir, const char *oldname,
2319 char *newname, size_t bufsize)
2321 struct stat buf;
2322 struct node *node;
2323 struct node *newnode;
2324 char *newpath;
2325 int res;
2326 int failctr = 10;
2328 do {
2329 pthread_mutex_lock(&f->lock);
2330 node = lookup_node(f, dir, oldname);
2331 if (node == NULL) {
2332 pthread_mutex_unlock(&f->lock);
2333 return NULL;
2335 do {
2336 f->hidectr ++;
2337 snprintf(newname, bufsize, ".fuse_hidden%08x%08x",
2338 (unsigned int) node->nodeid, f->hidectr);
2339 newnode = lookup_node(f, dir, newname);
2340 } while(newnode);
2342 res = try_get_path(f, dir, newname, &newpath, NULL, 0);
2343 pthread_mutex_unlock(&f->lock);
2344 if (res)
2345 break;
2347 res = fuse_fs_getattr(f->fs, newpath, &buf);
2348 if (res == -ENOENT)
2349 break;
2350 free(newpath);
2351 newpath = NULL;
2352 } while(res == 0 && --failctr);
2354 return newpath;
2357 static int hide_node(struct fuse *f, const char *oldpath,
2358 fuse_ino_t dir, const char *oldname)
2360 char newname[64];
2361 char *newpath;
2362 int err = -EBUSY;
2364 newpath = hidden_name(f, dir, oldname, newname, sizeof(newname));
2365 if (newpath) {
2366 err = fuse_fs_rename(f->fs, oldpath, newpath);
2367 if (!err)
2368 err = rename_node(f, dir, oldname, dir, newname, 1);
2369 free(newpath);
2371 return err;
2374 static int mtime_eq(const struct stat *stbuf, const struct timespec *ts)
2376 return stbuf->st_mtime == ts->tv_sec &&
2377 ST_MTIM_NSEC(stbuf) == ts->tv_nsec;
2380 #ifndef CLOCK_MONOTONIC
2381 #define CLOCK_MONOTONIC CLOCK_REALTIME
2382 #endif
2384 static void curr_time(struct timespec *now)
2386 static clockid_t clockid = CLOCK_MONOTONIC;
2387 int res = clock_gettime(clockid, now);
2388 if (res == -1 && errno == EINVAL) {
2389 clockid = CLOCK_REALTIME;
2390 res = clock_gettime(clockid, now);
2392 if (res == -1) {
2393 perror("fuse: clock_gettime");
2394 abort();
2398 static void update_stat(struct node *node, const struct stat *stbuf)
2400 if (node->cache_valid && (!mtime_eq(stbuf, &node->mtime) ||
2401 stbuf->st_size != node->size))
2402 node->cache_valid = 0;
2403 node->mtime.tv_sec = stbuf->st_mtime;
2404 node->mtime.tv_nsec = ST_MTIM_NSEC(stbuf);
2405 node->size = stbuf->st_size;
2406 curr_time(&node->stat_updated);
2409 static int lookup_path(struct fuse *f, fuse_ino_t nodeid,
2410 const char *name, const char *path,
2411 struct fuse_entry_param *e, struct fuse_file_info *fi)
2413 int res;
2415 memset(e, 0, sizeof(struct fuse_entry_param));
2416 if (fi)
2417 res = fuse_fs_fgetattr(f->fs, path, &e->attr, fi);
2418 else
2419 res = fuse_fs_getattr(f->fs, path, &e->attr);
2420 if (res == 0) {
2421 struct node *node;
2423 node = find_node(f, nodeid, name);
2424 if (node == NULL)
2425 res = -ENOMEM;
2426 else {
2427 e->ino = node->nodeid;
2428 e->generation = node->generation;
2429 e->entry_timeout = f->conf.entry_timeout;
2430 e->attr_timeout = f->conf.attr_timeout;
2431 if (f->conf.auto_cache) {
2432 pthread_mutex_lock(&f->lock);
2433 update_stat(node, &e->attr);
2434 pthread_mutex_unlock(&f->lock);
2436 set_stat(f, e->ino, &e->attr);
2437 if (f->conf.debug)
2438 fprintf(stderr, " NODEID: %lu\n",
2439 (unsigned long) e->ino);
2442 return res;
2445 static struct fuse_context_i *fuse_get_context_internal(void)
2447 struct fuse_context_i *c;
2449 c = (struct fuse_context_i *) pthread_getspecific(fuse_context_key);
2450 if (c == NULL) {
2451 c = (struct fuse_context_i *)
2452 calloc(1, sizeof(struct fuse_context_i));
2453 if (c == NULL) {
2454 /* This is hard to deal with properly, so just
2455 abort. If memory is so low that the
2456 context cannot be allocated, there's not
2457 much hope for the filesystem anyway */
2458 fprintf(stderr, "fuse: failed to allocate thread specific data\n");
2459 abort();
2461 pthread_setspecific(fuse_context_key, c);
2463 return c;
2466 static void fuse_freecontext(void *data)
2468 free(data);
2471 static int fuse_create_context_key(void)
2473 int err = 0;
2474 pthread_mutex_lock(&fuse_context_lock);
2475 if (!fuse_context_ref) {
2476 err = pthread_key_create(&fuse_context_key, fuse_freecontext);
2477 if (err) {
2478 fprintf(stderr, "fuse: failed to create thread specific key: %s\n",
2479 strerror(err));
2480 pthread_mutex_unlock(&fuse_context_lock);
2481 return -1;
2484 fuse_context_ref++;
2485 pthread_mutex_unlock(&fuse_context_lock);
2486 return 0;
2489 static void fuse_delete_context_key(void)
2491 pthread_mutex_lock(&fuse_context_lock);
2492 fuse_context_ref--;
2493 if (!fuse_context_ref) {
2494 free(pthread_getspecific(fuse_context_key));
2495 pthread_key_delete(fuse_context_key);
2497 pthread_mutex_unlock(&fuse_context_lock);
2500 static struct fuse *req_fuse_prepare(fuse_req_t req)
2502 struct fuse_context_i *c = fuse_get_context_internal();
2503 const struct fuse_ctx *ctx = fuse_req_ctx(req);
2504 c->req = req;
2505 c->ctx.fuse = req_fuse(req);
2506 c->ctx.uid = ctx->uid;
2507 c->ctx.gid = ctx->gid;
2508 c->ctx.pid = ctx->pid;
2509 c->ctx.umask = ctx->umask;
2510 return c->ctx.fuse;
2513 static inline void reply_err(fuse_req_t req, int err)
2515 /* fuse_reply_err() uses non-negated errno values */
2516 fuse_reply_err(req, -err);
2519 static void reply_entry(fuse_req_t req, const struct fuse_entry_param *e,
2520 int err)
2522 if (!err) {
2523 struct fuse *f = req_fuse(req);
2524 if (fuse_reply_entry(req, e) == -ENOENT) {
2525 /* Skip forget for negative result */
2526 if (e->ino != 0)
2527 forget_node(f, e->ino, 1);
2529 } else
2530 reply_err(req, err);
2533 void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn)
2535 fuse_get_context()->private_data = fs->user_data;
2536 if (!fs->op.write_buf)
2537 conn->want &= ~FUSE_CAP_SPLICE_READ;
2538 if (!fs->op.lock)
2539 conn->want &= ~FUSE_CAP_POSIX_LOCKS;
2540 if (!fs->op.flock)
2541 conn->want &= ~FUSE_CAP_FLOCK_LOCKS;
2542 if (fs->op.init)
2543 fs->user_data = fs->op.init(conn);
2546 static void fuse_lib_init(void *data, struct fuse_conn_info *conn)
2548 struct fuse *f = (struct fuse *) data;
2549 struct fuse_context_i *c = fuse_get_context_internal();
2551 memset(c, 0, sizeof(*c));
2552 c->ctx.fuse = f;
2553 conn->want |= FUSE_CAP_EXPORT_SUPPORT;
2554 fuse_fs_init(f->fs, conn);
2557 void fuse_fs_destroy(struct fuse_fs *fs)
2559 fuse_get_context()->private_data = fs->user_data;
2560 if (fs->op.destroy)
2561 fs->op.destroy(fs->user_data);
2562 if (fs->m)
2563 fuse_put_module(fs->m);
2564 free(fs);
2567 static void fuse_lib_destroy(void *data)
2569 struct fuse *f = (struct fuse *) data;
2570 struct fuse_context_i *c = fuse_get_context_internal();
2572 memset(c, 0, sizeof(*c));
2573 c->ctx.fuse = f;
2574 fuse_fs_destroy(f->fs);
2575 f->fs = NULL;
2578 static void fuse_lib_lookup(fuse_req_t req, fuse_ino_t parent,
2579 const char *name)
2581 struct fuse *f = req_fuse_prepare(req);
2582 struct fuse_entry_param e;
2583 char *path;
2584 int err;
2585 struct node *dot = NULL;
2587 if (name[0] == '.') {
2588 int len = strlen(name);
2590 if (len == 1 || (name[1] == '.' && len == 2)) {
2591 pthread_mutex_lock(&f->lock);
2592 if (len == 1) {
2593 if (f->conf.debug)
2594 fprintf(stderr, "LOOKUP-DOT\n");
2595 dot = get_node_nocheck(f, parent);
2596 if (dot == NULL) {
2597 pthread_mutex_unlock(&f->lock);
2598 reply_entry(req, &e, -ESTALE);
2599 return;
2601 dot->refctr++;
2602 } else {
2603 if (f->conf.debug)
2604 fprintf(stderr, "LOOKUP-DOTDOT\n");
2605 parent = get_node(f, parent)->parent->nodeid;
2607 pthread_mutex_unlock(&f->lock);
2608 name = NULL;
2612 err = get_path_name(f, parent, name, &path);
2613 if (!err) {
2614 struct fuse_intr_data d;
2615 if (f->conf.debug)
2616 fprintf(stderr, "LOOKUP %s\n", path);
2617 fuse_prepare_interrupt(f, req, &d);
2618 err = lookup_path(f, parent, name, path, &e, NULL);
2619 if (err == -ENOENT && f->conf.negative_timeout != 0.0) {
2620 e.ino = 0;
2621 e.entry_timeout = f->conf.negative_timeout;
2622 err = 0;
2624 fuse_finish_interrupt(f, req, &d);
2625 free_path(f, parent, path);
2627 if (dot) {
2628 pthread_mutex_lock(&f->lock);
2629 unref_node(f, dot);
2630 pthread_mutex_unlock(&f->lock);
2632 reply_entry(req, &e, err);
2635 static void do_forget(struct fuse *f, fuse_ino_t ino, uint64_t nlookup)
2637 if (f->conf.debug)
2638 fprintf(stderr, "FORGET %llu/%llu\n", (unsigned long long)ino,
2639 (unsigned long long) nlookup);
2640 forget_node(f, ino, nlookup);
2643 static void fuse_lib_forget(fuse_req_t req, fuse_ino_t ino,
2644 unsigned long nlookup)
2646 do_forget(req_fuse(req), ino, nlookup);
2647 fuse_reply_none(req);
2650 static void fuse_lib_forget_multi(fuse_req_t req, size_t count,
2651 struct fuse_forget_data *forgets)
2653 struct fuse *f = req_fuse(req);
2654 size_t i;
2656 for (i = 0; i < count; i++)
2657 do_forget(f, forgets[i].ino, forgets[i].nlookup);
2659 fuse_reply_none(req);
2663 static void fuse_lib_getattr(fuse_req_t req, fuse_ino_t ino,
2664 struct fuse_file_info *fi)
2666 struct fuse *f = req_fuse_prepare(req);
2667 struct stat buf;
2668 char *path;
2669 int err;
2671 memset(&buf, 0, sizeof(buf));
2673 if (fi != NULL && f->fs->op.fgetattr)
2674 err = get_path_nullok(f, ino, &path);
2675 else
2676 err = get_path(f, ino, &path);
2677 if (!err) {
2678 struct fuse_intr_data d;
2679 fuse_prepare_interrupt(f, req, &d);
2680 if (fi)
2681 err = fuse_fs_fgetattr(f->fs, path, &buf, fi);
2682 else
2683 err = fuse_fs_getattr(f->fs, path, &buf);
2684 fuse_finish_interrupt(f, req, &d);
2685 free_path(f, ino, path);
2687 if (!err) {
2688 struct node *node;
2690 pthread_mutex_lock(&f->lock);
2691 node = get_node(f, ino);
2692 if (node->is_hidden && buf.st_nlink > 0)
2693 buf.st_nlink--;
2694 if (f->conf.auto_cache)
2695 update_stat(node, &buf);
2696 pthread_mutex_unlock(&f->lock);
2697 set_stat(f, ino, &buf);
2698 fuse_reply_attr(req, &buf, f->conf.attr_timeout);
2699 } else
2700 reply_err(req, err);
2703 int fuse_fs_chmod(struct fuse_fs *fs, const char *path, mode_t mode)
2705 fuse_get_context()->private_data = fs->user_data;
2706 if (fs->op.chmod)
2707 return fs->op.chmod(path, mode);
2708 else
2709 return -ENOSYS;
2712 static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
2713 int valid, struct fuse_file_info *fi)
2715 struct fuse *f = req_fuse_prepare(req);
2716 struct stat buf;
2717 char *path;
2718 int err;
2720 if (valid == FUSE_SET_ATTR_SIZE && fi != NULL &&
2721 f->fs->op.ftruncate && f->fs->op.fgetattr)
2722 err = get_path_nullok(f, ino, &path);
2723 else
2724 err = get_path(f, ino, &path);
2725 if (!err) {
2726 struct fuse_intr_data d;
2727 fuse_prepare_interrupt(f, req, &d);
2728 err = 0;
2729 if (!err && (valid & FUSE_SET_ATTR_MODE))
2730 err = fuse_fs_chmod(f->fs, path, attr->st_mode);
2731 if (!err && (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID))) {
2732 uid_t uid = (valid & FUSE_SET_ATTR_UID) ?
2733 attr->st_uid : (uid_t) -1;
2734 gid_t gid = (valid & FUSE_SET_ATTR_GID) ?
2735 attr->st_gid : (gid_t) -1;
2736 err = fuse_fs_chown(f->fs, path, uid, gid);
2738 if (!err && (valid & FUSE_SET_ATTR_SIZE)) {
2739 if (fi)
2740 err = fuse_fs_ftruncate(f->fs, path,
2741 attr->st_size, fi);
2742 else
2743 err = fuse_fs_truncate(f->fs, path,
2744 attr->st_size);
2746 #ifdef HAVE_UTIMENSAT
2747 if (!err && f->utime_omit_ok &&
2748 (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME))) {
2749 struct timespec tv[2];
2751 tv[0].tv_sec = 0;
2752 tv[1].tv_sec = 0;
2753 tv[0].tv_nsec = UTIME_OMIT;
2754 tv[1].tv_nsec = UTIME_OMIT;
2756 if (valid & FUSE_SET_ATTR_ATIME_NOW)
2757 tv[0].tv_nsec = UTIME_NOW;
2758 else if (valid & FUSE_SET_ATTR_ATIME)
2759 tv[0] = attr->st_atim;
2761 if (valid & FUSE_SET_ATTR_MTIME_NOW)
2762 tv[1].tv_nsec = UTIME_NOW;
2763 else if (valid & FUSE_SET_ATTR_MTIME)
2764 tv[1] = attr->st_mtim;
2766 err = fuse_fs_utimens(f->fs, path, tv);
2767 } else
2768 #endif
2769 if (!err &&
2770 (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) ==
2771 (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) {
2772 struct timespec tv[2];
2773 tv[0].tv_sec = attr->st_atime;
2774 tv[0].tv_nsec = ST_ATIM_NSEC(attr);
2775 tv[1].tv_sec = attr->st_mtime;
2776 tv[1].tv_nsec = ST_MTIM_NSEC(attr);
2777 err = fuse_fs_utimens(f->fs, path, tv);
2779 if (!err) {
2780 if (fi)
2781 err = fuse_fs_fgetattr(f->fs, path, &buf, fi);
2782 else
2783 err = fuse_fs_getattr(f->fs, path, &buf);
2785 fuse_finish_interrupt(f, req, &d);
2786 free_path(f, ino, path);
2788 if (!err) {
2789 if (f->conf.auto_cache) {
2790 pthread_mutex_lock(&f->lock);
2791 update_stat(get_node(f, ino), &buf);
2792 pthread_mutex_unlock(&f->lock);
2794 set_stat(f, ino, &buf);
2795 fuse_reply_attr(req, &buf, f->conf.attr_timeout);
2796 } else
2797 reply_err(req, err);
2800 static void fuse_lib_access(fuse_req_t req, fuse_ino_t ino, int mask)
2802 struct fuse *f = req_fuse_prepare(req);
2803 char *path;
2804 int err;
2806 err = get_path(f, ino, &path);
2807 if (!err) {
2808 struct fuse_intr_data d;
2810 fuse_prepare_interrupt(f, req, &d);
2811 err = fuse_fs_access(f->fs, path, mask);
2812 fuse_finish_interrupt(f, req, &d);
2813 free_path(f, ino, path);
2815 reply_err(req, err);
2818 static void fuse_lib_readlink(fuse_req_t req, fuse_ino_t ino)
2820 struct fuse *f = req_fuse_prepare(req);
2821 char linkname[PATH_MAX + 1];
2822 char *path;
2823 int err;
2825 err = get_path(f, ino, &path);
2826 if (!err) {
2827 struct fuse_intr_data d;
2828 fuse_prepare_interrupt(f, req, &d);
2829 err = fuse_fs_readlink(f->fs, path, linkname, sizeof(linkname));
2830 fuse_finish_interrupt(f, req, &d);
2831 free_path(f, ino, path);
2833 if (!err) {
2834 linkname[PATH_MAX] = '\0';
2835 fuse_reply_readlink(req, linkname);
2836 } else
2837 reply_err(req, err);
2840 static void fuse_lib_mknod(fuse_req_t req, fuse_ino_t parent, const char *name,
2841 mode_t mode, dev_t rdev)
2843 struct fuse *f = req_fuse_prepare(req);
2844 struct fuse_entry_param e;
2845 char *path;
2846 int err;
2848 err = get_path_name(f, parent, name, &path);
2849 if (!err) {
2850 struct fuse_intr_data d;
2852 fuse_prepare_interrupt(f, req, &d);
2853 err = -ENOSYS;
2854 if (S_ISREG(mode)) {
2855 struct fuse_file_info fi;
2857 memset(&fi, 0, sizeof(fi));
2858 fi.flags = O_CREAT | O_EXCL | O_WRONLY;
2859 err = fuse_fs_create(f->fs, path, mode, &fi);
2860 if (!err) {
2861 err = lookup_path(f, parent, name, path, &e,
2862 &fi);
2863 fuse_fs_release(f->fs, path, &fi);
2866 if (err == -ENOSYS) {
2867 err = fuse_fs_mknod(f->fs, path, mode, rdev);
2868 if (!err)
2869 err = lookup_path(f, parent, name, path, &e,
2870 NULL);
2872 fuse_finish_interrupt(f, req, &d);
2873 free_path(f, parent, path);
2875 reply_entry(req, &e, err);
2878 static void fuse_lib_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name,
2879 mode_t mode)
2881 struct fuse *f = req_fuse_prepare(req);
2882 struct fuse_entry_param e;
2883 char *path;
2884 int err;
2886 err = get_path_name(f, parent, name, &path);
2887 if (!err) {
2888 struct fuse_intr_data d;
2890 fuse_prepare_interrupt(f, req, &d);
2891 err = fuse_fs_mkdir(f->fs, path, mode);
2892 if (!err)
2893 err = lookup_path(f, parent, name, path, &e, NULL);
2894 fuse_finish_interrupt(f, req, &d);
2895 free_path(f, parent, path);
2897 reply_entry(req, &e, err);
2900 static void fuse_lib_unlink(fuse_req_t req, fuse_ino_t parent,
2901 const char *name)
2903 struct fuse *f = req_fuse_prepare(req);
2904 struct node *wnode;
2905 char *path;
2906 int err;
2908 err = get_path_wrlock(f, parent, name, &path, &wnode);
2909 if (!err) {
2910 struct fuse_intr_data d;
2912 fuse_prepare_interrupt(f, req, &d);
2913 if (!f->conf.hard_remove && is_open(f, parent, name)) {
2914 err = hide_node(f, path, parent, name);
2915 } else {
2916 err = fuse_fs_unlink(f->fs, path);
2917 if (!err)
2918 remove_node(f, parent, name);
2920 fuse_finish_interrupt(f, req, &d);
2921 free_path_wrlock(f, parent, wnode, path);
2923 reply_err(req, err);
2926 static void fuse_lib_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name)
2928 struct fuse *f = req_fuse_prepare(req);
2929 struct node *wnode;
2930 char *path;
2931 int err;
2933 err = get_path_wrlock(f, parent, name, &path, &wnode);
2934 if (!err) {
2935 struct fuse_intr_data d;
2937 fuse_prepare_interrupt(f, req, &d);
2938 err = fuse_fs_rmdir(f->fs, path);
2939 fuse_finish_interrupt(f, req, &d);
2940 if (!err)
2941 remove_node(f, parent, name);
2942 free_path_wrlock(f, parent, wnode, path);
2944 reply_err(req, err);
2947 static void fuse_lib_symlink(fuse_req_t req, const char *linkname,
2948 fuse_ino_t parent, const char *name)
2950 struct fuse *f = req_fuse_prepare(req);
2951 struct fuse_entry_param e;
2952 char *path;
2953 int err;
2955 err = get_path_name(f, parent, name, &path);
2956 if (!err) {
2957 struct fuse_intr_data d;
2959 fuse_prepare_interrupt(f, req, &d);
2960 err = fuse_fs_symlink(f->fs, linkname, path);
2961 if (!err)
2962 err = lookup_path(f, parent, name, path, &e, NULL);
2963 fuse_finish_interrupt(f, req, &d);
2964 free_path(f, parent, path);
2966 reply_entry(req, &e, err);
2969 static void fuse_lib_rename(fuse_req_t req, fuse_ino_t olddir,
2970 const char *oldname, fuse_ino_t newdir,
2971 const char *newname)
2973 struct fuse *f = req_fuse_prepare(req);
2974 char *oldpath;
2975 char *newpath;
2976 struct node *wnode1;
2977 struct node *wnode2;
2978 int err;
2980 err = get_path2(f, olddir, oldname, newdir, newname,
2981 &oldpath, &newpath, &wnode1, &wnode2);
2982 if (!err) {
2983 struct fuse_intr_data d;
2984 err = 0;
2985 fuse_prepare_interrupt(f, req, &d);
2986 if (!f->conf.hard_remove && is_open(f, newdir, newname))
2987 err = hide_node(f, newpath, newdir, newname);
2988 if (!err) {
2989 err = fuse_fs_rename(f->fs, oldpath, newpath);
2990 if (!err)
2991 err = rename_node(f, olddir, oldname, newdir,
2992 newname, 0);
2994 fuse_finish_interrupt(f, req, &d);
2995 free_path2(f, olddir, newdir, wnode1, wnode2, oldpath, newpath);
2997 reply_err(req, err);
3000 static void fuse_lib_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent,
3001 const char *newname)
3003 struct fuse *f = req_fuse_prepare(req);
3004 struct fuse_entry_param e;
3005 char *oldpath;
3006 char *newpath;
3007 int err;
3009 err = get_path2(f, ino, NULL, newparent, newname,
3010 &oldpath, &newpath, NULL, NULL);
3011 if (!err) {
3012 struct fuse_intr_data d;
3014 fuse_prepare_interrupt(f, req, &d);
3015 err = fuse_fs_link(f->fs, oldpath, newpath);
3016 if (!err)
3017 err = lookup_path(f, newparent, newname, newpath,
3018 &e, NULL);
3019 fuse_finish_interrupt(f, req, &d);
3020 free_path2(f, ino, newparent, NULL, NULL, oldpath, newpath);
3022 reply_entry(req, &e, err);
3025 static void fuse_do_release(struct fuse *f, fuse_ino_t ino, const char *path,
3026 struct fuse_file_info *fi)
3028 struct node *node;
3029 int unlink_hidden = 0;
3030 const char *compatpath;
3032 if (path != NULL || f->nullpath_ok || f->conf.nopath)
3033 compatpath = path;
3034 else
3035 compatpath = "-";
3037 fuse_fs_release(f->fs, compatpath, fi);
3039 pthread_mutex_lock(&f->lock);
3040 node = get_node(f, ino);
3041 assert(node->open_count > 0);
3042 --node->open_count;
3043 if (node->is_hidden && !node->open_count) {
3044 unlink_hidden = 1;
3045 node->is_hidden = 0;
3047 pthread_mutex_unlock(&f->lock);
3049 if(unlink_hidden) {
3050 if (path) {
3051 fuse_fs_unlink(f->fs, path);
3052 } else if (f->conf.nopath) {
3053 char *unlinkpath;
3055 if (get_path(f, ino, &unlinkpath) == 0)
3056 fuse_fs_unlink(f->fs, unlinkpath);
3058 free_path(f, ino, unlinkpath);
3063 static void fuse_lib_create(fuse_req_t req, fuse_ino_t parent,
3064 const char *name, mode_t mode,
3065 struct fuse_file_info *fi)
3067 struct fuse *f = req_fuse_prepare(req);
3068 struct fuse_intr_data d;
3069 struct fuse_entry_param e;
3070 char *path;
3071 int err;
3073 err = get_path_name(f, parent, name, &path);
3074 if (!err) {
3075 fuse_prepare_interrupt(f, req, &d);
3076 err = fuse_fs_create(f->fs, path, mode, fi);
3077 if (!err) {
3078 err = lookup_path(f, parent, name, path, &e, fi);
3079 if (err)
3080 fuse_fs_release(f->fs, path, fi);
3081 else if (!S_ISREG(e.attr.st_mode)) {
3082 err = -EIO;
3083 fuse_fs_release(f->fs, path, fi);
3084 forget_node(f, e.ino, 1);
3085 } else {
3086 if (f->conf.direct_io)
3087 fi->direct_io = 1;
3088 if (f->conf.kernel_cache)
3089 fi->keep_cache = 1;
3093 fuse_finish_interrupt(f, req, &d);
3095 if (!err) {
3096 pthread_mutex_lock(&f->lock);
3097 get_node(f, e.ino)->open_count++;
3098 pthread_mutex_unlock(&f->lock);
3099 if (fuse_reply_create(req, &e, fi) == -ENOENT) {
3100 /* The open syscall was interrupted, so it
3101 must be cancelled */
3102 fuse_do_release(f, e.ino, path, fi);
3103 forget_node(f, e.ino, 1);
3105 } else {
3106 reply_err(req, err);
3109 free_path(f, parent, path);
3112 static double diff_timespec(const struct timespec *t1,
3113 const struct timespec *t2)
3115 return (t1->tv_sec - t2->tv_sec) +
3116 ((double) t1->tv_nsec - (double) t2->tv_nsec) / 1000000000.0;
3119 static void open_auto_cache(struct fuse *f, fuse_ino_t ino, const char *path,
3120 struct fuse_file_info *fi)
3122 struct node *node;
3124 pthread_mutex_lock(&f->lock);
3125 node = get_node(f, ino);
3126 if (node->cache_valid) {
3127 struct timespec now;
3129 curr_time(&now);
3130 if (diff_timespec(&now, &node->stat_updated) >
3131 f->conf.ac_attr_timeout) {
3132 struct stat stbuf;
3133 int err;
3134 pthread_mutex_unlock(&f->lock);
3135 err = fuse_fs_fgetattr(f->fs, path, &stbuf, fi);
3136 pthread_mutex_lock(&f->lock);
3137 if (!err)
3138 update_stat(node, &stbuf);
3139 else
3140 node->cache_valid = 0;
3143 if (node->cache_valid)
3144 fi->keep_cache = 1;
3146 node->cache_valid = 1;
3147 pthread_mutex_unlock(&f->lock);
3150 static void fuse_lib_open(fuse_req_t req, fuse_ino_t ino,
3151 struct fuse_file_info *fi)
3153 struct fuse *f = req_fuse_prepare(req);
3154 struct fuse_intr_data d;
3155 char *path;
3156 int err;
3158 err = get_path(f, ino, &path);
3159 if (!err) {
3160 fuse_prepare_interrupt(f, req, &d);
3161 err = fuse_fs_open(f->fs, path, fi);
3162 if (!err) {
3163 if (f->conf.direct_io)
3164 fi->direct_io = 1;
3165 if (f->conf.kernel_cache)
3166 fi->keep_cache = 1;
3168 if (f->conf.auto_cache)
3169 open_auto_cache(f, ino, path, fi);
3171 fuse_finish_interrupt(f, req, &d);
3173 if (!err) {
3174 pthread_mutex_lock(&f->lock);
3175 get_node(f, ino)->open_count++;
3176 pthread_mutex_unlock(&f->lock);
3177 if (fuse_reply_open(req, fi) == -ENOENT) {
3178 /* The open syscall was interrupted, so it
3179 must be cancelled */
3180 fuse_do_release(f, ino, path, fi);
3182 } else
3183 reply_err(req, err);
3185 free_path(f, ino, path);
3188 static void fuse_lib_read(fuse_req_t req, fuse_ino_t ino, size_t size,
3189 off_t off, struct fuse_file_info *fi)
3191 struct fuse *f = req_fuse_prepare(req);
3192 struct fuse_bufvec *buf = NULL;
3193 char *path;
3194 int res;
3196 res = get_path_nullok(f, ino, &path);
3197 if (res == 0) {
3198 struct fuse_intr_data d;
3200 fuse_prepare_interrupt(f, req, &d);
3201 res = fuse_fs_read_buf(f->fs, path, &buf, size, off, fi);
3202 fuse_finish_interrupt(f, req, &d);
3203 free_path(f, ino, path);
3206 if (res == 0)
3207 fuse_reply_data(req, buf, FUSE_BUF_SPLICE_MOVE);
3208 else
3209 reply_err(req, res);
3211 fuse_free_buf(buf);
3214 static void fuse_lib_write_buf(fuse_req_t req, fuse_ino_t ino,
3215 struct fuse_bufvec *buf, off_t off,
3216 struct fuse_file_info *fi)
3218 struct fuse *f = req_fuse_prepare(req);
3219 char *path;
3220 int res;
3222 res = get_path_nullok(f, ino, &path);
3223 if (res == 0) {
3224 struct fuse_intr_data d;
3226 fuse_prepare_interrupt(f, req, &d);
3227 res = fuse_fs_write_buf(f->fs, path, buf, off, fi);
3228 fuse_finish_interrupt(f, req, &d);
3229 free_path(f, ino, path);
3232 if (res >= 0)
3233 fuse_reply_write(req, res);
3234 else
3235 reply_err(req, res);
3238 static void fuse_lib_fsync(fuse_req_t req, fuse_ino_t ino, int datasync,
3239 struct fuse_file_info *fi)
3241 struct fuse *f = req_fuse_prepare(req);
3242 char *path;
3243 int err;
3245 err = get_path_nullok(f, ino, &path);
3246 if (!err) {
3247 struct fuse_intr_data d;
3249 fuse_prepare_interrupt(f, req, &d);
3250 err = fuse_fs_fsync(f->fs, path, datasync, fi);
3251 fuse_finish_interrupt(f, req, &d);
3252 free_path(f, ino, path);
3254 reply_err(req, err);
3257 static struct fuse_dh *get_dirhandle(const struct fuse_file_info *llfi,
3258 struct fuse_file_info *fi)
3260 struct fuse_dh *dh = (struct fuse_dh *) (uintptr_t) llfi->fh;
3261 memset(fi, 0, sizeof(struct fuse_file_info));
3262 fi->fh = dh->fh;
3263 fi->fh_old = dh->fh;
3264 return dh;
3267 static void fuse_lib_opendir(fuse_req_t req, fuse_ino_t ino,
3268 struct fuse_file_info *llfi)
3270 struct fuse *f = req_fuse_prepare(req);
3271 struct fuse_intr_data d;
3272 struct fuse_dh *dh;
3273 struct fuse_file_info fi;
3274 char *path;
3275 int err;
3277 dh = (struct fuse_dh *) malloc(sizeof(struct fuse_dh));
3278 if (dh == NULL) {
3279 reply_err(req, -ENOMEM);
3280 return;
3282 memset(dh, 0, sizeof(struct fuse_dh));
3283 dh->fuse = f;
3284 dh->contents = NULL;
3285 dh->len = 0;
3286 dh->filled = 0;
3287 dh->nodeid = ino;
3288 fuse_mutex_init(&dh->lock);
3290 llfi->fh = (uintptr_t) dh;
3292 memset(&fi, 0, sizeof(fi));
3293 fi.flags = llfi->flags;
3295 err = get_path(f, ino, &path);
3296 if (!err) {
3297 fuse_prepare_interrupt(f, req, &d);
3298 err = fuse_fs_opendir(f->fs, path, &fi);
3299 fuse_finish_interrupt(f, req, &d);
3300 dh->fh = fi.fh;
3302 if (!err) {
3303 if (fuse_reply_open(req, llfi) == -ENOENT) {
3304 /* The opendir syscall was interrupted, so it
3305 must be cancelled */
3306 fuse_fs_releasedir(f->fs, path, &fi);
3307 pthread_mutex_destroy(&dh->lock);
3308 free(dh);
3310 } else {
3311 reply_err(req, err);
3312 pthread_mutex_destroy(&dh->lock);
3313 free(dh);
3315 free_path(f, ino, path);
3318 static int extend_contents(struct fuse_dh *dh, unsigned minsize)
3320 if (minsize > dh->size) {
3321 char *newptr;
3322 unsigned newsize = dh->size;
3323 if (!newsize)
3324 newsize = 1024;
3325 while (newsize < minsize) {
3326 if (newsize >= 0x80000000)
3327 newsize = 0xffffffff;
3328 else
3329 newsize *= 2;
3332 newptr = (char *) realloc(dh->contents, newsize);
3333 if (!newptr) {
3334 dh->error = -ENOMEM;
3335 return -1;
3337 dh->contents = newptr;
3338 dh->size = newsize;
3340 return 0;
3343 static int fill_dir(void *dh_, const char *name, const struct stat *statp,
3344 off_t off)
3346 struct fuse_dh *dh = (struct fuse_dh *) dh_;
3347 struct stat stbuf;
3348 size_t newlen;
3350 if (statp)
3351 stbuf = *statp;
3352 else {
3353 memset(&stbuf, 0, sizeof(stbuf));
3354 stbuf.st_ino = FUSE_UNKNOWN_INO;
3357 if (!dh->fuse->conf.use_ino) {
3358 stbuf.st_ino = FUSE_UNKNOWN_INO;
3359 if (dh->fuse->conf.readdir_ino) {
3360 struct node *node;
3361 pthread_mutex_lock(&dh->fuse->lock);
3362 node = lookup_node(dh->fuse, dh->nodeid, name);
3363 if (node)
3364 stbuf.st_ino = (ino_t) node->nodeid;
3365 pthread_mutex_unlock(&dh->fuse->lock);
3369 if (off) {
3370 if (extend_contents(dh, dh->needlen) == -1)
3371 return 1;
3373 dh->filled = 0;
3374 newlen = dh->len +
3375 fuse_add_direntry(dh->req, dh->contents + dh->len,
3376 dh->needlen - dh->len, name,
3377 &stbuf, off);
3378 if (newlen > dh->needlen)
3379 return 1;
3380 } else {
3381 newlen = dh->len +
3382 fuse_add_direntry(dh->req, NULL, 0, name, NULL, 0);
3383 if (extend_contents(dh, newlen) == -1)
3384 return 1;
3386 fuse_add_direntry(dh->req, dh->contents + dh->len,
3387 dh->size - dh->len, name, &stbuf, newlen);
3389 dh->len = newlen;
3390 return 0;
3393 static int readdir_fill(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
3394 size_t size, off_t off, struct fuse_dh *dh,
3395 struct fuse_file_info *fi)
3397 char *path;
3398 int err;
3400 if (f->fs->op.readdir)
3401 err = get_path_nullok(f, ino, &path);
3402 else
3403 err = get_path(f, ino, &path);
3404 if (!err) {
3405 struct fuse_intr_data d;
3407 dh->len = 0;
3408 dh->error = 0;
3409 dh->needlen = size;
3410 dh->filled = 1;
3411 dh->req = req;
3412 fuse_prepare_interrupt(f, req, &d);
3413 err = fuse_fs_readdir(f->fs, path, dh, fill_dir, off, fi);
3414 fuse_finish_interrupt(f, req, &d);
3415 dh->req = NULL;
3416 if (!err)
3417 err = dh->error;
3418 if (err)
3419 dh->filled = 0;
3420 free_path(f, ino, path);
3422 return err;
3425 static void fuse_lib_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
3426 off_t off, struct fuse_file_info *llfi)
3428 struct fuse *f = req_fuse_prepare(req);
3429 struct fuse_file_info fi;
3430 struct fuse_dh *dh = get_dirhandle(llfi, &fi);
3432 pthread_mutex_lock(&dh->lock);
3433 /* According to SUS, directory contents need to be refreshed on
3434 rewinddir() */
3435 if (!off)
3436 dh->filled = 0;
3438 if (!dh->filled) {
3439 int err = readdir_fill(f, req, ino, size, off, dh, &fi);
3440 if (err) {
3441 reply_err(req, err);
3442 goto out;
3445 if (dh->filled) {
3446 if (off < dh->len) {
3447 if (off + size > dh->len)
3448 size = dh->len - off;
3449 } else
3450 size = 0;
3451 } else {
3452 size = dh->len;
3453 off = 0;
3455 fuse_reply_buf(req, dh->contents + off, size);
3456 out:
3457 pthread_mutex_unlock(&dh->lock);
3460 static void fuse_lib_releasedir(fuse_req_t req, fuse_ino_t ino,
3461 struct fuse_file_info *llfi)
3463 struct fuse *f = req_fuse_prepare(req);
3464 struct fuse_intr_data d;
3465 struct fuse_file_info fi;
3466 struct fuse_dh *dh = get_dirhandle(llfi, &fi);
3467 char *path;
3468 const char *compatpath;
3470 get_path_nullok(f, ino, &path);
3471 if (path != NULL || f->nullpath_ok || f->conf.nopath)
3472 compatpath = path;
3473 else
3474 compatpath = "-";
3476 fuse_prepare_interrupt(f, req, &d);
3477 fuse_fs_releasedir(f->fs, compatpath, &fi);
3478 fuse_finish_interrupt(f, req, &d);
3479 free_path(f, ino, path);
3481 pthread_mutex_lock(&dh->lock);
3482 pthread_mutex_unlock(&dh->lock);
3483 pthread_mutex_destroy(&dh->lock);
3484 free(dh->contents);
3485 free(dh);
3486 reply_err(req, 0);
3489 static void fuse_lib_fsyncdir(fuse_req_t req, fuse_ino_t ino, int datasync,
3490 struct fuse_file_info *llfi)
3492 struct fuse *f = req_fuse_prepare(req);
3493 struct fuse_file_info fi;
3494 char *path;
3495 int err;
3497 get_dirhandle(llfi, &fi);
3499 err = get_path_nullok(f, ino, &path);
3500 if (!err) {
3501 struct fuse_intr_data d;
3502 fuse_prepare_interrupt(f, req, &d);
3503 err = fuse_fs_fsyncdir(f->fs, path, datasync, &fi);
3504 fuse_finish_interrupt(f, req, &d);
3505 free_path(f, ino, path);
3507 reply_err(req, err);
3510 static void fuse_lib_statfs(fuse_req_t req, fuse_ino_t ino)
3512 struct fuse *f = req_fuse_prepare(req);
3513 struct statvfs buf;
3514 char *path = NULL;
3515 int err = 0;
3517 memset(&buf, 0, sizeof(buf));
3518 if (ino)
3519 err = get_path(f, ino, &path);
3521 if (!err) {
3522 struct fuse_intr_data d;
3523 fuse_prepare_interrupt(f, req, &d);
3524 err = fuse_fs_statfs(f->fs, path ? path : "/", &buf);
3525 fuse_finish_interrupt(f, req, &d);
3526 free_path(f, ino, path);
3529 if (!err)
3530 fuse_reply_statfs(req, &buf);
3531 else
3532 reply_err(req, err);
3535 static void fuse_lib_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
3536 const char *value, size_t size, int flags)
3538 struct fuse *f = req_fuse_prepare(req);
3539 char *path;
3540 int err;
3542 err = get_path(f, ino, &path);
3543 if (!err) {
3544 struct fuse_intr_data d;
3545 fuse_prepare_interrupt(f, req, &d);
3546 err = fuse_fs_setxattr(f->fs, path, name, value, size, flags);
3547 fuse_finish_interrupt(f, req, &d);
3548 free_path(f, ino, path);
3550 reply_err(req, err);
3553 static int common_getxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
3554 const char *name, char *value, size_t size)
3556 int err;
3557 char *path;
3559 err = get_path(f, ino, &path);
3560 if (!err) {
3561 struct fuse_intr_data d;
3562 fuse_prepare_interrupt(f, req, &d);
3563 err = fuse_fs_getxattr(f->fs, path, name, value, size);
3564 fuse_finish_interrupt(f, req, &d);
3565 free_path(f, ino, path);
3567 return err;
3570 static void fuse_lib_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
3571 size_t size)
3573 struct fuse *f = req_fuse_prepare(req);
3574 int res;
3576 if (size) {
3577 char *value = (char *) malloc(size);
3578 if (value == NULL) {
3579 reply_err(req, -ENOMEM);
3580 return;
3582 res = common_getxattr(f, req, ino, name, value, size);
3583 if (res > 0)
3584 fuse_reply_buf(req, value, res);
3585 else
3586 reply_err(req, res);
3587 free(value);
3588 } else {
3589 res = common_getxattr(f, req, ino, name, NULL, 0);
3590 if (res >= 0)
3591 fuse_reply_xattr(req, res);
3592 else
3593 reply_err(req, res);
3597 static int common_listxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
3598 char *list, size_t size)
3600 char *path;
3601 int err;
3603 err = get_path(f, ino, &path);
3604 if (!err) {
3605 struct fuse_intr_data d;
3606 fuse_prepare_interrupt(f, req, &d);
3607 err = fuse_fs_listxattr(f->fs, path, list, size);
3608 fuse_finish_interrupt(f, req, &d);
3609 free_path(f, ino, path);
3611 return err;
3614 static void fuse_lib_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
3616 struct fuse *f = req_fuse_prepare(req);
3617 int res;
3619 if (size) {
3620 char *list = (char *) malloc(size);
3621 if (list == NULL) {
3622 reply_err(req, -ENOMEM);
3623 return;
3625 res = common_listxattr(f, req, ino, list, size);
3626 if (res > 0)
3627 fuse_reply_buf(req, list, res);
3628 else
3629 reply_err(req, res);
3630 free(list);
3631 } else {
3632 res = common_listxattr(f, req, ino, NULL, 0);
3633 if (res >= 0)
3634 fuse_reply_xattr(req, res);
3635 else
3636 reply_err(req, res);
3640 static void fuse_lib_removexattr(fuse_req_t req, fuse_ino_t ino,
3641 const char *name)
3643 struct fuse *f = req_fuse_prepare(req);
3644 char *path;
3645 int err;
3647 err = get_path(f, ino, &path);
3648 if (!err) {
3649 struct fuse_intr_data d;
3650 fuse_prepare_interrupt(f, req, &d);
3651 err = fuse_fs_removexattr(f->fs, path, name);
3652 fuse_finish_interrupt(f, req, &d);
3653 free_path(f, ino, path);
3655 reply_err(req, err);
3658 static struct lock *locks_conflict(struct node *node, const struct lock *lock)
3660 struct lock *l;
3662 for (l = node->locks; l; l = l->next)
3663 if (l->owner != lock->owner &&
3664 lock->start <= l->end && l->start <= lock->end &&
3665 (l->type == F_WRLCK || lock->type == F_WRLCK))
3666 break;
3668 return l;
3671 static void delete_lock(struct lock **lockp)
3673 struct lock *l = *lockp;
3674 *lockp = l->next;
3675 free(l);
3678 static void insert_lock(struct lock **pos, struct lock *lock)
3680 lock->next = *pos;
3681 *pos = lock;
3684 static int locks_insert(struct node *node, struct lock *lock)
3686 struct lock **lp;
3687 struct lock *newl1 = NULL;
3688 struct lock *newl2 = NULL;
3690 if (lock->type != F_UNLCK || lock->start != 0 ||
3691 lock->end != OFFSET_MAX) {
3692 newl1 = malloc(sizeof(struct lock));
3693 newl2 = malloc(sizeof(struct lock));
3695 if (!newl1 || !newl2) {
3696 free(newl1);
3697 free(newl2);
3698 return -ENOLCK;
3702 for (lp = &node->locks; *lp;) {
3703 struct lock *l = *lp;
3704 if (l->owner != lock->owner)
3705 goto skip;
3707 if (lock->type == l->type) {
3708 if (l->end < lock->start - 1)
3709 goto skip;
3710 if (lock->end < l->start - 1)
3711 break;
3712 if (l->start <= lock->start && lock->end <= l->end)
3713 goto out;
3714 if (l->start < lock->start)
3715 lock->start = l->start;
3716 if (lock->end < l->end)
3717 lock->end = l->end;
3718 goto delete;
3719 } else {
3720 if (l->end < lock->start)
3721 goto skip;
3722 if (lock->end < l->start)
3723 break;
3724 if (lock->start <= l->start && l->end <= lock->end)
3725 goto delete;
3726 if (l->end <= lock->end) {
3727 l->end = lock->start - 1;
3728 goto skip;
3730 if (lock->start <= l->start) {
3731 l->start = lock->end + 1;
3732 break;
3734 *newl2 = *l;
3735 newl2->start = lock->end + 1;
3736 l->end = lock->start - 1;
3737 insert_lock(&l->next, newl2);
3738 newl2 = NULL;
3740 skip:
3741 lp = &l->next;
3742 continue;
3744 delete:
3745 delete_lock(lp);
3747 if (lock->type != F_UNLCK) {
3748 *newl1 = *lock;
3749 insert_lock(lp, newl1);
3750 newl1 = NULL;
3752 out:
3753 free(newl1);
3754 free(newl2);
3755 return 0;
3758 static void flock_to_lock(struct flock *flock, struct lock *lock)
3760 memset(lock, 0, sizeof(struct lock));
3761 lock->type = flock->l_type;
3762 lock->start = flock->l_start;
3763 lock->end =
3764 flock->l_len ? flock->l_start + flock->l_len - 1 : OFFSET_MAX;
3765 lock->pid = flock->l_pid;
3768 static void lock_to_flock(struct lock *lock, struct flock *flock)
3770 flock->l_type = lock->type;
3771 flock->l_start = lock->start;
3772 flock->l_len =
3773 (lock->end == OFFSET_MAX) ? 0 : lock->end - lock->start + 1;
3774 flock->l_pid = lock->pid;
3777 static int fuse_flush_common(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
3778 const char *path, struct fuse_file_info *fi)
3780 struct fuse_intr_data d;
3781 struct flock lock;
3782 struct lock l;
3783 int err;
3784 int errlock;
3786 fuse_prepare_interrupt(f, req, &d);
3787 memset(&lock, 0, sizeof(lock));
3788 lock.l_type = F_UNLCK;
3789 lock.l_whence = SEEK_SET;
3790 err = fuse_fs_flush(f->fs, path, fi);
3791 errlock = fuse_fs_lock(f->fs, path, fi, F_SETLK, &lock);
3792 fuse_finish_interrupt(f, req, &d);
3794 if (errlock != -ENOSYS) {
3795 flock_to_lock(&lock, &l);
3796 l.owner = fi->lock_owner;
3797 pthread_mutex_lock(&f->lock);
3798 locks_insert(get_node(f, ino), &l);
3799 pthread_mutex_unlock(&f->lock);
3801 /* if op.lock() is defined FLUSH is needed regardless
3802 of op.flush() */
3803 if (err == -ENOSYS)
3804 err = 0;
3806 return err;
3809 static void fuse_lib_release(fuse_req_t req, fuse_ino_t ino,
3810 struct fuse_file_info *fi)
3812 struct fuse *f = req_fuse_prepare(req);
3813 struct fuse_intr_data d;
3814 char *path;
3815 int err = 0;
3817 get_path_nullok(f, ino, &path);
3818 if (fi->flush) {
3819 err = fuse_flush_common(f, req, ino, path, fi);
3820 if (err == -ENOSYS)
3821 err = 0;
3824 fuse_prepare_interrupt(f, req, &d);
3825 fuse_do_release(f, ino, path, fi);
3826 fuse_finish_interrupt(f, req, &d);
3827 free_path(f, ino, path);
3829 reply_err(req, err);
3832 static void fuse_lib_flush(fuse_req_t req, fuse_ino_t ino,
3833 struct fuse_file_info *fi)
3835 struct fuse *f = req_fuse_prepare(req);
3836 char *path;
3837 int err;
3839 get_path_nullok(f, ino, &path);
3840 err = fuse_flush_common(f, req, ino, path, fi);
3841 free_path(f, ino, path);
3843 reply_err(req, err);
3846 static int fuse_lock_common(fuse_req_t req, fuse_ino_t ino,
3847 struct fuse_file_info *fi, struct flock *lock,
3848 int cmd)
3850 struct fuse *f = req_fuse_prepare(req);
3851 char *path;
3852 int err;
3854 err = get_path_nullok(f, ino, &path);
3855 if (!err) {
3856 struct fuse_intr_data d;
3857 fuse_prepare_interrupt(f, req, &d);
3858 err = fuse_fs_lock(f->fs, path, fi, cmd, lock);
3859 fuse_finish_interrupt(f, req, &d);
3860 free_path(f, ino, path);
3862 return err;
3865 static void fuse_lib_getlk(fuse_req_t req, fuse_ino_t ino,
3866 struct fuse_file_info *fi, struct flock *lock)
3868 int err;
3869 struct lock l;
3870 struct lock *conflict;
3871 struct fuse *f = req_fuse(req);
3873 flock_to_lock(lock, &l);
3874 l.owner = fi->lock_owner;
3875 pthread_mutex_lock(&f->lock);
3876 conflict = locks_conflict(get_node(f, ino), &l);
3877 if (conflict)
3878 lock_to_flock(conflict, lock);
3879 pthread_mutex_unlock(&f->lock);
3880 if (!conflict)
3881 err = fuse_lock_common(req, ino, fi, lock, F_GETLK);
3882 else
3883 err = 0;
3885 if (!err)
3886 fuse_reply_lock(req, lock);
3887 else
3888 reply_err(req, err);
3891 static void fuse_lib_setlk(fuse_req_t req, fuse_ino_t ino,
3892 struct fuse_file_info *fi, struct flock *lock,
3893 int sleep)
3895 int err = fuse_lock_common(req, ino, fi, lock,
3896 sleep ? F_SETLKW : F_SETLK);
3897 if (!err) {
3898 struct fuse *f = req_fuse(req);
3899 struct lock l;
3900 flock_to_lock(lock, &l);
3901 l.owner = fi->lock_owner;
3902 pthread_mutex_lock(&f->lock);
3903 locks_insert(get_node(f, ino), &l);
3904 pthread_mutex_unlock(&f->lock);
3906 reply_err(req, err);
3909 static void fuse_lib_flock(fuse_req_t req, fuse_ino_t ino,
3910 struct fuse_file_info *fi, int op)
3912 struct fuse *f = req_fuse_prepare(req);
3913 char *path;
3914 int err;
3916 err = get_path_nullok(f, ino, &path);
3917 if (err == 0) {
3918 struct fuse_intr_data d;
3919 fuse_prepare_interrupt(f, req, &d);
3920 err = fuse_fs_flock(f->fs, path, fi, op);
3921 fuse_finish_interrupt(f, req, &d);
3922 free_path(f, ino, path);
3924 reply_err(req, err);
3927 static void fuse_lib_bmap(fuse_req_t req, fuse_ino_t ino, size_t blocksize,
3928 uint64_t idx)
3930 struct fuse *f = req_fuse_prepare(req);
3931 struct fuse_intr_data d;
3932 char *path;
3933 int err;
3935 err = get_path(f, ino, &path);
3936 if (!err) {
3937 fuse_prepare_interrupt(f, req, &d);
3938 err = fuse_fs_bmap(f->fs, path, blocksize, &idx);
3939 fuse_finish_interrupt(f, req, &d);
3940 free_path(f, ino, path);
3942 if (!err)
3943 fuse_reply_bmap(req, idx);
3944 else
3945 reply_err(req, err);
3948 static void fuse_lib_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg,
3949 struct fuse_file_info *fi, unsigned int flags,
3950 const void *in_buf, size_t in_bufsz,
3951 size_t out_bufsz)
3953 struct fuse *f = req_fuse_prepare(req);
3954 struct fuse_intr_data d;
3955 char *path, *out_buf = NULL;
3956 int err;
3958 err = -EPERM;
3959 if (flags & FUSE_IOCTL_UNRESTRICTED)
3960 goto err;
3962 if (out_bufsz) {
3963 err = -ENOMEM;
3964 out_buf = malloc(out_bufsz);
3965 if (!out_buf)
3966 goto err;
3969 assert(!in_bufsz || !out_bufsz || in_bufsz == out_bufsz);
3970 if (out_buf)
3971 memcpy(out_buf, in_buf, in_bufsz);
3973 err = get_path_nullok(f, ino, &path);
3974 if (err)
3975 goto err;
3977 fuse_prepare_interrupt(f, req, &d);
3979 err = fuse_fs_ioctl(f->fs, path, cmd, arg, fi, flags,
3980 out_buf ?: (void *)in_buf);
3982 fuse_finish_interrupt(f, req, &d);
3983 free_path(f, ino, path);
3985 fuse_reply_ioctl(req, err, out_buf, out_bufsz);
3986 goto out;
3987 err:
3988 reply_err(req, err);
3989 out:
3990 free(out_buf);
3993 static void fuse_lib_poll(fuse_req_t req, fuse_ino_t ino,
3994 struct fuse_file_info *fi, struct fuse_pollhandle *ph)
3996 struct fuse *f = req_fuse_prepare(req);
3997 struct fuse_intr_data d;
3998 char *path;
3999 int err;
4000 unsigned revents = 0;
4002 err = get_path_nullok(f, ino, &path);
4003 if (!err) {
4004 fuse_prepare_interrupt(f, req, &d);
4005 err = fuse_fs_poll(f->fs, path, fi, ph, &revents);
4006 fuse_finish_interrupt(f, req, &d);
4007 free_path(f, ino, path);
4009 if (!err)
4010 fuse_reply_poll(req, revents);
4011 else
4012 reply_err(req, err);
4015 static void fuse_lib_fallocate(fuse_req_t req, fuse_ino_t ino, int mode,
4016 off_t offset, off_t length, struct fuse_file_info *fi)
4018 struct fuse *f = req_fuse_prepare(req);
4019 struct fuse_intr_data d;
4020 char *path;
4021 int err;
4023 err = get_path_nullok(f, ino, &path);
4024 if (!err) {
4025 fuse_prepare_interrupt(f, req, &d);
4026 err = fuse_fs_fallocate(f->fs, path, mode, offset, length, fi);
4027 fuse_finish_interrupt(f, req, &d);
4028 free_path(f, ino, path);
4030 reply_err(req, err);
4033 static int clean_delay(struct fuse *f)
4036 * This is calculating the delay between clean runs. To
4037 * reduce the number of cleans we are doing them 10 times
4038 * within the remember window.
4040 int min_sleep = 60;
4041 int max_sleep = 3600;
4042 int sleep_time = f->conf.remember / 10;
4044 if (sleep_time > max_sleep)
4045 return max_sleep;
4046 if (sleep_time < min_sleep)
4047 return min_sleep;
4048 return sleep_time;
4051 int fuse_clean_cache(struct fuse *f)
4053 struct node_lru *lnode;
4054 struct list_head *curr, *next;
4055 struct node *node;
4056 struct timespec now;
4058 pthread_mutex_lock(&f->lock);
4060 curr_time(&now);
4062 for (curr = f->lru_table.next; curr != &f->lru_table; curr = next) {
4063 double age;
4065 next = curr->next;
4066 lnode = list_entry(curr, struct node_lru, lru);
4067 node = &lnode->node;
4069 age = diff_timespec(&now, &lnode->forget_time);
4070 if (age <= f->conf.remember)
4071 break;
4073 assert(node->nlookup == 1);
4075 /* Don't forget active directories */
4076 if (node->refctr > 1)
4077 continue;
4079 node->nlookup = 0;
4080 unhash_name(f, node);
4081 unref_node(f, node);
4083 pthread_mutex_unlock(&f->lock);
4085 return clean_delay(f);
4088 static struct fuse_lowlevel_ops fuse_path_ops = {
4089 .init = fuse_lib_init,
4090 .destroy = fuse_lib_destroy,
4091 .lookup = fuse_lib_lookup,
4092 .forget = fuse_lib_forget,
4093 .forget_multi = fuse_lib_forget_multi,
4094 .getattr = fuse_lib_getattr,
4095 .setattr = fuse_lib_setattr,
4096 .access = fuse_lib_access,
4097 .readlink = fuse_lib_readlink,
4098 .mknod = fuse_lib_mknod,
4099 .mkdir = fuse_lib_mkdir,
4100 .unlink = fuse_lib_unlink,
4101 .rmdir = fuse_lib_rmdir,
4102 .symlink = fuse_lib_symlink,
4103 .rename = fuse_lib_rename,
4104 .link = fuse_lib_link,
4105 .create = fuse_lib_create,
4106 .open = fuse_lib_open,
4107 .read = fuse_lib_read,
4108 .write_buf = fuse_lib_write_buf,
4109 .flush = fuse_lib_flush,
4110 .release = fuse_lib_release,
4111 .fsync = fuse_lib_fsync,
4112 .opendir = fuse_lib_opendir,
4113 .readdir = fuse_lib_readdir,
4114 .releasedir = fuse_lib_releasedir,
4115 .fsyncdir = fuse_lib_fsyncdir,
4116 .statfs = fuse_lib_statfs,
4117 .setxattr = fuse_lib_setxattr,
4118 .getxattr = fuse_lib_getxattr,
4119 .listxattr = fuse_lib_listxattr,
4120 .removexattr = fuse_lib_removexattr,
4121 .getlk = fuse_lib_getlk,
4122 .setlk = fuse_lib_setlk,
4123 .flock = fuse_lib_flock,
4124 .bmap = fuse_lib_bmap,
4125 .ioctl = fuse_lib_ioctl,
4126 .poll = fuse_lib_poll,
4127 .fallocate = fuse_lib_fallocate,
4130 int fuse_notify_poll(struct fuse_pollhandle *ph)
4132 return fuse_lowlevel_notify_poll(ph);
4135 static void free_cmd(struct fuse_cmd *cmd)
4137 free(cmd->buf);
4138 free(cmd);
4141 void fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd)
4143 fuse_session_process(f->se, cmd->buf, cmd->buflen, cmd->ch);
4144 free_cmd(cmd);
4147 int fuse_exited(struct fuse *f)
4149 return fuse_session_exited(f->se);
4152 struct fuse_session *fuse_get_session(struct fuse *f)
4154 return f->se;
4157 static struct fuse_cmd *fuse_alloc_cmd(size_t bufsize)
4159 struct fuse_cmd *cmd = (struct fuse_cmd *) malloc(sizeof(*cmd));
4160 if (cmd == NULL) {
4161 fprintf(stderr, "fuse: failed to allocate cmd\n");
4162 return NULL;
4164 cmd->buf = (char *) malloc(bufsize);
4165 if (cmd->buf == NULL) {
4166 fprintf(stderr, "fuse: failed to allocate read buffer\n");
4167 free(cmd);
4168 return NULL;
4170 return cmd;
4173 struct fuse_cmd *fuse_read_cmd(struct fuse *f)
4175 struct fuse_chan *ch = fuse_session_next_chan(f->se, NULL);
4176 size_t bufsize = fuse_chan_bufsize(ch);
4177 struct fuse_cmd *cmd = fuse_alloc_cmd(bufsize);
4178 if (cmd != NULL) {
4179 int res = fuse_chan_recv(&ch, cmd->buf, bufsize);
4180 if (res <= 0) {
4181 free_cmd(cmd);
4182 if (res < 0 && res != -EINTR && res != -EAGAIN)
4183 fuse_exit(f);
4184 return NULL;
4186 cmd->buflen = res;
4187 cmd->ch = ch;
4189 return cmd;
4192 static int fuse_session_loop_remember(struct fuse *f)
4194 struct fuse_session *se = f->se;
4195 int res = 0;
4196 struct timespec now;
4197 time_t next_clean;
4198 struct fuse_chan *ch = fuse_session_next_chan(se, NULL);
4199 size_t bufsize = fuse_chan_bufsize(ch);
4200 char *buf = (char *) malloc(bufsize);
4201 struct pollfd fds = {
4202 .fd = fuse_chan_fd(ch),
4203 .events = POLLIN
4206 if (!buf) {
4207 fprintf(stderr, "fuse: failed to allocate read buffer\n");
4208 return -1;
4211 curr_time(&now);
4212 next_clean = now.tv_sec;
4213 while (!fuse_session_exited(se)) {
4214 struct fuse_chan *tmpch = ch;
4215 struct fuse_buf fbuf = {
4216 .mem = buf,
4217 .size = bufsize,
4219 unsigned timeout;
4221 curr_time(&now);
4222 if (now.tv_sec < next_clean)
4223 timeout = next_clean - now.tv_sec;
4224 else
4225 timeout = 0;
4227 res = poll(&fds, 1, timeout * 1000);
4228 if (res == -1) {
4229 if (errno == -EINTR)
4230 continue;
4231 else
4232 break;
4233 } else if (res > 0) {
4234 res = fuse_session_receive_buf(se, &fbuf, &tmpch);
4236 if (res == -EINTR)
4237 continue;
4238 if (res <= 0)
4239 break;
4241 fuse_session_process_buf(se, &fbuf, tmpch);
4242 } else {
4243 timeout = fuse_clean_cache(f);
4244 curr_time(&now);
4245 next_clean = now.tv_sec + timeout;
4249 free(buf);
4250 fuse_session_reset(se);
4251 return res < 0 ? -1 : 0;
4254 int fuse_loop(struct fuse *f)
4256 if (!f)
4257 return -1;
4259 if (lru_enabled(f))
4260 return fuse_session_loop_remember(f);
4262 return fuse_session_loop(f->se);
4265 int fuse_invalidate(struct fuse *f, const char *path)
4267 (void) f;
4268 (void) path;
4269 return -EINVAL;
4272 void fuse_exit(struct fuse *f)
4274 fuse_session_exit(f->se);
4277 struct fuse_context *fuse_get_context(void)
4279 return &fuse_get_context_internal()->ctx;
4283 * The size of fuse_context got extended, so need to be careful about
4284 * incompatibility (i.e. a new binary cannot work with an old
4285 * library).
4287 struct fuse_context *fuse_get_context_compat22(void);
4288 struct fuse_context *fuse_get_context_compat22(void)
4290 return &fuse_get_context_internal()->ctx;
4292 FUSE_SYMVER(".symver fuse_get_context_compat22,fuse_get_context@FUSE_2.2");
4294 int fuse_getgroups(int size, gid_t list[])
4296 fuse_req_t req = fuse_get_context_internal()->req;
4297 return fuse_req_getgroups(req, size, list);
4300 int fuse_interrupted(void)
4302 return fuse_req_interrupted(fuse_get_context_internal()->req);
4305 void fuse_set_getcontext_func(struct fuse_context *(*func)(void))
4307 (void) func;
4308 /* no-op */
4311 enum {
4312 KEY_HELP,
4315 #define FUSE_LIB_OPT(t, p, v) { t, offsetof(struct fuse_config, p), v }
4317 static const struct fuse_opt fuse_lib_opts[] = {
4318 FUSE_OPT_KEY("-h", KEY_HELP),
4319 FUSE_OPT_KEY("--help", KEY_HELP),
4320 FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP),
4321 FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP),
4322 FUSE_LIB_OPT("debug", debug, 1),
4323 FUSE_LIB_OPT("-d", debug, 1),
4324 FUSE_LIB_OPT("hard_remove", hard_remove, 1),
4325 FUSE_LIB_OPT("use_ino", use_ino, 1),
4326 FUSE_LIB_OPT("readdir_ino", readdir_ino, 1),
4327 FUSE_LIB_OPT("direct_io", direct_io, 1),
4328 FUSE_LIB_OPT("kernel_cache", kernel_cache, 1),
4329 FUSE_LIB_OPT("auto_cache", auto_cache, 1),
4330 FUSE_LIB_OPT("noauto_cache", auto_cache, 0),
4331 FUSE_LIB_OPT("umask=", set_mode, 1),
4332 FUSE_LIB_OPT("umask=%o", umask, 0),
4333 FUSE_LIB_OPT("uid=", set_uid, 1),
4334 FUSE_LIB_OPT("uid=%d", uid, 0),
4335 FUSE_LIB_OPT("gid=", set_gid, 1),
4336 FUSE_LIB_OPT("gid=%d", gid, 0),
4337 FUSE_LIB_OPT("entry_timeout=%lf", entry_timeout, 0),
4338 FUSE_LIB_OPT("attr_timeout=%lf", attr_timeout, 0),
4339 FUSE_LIB_OPT("ac_attr_timeout=%lf", ac_attr_timeout, 0),
4340 FUSE_LIB_OPT("ac_attr_timeout=", ac_attr_timeout_set, 1),
4341 FUSE_LIB_OPT("negative_timeout=%lf", negative_timeout, 0),
4342 FUSE_LIB_OPT("noforget", remember, -1),
4343 FUSE_LIB_OPT("remember=%u", remember, 0),
4344 FUSE_LIB_OPT("nopath", nopath, 1),
4345 FUSE_LIB_OPT("intr", intr, 1),
4346 FUSE_LIB_OPT("intr_signal=%d", intr_signal, 0),
4347 FUSE_LIB_OPT("modules=%s", modules, 0),
4348 FUSE_OPT_END
4351 static void fuse_lib_help(void)
4353 fprintf(stderr,
4354 " -o hard_remove immediate removal (don't hide files)\n"
4355 " -o use_ino let filesystem set inode numbers\n"
4356 " -o readdir_ino try to fill in d_ino in readdir\n"
4357 " -o direct_io use direct I/O\n"
4358 " -o kernel_cache cache files in kernel\n"
4359 " -o [no]auto_cache enable caching based on modification times (off)\n"
4360 " -o umask=M set file permissions (octal)\n"
4361 " -o uid=N set file owner\n"
4362 " -o gid=N set file group\n"
4363 " -o entry_timeout=T cache timeout for names (1.0s)\n"
4364 " -o negative_timeout=T cache timeout for deleted names (0.0s)\n"
4365 " -o attr_timeout=T cache timeout for attributes (1.0s)\n"
4366 " -o ac_attr_timeout=T auto cache timeout for attributes (attr_timeout)\n"
4367 " -o noforget never forget cached inodes\n"
4368 " -o remember=T remember cached inodes for T seconds (0s)\n"
4369 " -o intr allow requests to be interrupted\n"
4370 " -o intr_signal=NUM signal to send on interrupt (%i)\n"
4371 " -o modules=M1[:M2...] names of modules to push onto filesystem stack\n"
4372 "\n", FUSE_DEFAULT_INTR_SIGNAL);
4375 static void fuse_lib_help_modules(void)
4377 struct fuse_module *m;
4378 fprintf(stderr, "\nModule options:\n");
4379 pthread_mutex_lock(&fuse_context_lock);
4380 for (m = fuse_modules; m; m = m->next) {
4381 struct fuse_fs *fs = NULL;
4382 struct fuse_fs *newfs;
4383 struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
4384 if (fuse_opt_add_arg(&args, "") != -1 &&
4385 fuse_opt_add_arg(&args, "-h") != -1) {
4386 fprintf(stderr, "\n[%s]\n", m->name);
4387 newfs = m->factory(&args, &fs);
4388 assert(newfs == NULL);
4390 fuse_opt_free_args(&args);
4392 pthread_mutex_unlock(&fuse_context_lock);
4395 static int fuse_lib_opt_proc(void *data, const char *arg, int key,
4396 struct fuse_args *outargs)
4398 (void) arg; (void) outargs;
4400 if (key == KEY_HELP) {
4401 struct fuse_config *conf = (struct fuse_config *) data;
4402 fuse_lib_help();
4403 conf->help = 1;
4406 return 1;
4409 int fuse_is_lib_option(const char *opt)
4411 return fuse_lowlevel_is_lib_option(opt) ||
4412 fuse_opt_match(fuse_lib_opts, opt);
4415 static int fuse_init_intr_signal(int signum, int *installed)
4417 struct sigaction old_sa;
4419 if (sigaction(signum, NULL, &old_sa) == -1) {
4420 perror("fuse: cannot get old signal handler");
4421 return -1;
4424 if (old_sa.sa_handler == SIG_DFL) {
4425 struct sigaction sa;
4427 memset(&sa, 0, sizeof(struct sigaction));
4428 sa.sa_handler = fuse_intr_sighandler;
4429 sigemptyset(&sa.sa_mask);
4431 if (sigaction(signum, &sa, NULL) == -1) {
4432 perror("fuse: cannot set interrupt signal handler");
4433 return -1;
4435 *installed = 1;
4437 return 0;
4440 static void fuse_restore_intr_signal(int signum)
4442 struct sigaction sa;
4444 memset(&sa, 0, sizeof(struct sigaction));
4445 sa.sa_handler = SIG_DFL;
4446 sigaction(signum, &sa, NULL);
4450 static int fuse_push_module(struct fuse *f, const char *module,
4451 struct fuse_args *args)
4453 struct fuse_fs *fs[2] = { f->fs, NULL };
4454 struct fuse_fs *newfs;
4455 struct fuse_module *m = fuse_get_module(module);
4457 if (!m)
4458 return -1;
4460 newfs = m->factory(args, fs);
4461 if (!newfs) {
4462 fuse_put_module(m);
4463 return -1;
4465 newfs->m = m;
4466 f->fs = newfs;
4467 f->nullpath_ok = newfs->op.flag_nullpath_ok && f->nullpath_ok;
4468 f->conf.nopath = newfs->op.flag_nopath && f->conf.nopath;
4469 f->utime_omit_ok = newfs->op.flag_utime_omit_ok && f->utime_omit_ok;
4470 return 0;
4473 struct fuse_fs *fuse_fs_new(const struct fuse_operations *op, size_t op_size,
4474 void *user_data)
4476 struct fuse_fs *fs;
4478 if (sizeof(struct fuse_operations) < op_size) {
4479 fprintf(stderr, "fuse: warning: library too old, some operations may not not work\n");
4480 op_size = sizeof(struct fuse_operations);
4483 fs = (struct fuse_fs *) calloc(1, sizeof(struct fuse_fs));
4484 if (!fs) {
4485 fprintf(stderr, "fuse: failed to allocate fuse_fs object\n");
4486 return NULL;
4489 fs->user_data = user_data;
4490 if (op)
4491 memcpy(&fs->op, op, op_size);
4492 return fs;
4495 static int node_table_init(struct node_table *t)
4497 t->size = NODE_TABLE_MIN_SIZE;
4498 t->array = (struct node **) calloc(1, sizeof(struct node *) * t->size);
4499 if (t->array == NULL) {
4500 fprintf(stderr, "fuse: memory allocation failed\n");
4501 return -1;
4503 t->use = 0;
4504 t->split = 0;
4506 return 0;
4509 static void *fuse_prune_nodes(void *fuse)
4511 struct fuse *f = fuse;
4512 int sleep_time;
4514 while(1) {
4515 sleep_time = fuse_clean_cache(f);
4516 sleep(sleep_time);
4518 return NULL;
4521 int fuse_start_cleanup_thread(struct fuse *f)
4523 if (lru_enabled(f))
4524 return fuse_start_thread(&f->prune_thread, fuse_prune_nodes, f);
4526 return 0;
4529 void fuse_stop_cleanup_thread(struct fuse *f)
4531 if (lru_enabled(f)) {
4532 pthread_mutex_lock(&f->lock);
4533 pthread_cancel(f->prune_thread);
4534 pthread_mutex_unlock(&f->lock);
4535 pthread_join(f->prune_thread, NULL);
4539 struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args,
4540 const struct fuse_operations *op,
4541 size_t op_size, void *user_data, int compat)
4543 struct fuse *f;
4544 struct node *root;
4545 struct fuse_fs *fs;
4546 struct fuse_lowlevel_ops llop = fuse_path_ops;
4548 if (fuse_create_context_key() == -1)
4549 goto out;
4551 f = (struct fuse *) calloc(1, sizeof(struct fuse));
4552 if (f == NULL) {
4553 fprintf(stderr, "fuse: failed to allocate fuse object\n");
4554 goto out_delete_context_key;
4557 fs = fuse_fs_new(op, op_size, user_data);
4558 if (!fs)
4559 goto out_free;
4561 fs->compat = compat;
4562 f->fs = fs;
4563 f->nullpath_ok = fs->op.flag_nullpath_ok;
4564 f->conf.nopath = fs->op.flag_nopath;
4565 f->utime_omit_ok = fs->op.flag_utime_omit_ok;
4567 /* Oh f**k, this is ugly! */
4568 if (!fs->op.lock) {
4569 llop.getlk = NULL;
4570 llop.setlk = NULL;
4573 f->conf.entry_timeout = 1.0;
4574 f->conf.attr_timeout = 1.0;
4575 f->conf.negative_timeout = 0.0;
4576 f->conf.intr_signal = FUSE_DEFAULT_INTR_SIGNAL;
4578 f->pagesize = getpagesize();
4579 init_list_head(&f->partial_slabs);
4580 init_list_head(&f->full_slabs);
4581 init_list_head(&f->lru_table);
4583 if (fuse_opt_parse(args, &f->conf, fuse_lib_opts,
4584 fuse_lib_opt_proc) == -1)
4585 goto out_free_fs;
4587 if (f->conf.modules) {
4588 char *module;
4589 char *next;
4591 for (module = f->conf.modules; module; module = next) {
4592 char *p;
4593 for (p = module; *p && *p != ':'; p++);
4594 next = *p ? p + 1 : NULL;
4595 *p = '\0';
4596 if (module[0] &&
4597 fuse_push_module(f, module, args) == -1)
4598 goto out_free_fs;
4602 if (!f->conf.ac_attr_timeout_set)
4603 f->conf.ac_attr_timeout = f->conf.attr_timeout;
4605 #if defined(__FreeBSD__) || defined(__NetBSD__)
4607 * In FreeBSD, we always use these settings as inode numbers
4608 * are needed to make getcwd(3) work.
4610 f->conf.readdir_ino = 1;
4611 #endif
4613 if (compat && compat <= 25) {
4614 if (fuse_sync_compat_args(args) == -1)
4615 goto out_free_fs;
4618 f->se = fuse_lowlevel_new_common(args, &llop, sizeof(llop), f);
4619 if (f->se == NULL) {
4620 if (f->conf.help)
4621 fuse_lib_help_modules();
4622 goto out_free_fs;
4625 fuse_session_add_chan(f->se, ch);
4627 if (f->conf.debug) {
4628 fprintf(stderr, "nullpath_ok: %i\n", f->nullpath_ok);
4629 fprintf(stderr, "nopath: %i\n", f->conf.nopath);
4630 fprintf(stderr, "utime_omit_ok: %i\n", f->utime_omit_ok);
4633 /* Trace topmost layer by default */
4634 f->fs->debug = f->conf.debug;
4635 f->ctr = 0;
4636 f->generation = 0;
4637 if (node_table_init(&f->name_table) == -1)
4638 goto out_free_session;
4640 if (node_table_init(&f->id_table) == -1)
4641 goto out_free_name_table;
4643 fuse_mutex_init(&f->lock);
4645 root = alloc_node(f);
4646 if (root == NULL) {
4647 fprintf(stderr, "fuse: memory allocation failed\n");
4648 goto out_free_id_table;
4651 strcpy(root->inline_name, "/");
4652 root->name = root->inline_name;
4654 if (f->conf.intr &&
4655 fuse_init_intr_signal(f->conf.intr_signal,
4656 &f->intr_installed) == -1)
4657 goto out_free_root;
4659 root->parent = NULL;
4660 root->nodeid = FUSE_ROOT_ID;
4661 inc_nlookup(root);
4662 hash_id(f, root);
4664 return f;
4666 out_free_root:
4667 free(root);
4668 out_free_id_table:
4669 free(f->id_table.array);
4670 out_free_name_table:
4671 free(f->name_table.array);
4672 out_free_session:
4673 fuse_session_destroy(f->se);
4674 out_free_fs:
4675 /* Horrible compatibility hack to stop the destructor from being
4676 called on the filesystem without init being called first */
4677 fs->op.destroy = NULL;
4678 fuse_fs_destroy(f->fs);
4679 free(f->conf.modules);
4680 out_free:
4681 free(f);
4682 out_delete_context_key:
4683 fuse_delete_context_key();
4684 out:
4685 return NULL;
4688 struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args,
4689 const struct fuse_operations *op, size_t op_size,
4690 void *user_data)
4692 return fuse_new_common(ch, args, op, op_size, user_data, 0);
4695 void fuse_destroy(struct fuse *f)
4697 size_t i;
4699 if (f->conf.intr && f->intr_installed)
4700 fuse_restore_intr_signal(f->conf.intr_signal);
4702 if (f->fs) {
4703 struct fuse_context_i *c = fuse_get_context_internal();
4705 memset(c, 0, sizeof(*c));
4706 c->ctx.fuse = f;
4708 for (i = 0; i < f->id_table.size; i++) {
4709 struct node *node;
4711 for (node = f->id_table.array[i]; node != NULL;
4712 node = node->id_next) {
4713 if (node->is_hidden) {
4714 char *path;
4715 if (try_get_path(f, node->nodeid, NULL, &path, NULL, 0) == 0) {
4716 fuse_fs_unlink(f->fs, path);
4717 free(path);
4723 for (i = 0; i < f->id_table.size; i++) {
4724 struct node *node;
4725 struct node *next;
4727 for (node = f->id_table.array[i]; node != NULL; node = next) {
4728 next = node->id_next;
4729 free_node(f, node);
4730 f->id_table.use--;
4733 assert(list_empty(&f->partial_slabs));
4734 assert(list_empty(&f->full_slabs));
4736 free(f->id_table.array);
4737 free(f->name_table.array);
4738 pthread_mutex_destroy(&f->lock);
4739 fuse_session_destroy(f->se);
4740 free(f->conf.modules);
4741 free(f);
4742 fuse_delete_context_key();
4745 static struct fuse *fuse_new_common_compat25(int fd, struct fuse_args *args,
4746 const struct fuse_operations *op,
4747 size_t op_size, int compat)
4749 struct fuse *f = NULL;
4750 struct fuse_chan *ch = fuse_kern_chan_new(fd);
4752 if (ch)
4753 f = fuse_new_common(ch, args, op, op_size, NULL, compat);
4755 return f;
4758 /* called with fuse_context_lock held or during initialization (before
4759 main() has been called) */
4760 void fuse_register_module(struct fuse_module *mod)
4762 mod->ctr = 0;
4763 mod->so = fuse_current_so;
4764 if (mod->so)
4765 mod->so->ctr++;
4766 mod->next = fuse_modules;
4767 fuse_modules = mod;
4770 #if !defined(__FreeBSD__) && !defined(__NetBSD__)
4772 static struct fuse *fuse_new_common_compat(int fd, const char *opts,
4773 const struct fuse_operations *op,
4774 size_t op_size, int compat)
4776 struct fuse *f;
4777 struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
4779 if (fuse_opt_add_arg(&args, "") == -1)
4780 return NULL;
4781 if (opts &&
4782 (fuse_opt_add_arg(&args, "-o") == -1 ||
4783 fuse_opt_add_arg(&args, opts) == -1)) {
4784 fuse_opt_free_args(&args);
4785 return NULL;
4787 f = fuse_new_common_compat25(fd, &args, op, op_size, compat);
4788 fuse_opt_free_args(&args);
4790 return f;
4793 struct fuse *fuse_new_compat22(int fd, const char *opts,
4794 const struct fuse_operations_compat22 *op,
4795 size_t op_size)
4797 return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op,
4798 op_size, 22);
4801 struct fuse *fuse_new_compat2(int fd, const char *opts,
4802 const struct fuse_operations_compat2 *op)
4804 return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op,
4805 sizeof(struct fuse_operations_compat2),
4806 21);
4809 struct fuse *fuse_new_compat1(int fd, int flags,
4810 const struct fuse_operations_compat1 *op)
4812 const char *opts = NULL;
4813 if (flags & FUSE_DEBUG_COMPAT1)
4814 opts = "debug";
4815 return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op,
4816 sizeof(struct fuse_operations_compat1),
4817 11);
4820 FUSE_SYMVER(".symver fuse_exited,__fuse_exited@");
4821 FUSE_SYMVER(".symver fuse_process_cmd,__fuse_process_cmd@");
4822 FUSE_SYMVER(".symver fuse_read_cmd,__fuse_read_cmd@");
4823 FUSE_SYMVER(".symver fuse_set_getcontext_func,__fuse_set_getcontext_func@");
4824 FUSE_SYMVER(".symver fuse_new_compat2,fuse_new@");
4825 FUSE_SYMVER(".symver fuse_new_compat22,fuse_new@FUSE_2.2");
4827 #endif /* __FreeBSD__ || __NetBSD__ */
4829 struct fuse *fuse_new_compat25(int fd, struct fuse_args *args,
4830 const struct fuse_operations_compat25 *op,
4831 size_t op_size)
4833 return fuse_new_common_compat25(fd, args, (struct fuse_operations *) op,
4834 op_size, 25);
4837 FUSE_SYMVER(".symver fuse_new_compat25,fuse_new@FUSE_2.5");