1 /*
2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
4
5 This program can be distributed under the terms of the GNU LGPLv2.
6 See the file COPYING.LIB
7 */
8
9
10 /* For pthread_rwlock_t */
11 #define _GNU_SOURCE
12
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"
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <stddef.h>
26 #include <stdbool.h>
27 #include <unistd.h>
28 #include <time.h>
29 #include <fcntl.h>
30 #include <limits.h>
31 #include <errno.h>
32 #include <signal.h>
33 #include <dlfcn.h>
34 #include <assert.h>
35 #include <poll.h>
36 #include <sys/param.h>
37 #include <sys/uio.h>
38 #include <sys/time.h>
39 #include <sys/mman.h>
40 #include <sys/file.h>
41
42 #define FUSE_NODE_SLAB 1
43
44 #ifndef MAP_ANONYMOUS
45 #undef FUSE_NODE_SLAB
46 #endif
47
48 #define FUSE_DEFAULT_INTR_SIGNAL SIGUSR1
49
50 #define FUSE_UNKNOWN_INO 0xffffffff
51 #define OFFSET_MAX 0x7fffffffffffffffLL
52
53 #define NODE_TABLE_MIN_SIZE 8192
54
55 struct fuse_config {
56 unsigned int uid;
57 unsigned int gid;
58 unsigned int umask;
59 double entry_timeout;
60 double negative_timeout;
61 double attr_timeout;
62 double ac_attr_timeout;
63 int ac_attr_timeout_set;
64 int remember;
65 int nopath;
66 int debug;
67 int hard_remove;
68 int use_ino;
69 int readdir_ino;
70 int set_mode;
71 int set_uid;
72 int set_gid;
73 int direct_io;
74 int kernel_cache;
75 int auto_cache;
76 int intr;
77 int intr_signal;
78 int help;
79 char *modules;
80 };
81
82 struct fuse_fs {
83 struct fuse_operations op;
84 struct fuse_module *m;
85 void *user_data;
86 int compat;
87 int debug;
88 };
89
90 struct fusemod_so {
91 void *handle;
92 int ctr;
93 };
94
95 struct lock_queue_element {
96 struct lock_queue_element *next;
97 pthread_cond_t cond;
98 fuse_ino_t nodeid1;
99 const char *name1;
100 char **path1;
101 struct node **wnode1;
102 fuse_ino_t nodeid2;
103 const char *name2;
104 char **path2;
105 struct node **wnode2;
106 int err;
107 bool first_locked : 1;
108 bool second_locked : 1;
109 bool done : 1;
110 };
111
112 struct node_table {
113 struct node **array;
114 size_t use;
115 size_t size;
116 size_t split;
117 };
118
119 #define container_of(ptr, type, member) ({ \
120 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
121 (type *)( (char *)__mptr - offsetof(type,member) );})
122
123 #define list_entry(ptr, type, member) \
124 container_of(ptr, type, member)
125
126 struct list_head {
127 struct list_head *next;
128 struct list_head *prev;
129 };
130
131 struct node_slab {
132 struct list_head list; /* must be the first member */
133 struct list_head freelist;
134 int used;
135 };
136
137 struct fuse {
138 struct fuse_session *se;
139 struct node_table name_table;
140 struct node_table id_table;
141 struct list_head lru_table;
142 fuse_ino_t ctr;
143 unsigned int generation;
144 unsigned int hidectr;
145 pthread_mutex_t lock;
146 struct fuse_config conf;
147 int intr_installed;
148 struct fuse_fs *fs;
149 int nullpath_ok;
150 int utime_omit_ok;
151 struct lock_queue_element *lockq;
152 int pagesize;
153 struct list_head partial_slabs;
154 struct list_head full_slabs;
155 pthread_t prune_thread;
156 };
157
158 struct lock {
159 int type;
160 off_t start;
161 off_t end;
162 pid_t pid;
163 uint64_t owner;
164 struct lock *next;
165 };
166
167 struct node {
168 struct node *name_next;
169 struct node *id_next;
170 fuse_ino_t nodeid;
171 unsigned int generation;
172 int refctr;
173 struct node *parent;
174 char *name;
175 uint64_t nlookup;
176 int open_count;
177 struct timespec stat_updated;
178 struct timespec mtime;
179 off_t size;
180 struct lock *locks;
181 unsigned int is_hidden : 1;
182 unsigned int cache_valid : 1;
183 int treelock;
184 char inline_name[32];
185 };
186
187 #define TREELOCK_WRITE -1
188 #define TREELOCK_WAIT_OFFSET INT_MIN
189
190 struct node_lru {
191 struct node node;
192 struct list_head lru;
193 struct timespec forget_time;
194 };
195
196 struct fuse_dh {
197 pthread_mutex_t lock;
198 struct fuse *fuse;
199 fuse_req_t req;
200 char *contents;
201 int allocated;
202 unsigned len;
203 unsigned size;
204 unsigned needlen;
205 int filled;
206 uint64_t fh;
207 int error;
208 fuse_ino_t nodeid;
209 };
210
211 /* old dir handle */
212 struct fuse_dirhandle {
213 fuse_fill_dir_t filler;
214 void *buf;
215 };
216
217 struct fuse_context_i {
218 struct fuse_context ctx;
219 fuse_req_t req;
220 };
221
222 static pthread_key_t fuse_context_key;
223 static pthread_mutex_t fuse_context_lock = PTHREAD_MUTEX_INITIALIZER;
224 static int fuse_context_ref;
225 static struct fusemod_so *fuse_current_so;
226 static struct fuse_module *fuse_modules;
227
fuse_load_so_name(const char * soname)228 static int fuse_load_so_name(const char *soname)
229 {
230 struct fusemod_so *so;
231
232 so = calloc(1, sizeof(struct fusemod_so));
233 if (!so) {
234 fprintf(stderr, "fuse: memory allocation failed\n");
235 return -1;
236 }
237
238 fuse_current_so = so;
239 so->handle = dlopen(soname, RTLD_NOW);
240 fuse_current_so = NULL;
241 if (!so->handle) {
242 fprintf(stderr, "fuse: %s\n", dlerror());
243 goto err;
244 }
245 if (!so->ctr) {
246 fprintf(stderr, "fuse: %s did not register any modules\n",
247 soname);
248 goto err;
249 }
250 return 0;
251
252 err:
253 if (so->handle)
254 dlclose(so->handle);
255 free(so);
256 return -1;
257 }
258
fuse_load_so_module(const char * module)259 static int fuse_load_so_module(const char *module)
260 {
261 int res;
262 char *soname = malloc(strlen(module) + 64);
263 if (!soname) {
264 fprintf(stderr, "fuse: memory allocation failed\n");
265 return -1;
266 }
267 sprintf(soname, "libfusemod_%s.so", module);
268 res = fuse_load_so_name(soname);
269 free(soname);
270 return res;
271 }
272
fuse_find_module(const char * module)273 static struct fuse_module *fuse_find_module(const char *module)
274 {
275 struct fuse_module *m;
276 for (m = fuse_modules; m; m = m->next) {
277 if (strcmp(module, m->name) == 0) {
278 m->ctr++;
279 break;
280 }
281 }
282 return m;
283 }
284
fuse_get_module(const char * module)285 static struct fuse_module *fuse_get_module(const char *module)
286 {
287 struct fuse_module *m;
288
289 pthread_mutex_lock(&fuse_context_lock);
290 m = fuse_find_module(module);
291 if (!m) {
292 int err = fuse_load_so_module(module);
293 if (!err)
294 m = fuse_find_module(module);
295 }
296 pthread_mutex_unlock(&fuse_context_lock);
297 return m;
298 }
299
fuse_put_module(struct fuse_module * m)300 static void fuse_put_module(struct fuse_module *m)
301 {
302 pthread_mutex_lock(&fuse_context_lock);
303 assert(m->ctr > 0);
304 m->ctr--;
305 if (!m->ctr && m->so) {
306 struct fusemod_so *so = m->so;
307 assert(so->ctr > 0);
308 so->ctr--;
309 if (!so->ctr) {
310 struct fuse_module **mp;
311 for (mp = &fuse_modules; *mp;) {
312 if ((*mp)->so == so)
313 *mp = (*mp)->next;
314 else
315 mp = &(*mp)->next;
316 }
317 dlclose(so->handle);
318 free(so);
319 }
320 }
321 pthread_mutex_unlock(&fuse_context_lock);
322 }
323
init_list_head(struct list_head * list)324 static void init_list_head(struct list_head *list)
325 {
326 list->next = list;
327 list->prev = list;
328 }
329
list_empty(const struct list_head * head)330 static int list_empty(const struct list_head *head)
331 {
332 return head->next == head;
333 }
334
list_add(struct list_head * new,struct list_head * prev,struct list_head * next)335 static void list_add(struct list_head *new, struct list_head *prev,
336 struct list_head *next)
337 {
338 next->prev = new;
339 new->next = next;
340 new->prev = prev;
341 prev->next = new;
342 }
343
list_add_head(struct list_head * new,struct list_head * head)344 static inline void list_add_head(struct list_head *new, struct list_head *head)
345 {
346 list_add(new, head, head->next);
347 }
348
list_add_tail(struct list_head * new,struct list_head * head)349 static inline void list_add_tail(struct list_head *new, struct list_head *head)
350 {
351 list_add(new, head->prev, head);
352 }
353
list_del(struct list_head * entry)354 static inline void list_del(struct list_head *entry)
355 {
356 struct list_head *prev = entry->prev;
357 struct list_head *next = entry->next;
358
359 next->prev = prev;
360 prev->next = next;
361 }
362
lru_enabled(struct fuse * f)363 static inline int lru_enabled(struct fuse *f)
364 {
365 return f->conf.remember > 0;
366 }
367
node_lru(struct node * node)368 static struct node_lru *node_lru(struct node *node)
369 {
370 return (struct node_lru *) node;
371 }
372
get_node_size(struct fuse * f)373 static size_t get_node_size(struct fuse *f)
374 {
375 if (lru_enabled(f))
376 return sizeof(struct node_lru);
377 else
378 return sizeof(struct node);
379 }
380
381 #ifdef FUSE_NODE_SLAB
list_to_slab(struct list_head * head)382 static struct node_slab *list_to_slab(struct list_head *head)
383 {
384 return (struct node_slab *) head;
385 }
386
node_to_slab(struct fuse * f,struct node * node)387 static struct node_slab *node_to_slab(struct fuse *f, struct node *node)
388 {
389 return (struct node_slab *) (((uintptr_t) node) & ~((uintptr_t) f->pagesize - 1));
390 }
391
alloc_slab(struct fuse * f)392 static int alloc_slab(struct fuse *f)
393 {
394 void *mem;
395 struct node_slab *slab;
396 char *start;
397 size_t num;
398 size_t i;
399 size_t node_size = get_node_size(f);
400
401 mem = mmap(NULL, f->pagesize, PROT_READ | PROT_WRITE,
402 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
403
404 if (mem == MAP_FAILED)
405 return -1;
406
407 slab = mem;
408 init_list_head(&slab->freelist);
409 slab->used = 0;
410 num = (f->pagesize - sizeof(struct node_slab)) / node_size;
411
412 start = (char *) mem + f->pagesize - num * node_size;
413 for (i = 0; i < num; i++) {
414 struct list_head *n;
415
416 n = (struct list_head *) (start + i * node_size);
417 list_add_tail(n, &slab->freelist);
418 }
419 list_add_tail(&slab->list, &f->partial_slabs);
420
421 return 0;
422 }
423
alloc_node(struct fuse * f)424 static struct node *alloc_node(struct fuse *f)
425 {
426 struct node_slab *slab;
427 struct list_head *node;
428
429 if (list_empty(&f->partial_slabs)) {
430 int res = alloc_slab(f);
431 if (res != 0)
432 return NULL;
433 }
434 slab = list_to_slab(f->partial_slabs.next);
435 slab->used++;
436 node = slab->freelist.next;
437 list_del(node);
438 if (list_empty(&slab->freelist)) {
439 list_del(&slab->list);
440 list_add_tail(&slab->list, &f->full_slabs);
441 }
442 memset(node, 0, sizeof(struct node));
443
444 return (struct node *) node;
445 }
446
free_slab(struct fuse * f,struct node_slab * slab)447 static void free_slab(struct fuse *f, struct node_slab *slab)
448 {
449 int res;
450
451 list_del(&slab->list);
452 res = munmap(slab, f->pagesize);
453 if (res == -1)
454 fprintf(stderr, "fuse warning: munmap(%p) failed\n", slab);
455 }
456
free_node_mem(struct fuse * f,struct node * node)457 static void free_node_mem(struct fuse *f, struct node *node)
458 {
459 struct node_slab *slab = node_to_slab(f, node);
460 struct list_head *n = (struct list_head *) node;
461
462 slab->used--;
463 if (slab->used) {
464 if (list_empty(&slab->freelist)) {
465 list_del(&slab->list);
466 list_add_tail(&slab->list, &f->partial_slabs);
467 }
468 list_add_head(n, &slab->freelist);
469 } else {
470 free_slab(f, slab);
471 }
472 }
473 #else
alloc_node(struct fuse * f)474 static struct node *alloc_node(struct fuse *f)
475 {
476 return (struct node *) calloc(1, get_node_size(f));
477 }
478
free_node_mem(struct fuse * f,struct node * node)479 static void free_node_mem(struct fuse *f, struct node *node)
480 {
481 (void) f;
482 free(node);
483 }
484 #endif
485
id_hash(struct fuse * f,fuse_ino_t ino)486 static size_t id_hash(struct fuse *f, fuse_ino_t ino)
487 {
488 uint64_t hash = ((uint32_t) ino * 2654435761U) % f->id_table.size;
489 uint64_t oldhash = hash % (f->id_table.size / 2);
490
491 if (oldhash >= f->id_table.split)
492 return oldhash;
493 else
494 return hash;
495 }
496
get_node_nocheck(struct fuse * f,fuse_ino_t nodeid)497 static struct node *get_node_nocheck(struct fuse *f, fuse_ino_t nodeid)
498 {
499 size_t hash = id_hash(f, nodeid);
500 struct node *node;
501
502 for (node = f->id_table.array[hash]; node != NULL; node = node->id_next)
503 if (node->nodeid == nodeid)
504 return node;
505
506 return NULL;
507 }
508
get_node(struct fuse * f,fuse_ino_t nodeid)509 static struct node *get_node(struct fuse *f, fuse_ino_t nodeid)
510 {
511 struct node *node = get_node_nocheck(f, nodeid);
512 if (!node) {
513 fprintf(stderr, "fuse internal error: node %llu not found\n",
514 (unsigned long long) nodeid);
515 abort();
516 }
517 return node;
518 }
519
520 static void curr_time(struct timespec *now);
521 static double diff_timespec(const struct timespec *t1,
522 const struct timespec *t2);
523
remove_node_lru(struct node * node)524 static void remove_node_lru(struct node *node)
525 {
526 struct node_lru *lnode = node_lru(node);
527 list_del(&lnode->lru);
528 init_list_head(&lnode->lru);
529 }
530
set_forget_time(struct fuse * f,struct node * node)531 static void set_forget_time(struct fuse *f, struct node *node)
532 {
533 struct node_lru *lnode = node_lru(node);
534
535 list_del(&lnode->lru);
536 list_add_tail(&lnode->lru, &f->lru_table);
537 curr_time(&lnode->forget_time);
538 }
539
free_node(struct fuse * f,struct node * node)540 static void free_node(struct fuse *f, struct node *node)
541 {
542 if (node->name != node->inline_name)
543 free(node->name);
544 free_node_mem(f, node);
545 }
546
node_table_reduce(struct node_table * t)547 static void node_table_reduce(struct node_table *t)
548 {
549 size_t newsize = t->size / 2;
550 void *newarray;
551
552 if (newsize < NODE_TABLE_MIN_SIZE)
553 return;
554
555 newarray = realloc(t->array, sizeof(struct node *) * newsize);
556 if (newarray != NULL)
557 t->array = newarray;
558
559 t->size = newsize;
560 t->split = t->size / 2;
561 }
562
remerge_id(struct fuse * f)563 static void remerge_id(struct fuse *f)
564 {
565 struct node_table *t = &f->id_table;
566 int iter;
567
568 if (t->split == 0)
569 node_table_reduce(t);
570
571 for (iter = 8; t->split > 0 && iter; iter--) {
572 struct node **upper;
573
574 t->split--;
575 upper = &t->array[t->split + t->size / 2];
576 if (*upper) {
577 struct node **nodep;
578
579 for (nodep = &t->array[t->split]; *nodep;
580 nodep = &(*nodep)->id_next);
581
582 *nodep = *upper;
583 *upper = NULL;
584 break;
585 }
586 }
587 }
588
unhash_id(struct fuse * f,struct node * node)589 static void unhash_id(struct fuse *f, struct node *node)
590 {
591 struct node **nodep = &f->id_table.array[id_hash(f, node->nodeid)];
592
593 for (; *nodep != NULL; nodep = &(*nodep)->id_next)
594 if (*nodep == node) {
595 *nodep = node->id_next;
596 f->id_table.use--;
597
598 if(f->id_table.use < f->id_table.size / 4)
599 remerge_id(f);
600 return;
601 }
602 }
603
node_table_resize(struct node_table * t)604 static int node_table_resize(struct node_table *t)
605 {
606 size_t newsize = t->size * 2;
607 void *newarray;
608
609 newarray = realloc(t->array, sizeof(struct node *) * newsize);
610 if (newarray == NULL)
611 return -1;
612
613 t->array = newarray;
614 memset(t->array + t->size, 0, t->size * sizeof(struct node *));
615 t->size = newsize;
616 t->split = 0;
617
618 return 0;
619 }
620
rehash_id(struct fuse * f)621 static void rehash_id(struct fuse *f)
622 {
623 struct node_table *t = &f->id_table;
624 struct node **nodep;
625 struct node **next;
626 size_t hash;
627
628 if (t->split == t->size / 2)
629 return;
630
631 hash = t->split;
632 t->split++;
633 for (nodep = &t->array[hash]; *nodep != NULL; nodep = next) {
634 struct node *node = *nodep;
635 size_t newhash = id_hash(f, node->nodeid);
636
637 if (newhash != hash) {
638 next = nodep;
639 *nodep = node->id_next;
640 node->id_next = t->array[newhash];
641 t->array[newhash] = node;
642 } else {
643 next = &node->id_next;
644 }
645 }
646 if (t->split == t->size / 2)
647 node_table_resize(t);
648 }
649
hash_id(struct fuse * f,struct node * node)650 static void hash_id(struct fuse *f, struct node *node)
651 {
652 size_t hash = id_hash(f, node->nodeid);
653 node->id_next = f->id_table.array[hash];
654 f->id_table.array[hash] = node;
655 f->id_table.use++;
656
657 if (f->id_table.use >= f->id_table.size / 2)
658 rehash_id(f);
659 }
660
name_hash(struct fuse * f,fuse_ino_t parent,const char * name)661 static size_t name_hash(struct fuse *f, fuse_ino_t parent,
662 const char *name)
663 {
664 uint64_t hash = parent;
665 uint64_t oldhash;
666
667 for (; *name; name++)
668 hash = hash * 31 + (unsigned char) *name;
669
670 hash %= f->name_table.size;
671 oldhash = hash % (f->name_table.size / 2);
672 if (oldhash >= f->name_table.split)
673 return oldhash;
674 else
675 return hash;
676 }
677
678 static void unref_node(struct fuse *f, struct node *node);
679
remerge_name(struct fuse * f)680 static void remerge_name(struct fuse *f)
681 {
682 struct node_table *t = &f->name_table;
683 int iter;
684
685 if (t->split == 0)
686 node_table_reduce(t);
687
688 for (iter = 8; t->split > 0 && iter; iter--) {
689 struct node **upper;
690
691 t->split--;
692 upper = &t->array[t->split + t->size / 2];
693 if (*upper) {
694 struct node **nodep;
695
696 for (nodep = &t->array[t->split]; *nodep;
697 nodep = &(*nodep)->name_next);
698
699 *nodep = *upper;
700 *upper = NULL;
701 break;
702 }
703 }
704 }
705
unhash_name(struct fuse * f,struct node * node)706 static void unhash_name(struct fuse *f, struct node *node)
707 {
708 if (node->name) {
709 size_t hash = name_hash(f, node->parent->nodeid, node->name);
710 struct node **nodep = &f->name_table.array[hash];
711
712 for (; *nodep != NULL; nodep = &(*nodep)->name_next)
713 if (*nodep == node) {
714 *nodep = node->name_next;
715 node->name_next = NULL;
716 unref_node(f, node->parent);
717 if (node->name != node->inline_name)
718 free(node->name);
719 node->name = NULL;
720 node->parent = NULL;
721 f->name_table.use--;
722
723 if (f->name_table.use < f->name_table.size / 4)
724 remerge_name(f);
725 return;
726 }
727 fprintf(stderr,
728 "fuse internal error: unable to unhash node: %llu\n",
729 (unsigned long long) node->nodeid);
730 abort();
731 }
732 }
733
rehash_name(struct fuse * f)734 static void rehash_name(struct fuse *f)
735 {
736 struct node_table *t = &f->name_table;
737 struct node **nodep;
738 struct node **next;
739 size_t hash;
740
741 if (t->split == t->size / 2)
742 return;
743
744 hash = t->split;
745 t->split++;
746 for (nodep = &t->array[hash]; *nodep != NULL; nodep = next) {
747 struct node *node = *nodep;
748 size_t newhash = name_hash(f, node->parent->nodeid, node->name);
749
750 if (newhash != hash) {
751 next = nodep;
752 *nodep = node->name_next;
753 node->name_next = t->array[newhash];
754 t->array[newhash] = node;
755 } else {
756 next = &node->name_next;
757 }
758 }
759 if (t->split == t->size / 2)
760 node_table_resize(t);
761 }
762
hash_name(struct fuse * f,struct node * node,fuse_ino_t parentid,const char * name)763 static int hash_name(struct fuse *f, struct node *node, fuse_ino_t parentid,
764 const char *name)
765 {
766 size_t hash = name_hash(f, parentid, name);
767 struct node *parent = get_node(f, parentid);
768 if (strlen(name) < sizeof(node->inline_name)) {
769 strcpy(node->inline_name, name);
770 node->name = node->inline_name;
771 } else {
772 node->name = strdup(name);
773 if (node->name == NULL)
774 return -1;
775 }
776
777 parent->refctr ++;
778 node->parent = parent;
779 node->name_next = f->name_table.array[hash];
780 f->name_table.array[hash] = node;
781 f->name_table.use++;
782
783 if (f->name_table.use >= f->name_table.size / 2)
784 rehash_name(f);
785
786 return 0;
787 }
788
delete_node(struct fuse * f,struct node * node)789 static void delete_node(struct fuse *f, struct node *node)
790 {
791 if (f->conf.debug)
792 fprintf(stderr, "DELETE: %llu\n",
793 (unsigned long long) node->nodeid);
794
795 assert(node->treelock == 0);
796 unhash_name(f, node);
797 if (lru_enabled(f))
798 remove_node_lru(node);
799 unhash_id(f, node);
800 free_node(f, node);
801 }
802
unref_node(struct fuse * f,struct node * node)803 static void unref_node(struct fuse *f, struct node *node)
804 {
805 assert(node->refctr > 0);
806 node->refctr --;
807 if (!node->refctr)
808 delete_node(f, node);
809 }
810
next_id(struct fuse * f)811 static fuse_ino_t next_id(struct fuse *f)
812 {
813 do {
814 f->ctr = (f->ctr + 1) & 0xffffffff;
815 if (!f->ctr)
816 f->generation ++;
817 } while (f->ctr == 0 || f->ctr == FUSE_UNKNOWN_INO ||
818 get_node_nocheck(f, f->ctr) != NULL);
819 return f->ctr;
820 }
821
lookup_node(struct fuse * f,fuse_ino_t parent,const char * name)822 static struct node *lookup_node(struct fuse *f, fuse_ino_t parent,
823 const char *name)
824 {
825 size_t hash = name_hash(f, parent, name);
826 struct node *node;
827
828 for (node = f->name_table.array[hash]; node != NULL; node = node->name_next)
829 if (node->parent->nodeid == parent &&
830 strcmp(node->name, name) == 0)
831 return node;
832
833 return NULL;
834 }
835
inc_nlookup(struct node * node)836 static void inc_nlookup(struct node *node)
837 {
838 if (!node->nlookup)
839 node->refctr++;
840 node->nlookup++;
841 }
842
find_node(struct fuse * f,fuse_ino_t parent,const char * name)843 static struct node *find_node(struct fuse *f, fuse_ino_t parent,
844 const char *name)
845 {
846 struct node *node;
847
848 pthread_mutex_lock(&f->lock);
849 if (!name)
850 node = get_node(f, parent);
851 else
852 node = lookup_node(f, parent, name);
853 if (node == NULL) {
854 node = alloc_node(f);
855 if (node == NULL)
856 goto out_err;
857
858 node->nodeid = next_id(f);
859 node->generation = f->generation;
860 if (f->conf.remember)
861 inc_nlookup(node);
862
863 if (hash_name(f, node, parent, name) == -1) {
864 free_node(f, node);
865 node = NULL;
866 goto out_err;
867 }
868 hash_id(f, node);
869 if (lru_enabled(f)) {
870 struct node_lru *lnode = node_lru(node);
871 init_list_head(&lnode->lru);
872 }
873 } else if (lru_enabled(f) && node->nlookup == 1) {
874 remove_node_lru(node);
875 }
876 inc_nlookup(node);
877 out_err:
878 pthread_mutex_unlock(&f->lock);
879 return node;
880 }
881
add_name(char ** buf,unsigned * bufsize,char * s,const char * name)882 static char *add_name(char **buf, unsigned *bufsize, char *s, const char *name)
883 {
884 size_t len = strlen(name);
885
886 if (s - len <= *buf) {
887 unsigned pathlen = *bufsize - (s - *buf);
888 unsigned newbufsize = *bufsize;
889 char *newbuf;
890
891 while (newbufsize < pathlen + len + 1) {
892 if (newbufsize >= 0x80000000)
893 newbufsize = 0xffffffff;
894 else
895 newbufsize *= 2;
896 }
897
898 newbuf = realloc(*buf, newbufsize);
899 if (newbuf == NULL)
900 return NULL;
901
902 *buf = newbuf;
903 s = newbuf + newbufsize - pathlen;
904 memmove(s, newbuf + *bufsize - pathlen, pathlen);
905 *bufsize = newbufsize;
906 }
907 s -= len;
908 strncpy(s, name, len);
909 s--;
910 *s = '/';
911
912 return s;
913 }
914
unlock_path(struct fuse * f,fuse_ino_t nodeid,struct node * wnode,struct node * end)915 static void unlock_path(struct fuse *f, fuse_ino_t nodeid, struct node *wnode,
916 struct node *end)
917 {
918 struct node *node;
919
920 if (wnode) {
921 assert(wnode->treelock == TREELOCK_WRITE);
922 wnode->treelock = 0;
923 }
924
925 for (node = get_node(f, nodeid);
926 node != end && node->nodeid != FUSE_ROOT_ID; node = node->parent) {
927 assert(node->treelock != 0);
928 assert(node->treelock != TREELOCK_WAIT_OFFSET);
929 assert(node->treelock != TREELOCK_WRITE);
930 node->treelock--;
931 if (node->treelock == TREELOCK_WAIT_OFFSET)
932 node->treelock = 0;
933 }
934 }
935
try_get_path(struct fuse * f,fuse_ino_t nodeid,const char * name,char ** path,struct node ** wnodep,bool need_lock)936 static int try_get_path(struct fuse *f, fuse_ino_t nodeid, const char *name,
937 char **path, struct node **wnodep, bool need_lock)
938 {
939 unsigned bufsize = 256;
940 char *buf;
941 char *s;
942 struct node *node;
943 struct node *wnode = NULL;
944 int err;
945
946 *path = NULL;
947
948 err = -ENOMEM;
949 buf = malloc(bufsize);
950 if (buf == NULL)
951 goto out_err;
952
953 s = buf + bufsize - 1;
954 *s = '\0';
955
956 if (name != NULL) {
957 s = add_name(&buf, &bufsize, s, name);
958 err = -ENOMEM;
959 if (s == NULL)
960 goto out_free;
961 }
962
963 if (wnodep) {
964 assert(need_lock);
965 wnode = lookup_node(f, nodeid, name);
966 if (wnode) {
967 if (wnode->treelock != 0) {
968 if (wnode->treelock > 0)
969 wnode->treelock += TREELOCK_WAIT_OFFSET;
970 err = -EAGAIN;
971 goto out_free;
972 }
973 wnode->treelock = TREELOCK_WRITE;
974 }
975 }
976
977 for (node = get_node(f, nodeid); node->nodeid != FUSE_ROOT_ID;
978 node = node->parent) {
979 err = -ENOENT;
980 if (node->name == NULL || node->parent == NULL)
981 goto out_unlock;
982
983 err = -ENOMEM;
984 s = add_name(&buf, &bufsize, s, node->name);
985 if (s == NULL)
986 goto out_unlock;
987
988 if (need_lock) {
989 err = -EAGAIN;
990 if (node->treelock < 0)
991 goto out_unlock;
992
993 node->treelock++;
994 }
995 }
996
997 if (s[0])
998 memmove(buf, s, bufsize - (s - buf));
999 else
1000 strcpy(buf, "/");
1001
1002 *path = buf;
1003 if (wnodep)
1004 *wnodep = wnode;
1005
1006 return 0;
1007
1008 out_unlock:
1009 if (need_lock)
1010 unlock_path(f, nodeid, wnode, node);
1011 out_free:
1012 free(buf);
1013
1014 out_err:
1015 return err;
1016 }
1017
queue_element_unlock(struct fuse * f,struct lock_queue_element * qe)1018 static void queue_element_unlock(struct fuse *f, struct lock_queue_element *qe)
1019 {
1020 struct node *wnode;
1021
1022 if (qe->first_locked) {
1023 wnode = qe->wnode1 ? *qe->wnode1 : NULL;
1024 unlock_path(f, qe->nodeid1, wnode, NULL);
1025 qe->first_locked = false;
1026 }
1027 if (qe->second_locked) {
1028 wnode = qe->wnode2 ? *qe->wnode2 : NULL;
1029 unlock_path(f, qe->nodeid2, wnode, NULL);
1030 qe->second_locked = false;
1031 }
1032 }
1033
queue_element_wakeup(struct fuse * f,struct lock_queue_element * qe)1034 static void queue_element_wakeup(struct fuse *f, struct lock_queue_element *qe)
1035 {
1036 int err;
1037 bool first = (qe == f->lockq);
1038
1039 if (!qe->path1) {
1040 /* Just waiting for it to be unlocked */
1041 if (get_node(f, qe->nodeid1)->treelock == 0)
1042 pthread_cond_signal(&qe->cond);
1043
1044 return;
1045 }
1046
1047 if (!qe->first_locked) {
1048 err = try_get_path(f, qe->nodeid1, qe->name1, qe->path1,
1049 qe->wnode1, true);
1050 if (!err)
1051 qe->first_locked = true;
1052 else if (err != -EAGAIN)
1053 goto err_unlock;
1054 }
1055 if (!qe->second_locked && qe->path2) {
1056 err = try_get_path(f, qe->nodeid2, qe->name2, qe->path2,
1057 qe->wnode2, true);
1058 if (!err)
1059 qe->second_locked = true;
1060 else if (err != -EAGAIN)
1061 goto err_unlock;
1062 }
1063
1064 if (qe->first_locked && (qe->second_locked || !qe->path2)) {
1065 err = 0;
1066 goto done;
1067 }
1068
1069 /*
1070 * Only let the first element be partially locked otherwise there could
1071 * be a deadlock.
1072 *
1073 * But do allow the first element to be partially locked to prevent
1074 * starvation.
1075 */
1076 if (!first)
1077 queue_element_unlock(f, qe);
1078
1079 /* keep trying */
1080 return;
1081
1082 err_unlock:
1083 queue_element_unlock(f, qe);
1084 done:
1085 qe->err = err;
1086 qe->done = true;
1087 pthread_cond_signal(&qe->cond);
1088 }
1089
wake_up_queued(struct fuse * f)1090 static void wake_up_queued(struct fuse *f)
1091 {
1092 struct lock_queue_element *qe;
1093
1094 for (qe = f->lockq; qe != NULL; qe = qe->next)
1095 queue_element_wakeup(f, qe);
1096 }
1097
debug_path(struct fuse * f,const char * msg,fuse_ino_t nodeid,const char * name,bool wr)1098 static void debug_path(struct fuse *f, const char *msg, fuse_ino_t nodeid,
1099 const char *name, bool wr)
1100 {
1101 if (f->conf.debug) {
1102 struct node *wnode = NULL;
1103
1104 if (wr)
1105 wnode = lookup_node(f, nodeid, name);
1106
1107 if (wnode)
1108 fprintf(stderr, "%s %li (w)\n", msg, wnode->nodeid);
1109 else
1110 fprintf(stderr, "%s %li\n", msg, nodeid);
1111 }
1112 }
1113
queue_path(struct fuse * f,struct lock_queue_element * qe)1114 static void queue_path(struct fuse *f, struct lock_queue_element *qe)
1115 {
1116 struct lock_queue_element **qp;
1117
1118 qe->done = false;
1119 qe->first_locked = false;
1120 qe->second_locked = false;
1121 pthread_cond_init(&qe->cond, NULL);
1122 qe->next = NULL;
1123 for (qp = &f->lockq; *qp != NULL; qp = &(*qp)->next);
1124 *qp = qe;
1125 }
1126
dequeue_path(struct fuse * f,struct lock_queue_element * qe)1127 static void dequeue_path(struct fuse *f, struct lock_queue_element *qe)
1128 {
1129 struct lock_queue_element **qp;
1130
1131 pthread_cond_destroy(&qe->cond);
1132 for (qp = &f->lockq; *qp != qe; qp = &(*qp)->next);
1133 *qp = qe->next;
1134 }
1135
wait_path(struct fuse * f,struct lock_queue_element * qe)1136 static int wait_path(struct fuse *f, struct lock_queue_element *qe)
1137 {
1138 queue_path(f, qe);
1139
1140 do {
1141 pthread_cond_wait(&qe->cond, &f->lock);
1142 } while (!qe->done);
1143
1144 dequeue_path(f, qe);
1145
1146 return qe->err;
1147 }
1148
get_path_common(struct fuse * f,fuse_ino_t nodeid,const char * name,char ** path,struct node ** wnode)1149 static int get_path_common(struct fuse *f, fuse_ino_t nodeid, const char *name,
1150 char **path, struct node **wnode)
1151 {
1152 int err;
1153
1154 pthread_mutex_lock(&f->lock);
1155 err = try_get_path(f, nodeid, name, path, wnode, true);
1156 if (err == -EAGAIN) {
1157 struct lock_queue_element qe = {
1158 .nodeid1 = nodeid,
1159 .name1 = name,
1160 .path1 = path,
1161 .wnode1 = wnode,
1162 };
1163 debug_path(f, "QUEUE PATH", nodeid, name, !!wnode);
1164 err = wait_path(f, &qe);
1165 debug_path(f, "DEQUEUE PATH", nodeid, name, !!wnode);
1166 }
1167 pthread_mutex_unlock(&f->lock);
1168
1169 return err;
1170 }
1171
get_path(struct fuse * f,fuse_ino_t nodeid,char ** path)1172 static int get_path(struct fuse *f, fuse_ino_t nodeid, char **path)
1173 {
1174 return get_path_common(f, nodeid, NULL, path, NULL);
1175 }
1176
get_path_nullok(struct fuse * f,fuse_ino_t nodeid,char ** path)1177 static int get_path_nullok(struct fuse *f, fuse_ino_t nodeid, char **path)
1178 {
1179 int err = 0;
1180
1181 if (f->conf.nopath) {
1182 *path = NULL;
1183 } else {
1184 err = get_path_common(f, nodeid, NULL, path, NULL);
1185 if (err == -ENOENT && f->nullpath_ok)
1186 err = 0;
1187 }
1188
1189 return err;
1190 }
1191
get_path_name(struct fuse * f,fuse_ino_t nodeid,const char * name,char ** path)1192 static int get_path_name(struct fuse *f, fuse_ino_t nodeid, const char *name,
1193 char **path)
1194 {
1195 return get_path_common(f, nodeid, name, path, NULL);
1196 }
1197
get_path_wrlock(struct fuse * f,fuse_ino_t nodeid,const char * name,char ** path,struct node ** wnode)1198 static int get_path_wrlock(struct fuse *f, fuse_ino_t nodeid, const char *name,
1199 char **path, struct node **wnode)
1200 {
1201 return get_path_common(f, nodeid, name, path, wnode);
1202 }
1203
1204 #if defined(__FreeBSD__) || defined(__DragonFly__)
1205 #define CHECK_DIR_LOOP
1206 #endif
1207
1208 #if defined(CHECK_DIR_LOOP)
check_dir_loop(struct fuse * f,fuse_ino_t nodeid1,const char * name1,fuse_ino_t nodeid2,const char * name2)1209 static int check_dir_loop(struct fuse *f,
1210 fuse_ino_t nodeid1, const char *name1,
1211 fuse_ino_t nodeid2, const char *name2)
1212 {
1213 struct node *node, *node1, *node2;
1214 fuse_ino_t id1, id2;
1215
1216 node1 = lookup_node(f, nodeid1, name1);
1217 id1 = node1 ? node1->nodeid : nodeid1;
1218
1219 node2 = lookup_node(f, nodeid2, name2);
1220 id2 = node2 ? node2->nodeid : nodeid2;
1221
1222 for (node = get_node(f, id2); node->nodeid != FUSE_ROOT_ID;
1223 node = node->parent) {
1224 if (node->name == NULL || node->parent == NULL)
1225 break;
1226
1227 if (node->nodeid != id2 && node->nodeid == id1)
1228 return -EINVAL;
1229 }
1230
1231 if (node2)
1232 {
1233 for (node = get_node(f, id1); node->nodeid != FUSE_ROOT_ID;
1234 node = node->parent) {
1235 if (node->name == NULL || node->parent == NULL)
1236 break;
1237
1238 if (node->nodeid != id1 && node->nodeid == id2)
1239 return -ENOTEMPTY;
1240 }
1241 }
1242
1243 return 0;
1244 }
1245 #endif
1246
try_get_path2(struct fuse * f,fuse_ino_t nodeid1,const char * name1,fuse_ino_t nodeid2,const char * name2,char ** path1,char ** path2,struct node ** wnode1,struct node ** wnode2)1247 static int try_get_path2(struct fuse *f, fuse_ino_t nodeid1, const char *name1,
1248 fuse_ino_t nodeid2, const char *name2,
1249 char **path1, char **path2,
1250 struct node **wnode1, struct node **wnode2)
1251 {
1252 int err;
1253
1254 /* FIXME: locking two paths needs deadlock checking */
1255 err = try_get_path(f, nodeid1, name1, path1, wnode1, true);
1256 if (!err) {
1257 err = try_get_path(f, nodeid2, name2, path2, wnode2, true);
1258 if (err) {
1259 struct node *wn1 = wnode1 ? *wnode1 : NULL;
1260
1261 unlock_path(f, nodeid1, wn1, NULL);
1262 free(*path1);
1263 }
1264 }
1265 return err;
1266 }
1267
get_path2(struct fuse * f,fuse_ino_t nodeid1,const char * name1,fuse_ino_t nodeid2,const char * name2,char ** path1,char ** path2,struct node ** wnode1,struct node ** wnode2)1268 static int get_path2(struct fuse *f, fuse_ino_t nodeid1, const char *name1,
1269 fuse_ino_t nodeid2, const char *name2,
1270 char **path1, char **path2,
1271 struct node **wnode1, struct node **wnode2)
1272 {
1273 int err;
1274
1275 pthread_mutex_lock(&f->lock);
1276
1277 #if defined(CHECK_DIR_LOOP)
1278 if (name1)
1279 {
1280 // called during rename; perform dir loop check
1281 err = check_dir_loop(f, nodeid1, name1, nodeid2, name2);
1282 if (err)
1283 goto out_unlock;
1284 }
1285 #endif
1286
1287 err = try_get_path2(f, nodeid1, name1, nodeid2, name2,
1288 path1, path2, wnode1, wnode2);
1289 if (err == -EAGAIN) {
1290 struct lock_queue_element qe = {
1291 .nodeid1 = nodeid1,
1292 .name1 = name1,
1293 .path1 = path1,
1294 .wnode1 = wnode1,
1295 .nodeid2 = nodeid2,
1296 .name2 = name2,
1297 .path2 = path2,
1298 .wnode2 = wnode2,
1299 };
1300
1301 debug_path(f, "QUEUE PATH1", nodeid1, name1, !!wnode1);
1302 debug_path(f, " PATH2", nodeid2, name2, !!wnode2);
1303 err = wait_path(f, &qe);
1304 debug_path(f, "DEQUEUE PATH1", nodeid1, name1, !!wnode1);
1305 debug_path(f, " PATH2", nodeid2, name2, !!wnode2);
1306 }
1307
1308 #if defined(CHECK_DIR_LOOP)
1309 out_unlock:
1310 #endif
1311 pthread_mutex_unlock(&f->lock);
1312
1313 return err;
1314 }
1315
free_path_wrlock(struct fuse * f,fuse_ino_t nodeid,struct node * wnode,char * path)1316 static void free_path_wrlock(struct fuse *f, fuse_ino_t nodeid,
1317 struct node *wnode, char *path)
1318 {
1319 pthread_mutex_lock(&f->lock);
1320 unlock_path(f, nodeid, wnode, NULL);
1321 if (f->lockq)
1322 wake_up_queued(f);
1323 pthread_mutex_unlock(&f->lock);
1324 free(path);
1325 }
1326
free_path(struct fuse * f,fuse_ino_t nodeid,char * path)1327 static void free_path(struct fuse *f, fuse_ino_t nodeid, char *path)
1328 {
1329 if (path)
1330 free_path_wrlock(f, nodeid, NULL, path);
1331 }
1332
free_path2(struct fuse * f,fuse_ino_t nodeid1,fuse_ino_t nodeid2,struct node * wnode1,struct node * wnode2,char * path1,char * path2)1333 static void free_path2(struct fuse *f, fuse_ino_t nodeid1, fuse_ino_t nodeid2,
1334 struct node *wnode1, struct node *wnode2,
1335 char *path1, char *path2)
1336 {
1337 pthread_mutex_lock(&f->lock);
1338 unlock_path(f, nodeid1, wnode1, NULL);
1339 unlock_path(f, nodeid2, wnode2, NULL);
1340 wake_up_queued(f);
1341 pthread_mutex_unlock(&f->lock);
1342 free(path1);
1343 free(path2);
1344 }
1345
forget_node(struct fuse * f,fuse_ino_t nodeid,uint64_t nlookup)1346 static void forget_node(struct fuse *f, fuse_ino_t nodeid, uint64_t nlookup)
1347 {
1348 struct node *node;
1349 if (nodeid == FUSE_ROOT_ID)
1350 return;
1351 pthread_mutex_lock(&f->lock);
1352 node = get_node(f, nodeid);
1353
1354 /*
1355 * Node may still be locked due to interrupt idiocy in open,
1356 * create and opendir
1357 */
1358 while (node->nlookup == nlookup && node->treelock) {
1359 struct lock_queue_element qe = {
1360 .nodeid1 = nodeid,
1361 };
1362
1363 debug_path(f, "QUEUE PATH (forget)", nodeid, NULL, false);
1364 queue_path(f, &qe);
1365
1366 do {
1367 pthread_cond_wait(&qe.cond, &f->lock);
1368 } while (node->nlookup == nlookup && node->treelock);
1369
1370 dequeue_path(f, &qe);
1371 debug_path(f, "DEQUEUE_PATH (forget)", nodeid, NULL, false);
1372 }
1373
1374 assert(node->nlookup >= nlookup);
1375 node->nlookup -= nlookup;
1376 if (!node->nlookup) {
1377 unref_node(f, node);
1378 } else if (lru_enabled(f) && node->nlookup == 1) {
1379 set_forget_time(f, node);
1380 }
1381 pthread_mutex_unlock(&f->lock);
1382 }
1383
unlink_node(struct fuse * f,struct node * node)1384 static void unlink_node(struct fuse *f, struct node *node)
1385 {
1386 if (f->conf.remember) {
1387 assert(node->nlookup > 1);
1388 node->nlookup--;
1389 }
1390 unhash_name(f, node);
1391 }
1392
remove_node(struct fuse * f,fuse_ino_t dir,const char * name)1393 static void remove_node(struct fuse *f, fuse_ino_t dir, const char *name)
1394 {
1395 struct node *node;
1396
1397 pthread_mutex_lock(&f->lock);
1398 node = lookup_node(f, dir, name);
1399 if (node != NULL)
1400 unlink_node(f, node);
1401 pthread_mutex_unlock(&f->lock);
1402 }
1403
rename_node(struct fuse * f,fuse_ino_t olddir,const char * oldname,fuse_ino_t newdir,const char * newname,int hide)1404 static int rename_node(struct fuse *f, fuse_ino_t olddir, const char *oldname,
1405 fuse_ino_t newdir, const char *newname, int hide)
1406 {
1407 struct node *node;
1408 struct node *newnode;
1409 int err = 0;
1410
1411 pthread_mutex_lock(&f->lock);
1412 node = lookup_node(f, olddir, oldname);
1413 newnode = lookup_node(f, newdir, newname);
1414 if (node == NULL)
1415 goto out;
1416
1417 if (newnode != NULL) {
1418 if (hide) {
1419 fprintf(stderr, "fuse: hidden file got created during hiding\n");
1420 err = -EBUSY;
1421 goto out;
1422 }
1423 unlink_node(f, newnode);
1424 }
1425
1426 unhash_name(f, node);
1427 if (hash_name(f, node, newdir, newname) == -1) {
1428 err = -ENOMEM;
1429 goto out;
1430 }
1431
1432 if (hide)
1433 node->is_hidden = 1;
1434
1435 out:
1436 pthread_mutex_unlock(&f->lock);
1437 return err;
1438 }
1439
set_stat(struct fuse * f,fuse_ino_t nodeid,struct stat * stbuf)1440 static void set_stat(struct fuse *f, fuse_ino_t nodeid, struct stat *stbuf)
1441 {
1442 if (!f->conf.use_ino)
1443 stbuf->st_ino = nodeid;
1444 if (f->conf.set_mode)
1445 stbuf->st_mode = (stbuf->st_mode & S_IFMT) |
1446 (0777 & ~f->conf.umask);
1447 if (f->conf.set_uid)
1448 stbuf->st_uid = f->conf.uid;
1449 if (f->conf.set_gid)
1450 stbuf->st_gid = f->conf.gid;
1451 }
1452
req_fuse(fuse_req_t req)1453 static struct fuse *req_fuse(fuse_req_t req)
1454 {
1455 return (struct fuse *) fuse_req_userdata(req);
1456 }
1457
fuse_intr_sighandler(int sig)1458 static void fuse_intr_sighandler(int sig)
1459 {
1460 (void) sig;
1461 /* Nothing to do */
1462 }
1463
1464 struct fuse_intr_data {
1465 pthread_t id;
1466 pthread_cond_t cond;
1467 int finished;
1468 };
1469
fuse_interrupt(fuse_req_t req,void * d_)1470 static void fuse_interrupt(fuse_req_t req, void *d_)
1471 {
1472 struct fuse_intr_data *d = d_;
1473 struct fuse *f = req_fuse(req);
1474
1475 if (d->id == pthread_self())
1476 return;
1477
1478 pthread_mutex_lock(&f->lock);
1479 while (!d->finished) {
1480 struct timeval now;
1481 struct timespec timeout;
1482
1483 pthread_kill(d->id, f->conf.intr_signal);
1484 gettimeofday(&now, NULL);
1485 timeout.tv_sec = now.tv_sec + 1;
1486 timeout.tv_nsec = now.tv_usec * 1000;
1487 pthread_cond_timedwait(&d->cond, &f->lock, &timeout);
1488 }
1489 pthread_mutex_unlock(&f->lock);
1490 }
1491
fuse_do_finish_interrupt(struct fuse * f,fuse_req_t req,struct fuse_intr_data * d)1492 static void fuse_do_finish_interrupt(struct fuse *f, fuse_req_t req,
1493 struct fuse_intr_data *d)
1494 {
1495 pthread_mutex_lock(&f->lock);
1496 d->finished = 1;
1497 pthread_cond_broadcast(&d->cond);
1498 pthread_mutex_unlock(&f->lock);
1499 fuse_req_interrupt_func(req, NULL, NULL);
1500 pthread_cond_destroy(&d->cond);
1501 }
1502
fuse_do_prepare_interrupt(fuse_req_t req,struct fuse_intr_data * d)1503 static void fuse_do_prepare_interrupt(fuse_req_t req, struct fuse_intr_data *d)
1504 {
1505 d->id = pthread_self();
1506 pthread_cond_init(&d->cond, NULL);
1507 d->finished = 0;
1508 fuse_req_interrupt_func(req, fuse_interrupt, d);
1509 }
1510
fuse_finish_interrupt(struct fuse * f,fuse_req_t req,struct fuse_intr_data * d)1511 static inline void fuse_finish_interrupt(struct fuse *f, fuse_req_t req,
1512 struct fuse_intr_data *d)
1513 {
1514 if (f->conf.intr)
1515 fuse_do_finish_interrupt(f, req, d);
1516 }
1517
fuse_prepare_interrupt(struct fuse * f,fuse_req_t req,struct fuse_intr_data * d)1518 static inline void fuse_prepare_interrupt(struct fuse *f, fuse_req_t req,
1519 struct fuse_intr_data *d)
1520 {
1521 if (f->conf.intr)
1522 fuse_do_prepare_interrupt(req, d);
1523 }
1524
1525 #if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__)
1526
fuse_compat_open(struct fuse_fs * fs,const char * path,struct fuse_file_info * fi)1527 static int fuse_compat_open(struct fuse_fs *fs, const char *path,
1528 struct fuse_file_info *fi)
1529 {
1530 int err;
1531 if (!fs->compat || fs->compat >= 25)
1532 err = fs->op.open(path, fi);
1533 else if (fs->compat == 22) {
1534 struct fuse_file_info_compat tmp;
1535 memcpy(&tmp, fi, sizeof(tmp));
1536 err = ((struct fuse_operations_compat22 *) &fs->op)->open(path,
1537 &tmp);
1538 memcpy(fi, &tmp, sizeof(tmp));
1539 fi->fh = tmp.fh;
1540 } else
1541 err = ((struct fuse_operations_compat2 *) &fs->op)
1542 ->open(path, fi->flags);
1543 return err;
1544 }
1545
fuse_compat_release(struct fuse_fs * fs,const char * path,struct fuse_file_info * fi)1546 static int fuse_compat_release(struct fuse_fs *fs, const char *path,
1547 struct fuse_file_info *fi)
1548 {
1549 if (!fs->compat || fs->compat >= 22)
1550 return fs->op.release(path, fi);
1551 else
1552 return ((struct fuse_operations_compat2 *) &fs->op)
1553 ->release(path, fi->flags);
1554 }
1555
fuse_compat_opendir(struct fuse_fs * fs,const char * path,struct fuse_file_info * fi)1556 static int fuse_compat_opendir(struct fuse_fs *fs, const char *path,
1557 struct fuse_file_info *fi)
1558 {
1559 if (!fs->compat || fs->compat >= 25)
1560 return fs->op.opendir(path, fi);
1561 else {
1562 int err;
1563 struct fuse_file_info_compat tmp;
1564 memcpy(&tmp, fi, sizeof(tmp));
1565 err = ((struct fuse_operations_compat22 *) &fs->op)
1566 ->opendir(path, &tmp);
1567 memcpy(fi, &tmp, sizeof(tmp));
1568 fi->fh = tmp.fh;
1569 return err;
1570 }
1571 }
1572
convert_statfs_compat(struct fuse_statfs_compat1 * compatbuf,struct statvfs * stbuf)1573 static void convert_statfs_compat(struct fuse_statfs_compat1 *compatbuf,
1574 struct statvfs *stbuf)
1575 {
1576 stbuf->f_bsize = compatbuf->block_size;
1577 stbuf->f_blocks = compatbuf->blocks;
1578 stbuf->f_bfree = compatbuf->blocks_free;
1579 stbuf->f_bavail = compatbuf->blocks_free;
1580 stbuf->f_files = compatbuf->files;
1581 stbuf->f_ffree = compatbuf->files_free;
1582 stbuf->f_namemax = compatbuf->namelen;
1583 }
1584
convert_statfs_old(struct statfs * oldbuf,struct statvfs * stbuf)1585 static void convert_statfs_old(struct statfs *oldbuf, struct statvfs *stbuf)
1586 {
1587 stbuf->f_bsize = oldbuf->f_bsize;
1588 stbuf->f_blocks = oldbuf->f_blocks;
1589 stbuf->f_bfree = oldbuf->f_bfree;
1590 stbuf->f_bavail = oldbuf->f_bavail;
1591 stbuf->f_files = oldbuf->f_files;
1592 stbuf->f_ffree = oldbuf->f_ffree;
1593 stbuf->f_namemax = oldbuf->f_namelen;
1594 }
1595
fuse_compat_statfs(struct fuse_fs * fs,const char * path,struct statvfs * buf)1596 static int fuse_compat_statfs(struct fuse_fs *fs, const char *path,
1597 struct statvfs *buf)
1598 {
1599 int err;
1600
1601 if (!fs->compat || fs->compat >= 25) {
1602 err = fs->op.statfs(fs->compat == 25 ? "/" : path, buf);
1603 } else if (fs->compat > 11) {
1604 struct statfs oldbuf;
1605 err = ((struct fuse_operations_compat22 *) &fs->op)
1606 ->statfs("/", &oldbuf);
1607 if (!err)
1608 convert_statfs_old(&oldbuf, buf);
1609 } else {
1610 struct fuse_statfs_compat1 compatbuf;
1611 memset(&compatbuf, 0, sizeof(struct fuse_statfs_compat1));
1612 err = ((struct fuse_operations_compat1 *) &fs->op)
1613 ->statfs(&compatbuf);
1614 if (!err)
1615 convert_statfs_compat(&compatbuf, buf);
1616 }
1617 return err;
1618 }
1619
1620 #else /* __FreeBSD__ || __NetBSD__ */
1621
fuse_compat_open(struct fuse_fs * fs,char * path,struct fuse_file_info * fi)1622 static inline int fuse_compat_open(struct fuse_fs *fs, char *path,
1623 struct fuse_file_info *fi)
1624 {
1625 return fs->op.open(path, fi);
1626 }
1627
fuse_compat_release(struct fuse_fs * fs,const char * path,struct fuse_file_info * fi)1628 static inline int fuse_compat_release(struct fuse_fs *fs, const char *path,
1629 struct fuse_file_info *fi)
1630 {
1631 return fs->op.release(path, fi);
1632 }
1633
fuse_compat_opendir(struct fuse_fs * fs,const char * path,struct fuse_file_info * fi)1634 static inline int fuse_compat_opendir(struct fuse_fs *fs, const char *path,
1635 struct fuse_file_info *fi)
1636 {
1637 return fs->op.opendir(path, fi);
1638 }
1639
fuse_compat_statfs(struct fuse_fs * fs,const char * path,struct statvfs * buf)1640 static inline int fuse_compat_statfs(struct fuse_fs *fs, const char *path,
1641 struct statvfs *buf)
1642 {
1643 return fs->op.statfs(fs->compat == 25 ? "/" : path, buf);
1644 }
1645
1646 #endif /* __FreeBSD__ || __NetBSD__ */
1647
fuse_fs_getattr(struct fuse_fs * fs,const char * path,struct stat * buf)1648 int fuse_fs_getattr(struct fuse_fs *fs, const char *path, struct stat *buf)
1649 {
1650 fuse_get_context()->private_data = fs->user_data;
1651 if (fs->op.getattr) {
1652 if (fs->debug)
1653 fprintf(stderr, "getattr %s\n", path);
1654
1655 return fs->op.getattr(path, buf);
1656 } else {
1657 return -ENOSYS;
1658 }
1659 }
1660
fuse_fs_fgetattr(struct fuse_fs * fs,const char * path,struct stat * buf,struct fuse_file_info * fi)1661 int fuse_fs_fgetattr(struct fuse_fs *fs, const char *path, struct stat *buf,
1662 struct fuse_file_info *fi)
1663 {
1664 fuse_get_context()->private_data = fs->user_data;
1665 if (fs->op.fgetattr) {
1666 if (fs->debug)
1667 fprintf(stderr, "fgetattr[%llu] %s\n",
1668 (unsigned long long) fi->fh, path);
1669
1670 return fs->op.fgetattr(path, buf, fi);
1671 } else if (path && fs->op.getattr) {
1672 if (fs->debug)
1673 fprintf(stderr, "getattr %s\n", path);
1674
1675 return fs->op.getattr(path, buf);
1676 } else {
1677 return -ENOSYS;
1678 }
1679 }
1680
fuse_fs_rename(struct fuse_fs * fs,const char * oldpath,const char * newpath)1681 int fuse_fs_rename(struct fuse_fs *fs, const char *oldpath,
1682 const char *newpath)
1683 {
1684 fuse_get_context()->private_data = fs->user_data;
1685 if (fs->op.rename) {
1686 if (fs->debug)
1687 fprintf(stderr, "rename %s %s\n", oldpath, newpath);
1688
1689 return fs->op.rename(oldpath, newpath);
1690 } else {
1691 return -ENOSYS;
1692 }
1693 }
1694
fuse_fs_unlink(struct fuse_fs * fs,const char * path)1695 int fuse_fs_unlink(struct fuse_fs *fs, const char *path)
1696 {
1697 fuse_get_context()->private_data = fs->user_data;
1698 if (fs->op.unlink) {
1699 if (fs->debug)
1700 fprintf(stderr, "unlink %s\n", path);
1701
1702 return fs->op.unlink(path);
1703 } else {
1704 return -ENOSYS;
1705 }
1706 }
1707
fuse_fs_rmdir(struct fuse_fs * fs,const char * path)1708 int fuse_fs_rmdir(struct fuse_fs *fs, const char *path)
1709 {
1710 fuse_get_context()->private_data = fs->user_data;
1711 if (fs->op.rmdir) {
1712 if (fs->debug)
1713 fprintf(stderr, "rmdir %s\n", path);
1714
1715 return fs->op.rmdir(path);
1716 } else {
1717 return -ENOSYS;
1718 }
1719 }
1720
fuse_fs_symlink(struct fuse_fs * fs,const char * linkname,const char * path)1721 int fuse_fs_symlink(struct fuse_fs *fs, const char *linkname, const char *path)
1722 {
1723 fuse_get_context()->private_data = fs->user_data;
1724 if (fs->op.symlink) {
1725 if (fs->debug)
1726 fprintf(stderr, "symlink %s %s\n", linkname, path);
1727
1728 return fs->op.symlink(linkname, path);
1729 } else {
1730 return -ENOSYS;
1731 }
1732 }
1733
fuse_fs_link(struct fuse_fs * fs,const char * oldpath,const char * newpath)1734 int fuse_fs_link(struct fuse_fs *fs, const char *oldpath, const char *newpath)
1735 {
1736 fuse_get_context()->private_data = fs->user_data;
1737 if (fs->op.link) {
1738 if (fs->debug)
1739 fprintf(stderr, "link %s %s\n", oldpath, newpath);
1740
1741 return fs->op.link(oldpath, newpath);
1742 } else {
1743 return -ENOSYS;
1744 }
1745 }
1746
fuse_fs_release(struct fuse_fs * fs,const char * path,struct fuse_file_info * fi)1747 int fuse_fs_release(struct fuse_fs *fs, const char *path,
1748 struct fuse_file_info *fi)
1749 {
1750 fuse_get_context()->private_data = fs->user_data;
1751 if (fs->op.release) {
1752 if (fs->debug)
1753 fprintf(stderr, "release%s[%llu] flags: 0x%x\n",
1754 fi->flush ? "+flush" : "",
1755 (unsigned long long) fi->fh, fi->flags);
1756
1757 return fuse_compat_release(fs, path, fi);
1758 } else {
1759 return 0;
1760 }
1761 }
1762
fuse_fs_opendir(struct fuse_fs * fs,const char * path,struct fuse_file_info * fi)1763 int fuse_fs_opendir(struct fuse_fs *fs, const char *path,
1764 struct fuse_file_info *fi)
1765 {
1766 fuse_get_context()->private_data = fs->user_data;
1767 if (fs->op.opendir) {
1768 int err;
1769
1770 if (fs->debug)
1771 fprintf(stderr, "opendir flags: 0x%x %s\n", fi->flags,
1772 path);
1773
1774 err = fuse_compat_opendir(fs, path, fi);
1775
1776 if (fs->debug && !err)
1777 fprintf(stderr, " opendir[%lli] flags: 0x%x %s\n",
1778 (unsigned long long) fi->fh, fi->flags, path);
1779
1780 return err;
1781 } else {
1782 return 0;
1783 }
1784 }
1785
fuse_fs_open(struct fuse_fs * fs,const char * path,struct fuse_file_info * fi)1786 int fuse_fs_open(struct fuse_fs *fs, const char *path,
1787 struct fuse_file_info *fi)
1788 {
1789 fuse_get_context()->private_data = fs->user_data;
1790 if (fs->op.open) {
1791 int err;
1792
1793 if (fs->debug)
1794 fprintf(stderr, "open flags: 0x%x %s\n", fi->flags,
1795 path);
1796
1797 err = fuse_compat_open(fs, path, fi);
1798
1799 if (fs->debug && !err)
1800 fprintf(stderr, " open[%lli] flags: 0x%x %s\n",
1801 (unsigned long long) fi->fh, fi->flags, path);
1802
1803 return err;
1804 } else {
1805 return 0;
1806 }
1807 }
1808
fuse_free_buf(struct fuse_bufvec * buf)1809 static void fuse_free_buf(struct fuse_bufvec *buf)
1810 {
1811 if (buf != NULL) {
1812 size_t i;
1813
1814 for (i = 0; i < buf->count; i++)
1815 free(buf->buf[i].mem);
1816 free(buf);
1817 }
1818 }
1819
fuse_fs_read_buf(struct fuse_fs * fs,const char * path,struct fuse_bufvec ** bufp,size_t size,off_t off,struct fuse_file_info * fi)1820 int fuse_fs_read_buf(struct fuse_fs *fs, const char *path,
1821 struct fuse_bufvec **bufp, size_t size, off_t off,
1822 struct fuse_file_info *fi)
1823 {
1824 fuse_get_context()->private_data = fs->user_data;
1825 if (fs->op.read || fs->op.read_buf) {
1826 int res;
1827
1828 if (fs->debug)
1829 fprintf(stderr,
1830 "read[%llu] %zu bytes from %llu flags: 0x%x\n",
1831 (unsigned long long) fi->fh,
1832 size, (unsigned long long) off, fi->flags);
1833
1834 if (fs->op.read_buf) {
1835 res = fs->op.read_buf(path, bufp, size, off, fi);
1836 } else {
1837 struct fuse_bufvec *buf;
1838 void *mem;
1839
1840 buf = malloc(sizeof(struct fuse_bufvec));
1841 if (buf == NULL)
1842 return -ENOMEM;
1843
1844 mem = malloc(size);
1845 if (mem == NULL) {
1846 free(buf);
1847 return -ENOMEM;
1848 }
1849 *buf = FUSE_BUFVEC_INIT(size);
1850 buf->buf[0].mem = mem;
1851 *bufp = buf;
1852
1853 res = fs->op.read(path, mem, size, off, fi);
1854 if (res >= 0)
1855 buf->buf[0].size = res;
1856 }
1857
1858 if (fs->debug && res >= 0)
1859 fprintf(stderr, " read[%llu] %zu bytes from %llu\n",
1860 (unsigned long long) fi->fh,
1861 fuse_buf_size(*bufp),
1862 (unsigned long long) off);
1863 if (res >= 0 && fuse_buf_size(*bufp) > (int) size)
1864 fprintf(stderr, "fuse: read too many bytes\n");
1865
1866 if (res < 0)
1867 return res;
1868
1869 return 0;
1870 } else {
1871 return -ENOSYS;
1872 }
1873 }
1874
fuse_fs_read(struct fuse_fs * fs,const char * path,char * mem,size_t size,off_t off,struct fuse_file_info * fi)1875 int fuse_fs_read(struct fuse_fs *fs, const char *path, char *mem, size_t size,
1876 off_t off, struct fuse_file_info *fi)
1877 {
1878 int res;
1879 struct fuse_bufvec *buf = NULL;
1880
1881 res = fuse_fs_read_buf(fs, path, &buf, size, off, fi);
1882 if (res == 0) {
1883 struct fuse_bufvec dst = FUSE_BUFVEC_INIT(size);
1884
1885 dst.buf[0].mem = mem;
1886 res = fuse_buf_copy(&dst, buf, 0);
1887 }
1888 fuse_free_buf(buf);
1889
1890 return res;
1891 }
1892
fuse_fs_write_buf(struct fuse_fs * fs,const char * path,struct fuse_bufvec * buf,off_t off,struct fuse_file_info * fi)1893 int fuse_fs_write_buf(struct fuse_fs *fs, const char *path,
1894 struct fuse_bufvec *buf, off_t off,
1895 struct fuse_file_info *fi)
1896 {
1897 fuse_get_context()->private_data = fs->user_data;
1898 if (fs->op.write_buf || fs->op.write) {
1899 int res;
1900 size_t size = fuse_buf_size(buf);
1901
1902 assert(buf->idx == 0 && buf->off == 0);
1903 if (fs->debug)
1904 fprintf(stderr,
1905 "write%s[%llu] %zu bytes to %llu flags: 0x%x\n",
1906 fi->writepage ? "page" : "",
1907 (unsigned long long) fi->fh,
1908 size,
1909 (unsigned long long) off,
1910 fi->flags);
1911
1912 if (fs->op.write_buf) {
1913 res = fs->op.write_buf(path, buf, off, fi);
1914 } else {
1915 void *mem = NULL;
1916 struct fuse_buf *flatbuf;
1917 struct fuse_bufvec tmp = FUSE_BUFVEC_INIT(size);
1918
1919 if (buf->count == 1 &&
1920 !(buf->buf[0].flags & FUSE_BUF_IS_FD)) {
1921 flatbuf = &buf->buf[0];
1922 } else {
1923 res = -ENOMEM;
1924 mem = malloc(size);
1925 if (mem == NULL)
1926 goto out;
1927
1928 tmp.buf[0].mem = mem;
1929 res = fuse_buf_copy(&tmp, buf, 0);
1930 if (res <= 0)
1931 goto out_free;
1932
1933 tmp.buf[0].size = res;
1934 flatbuf = &tmp.buf[0];
1935 }
1936
1937 res = fs->op.write(path, flatbuf->mem, flatbuf->size,
1938 off, fi);
1939 out_free:
1940 free(mem);
1941 }
1942 out:
1943 if (fs->debug && res >= 0)
1944 fprintf(stderr, " write%s[%llu] %u bytes to %llu\n",
1945 fi->writepage ? "page" : "",
1946 (unsigned long long) fi->fh, res,
1947 (unsigned long long) off);
1948 if (res > (int) size)
1949 fprintf(stderr, "fuse: wrote too many bytes\n");
1950
1951 return res;
1952 } else {
1953 return -ENOSYS;
1954 }
1955 }
1956
fuse_fs_write(struct fuse_fs * fs,const char * path,const char * mem,size_t size,off_t off,struct fuse_file_info * fi)1957 int fuse_fs_write(struct fuse_fs *fs, const char *path, const char *mem,
1958 size_t size, off_t off, struct fuse_file_info *fi)
1959 {
1960 struct fuse_bufvec bufv = FUSE_BUFVEC_INIT(size);
1961
1962 bufv.buf[0].mem = (void *) mem;
1963
1964 return fuse_fs_write_buf(fs, path, &bufv, off, fi);
1965 }
1966
fuse_fs_fsync(struct fuse_fs * fs,const char * path,int datasync,struct fuse_file_info * fi)1967 int fuse_fs_fsync(struct fuse_fs *fs, const char *path, int datasync,
1968 struct fuse_file_info *fi)
1969 {
1970 fuse_get_context()->private_data = fs->user_data;
1971 if (fs->op.fsync) {
1972 if (fs->debug)
1973 fprintf(stderr, "fsync[%llu] datasync: %i\n",
1974 (unsigned long long) fi->fh, datasync);
1975
1976 return fs->op.fsync(path, datasync, fi);
1977 } else {
1978 return -ENOSYS;
1979 }
1980 }
1981
fuse_fs_fsyncdir(struct fuse_fs * fs,const char * path,int datasync,struct fuse_file_info * fi)1982 int fuse_fs_fsyncdir(struct fuse_fs *fs, const char *path, int datasync,
1983 struct fuse_file_info *fi)
1984 {
1985 fuse_get_context()->private_data = fs->user_data;
1986 if (fs->op.fsyncdir) {
1987 if (fs->debug)
1988 fprintf(stderr, "fsyncdir[%llu] datasync: %i\n",
1989 (unsigned long long) fi->fh, datasync);
1990
1991 return fs->op.fsyncdir(path, datasync, fi);
1992 } else {
1993 return -ENOSYS;
1994 }
1995 }
1996
fuse_fs_flush(struct fuse_fs * fs,const char * path,struct fuse_file_info * fi)1997 int fuse_fs_flush(struct fuse_fs *fs, const char *path,
1998 struct fuse_file_info *fi)
1999 {
2000 fuse_get_context()->private_data = fs->user_data;
2001 if (fs->op.flush) {
2002 if (fs->debug)
2003 fprintf(stderr, "flush[%llu]\n",
2004 (unsigned long long) fi->fh);
2005
2006 return fs->op.flush(path, fi);
2007 } else {
2008 return -ENOSYS;
2009 }
2010 }
2011
fuse_fs_statfs(struct fuse_fs * fs,const char * path,struct statvfs * buf)2012 int fuse_fs_statfs(struct fuse_fs *fs, const char *path, struct statvfs *buf)
2013 {
2014 fuse_get_context()->private_data = fs->user_data;
2015 if (fs->op.statfs) {
2016 if (fs->debug)
2017 fprintf(stderr, "statfs %s\n", path);
2018
2019 return fuse_compat_statfs(fs, path, buf);
2020 } else {
2021 buf->f_namemax = 255;
2022 buf->f_bsize = 512;
2023 return 0;
2024 }
2025 }
2026
fuse_fs_releasedir(struct fuse_fs * fs,const char * path,struct fuse_file_info * fi)2027 int fuse_fs_releasedir(struct fuse_fs *fs, const char *path,
2028 struct fuse_file_info *fi)
2029 {
2030 fuse_get_context()->private_data = fs->user_data;
2031 if (fs->op.releasedir) {
2032 if (fs->debug)
2033 fprintf(stderr, "releasedir[%llu] flags: 0x%x\n",
2034 (unsigned long long) fi->fh, fi->flags);
2035
2036 return fs->op.releasedir(path, fi);
2037 } else {
2038 return 0;
2039 }
2040 }
2041
fill_dir_old(struct fuse_dirhandle * dh,const char * name,int type,ino_t ino)2042 static int fill_dir_old(struct fuse_dirhandle *dh, const char *name, int type,
2043 ino_t ino)
2044 {
2045 int res;
2046 struct stat stbuf;
2047
2048 memset(&stbuf, 0, sizeof(stbuf));
2049 stbuf.st_mode = type << 12;
2050 stbuf.st_ino = ino;
2051
2052 res = dh->filler(dh->buf, name, &stbuf, 0);
2053 return res ? -ENOMEM : 0;
2054 }
2055
fuse_fs_readdir(struct fuse_fs * fs,const char * path,void * buf,fuse_fill_dir_t filler,off_t off,struct fuse_file_info * fi)2056 int fuse_fs_readdir(struct fuse_fs *fs, const char *path, void *buf,
2057 fuse_fill_dir_t filler, off_t off,
2058 struct fuse_file_info *fi)
2059 {
2060 fuse_get_context()->private_data = fs->user_data;
2061 if (fs->op.readdir) {
2062 if (fs->debug)
2063 fprintf(stderr, "readdir[%llu] from %llu\n",
2064 (unsigned long long) fi->fh,
2065 (unsigned long long) off);
2066
2067 return fs->op.readdir(path, buf, filler, off, fi);
2068 } else if (fs->op.getdir) {
2069 struct fuse_dirhandle dh;
2070
2071 if (fs->debug)
2072 fprintf(stderr, "getdir[%llu]\n",
2073 (unsigned long long) fi->fh);
2074
2075 dh.filler = filler;
2076 dh.buf = buf;
2077 return fs->op.getdir(path, &dh, fill_dir_old);
2078 } else {
2079 return -ENOSYS;
2080 }
2081 }
2082
fuse_fs_create(struct fuse_fs * fs,const char * path,mode_t mode,struct fuse_file_info * fi)2083 int fuse_fs_create(struct fuse_fs *fs, const char *path, mode_t mode,
2084 struct fuse_file_info *fi)
2085 {
2086 fuse_get_context()->private_data = fs->user_data;
2087 if (fs->op.create) {
2088 int err;
2089
2090 if (fs->debug)
2091 fprintf(stderr,
2092 "create flags: 0x%x %s 0%o umask=0%03o\n",
2093 fi->flags, path, mode,
2094 fuse_get_context()->umask);
2095
2096 err = fs->op.create(path, mode, fi);
2097
2098 if (fs->debug && !err)
2099 fprintf(stderr, " create[%llu] flags: 0x%x %s\n",
2100 (unsigned long long) fi->fh, fi->flags, path);
2101
2102 return err;
2103 } else {
2104 return -ENOSYS;
2105 }
2106 }
2107
fuse_fs_lock(struct fuse_fs * fs,const char * path,struct fuse_file_info * fi,int cmd,struct flock * lock)2108 int fuse_fs_lock(struct fuse_fs *fs, const char *path,
2109 struct fuse_file_info *fi, int cmd, struct flock *lock)
2110 {
2111 fuse_get_context()->private_data = fs->user_data;
2112 if (fs->op.lock) {
2113 if (fs->debug)
2114 fprintf(stderr, "lock[%llu] %s %s start: %llu len: %llu pid: %llu\n",
2115 (unsigned long long) fi->fh,
2116 (cmd == F_GETLK ? "F_GETLK" :
2117 (cmd == F_SETLK ? "F_SETLK" :
2118 (cmd == F_SETLKW ? "F_SETLKW" : "???"))),
2119 (lock->l_type == F_RDLCK ? "F_RDLCK" :
2120 (lock->l_type == F_WRLCK ? "F_WRLCK" :
2121 (lock->l_type == F_UNLCK ? "F_UNLCK" :
2122 "???"))),
2123 (unsigned long long) lock->l_start,
2124 (unsigned long long) lock->l_len,
2125 (unsigned long long) lock->l_pid);
2126
2127 return fs->op.lock(path, fi, cmd, lock);
2128 } else {
2129 return -ENOSYS;
2130 }
2131 }
2132
fuse_fs_flock(struct fuse_fs * fs,const char * path,struct fuse_file_info * fi,int op)2133 int fuse_fs_flock(struct fuse_fs *fs, const char *path,
2134 struct fuse_file_info *fi, int op)
2135 {
2136 fuse_get_context()->private_data = fs->user_data;
2137 if (fs->op.flock) {
2138 if (fs->debug) {
2139 int xop = op & ~LOCK_NB;
2140
2141 fprintf(stderr, "lock[%llu] %s%s\n",
2142 (unsigned long long) fi->fh,
2143 xop == LOCK_SH ? "LOCK_SH" :
2144 (xop == LOCK_EX ? "LOCK_EX" :
2145 (xop == LOCK_UN ? "LOCK_UN" : "???")),
2146 (op & LOCK_NB) ? "|LOCK_NB" : "");
2147 }
2148 return fs->op.flock(path, fi, op);
2149 } else {
2150 return -ENOSYS;
2151 }
2152 }
2153
fuse_fs_chown(struct fuse_fs * fs,const char * path,uid_t uid,gid_t gid)2154 int fuse_fs_chown(struct fuse_fs *fs, const char *path, uid_t uid, gid_t gid)
2155 {
2156 fuse_get_context()->private_data = fs->user_data;
2157 if (fs->op.chown) {
2158 if (fs->debug)
2159 fprintf(stderr, "chown %s %lu %lu\n", path,
2160 (unsigned long) uid, (unsigned long) gid);
2161
2162 return fs->op.chown(path, uid, gid);
2163 } else {
2164 return -ENOSYS;
2165 }
2166 }
2167
fuse_fs_truncate(struct fuse_fs * fs,const char * path,off_t size)2168 int fuse_fs_truncate(struct fuse_fs *fs, const char *path, off_t size)
2169 {
2170 fuse_get_context()->private_data = fs->user_data;
2171 if (fs->op.truncate) {
2172 if (fs->debug)
2173 fprintf(stderr, "truncate %s %llu\n", path,
2174 (unsigned long long) size);
2175
2176 return fs->op.truncate(path, size);
2177 } else {
2178 return -ENOSYS;
2179 }
2180 }
2181
fuse_fs_ftruncate(struct fuse_fs * fs,const char * path,off_t size,struct fuse_file_info * fi)2182 int fuse_fs_ftruncate(struct fuse_fs *fs, const char *path, off_t size,
2183 struct fuse_file_info *fi)
2184 {
2185 fuse_get_context()->private_data = fs->user_data;
2186 if (fs->op.ftruncate) {
2187 if (fs->debug)
2188 fprintf(stderr, "ftruncate[%llu] %llu\n",
2189 (unsigned long long) fi->fh,
2190 (unsigned long long) size);
2191
2192 return fs->op.ftruncate(path, size, fi);
2193 } else if (path && fs->op.truncate) {
2194 if (fs->debug)
2195 fprintf(stderr, "truncate %s %llu\n", path,
2196 (unsigned long long) size);
2197
2198 return fs->op.truncate(path, size);
2199 } else {
2200 return -ENOSYS;
2201 }
2202 }
2203
fuse_fs_utimens(struct fuse_fs * fs,const char * path,const struct timespec tv[2])2204 int fuse_fs_utimens(struct fuse_fs *fs, const char *path,
2205 const struct timespec tv[2])
2206 {
2207 fuse_get_context()->private_data = fs->user_data;
2208 if (fs->op.utimens) {
2209 if (fs->debug)
2210 fprintf(stderr, "utimens %s %li.%09lu %li.%09lu\n",
2211 path, tv[0].tv_sec, tv[0].tv_nsec,
2212 tv[1].tv_sec, tv[1].tv_nsec);
2213
2214 return fs->op.utimens(path, tv);
2215 } else if(fs->op.utime) {
2216 struct utimbuf buf;
2217
2218 if (fs->debug)
2219 fprintf(stderr, "utime %s %li %li\n", path,
2220 tv[0].tv_sec, tv[1].tv_sec);
2221
2222 buf.actime = tv[0].tv_sec;
2223 buf.modtime = tv[1].tv_sec;
2224 return fs->op.utime(path, &buf);
2225 } else {
2226 return -ENOSYS;
2227 }
2228 }
2229
fuse_fs_access(struct fuse_fs * fs,const char * path,int mask)2230 int fuse_fs_access(struct fuse_fs *fs, const char *path, int mask)
2231 {
2232 fuse_get_context()->private_data = fs->user_data;
2233 if (fs->op.access) {
2234 if (fs->debug)
2235 fprintf(stderr, "access %s 0%o\n", path, mask);
2236
2237 return fs->op.access(path, mask);
2238 } else {
2239 return -ENOSYS;
2240 }
2241 }
2242
fuse_fs_readlink(struct fuse_fs * fs,const char * path,char * buf,size_t len)2243 int fuse_fs_readlink(struct fuse_fs *fs, const char *path, char *buf,
2244 size_t len)
2245 {
2246 fuse_get_context()->private_data = fs->user_data;
2247 if (fs->op.readlink) {
2248 if (fs->debug)
2249 fprintf(stderr, "readlink %s %lu\n", path,
2250 (unsigned long) len);
2251
2252 return fs->op.readlink(path, buf, len);
2253 } else {
2254 return -ENOSYS;
2255 }
2256 }
2257
fuse_fs_mknod(struct fuse_fs * fs,const char * path,mode_t mode,dev_t rdev)2258 int fuse_fs_mknod(struct fuse_fs *fs, const char *path, mode_t mode,
2259 dev_t rdev)
2260 {
2261 fuse_get_context()->private_data = fs->user_data;
2262 if (fs->op.mknod) {
2263 if (fs->debug)
2264 fprintf(stderr, "mknod %s 0%o 0x%llx umask=0%03o\n",
2265 path, mode, (unsigned long long) rdev,
2266 fuse_get_context()->umask);
2267
2268 return fs->op.mknod(path, mode, rdev);
2269 } else {
2270 return -ENOSYS;
2271 }
2272 }
2273
fuse_fs_mkdir(struct fuse_fs * fs,const char * path,mode_t mode)2274 int fuse_fs_mkdir(struct fuse_fs *fs, const char *path, mode_t mode)
2275 {
2276 fuse_get_context()->private_data = fs->user_data;
2277 if (fs->op.mkdir) {
2278 if (fs->debug)
2279 fprintf(stderr, "mkdir %s 0%o umask=0%03o\n",
2280 path, mode, fuse_get_context()->umask);
2281
2282 return fs->op.mkdir(path, mode);
2283 } else {
2284 return -ENOSYS;
2285 }
2286 }
2287
fuse_fs_setxattr(struct fuse_fs * fs,const char * path,const char * name,const char * value,size_t size,int flags)2288 int fuse_fs_setxattr(struct fuse_fs *fs, const char *path, const char *name,
2289 const char *value, size_t size, int flags)
2290 {
2291 fuse_get_context()->private_data = fs->user_data;
2292 if (fs->op.setxattr) {
2293 if (fs->debug)
2294 fprintf(stderr, "setxattr %s %s %lu 0x%x\n",
2295 path, name, (unsigned long) size, flags);
2296
2297 return fs->op.setxattr(path, name, value, size, flags);
2298 } else {
2299 return -ENOSYS;
2300 }
2301 }
2302
fuse_fs_getxattr(struct fuse_fs * fs,const char * path,const char * name,char * value,size_t size)2303 int fuse_fs_getxattr(struct fuse_fs *fs, const char *path, const char *name,
2304 char *value, size_t size)
2305 {
2306 fuse_get_context()->private_data = fs->user_data;
2307 if (fs->op.getxattr) {
2308 if (fs->debug)
2309 fprintf(stderr, "getxattr %s %s %lu\n",
2310 path, name, (unsigned long) size);
2311
2312 return fs->op.getxattr(path, name, value, size);
2313 } else {
2314 return -ENOSYS;
2315 }
2316 }
2317
fuse_fs_listxattr(struct fuse_fs * fs,const char * path,char * list,size_t size)2318 int fuse_fs_listxattr(struct fuse_fs *fs, const char *path, char *list,
2319 size_t size)
2320 {
2321 fuse_get_context()->private_data = fs->user_data;
2322 if (fs->op.listxattr) {
2323 if (fs->debug)
2324 fprintf(stderr, "listxattr %s %lu\n",
2325 path, (unsigned long) size);
2326
2327 return fs->op.listxattr(path, list, size);
2328 } else {
2329 return -ENOSYS;
2330 }
2331 }
2332
fuse_fs_bmap(struct fuse_fs * fs,const char * path,size_t blocksize,uint64_t * idx)2333 int fuse_fs_bmap(struct fuse_fs *fs, const char *path, size_t blocksize,
2334 uint64_t *idx)
2335 {
2336 fuse_get_context()->private_data = fs->user_data;
2337 if (fs->op.bmap) {
2338 if (fs->debug)
2339 fprintf(stderr, "bmap %s blocksize: %lu index: %llu\n",
2340 path, (unsigned long) blocksize,
2341 (unsigned long long) *idx);
2342
2343 return fs->op.bmap(path, blocksize, idx);
2344 } else {
2345 return -ENOSYS;
2346 }
2347 }
2348
fuse_fs_removexattr(struct fuse_fs * fs,const char * path,const char * name)2349 int fuse_fs_removexattr(struct fuse_fs *fs, const char *path, const char *name)
2350 {
2351 fuse_get_context()->private_data = fs->user_data;
2352 if (fs->op.removexattr) {
2353 if (fs->debug)
2354 fprintf(stderr, "removexattr %s %s\n", path, name);
2355
2356 return fs->op.removexattr(path, name);
2357 } else {
2358 return -ENOSYS;
2359 }
2360 }
2361
fuse_fs_ioctl(struct fuse_fs * fs,const char * path,int cmd,void * arg,struct fuse_file_info * fi,unsigned int flags,void * data)2362 int fuse_fs_ioctl(struct fuse_fs *fs, const char *path, int cmd, void *arg,
2363 struct fuse_file_info *fi, unsigned int flags, void *data)
2364 {
2365 fuse_get_context()->private_data = fs->user_data;
2366 if (fs->op.ioctl) {
2367 if (fs->debug)
2368 fprintf(stderr, "ioctl[%llu] 0x%x flags: 0x%x\n",
2369 (unsigned long long) fi->fh, cmd, flags);
2370
2371 return fs->op.ioctl(path, cmd, arg, fi, flags, data);
2372 } else
2373 return -ENOSYS;
2374 }
2375
fuse_fs_poll(struct fuse_fs * fs,const char * path,struct fuse_file_info * fi,struct fuse_pollhandle * ph,unsigned * reventsp)2376 int fuse_fs_poll(struct fuse_fs *fs, const char *path,
2377 struct fuse_file_info *fi, struct fuse_pollhandle *ph,
2378 unsigned *reventsp)
2379 {
2380 fuse_get_context()->private_data = fs->user_data;
2381 if (fs->op.poll) {
2382 int res;
2383
2384 if (fs->debug)
2385 fprintf(stderr, "poll[%llu] ph: %p\n",
2386 (unsigned long long) fi->fh, ph);
2387
2388 res = fs->op.poll(path, fi, ph, reventsp);
2389
2390 if (fs->debug && !res)
2391 fprintf(stderr, " poll[%llu] revents: 0x%x\n",
2392 (unsigned long long) fi->fh, *reventsp);
2393
2394 return res;
2395 } else
2396 return -ENOSYS;
2397 }
2398
fuse_fs_fallocate(struct fuse_fs * fs,const char * path,int mode,off_t offset,off_t length,struct fuse_file_info * fi)2399 int fuse_fs_fallocate(struct fuse_fs *fs, const char *path, int mode,
2400 off_t offset, off_t length, struct fuse_file_info *fi)
2401 {
2402 fuse_get_context()->private_data = fs->user_data;
2403 if (fs->op.fallocate) {
2404 if (fs->debug)
2405 fprintf(stderr, "fallocate %s mode %x, offset: %llu, length: %llu\n",
2406 path,
2407 mode,
2408 (unsigned long long) offset,
2409 (unsigned long long) length);
2410
2411 return fs->op.fallocate(path, mode, offset, length, fi);
2412 } else
2413 return -ENOSYS;
2414 }
2415
is_open(struct fuse * f,fuse_ino_t dir,const char * name)2416 static int is_open(struct fuse *f, fuse_ino_t dir, const char *name)
2417 {
2418 struct node *node;
2419 int isopen = 0;
2420 pthread_mutex_lock(&f->lock);
2421 node = lookup_node(f, dir, name);
2422 if (node && node->open_count > 0)
2423 isopen = 1;
2424 pthread_mutex_unlock(&f->lock);
2425 return isopen;
2426 }
2427
hidden_name(struct fuse * f,fuse_ino_t dir,const char * oldname,char * newname,size_t bufsize)2428 static char *hidden_name(struct fuse *f, fuse_ino_t dir, const char *oldname,
2429 char *newname, size_t bufsize)
2430 {
2431 struct stat buf;
2432 struct node *node;
2433 struct node *newnode;
2434 char *newpath;
2435 int res;
2436 int failctr = 10;
2437
2438 do {
2439 pthread_mutex_lock(&f->lock);
2440 node = lookup_node(f, dir, oldname);
2441 if (node == NULL) {
2442 pthread_mutex_unlock(&f->lock);
2443 return NULL;
2444 }
2445 do {
2446 f->hidectr ++;
2447 snprintf(newname, bufsize, ".fuse_hidden%08x%08x",
2448 (unsigned int) node->nodeid, f->hidectr);
2449 newnode = lookup_node(f, dir, newname);
2450 } while(newnode);
2451
2452 res = try_get_path(f, dir, newname, &newpath, NULL, false);
2453 pthread_mutex_unlock(&f->lock);
2454 if (res)
2455 break;
2456
2457 memset(&buf, 0, sizeof(buf));
2458 res = fuse_fs_getattr(f->fs, newpath, &buf);
2459 if (res == -ENOENT)
2460 break;
2461 free(newpath);
2462 newpath = NULL;
2463 } while(res == 0 && --failctr);
2464
2465 return newpath;
2466 }
2467
hide_node(struct fuse * f,const char * oldpath,fuse_ino_t dir,const char * oldname)2468 static int hide_node(struct fuse *f, const char *oldpath,
2469 fuse_ino_t dir, const char *oldname)
2470 {
2471 char newname[64];
2472 char *newpath;
2473 int err = -EBUSY;
2474
2475 newpath = hidden_name(f, dir, oldname, newname, sizeof(newname));
2476 if (newpath) {
2477 err = fuse_fs_rename(f->fs, oldpath, newpath);
2478 if (!err)
2479 err = rename_node(f, dir, oldname, dir, newname, 1);
2480 free(newpath);
2481 }
2482 return err;
2483 }
2484
mtime_eq(const struct stat * stbuf,const struct timespec * ts)2485 static int mtime_eq(const struct stat *stbuf, const struct timespec *ts)
2486 {
2487 return stbuf->st_mtime == ts->tv_sec &&
2488 ST_MTIM_NSEC(stbuf) == ts->tv_nsec;
2489 }
2490
2491 #ifndef CLOCK_MONOTONIC
2492 #define CLOCK_MONOTONIC CLOCK_REALTIME
2493 #endif
2494
curr_time(struct timespec * now)2495 static void curr_time(struct timespec *now)
2496 {
2497 static clockid_t clockid = CLOCK_MONOTONIC;
2498 int res = clock_gettime(clockid, now);
2499 if (res == -1 && errno == EINVAL) {
2500 clockid = CLOCK_REALTIME;
2501 res = clock_gettime(clockid, now);
2502 }
2503 if (res == -1) {
2504 perror("fuse: clock_gettime");
2505 abort();
2506 }
2507 }
2508
update_stat(struct node * node,const struct stat * stbuf)2509 static void update_stat(struct node *node, const struct stat *stbuf)
2510 {
2511 if (node->cache_valid && (!mtime_eq(stbuf, &node->mtime) ||
2512 stbuf->st_size != node->size))
2513 node->cache_valid = 0;
2514 node->mtime.tv_sec = stbuf->st_mtime;
2515 node->mtime.tv_nsec = ST_MTIM_NSEC(stbuf);
2516 node->size = stbuf->st_size;
2517 curr_time(&node->stat_updated);
2518 }
2519
lookup_path(struct fuse * f,fuse_ino_t nodeid,const char * name,const char * path,struct fuse_entry_param * e,struct fuse_file_info * fi)2520 static int lookup_path(struct fuse *f, fuse_ino_t nodeid,
2521 const char *name, const char *path,
2522 struct fuse_entry_param *e, struct fuse_file_info *fi)
2523 {
2524 int res;
2525
2526 memset(e, 0, sizeof(struct fuse_entry_param));
2527 if (fi)
2528 res = fuse_fs_fgetattr(f->fs, path, &e->attr, fi);
2529 else
2530 res = fuse_fs_getattr(f->fs, path, &e->attr);
2531 if (res == 0) {
2532 struct node *node;
2533
2534 node = find_node(f, nodeid, name);
2535 if (node == NULL)
2536 res = -ENOMEM;
2537 else {
2538 e->ino = node->nodeid;
2539 e->generation = node->generation;
2540 e->entry_timeout = f->conf.entry_timeout;
2541 e->attr_timeout = f->conf.attr_timeout;
2542 if (f->conf.auto_cache) {
2543 pthread_mutex_lock(&f->lock);
2544 update_stat(node, &e->attr);
2545 pthread_mutex_unlock(&f->lock);
2546 }
2547 set_stat(f, e->ino, &e->attr);
2548 if (f->conf.debug)
2549 fprintf(stderr, " NODEID: %lu\n",
2550 (unsigned long) e->ino);
2551 }
2552 }
2553 return res;
2554 }
2555
fuse_get_context_internal(void)2556 static struct fuse_context_i *fuse_get_context_internal(void)
2557 {
2558 struct fuse_context_i *c;
2559
2560 c = (struct fuse_context_i *) pthread_getspecific(fuse_context_key);
2561 if (c == NULL) {
2562 c = (struct fuse_context_i *)
2563 calloc(1, sizeof(struct fuse_context_i));
2564 if (c == NULL) {
2565 /* This is hard to deal with properly, so just
2566 abort. If memory is so low that the
2567 context cannot be allocated, there's not
2568 much hope for the filesystem anyway */
2569 fprintf(stderr, "fuse: failed to allocate thread specific data\n");
2570 abort();
2571 }
2572 pthread_setspecific(fuse_context_key, c);
2573 }
2574 return c;
2575 }
2576
fuse_freecontext(void * data)2577 static void fuse_freecontext(void *data)
2578 {
2579 free(data);
2580 }
2581
fuse_create_context_key(void)2582 static int fuse_create_context_key(void)
2583 {
2584 int err = 0;
2585 pthread_mutex_lock(&fuse_context_lock);
2586 if (!fuse_context_ref) {
2587 err = pthread_key_create(&fuse_context_key, fuse_freecontext);
2588 if (err) {
2589 fprintf(stderr, "fuse: failed to create thread specific key: %s\n",
2590 strerror(err));
2591 pthread_mutex_unlock(&fuse_context_lock);
2592 return -1;
2593 }
2594 }
2595 fuse_context_ref++;
2596 pthread_mutex_unlock(&fuse_context_lock);
2597 return 0;
2598 }
2599
fuse_delete_context_key(void)2600 static void fuse_delete_context_key(void)
2601 {
2602 pthread_mutex_lock(&fuse_context_lock);
2603 fuse_context_ref--;
2604 if (!fuse_context_ref) {
2605 free(pthread_getspecific(fuse_context_key));
2606 pthread_key_delete(fuse_context_key);
2607 }
2608 pthread_mutex_unlock(&fuse_context_lock);
2609 }
2610
req_fuse_prepare(fuse_req_t req)2611 static struct fuse *req_fuse_prepare(fuse_req_t req)
2612 {
2613 struct fuse_context_i *c = fuse_get_context_internal();
2614 const struct fuse_ctx *ctx = fuse_req_ctx(req);
2615 c->req = req;
2616 c->ctx.fuse = req_fuse(req);
2617 c->ctx.uid = ctx->uid;
2618 c->ctx.gid = ctx->gid;
2619 c->ctx.pid = ctx->pid;
2620 c->ctx.umask = ctx->umask;
2621 return c->ctx.fuse;
2622 }
2623
reply_err(fuse_req_t req,int err)2624 static inline void reply_err(fuse_req_t req, int err)
2625 {
2626 /* fuse_reply_err() uses non-negated errno values */
2627 fuse_reply_err(req, -err);
2628 }
2629
reply_entry(fuse_req_t req,const struct fuse_entry_param * e,int err)2630 static void reply_entry(fuse_req_t req, const struct fuse_entry_param *e,
2631 int err)
2632 {
2633 if (!err) {
2634 struct fuse *f = req_fuse(req);
2635 if (fuse_reply_entry(req, e) == -ENOENT) {
2636 /* Skip forget for negative result */
2637 if (e->ino != 0)
2638 forget_node(f, e->ino, 1);
2639 }
2640 } else
2641 reply_err(req, err);
2642 }
2643
fuse_fs_init(struct fuse_fs * fs,struct fuse_conn_info * conn)2644 void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn)
2645 {
2646 fuse_get_context()->private_data = fs->user_data;
2647 if (!fs->op.write_buf)
2648 conn->want &= ~FUSE_CAP_SPLICE_READ;
2649 if (!fs->op.lock)
2650 conn->want &= ~FUSE_CAP_POSIX_LOCKS;
2651 if (!fs->op.flock)
2652 conn->want &= ~FUSE_CAP_FLOCK_LOCKS;
2653 if (fs->op.init)
2654 fs->user_data = fs->op.init(conn);
2655 }
2656
fuse_lib_init(void * data,struct fuse_conn_info * conn)2657 static void fuse_lib_init(void *data, struct fuse_conn_info *conn)
2658 {
2659 struct fuse *f = (struct fuse *) data;
2660 struct fuse_context_i *c = fuse_get_context_internal();
2661
2662 memset(c, 0, sizeof(*c));
2663 c->ctx.fuse = f;
2664 conn->want |= FUSE_CAP_EXPORT_SUPPORT;
2665 fuse_fs_init(f->fs, conn);
2666 }
2667
fuse_fs_destroy(struct fuse_fs * fs)2668 void fuse_fs_destroy(struct fuse_fs *fs)
2669 {
2670 fuse_get_context()->private_data = fs->user_data;
2671 if (fs->op.destroy)
2672 fs->op.destroy(fs->user_data);
2673 if (fs->m)
2674 fuse_put_module(fs->m);
2675 free(fs);
2676 }
2677
fuse_lib_destroy(void * data)2678 static void fuse_lib_destroy(void *data)
2679 {
2680 struct fuse *f = (struct fuse *) data;
2681 struct fuse_context_i *c = fuse_get_context_internal();
2682
2683 memset(c, 0, sizeof(*c));
2684 c->ctx.fuse = f;
2685 fuse_fs_destroy(f->fs);
2686 f->fs = NULL;
2687 }
2688
fuse_lib_lookup(fuse_req_t req,fuse_ino_t parent,const char * name)2689 static void fuse_lib_lookup(fuse_req_t req, fuse_ino_t parent,
2690 const char *name)
2691 {
2692 struct fuse *f = req_fuse_prepare(req);
2693 struct fuse_entry_param e;
2694 char *path;
2695 int err;
2696 struct node *dot = NULL;
2697
2698 if (name[0] == '.') {
2699 int len = strlen(name);
2700
2701 if (len == 1 || (name[1] == '.' && len == 2)) {
2702 pthread_mutex_lock(&f->lock);
2703 if (len == 1) {
2704 if (f->conf.debug)
2705 fprintf(stderr, "LOOKUP-DOT\n");
2706 dot = get_node_nocheck(f, parent);
2707 if (dot == NULL) {
2708 pthread_mutex_unlock(&f->lock);
2709 reply_entry(req, &e, -ESTALE);
2710 return;
2711 }
2712 dot->refctr++;
2713 } else {
2714 if (f->conf.debug)
2715 fprintf(stderr, "LOOKUP-DOTDOT\n");
2716 parent = get_node(f, parent)->parent->nodeid;
2717 }
2718 pthread_mutex_unlock(&f->lock);
2719 name = NULL;
2720 }
2721 }
2722
2723 err = get_path_name(f, parent, name, &path);
2724 if (!err) {
2725 struct fuse_intr_data d;
2726 if (f->conf.debug)
2727 fprintf(stderr, "LOOKUP %s\n", path);
2728 fuse_prepare_interrupt(f, req, &d);
2729 err = lookup_path(f, parent, name, path, &e, NULL);
2730 if (err == -ENOENT && f->conf.negative_timeout != 0.0) {
2731 e.ino = 0;
2732 e.entry_timeout = f->conf.negative_timeout;
2733 err = 0;
2734 }
2735 fuse_finish_interrupt(f, req, &d);
2736 free_path(f, parent, path);
2737 }
2738 if (dot) {
2739 pthread_mutex_lock(&f->lock);
2740 unref_node(f, dot);
2741 pthread_mutex_unlock(&f->lock);
2742 }
2743 reply_entry(req, &e, err);
2744 }
2745
do_forget(struct fuse * f,fuse_ino_t ino,uint64_t nlookup)2746 static void do_forget(struct fuse *f, fuse_ino_t ino, uint64_t nlookup)
2747 {
2748 if (f->conf.debug)
2749 fprintf(stderr, "FORGET %llu/%llu\n", (unsigned long long)ino,
2750 (unsigned long long) nlookup);
2751 forget_node(f, ino, nlookup);
2752 }
2753
fuse_lib_forget(fuse_req_t req,fuse_ino_t ino,unsigned long nlookup)2754 static void fuse_lib_forget(fuse_req_t req, fuse_ino_t ino,
2755 unsigned long nlookup)
2756 {
2757 do_forget(req_fuse(req), ino, nlookup);
2758 fuse_reply_none(req);
2759 }
2760
fuse_lib_forget_multi(fuse_req_t req,size_t count,struct fuse_forget_data * forgets)2761 static void fuse_lib_forget_multi(fuse_req_t req, size_t count,
2762 struct fuse_forget_data *forgets)
2763 {
2764 struct fuse *f = req_fuse(req);
2765 size_t i;
2766
2767 for (i = 0; i < count; i++)
2768 do_forget(f, forgets[i].ino, forgets[i].nlookup);
2769
2770 fuse_reply_none(req);
2771 }
2772
2773
fuse_lib_getattr(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * fi)2774 static void fuse_lib_getattr(fuse_req_t req, fuse_ino_t ino,
2775 struct fuse_file_info *fi)
2776 {
2777 struct fuse *f = req_fuse_prepare(req);
2778 struct stat buf;
2779 char *path;
2780 int err;
2781
2782 memset(&buf, 0, sizeof(buf));
2783
2784 if (fi != NULL && f->fs->op.fgetattr)
2785 err = get_path_nullok(f, ino, &path);
2786 else
2787 err = get_path(f, ino, &path);
2788 if (!err) {
2789 struct fuse_intr_data d;
2790 fuse_prepare_interrupt(f, req, &d);
2791 if (fi)
2792 err = fuse_fs_fgetattr(f->fs, path, &buf, fi);
2793 else
2794 err = fuse_fs_getattr(f->fs, path, &buf);
2795 fuse_finish_interrupt(f, req, &d);
2796 free_path(f, ino, path);
2797 }
2798 if (!err) {
2799 struct node *node;
2800
2801 pthread_mutex_lock(&f->lock);
2802 node = get_node(f, ino);
2803 if (node->is_hidden && buf.st_nlink > 0)
2804 buf.st_nlink--;
2805 if (f->conf.auto_cache)
2806 update_stat(node, &buf);
2807 pthread_mutex_unlock(&f->lock);
2808 set_stat(f, ino, &buf);
2809 fuse_reply_attr(req, &buf, f->conf.attr_timeout);
2810 } else
2811 reply_err(req, err);
2812 }
2813
fuse_fs_chmod(struct fuse_fs * fs,const char * path,mode_t mode)2814 int fuse_fs_chmod(struct fuse_fs *fs, const char *path, mode_t mode)
2815 {
2816 fuse_get_context()->private_data = fs->user_data;
2817 if (fs->op.chmod)
2818 return fs->op.chmod(path, mode);
2819 else
2820 return -ENOSYS;
2821 }
2822
fuse_lib_setattr(fuse_req_t req,fuse_ino_t ino,struct stat * attr,int valid,struct fuse_file_info * fi)2823 static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
2824 int valid, struct fuse_file_info *fi)
2825 {
2826 struct fuse *f = req_fuse_prepare(req);
2827 struct stat buf;
2828 char *path;
2829 int err;
2830
2831 memset(&buf, 0, sizeof(buf));
2832 if (valid == FUSE_SET_ATTR_SIZE && fi != NULL &&
2833 f->fs->op.ftruncate && f->fs->op.fgetattr)
2834 err = get_path_nullok(f, ino, &path);
2835 else
2836 err = get_path(f, ino, &path);
2837 if (!err) {
2838 struct fuse_intr_data d;
2839 fuse_prepare_interrupt(f, req, &d);
2840 err = 0;
2841 if (!err && (valid & FUSE_SET_ATTR_MODE))
2842 err = fuse_fs_chmod(f->fs, path, attr->st_mode);
2843 if (!err && (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID))) {
2844 uid_t uid = (valid & FUSE_SET_ATTR_UID) ?
2845 attr->st_uid : (uid_t) -1;
2846 gid_t gid = (valid & FUSE_SET_ATTR_GID) ?
2847 attr->st_gid : (gid_t) -1;
2848 err = fuse_fs_chown(f->fs, path, uid, gid);
2849 }
2850 if (!err && (valid & FUSE_SET_ATTR_SIZE)) {
2851 if (fi)
2852 err = fuse_fs_ftruncate(f->fs, path,
2853 attr->st_size, fi);
2854 else
2855 err = fuse_fs_truncate(f->fs, path,
2856 attr->st_size);
2857 }
2858 #ifdef HAVE_UTIMENSAT
2859 if (!err && f->utime_omit_ok &&
2860 (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME))) {
2861 struct timespec tv[2];
2862
2863 tv[0].tv_sec = 0;
2864 tv[1].tv_sec = 0;
2865 tv[0].tv_nsec = UTIME_OMIT;
2866 tv[1].tv_nsec = UTIME_OMIT;
2867
2868 if (valid & FUSE_SET_ATTR_ATIME_NOW)
2869 tv[0].tv_nsec = UTIME_NOW;
2870 else if (valid & FUSE_SET_ATTR_ATIME)
2871 tv[0] = attr->st_atim;
2872
2873 if (valid & FUSE_SET_ATTR_MTIME_NOW)
2874 tv[1].tv_nsec = UTIME_NOW;
2875 else if (valid & FUSE_SET_ATTR_MTIME)
2876 tv[1] = attr->st_mtim;
2877
2878 err = fuse_fs_utimens(f->fs, path, tv);
2879 } else
2880 #endif
2881 if (!err &&
2882 (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) ==
2883 (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) {
2884 struct timespec tv[2];
2885 tv[0].tv_sec = attr->st_atime;
2886 tv[0].tv_nsec = ST_ATIM_NSEC(attr);
2887 tv[1].tv_sec = attr->st_mtime;
2888 tv[1].tv_nsec = ST_MTIM_NSEC(attr);
2889 err = fuse_fs_utimens(f->fs, path, tv);
2890 }
2891 if (!err) {
2892 if (fi)
2893 err = fuse_fs_fgetattr(f->fs, path, &buf, fi);
2894 else
2895 err = fuse_fs_getattr(f->fs, path, &buf);
2896 }
2897 fuse_finish_interrupt(f, req, &d);
2898 free_path(f, ino, path);
2899 }
2900 if (!err) {
2901 if (f->conf.auto_cache) {
2902 pthread_mutex_lock(&f->lock);
2903 update_stat(get_node(f, ino), &buf);
2904 pthread_mutex_unlock(&f->lock);
2905 }
2906 set_stat(f, ino, &buf);
2907 fuse_reply_attr(req, &buf, f->conf.attr_timeout);
2908 } else
2909 reply_err(req, err);
2910 }
2911
fuse_lib_access(fuse_req_t req,fuse_ino_t ino,int mask)2912 static void fuse_lib_access(fuse_req_t req, fuse_ino_t ino, int mask)
2913 {
2914 struct fuse *f = req_fuse_prepare(req);
2915 char *path;
2916 int err;
2917
2918 err = get_path(f, ino, &path);
2919 if (!err) {
2920 struct fuse_intr_data d;
2921
2922 fuse_prepare_interrupt(f, req, &d);
2923 err = fuse_fs_access(f->fs, path, mask);
2924 fuse_finish_interrupt(f, req, &d);
2925 free_path(f, ino, path);
2926 }
2927 reply_err(req, err);
2928 }
2929
fuse_lib_readlink(fuse_req_t req,fuse_ino_t ino)2930 static void fuse_lib_readlink(fuse_req_t req, fuse_ino_t ino)
2931 {
2932 struct fuse *f = req_fuse_prepare(req);
2933 char linkname[PATH_MAX + 1];
2934 char *path;
2935 int err;
2936
2937 err = get_path(f, ino, &path);
2938 if (!err) {
2939 struct fuse_intr_data d;
2940 fuse_prepare_interrupt(f, req, &d);
2941 err = fuse_fs_readlink(f->fs, path, linkname, sizeof(linkname));
2942 fuse_finish_interrupt(f, req, &d);
2943 free_path(f, ino, path);
2944 }
2945 if (!err) {
2946 linkname[PATH_MAX] = '\0';
2947 fuse_reply_readlink(req, linkname);
2948 } else
2949 reply_err(req, err);
2950 }
2951
fuse_lib_mknod(fuse_req_t req,fuse_ino_t parent,const char * name,mode_t mode,dev_t rdev)2952 static void fuse_lib_mknod(fuse_req_t req, fuse_ino_t parent, const char *name,
2953 mode_t mode, dev_t rdev)
2954 {
2955 struct fuse *f = req_fuse_prepare(req);
2956 struct fuse_entry_param e;
2957 char *path;
2958 int err;
2959
2960 err = get_path_name(f, parent, name, &path);
2961 if (!err) {
2962 struct fuse_intr_data d;
2963
2964 fuse_prepare_interrupt(f, req, &d);
2965 err = -ENOSYS;
2966 if (S_ISREG(mode)) {
2967 struct fuse_file_info fi;
2968
2969 memset(&fi, 0, sizeof(fi));
2970 fi.flags = O_CREAT | O_EXCL | O_WRONLY;
2971 err = fuse_fs_create(f->fs, path, mode, &fi);
2972 if (!err) {
2973 err = lookup_path(f, parent, name, path, &e,
2974 &fi);
2975 fuse_fs_release(f->fs, path, &fi);
2976 }
2977 }
2978 if (err == -ENOSYS) {
2979 err = fuse_fs_mknod(f->fs, path, mode, rdev);
2980 if (!err)
2981 err = lookup_path(f, parent, name, path, &e,
2982 NULL);
2983 }
2984 fuse_finish_interrupt(f, req, &d);
2985 free_path(f, parent, path);
2986 }
2987 reply_entry(req, &e, err);
2988 }
2989
fuse_lib_mkdir(fuse_req_t req,fuse_ino_t parent,const char * name,mode_t mode)2990 static void fuse_lib_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name,
2991 mode_t mode)
2992 {
2993 struct fuse *f = req_fuse_prepare(req);
2994 struct fuse_entry_param e;
2995 char *path;
2996 int err;
2997
2998 err = get_path_name(f, parent, name, &path);
2999 if (!err) {
3000 struct fuse_intr_data d;
3001
3002 fuse_prepare_interrupt(f, req, &d);
3003 err = fuse_fs_mkdir(f->fs, path, mode);
3004 if (!err)
3005 err = lookup_path(f, parent, name, path, &e, NULL);
3006 fuse_finish_interrupt(f, req, &d);
3007 free_path(f, parent, path);
3008 }
3009 reply_entry(req, &e, err);
3010 }
3011
fuse_lib_unlink(fuse_req_t req,fuse_ino_t parent,const char * name)3012 static void fuse_lib_unlink(fuse_req_t req, fuse_ino_t parent,
3013 const char *name)
3014 {
3015 struct fuse *f = req_fuse_prepare(req);
3016 struct node *wnode;
3017 char *path;
3018 int err;
3019
3020 err = get_path_wrlock(f, parent, name, &path, &wnode);
3021 if (!err) {
3022 struct fuse_intr_data d;
3023
3024 fuse_prepare_interrupt(f, req, &d);
3025 if (!f->conf.hard_remove && is_open(f, parent, name)) {
3026 err = hide_node(f, path, parent, name);
3027 } else {
3028 err = fuse_fs_unlink(f->fs, path);
3029 if (!err)
3030 remove_node(f, parent, name);
3031 }
3032 fuse_finish_interrupt(f, req, &d);
3033 free_path_wrlock(f, parent, wnode, path);
3034 }
3035 reply_err(req, err);
3036 }
3037
fuse_lib_rmdir(fuse_req_t req,fuse_ino_t parent,const char * name)3038 static void fuse_lib_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name)
3039 {
3040 struct fuse *f = req_fuse_prepare(req);
3041 struct node *wnode;
3042 char *path;
3043 int err;
3044
3045 err = get_path_wrlock(f, parent, name, &path, &wnode);
3046 if (!err) {
3047 struct fuse_intr_data d;
3048
3049 fuse_prepare_interrupt(f, req, &d);
3050 err = fuse_fs_rmdir(f->fs, path);
3051 fuse_finish_interrupt(f, req, &d);
3052 if (!err)
3053 remove_node(f, parent, name);
3054 free_path_wrlock(f, parent, wnode, path);
3055 }
3056 reply_err(req, err);
3057 }
3058
fuse_lib_symlink(fuse_req_t req,const char * linkname,fuse_ino_t parent,const char * name)3059 static void fuse_lib_symlink(fuse_req_t req, const char *linkname,
3060 fuse_ino_t parent, const char *name)
3061 {
3062 struct fuse *f = req_fuse_prepare(req);
3063 struct fuse_entry_param e;
3064 char *path;
3065 int err;
3066
3067 err = get_path_name(f, parent, name, &path);
3068 if (!err) {
3069 struct fuse_intr_data d;
3070
3071 fuse_prepare_interrupt(f, req, &d);
3072 err = fuse_fs_symlink(f->fs, linkname, path);
3073 if (!err)
3074 err = lookup_path(f, parent, name, path, &e, NULL);
3075 fuse_finish_interrupt(f, req, &d);
3076 free_path(f, parent, path);
3077 }
3078 reply_entry(req, &e, err);
3079 }
3080
fuse_lib_rename(fuse_req_t req,fuse_ino_t olddir,const char * oldname,fuse_ino_t newdir,const char * newname)3081 static void fuse_lib_rename(fuse_req_t req, fuse_ino_t olddir,
3082 const char *oldname, fuse_ino_t newdir,
3083 const char *newname)
3084 {
3085 struct fuse *f = req_fuse_prepare(req);
3086 char *oldpath;
3087 char *newpath;
3088 struct node *wnode1;
3089 struct node *wnode2;
3090 int err;
3091
3092 err = get_path2(f, olddir, oldname, newdir, newname,
3093 &oldpath, &newpath, &wnode1, &wnode2);
3094 if (!err) {
3095 struct fuse_intr_data d;
3096 err = 0;
3097 fuse_prepare_interrupt(f, req, &d);
3098 if (!f->conf.hard_remove && is_open(f, newdir, newname))
3099 err = hide_node(f, newpath, newdir, newname);
3100 if (!err) {
3101 err = fuse_fs_rename(f->fs, oldpath, newpath);
3102 if (!err)
3103 err = rename_node(f, olddir, oldname, newdir,
3104 newname, 0);
3105 }
3106 fuse_finish_interrupt(f, req, &d);
3107 free_path2(f, olddir, newdir, wnode1, wnode2, oldpath, newpath);
3108 }
3109 reply_err(req, err);
3110 }
3111
fuse_lib_link(fuse_req_t req,fuse_ino_t ino,fuse_ino_t newparent,const char * newname)3112 static void fuse_lib_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent,
3113 const char *newname)
3114 {
3115 struct fuse *f = req_fuse_prepare(req);
3116 struct fuse_entry_param e;
3117 char *oldpath;
3118 char *newpath;
3119 int err;
3120
3121 err = get_path2(f, ino, NULL, newparent, newname,
3122 &oldpath, &newpath, NULL, NULL);
3123 if (!err) {
3124 struct fuse_intr_data d;
3125
3126 fuse_prepare_interrupt(f, req, &d);
3127 err = fuse_fs_link(f->fs, oldpath, newpath);
3128 if (!err)
3129 err = lookup_path(f, newparent, newname, newpath,
3130 &e, NULL);
3131 fuse_finish_interrupt(f, req, &d);
3132 free_path2(f, ino, newparent, NULL, NULL, oldpath, newpath);
3133 }
3134 reply_entry(req, &e, err);
3135 }
3136
fuse_do_release(struct fuse * f,fuse_ino_t ino,const char * path,struct fuse_file_info * fi)3137 static void fuse_do_release(struct fuse *f, fuse_ino_t ino, const char *path,
3138 struct fuse_file_info *fi)
3139 {
3140 struct node *node;
3141 int unlink_hidden = 0;
3142 const char *compatpath;
3143
3144 if (path != NULL || f->nullpath_ok || f->conf.nopath)
3145 compatpath = path;
3146 else
3147 compatpath = "-";
3148
3149 fuse_fs_release(f->fs, compatpath, fi);
3150
3151 pthread_mutex_lock(&f->lock);
3152 node = get_node(f, ino);
3153 assert(node->open_count > 0);
3154 --node->open_count;
3155 if (node->is_hidden && !node->open_count) {
3156 unlink_hidden = 1;
3157 node->is_hidden = 0;
3158 }
3159 pthread_mutex_unlock(&f->lock);
3160
3161 if(unlink_hidden) {
3162 if (path) {
3163 fuse_fs_unlink(f->fs, path);
3164 } else if (f->conf.nopath) {
3165 char *unlinkpath;
3166
3167 if (get_path(f, ino, &unlinkpath) == 0)
3168 fuse_fs_unlink(f->fs, unlinkpath);
3169
3170 free_path(f, ino, unlinkpath);
3171 }
3172 }
3173 }
3174
fuse_lib_create(fuse_req_t req,fuse_ino_t parent,const char * name,mode_t mode,struct fuse_file_info * fi)3175 static void fuse_lib_create(fuse_req_t req, fuse_ino_t parent,
3176 const char *name, mode_t mode,
3177 struct fuse_file_info *fi)
3178 {
3179 struct fuse *f = req_fuse_prepare(req);
3180 struct fuse_intr_data d;
3181 struct fuse_entry_param e;
3182 char *path;
3183 int err;
3184
3185 err = get_path_name(f, parent, name, &path);
3186 if (!err) {
3187 fuse_prepare_interrupt(f, req, &d);
3188 err = fuse_fs_create(f->fs, path, mode, fi);
3189 if (!err) {
3190 err = lookup_path(f, parent, name, path, &e, fi);
3191 if (err)
3192 fuse_fs_release(f->fs, path, fi);
3193 else if (!S_ISREG(e.attr.st_mode)) {
3194 err = -EIO;
3195 fuse_fs_release(f->fs, path, fi);
3196 forget_node(f, e.ino, 1);
3197 } else {
3198 if (f->conf.direct_io)
3199 fi->direct_io = 1;
3200 if (f->conf.kernel_cache)
3201 fi->keep_cache = 1;
3202
3203 }
3204 }
3205 fuse_finish_interrupt(f, req, &d);
3206 }
3207 if (!err) {
3208 pthread_mutex_lock(&f->lock);
3209 get_node(f, e.ino)->open_count++;
3210 pthread_mutex_unlock(&f->lock);
3211 if (fuse_reply_create(req, &e, fi) == -ENOENT) {
3212 /* The open syscall was interrupted, so it
3213 must be cancelled */
3214 fuse_do_release(f, e.ino, path, fi);
3215 forget_node(f, e.ino, 1);
3216 }
3217 } else {
3218 reply_err(req, err);
3219 }
3220
3221 free_path(f, parent, path);
3222 }
3223
diff_timespec(const struct timespec * t1,const struct timespec * t2)3224 static double diff_timespec(const struct timespec *t1,
3225 const struct timespec *t2)
3226 {
3227 return (t1->tv_sec - t2->tv_sec) +
3228 ((double) t1->tv_nsec - (double) t2->tv_nsec) / 1000000000.0;
3229 }
3230
open_auto_cache(struct fuse * f,fuse_ino_t ino,const char * path,struct fuse_file_info * fi)3231 static void open_auto_cache(struct fuse *f, fuse_ino_t ino, const char *path,
3232 struct fuse_file_info *fi)
3233 {
3234 struct node *node;
3235
3236 pthread_mutex_lock(&f->lock);
3237 node = get_node(f, ino);
3238 if (node->cache_valid) {
3239 struct timespec now;
3240
3241 curr_time(&now);
3242 if (diff_timespec(&now, &node->stat_updated) >
3243 f->conf.ac_attr_timeout) {
3244 struct stat stbuf;
3245 int err;
3246 pthread_mutex_unlock(&f->lock);
3247 err = fuse_fs_fgetattr(f->fs, path, &stbuf, fi);
3248 pthread_mutex_lock(&f->lock);
3249 if (!err)
3250 update_stat(node, &stbuf);
3251 else
3252 node->cache_valid = 0;
3253 }
3254 }
3255 if (node->cache_valid)
3256 fi->keep_cache = 1;
3257
3258 node->cache_valid = 1;
3259 pthread_mutex_unlock(&f->lock);
3260 }
3261
fuse_lib_open(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * fi)3262 static void fuse_lib_open(fuse_req_t req, fuse_ino_t ino,
3263 struct fuse_file_info *fi)
3264 {
3265 struct fuse *f = req_fuse_prepare(req);
3266 struct fuse_intr_data d;
3267 char *path;
3268 int err;
3269
3270 err = get_path(f, ino, &path);
3271 if (!err) {
3272 fuse_prepare_interrupt(f, req, &d);
3273 err = fuse_fs_open(f->fs, path, fi);
3274 if (!err) {
3275 if (f->conf.direct_io)
3276 fi->direct_io = 1;
3277 if (f->conf.kernel_cache)
3278 fi->keep_cache = 1;
3279
3280 if (f->conf.auto_cache)
3281 open_auto_cache(f, ino, path, fi);
3282 }
3283 fuse_finish_interrupt(f, req, &d);
3284 }
3285 if (!err) {
3286 pthread_mutex_lock(&f->lock);
3287 get_node(f, ino)->open_count++;
3288 pthread_mutex_unlock(&f->lock);
3289 if (fuse_reply_open(req, fi) == -ENOENT) {
3290 /* The open syscall was interrupted, so it
3291 must be cancelled */
3292 fuse_do_release(f, ino, path, fi);
3293 }
3294 } else
3295 reply_err(req, err);
3296
3297 free_path(f, ino, path);
3298 }
3299
fuse_lib_read(fuse_req_t req,fuse_ino_t ino,size_t size,off_t off,struct fuse_file_info * fi)3300 static void fuse_lib_read(fuse_req_t req, fuse_ino_t ino, size_t size,
3301 off_t off, struct fuse_file_info *fi)
3302 {
3303 struct fuse *f = req_fuse_prepare(req);
3304 struct fuse_bufvec *buf = NULL;
3305 char *path;
3306 int res;
3307
3308 res = get_path_nullok(f, ino, &path);
3309 if (res == 0) {
3310 struct fuse_intr_data d;
3311
3312 fuse_prepare_interrupt(f, req, &d);
3313 res = fuse_fs_read_buf(f->fs, path, &buf, size, off, fi);
3314 fuse_finish_interrupt(f, req, &d);
3315 free_path(f, ino, path);
3316 }
3317
3318 if (res == 0)
3319 fuse_reply_data(req, buf, FUSE_BUF_SPLICE_MOVE);
3320 else
3321 reply_err(req, res);
3322
3323 fuse_free_buf(buf);
3324 }
3325
fuse_lib_write_buf(fuse_req_t req,fuse_ino_t ino,struct fuse_bufvec * buf,off_t off,struct fuse_file_info * fi)3326 static void fuse_lib_write_buf(fuse_req_t req, fuse_ino_t ino,
3327 struct fuse_bufvec *buf, off_t off,
3328 struct fuse_file_info *fi)
3329 {
3330 struct fuse *f = req_fuse_prepare(req);
3331 char *path;
3332 int res;
3333
3334 res = get_path_nullok(f, ino, &path);
3335 if (res == 0) {
3336 struct fuse_intr_data d;
3337
3338 fuse_prepare_interrupt(f, req, &d);
3339 res = fuse_fs_write_buf(f->fs, path, buf, off, fi);
3340 fuse_finish_interrupt(f, req, &d);
3341 free_path(f, ino, path);
3342 }
3343
3344 if (res >= 0)
3345 fuse_reply_write(req, res);
3346 else
3347 reply_err(req, res);
3348 }
3349
fuse_lib_fsync(fuse_req_t req,fuse_ino_t ino,int datasync,struct fuse_file_info * fi)3350 static void fuse_lib_fsync(fuse_req_t req, fuse_ino_t ino, int datasync,
3351 struct fuse_file_info *fi)
3352 {
3353 struct fuse *f = req_fuse_prepare(req);
3354 char *path;
3355 int err;
3356
3357 err = get_path_nullok(f, ino, &path);
3358 if (!err) {
3359 struct fuse_intr_data d;
3360
3361 fuse_prepare_interrupt(f, req, &d);
3362 err = fuse_fs_fsync(f->fs, path, datasync, fi);
3363 fuse_finish_interrupt(f, req, &d);
3364 free_path(f, ino, path);
3365 }
3366 reply_err(req, err);
3367 }
3368
get_dirhandle(const struct fuse_file_info * llfi,struct fuse_file_info * fi)3369 static struct fuse_dh *get_dirhandle(const struct fuse_file_info *llfi,
3370 struct fuse_file_info *fi)
3371 {
3372 struct fuse_dh *dh = (struct fuse_dh *) (uintptr_t) llfi->fh;
3373 memset(fi, 0, sizeof(struct fuse_file_info));
3374 fi->fh = dh->fh;
3375 fi->fh_old = dh->fh;
3376 return dh;
3377 }
3378
fuse_lib_opendir(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * llfi)3379 static void fuse_lib_opendir(fuse_req_t req, fuse_ino_t ino,
3380 struct fuse_file_info *llfi)
3381 {
3382 struct fuse *f = req_fuse_prepare(req);
3383 struct fuse_intr_data d;
3384 struct fuse_dh *dh;
3385 struct fuse_file_info fi;
3386 char *path;
3387 int err;
3388
3389 dh = (struct fuse_dh *) malloc(sizeof(struct fuse_dh));
3390 if (dh == NULL) {
3391 reply_err(req, -ENOMEM);
3392 return;
3393 }
3394 memset(dh, 0, sizeof(struct fuse_dh));
3395 dh->fuse = f;
3396 dh->contents = NULL;
3397 dh->len = 0;
3398 dh->filled = 0;
3399 dh->nodeid = ino;
3400 fuse_mutex_init(&dh->lock);
3401
3402 llfi->fh = (uintptr_t) dh;
3403
3404 memset(&fi, 0, sizeof(fi));
3405 fi.flags = llfi->flags;
3406
3407 err = get_path(f, ino, &path);
3408 if (!err) {
3409 fuse_prepare_interrupt(f, req, &d);
3410 err = fuse_fs_opendir(f->fs, path, &fi);
3411 fuse_finish_interrupt(f, req, &d);
3412 dh->fh = fi.fh;
3413 }
3414 if (!err) {
3415 if (fuse_reply_open(req, llfi) == -ENOENT) {
3416 /* The opendir syscall was interrupted, so it
3417 must be cancelled */
3418 fuse_fs_releasedir(f->fs, path, &fi);
3419 pthread_mutex_destroy(&dh->lock);
3420 free(dh);
3421 }
3422 } else {
3423 reply_err(req, err);
3424 pthread_mutex_destroy(&dh->lock);
3425 free(dh);
3426 }
3427 free_path(f, ino, path);
3428 }
3429
extend_contents(struct fuse_dh * dh,unsigned minsize)3430 static int extend_contents(struct fuse_dh *dh, unsigned minsize)
3431 {
3432 if (minsize > dh->size) {
3433 char *newptr;
3434 unsigned newsize = dh->size;
3435 if (!newsize)
3436 newsize = 1024;
3437 while (newsize < minsize) {
3438 if (newsize >= 0x80000000)
3439 newsize = 0xffffffff;
3440 else
3441 newsize *= 2;
3442 }
3443
3444 newptr = (char *) realloc(dh->contents, newsize);
3445 if (!newptr) {
3446 dh->error = -ENOMEM;
3447 return -1;
3448 }
3449 dh->contents = newptr;
3450 dh->size = newsize;
3451 }
3452 return 0;
3453 }
3454
fill_dir(void * dh_,const char * name,const struct stat * statp,off_t off)3455 static int fill_dir(void *dh_, const char *name, const struct stat *statp,
3456 off_t off)
3457 {
3458 struct fuse_dh *dh = (struct fuse_dh *) dh_;
3459 struct stat stbuf;
3460 size_t newlen;
3461
3462 if (statp)
3463 stbuf = *statp;
3464 else {
3465 memset(&stbuf, 0, sizeof(stbuf));
3466 stbuf.st_ino = FUSE_UNKNOWN_INO;
3467 }
3468
3469 if (!dh->fuse->conf.use_ino) {
3470 stbuf.st_ino = FUSE_UNKNOWN_INO;
3471 if (dh->fuse->conf.readdir_ino) {
3472 struct node *node;
3473 pthread_mutex_lock(&dh->fuse->lock);
3474 node = lookup_node(dh->fuse, dh->nodeid, name);
3475 if (node)
3476 stbuf.st_ino = (ino_t) node->nodeid;
3477 pthread_mutex_unlock(&dh->fuse->lock);
3478 }
3479 }
3480
3481 if (off) {
3482 if (dh->filled) {
3483 dh->error = -EIO;
3484 return 1;
3485 }
3486
3487 if (extend_contents(dh, dh->needlen) == -1)
3488 return 1;
3489
3490 newlen = dh->len +
3491 fuse_add_direntry(dh->req, dh->contents + dh->len,
3492 dh->needlen - dh->len, name,
3493 &stbuf, off);
3494 if (newlen > dh->needlen)
3495 return 1;
3496 } else {
3497 dh->filled = 1;
3498
3499 newlen = dh->len +
3500 fuse_add_direntry(dh->req, NULL, 0, name, NULL, 0);
3501 if (extend_contents(dh, newlen) == -1)
3502 return 1;
3503
3504 fuse_add_direntry(dh->req, dh->contents + dh->len,
3505 dh->size - dh->len, name, &stbuf, newlen);
3506 }
3507 dh->len = newlen;
3508 return 0;
3509 }
3510
readdir_fill(struct fuse * f,fuse_req_t req,fuse_ino_t ino,size_t size,off_t off,struct fuse_dh * dh,struct fuse_file_info * fi)3511 static int readdir_fill(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
3512 size_t size, off_t off, struct fuse_dh *dh,
3513 struct fuse_file_info *fi)
3514 {
3515 char *path;
3516 int err;
3517
3518 if (f->fs->op.readdir)
3519 err = get_path_nullok(f, ino, &path);
3520 else
3521 err = get_path(f, ino, &path);
3522 if (!err) {
3523 struct fuse_intr_data d;
3524
3525 dh->len = 0;
3526 dh->error = 0;
3527 dh->needlen = size;
3528 dh->filled = 0;
3529 dh->req = req;
3530 fuse_prepare_interrupt(f, req, &d);
3531 err = fuse_fs_readdir(f->fs, path, dh, fill_dir, off, fi);
3532 fuse_finish_interrupt(f, req, &d);
3533 dh->req = NULL;
3534 if (!err)
3535 err = dh->error;
3536 if (err)
3537 dh->filled = 0;
3538 free_path(f, ino, path);
3539 }
3540 return err;
3541 }
3542
fuse_lib_readdir(fuse_req_t req,fuse_ino_t ino,size_t size,off_t off,struct fuse_file_info * llfi)3543 static void fuse_lib_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
3544 off_t off, struct fuse_file_info *llfi)
3545 {
3546 struct fuse *f = req_fuse_prepare(req);
3547 struct fuse_file_info fi;
3548 struct fuse_dh *dh = get_dirhandle(llfi, &fi);
3549
3550 pthread_mutex_lock(&dh->lock);
3551 /* According to SUS, directory contents need to be refreshed on
3552 rewinddir() */
3553 if (!off)
3554 dh->filled = 0;
3555
3556 if (!dh->filled) {
3557 int err = readdir_fill(f, req, ino, size, off, dh, &fi);
3558 if (err) {
3559 reply_err(req, err);
3560 goto out;
3561 }
3562 }
3563 if (dh->filled) {
3564 if (off < dh->len) {
3565 if (off + size > dh->len)
3566 size = dh->len - off;
3567 } else
3568 size = 0;
3569 } else {
3570 size = dh->len;
3571 off = 0;
3572 }
3573 fuse_reply_buf(req, dh->contents + off, size);
3574 out:
3575 pthread_mutex_unlock(&dh->lock);
3576 }
3577
fuse_lib_releasedir(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * llfi)3578 static void fuse_lib_releasedir(fuse_req_t req, fuse_ino_t ino,
3579 struct fuse_file_info *llfi)
3580 {
3581 struct fuse *f = req_fuse_prepare(req);
3582 struct fuse_intr_data d;
3583 struct fuse_file_info fi;
3584 struct fuse_dh *dh = get_dirhandle(llfi, &fi);
3585 char *path;
3586 const char *compatpath;
3587
3588 get_path_nullok(f, ino, &path);
3589 if (path != NULL || f->nullpath_ok || f->conf.nopath)
3590 compatpath = path;
3591 else
3592 compatpath = "-";
3593
3594 fuse_prepare_interrupt(f, req, &d);
3595 fuse_fs_releasedir(f->fs, compatpath, &fi);
3596 fuse_finish_interrupt(f, req, &d);
3597 free_path(f, ino, path);
3598
3599 pthread_mutex_lock(&dh->lock);
3600 pthread_mutex_unlock(&dh->lock);
3601 pthread_mutex_destroy(&dh->lock);
3602 free(dh->contents);
3603 free(dh);
3604 reply_err(req, 0);
3605 }
3606
fuse_lib_fsyncdir(fuse_req_t req,fuse_ino_t ino,int datasync,struct fuse_file_info * llfi)3607 static void fuse_lib_fsyncdir(fuse_req_t req, fuse_ino_t ino, int datasync,
3608 struct fuse_file_info *llfi)
3609 {
3610 struct fuse *f = req_fuse_prepare(req);
3611 struct fuse_file_info fi;
3612 char *path;
3613 int err;
3614
3615 get_dirhandle(llfi, &fi);
3616
3617 err = get_path_nullok(f, ino, &path);
3618 if (!err) {
3619 struct fuse_intr_data d;
3620 fuse_prepare_interrupt(f, req, &d);
3621 err = fuse_fs_fsyncdir(f->fs, path, datasync, &fi);
3622 fuse_finish_interrupt(f, req, &d);
3623 free_path(f, ino, path);
3624 }
3625 reply_err(req, err);
3626 }
3627
fuse_lib_statfs(fuse_req_t req,fuse_ino_t ino)3628 static void fuse_lib_statfs(fuse_req_t req, fuse_ino_t ino)
3629 {
3630 struct fuse *f = req_fuse_prepare(req);
3631 struct statvfs buf;
3632 char *path = NULL;
3633 int err = 0;
3634
3635 memset(&buf, 0, sizeof(buf));
3636 if (ino)
3637 err = get_path(f, ino, &path);
3638
3639 if (!err) {
3640 struct fuse_intr_data d;
3641 fuse_prepare_interrupt(f, req, &d);
3642 err = fuse_fs_statfs(f->fs, path ? path : "/", &buf);
3643 fuse_finish_interrupt(f, req, &d);
3644 free_path(f, ino, path);
3645 }
3646
3647 if (!err)
3648 fuse_reply_statfs(req, &buf);
3649 else
3650 reply_err(req, err);
3651 }
3652
fuse_lib_setxattr(fuse_req_t req,fuse_ino_t ino,const char * name,const char * value,size_t size,int flags)3653 static void fuse_lib_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
3654 const char *value, size_t size, int flags)
3655 {
3656 struct fuse *f = req_fuse_prepare(req);
3657 char *path;
3658 int err;
3659
3660 err = get_path(f, ino, &path);
3661 if (!err) {
3662 struct fuse_intr_data d;
3663 fuse_prepare_interrupt(f, req, &d);
3664 err = fuse_fs_setxattr(f->fs, path, name, value, size, flags);
3665 fuse_finish_interrupt(f, req, &d);
3666 free_path(f, ino, path);
3667 }
3668 reply_err(req, err);
3669 }
3670
common_getxattr(struct fuse * f,fuse_req_t req,fuse_ino_t ino,const char * name,char * value,size_t size)3671 static int common_getxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
3672 const char *name, char *value, size_t size)
3673 {
3674 int err;
3675 char *path;
3676
3677 err = get_path(f, ino, &path);
3678 if (!err) {
3679 struct fuse_intr_data d;
3680 fuse_prepare_interrupt(f, req, &d);
3681 err = fuse_fs_getxattr(f->fs, path, name, value, size);
3682 fuse_finish_interrupt(f, req, &d);
3683 free_path(f, ino, path);
3684 }
3685 return err;
3686 }
3687
fuse_lib_getxattr(fuse_req_t req,fuse_ino_t ino,const char * name,size_t size)3688 static void fuse_lib_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
3689 size_t size)
3690 {
3691 struct fuse *f = req_fuse_prepare(req);
3692 int res;
3693
3694 if (size) {
3695 char *value = (char *) malloc(size);
3696 if (value == NULL) {
3697 reply_err(req, -ENOMEM);
3698 return;
3699 }
3700 res = common_getxattr(f, req, ino, name, value, size);
3701 if (res > 0)
3702 fuse_reply_buf(req, value, res);
3703 else
3704 reply_err(req, res);
3705 free(value);
3706 } else {
3707 res = common_getxattr(f, req, ino, name, NULL, 0);
3708 if (res >= 0)
3709 fuse_reply_xattr(req, res);
3710 else
3711 reply_err(req, res);
3712 }
3713 }
3714
common_listxattr(struct fuse * f,fuse_req_t req,fuse_ino_t ino,char * list,size_t size)3715 static int common_listxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
3716 char *list, size_t size)
3717 {
3718 char *path;
3719 int err;
3720
3721 err = get_path(f, ino, &path);
3722 if (!err) {
3723 struct fuse_intr_data d;
3724 fuse_prepare_interrupt(f, req, &d);
3725 err = fuse_fs_listxattr(f->fs, path, list, size);
3726 fuse_finish_interrupt(f, req, &d);
3727 free_path(f, ino, path);
3728 }
3729 return err;
3730 }
3731
fuse_lib_listxattr(fuse_req_t req,fuse_ino_t ino,size_t size)3732 static void fuse_lib_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
3733 {
3734 struct fuse *f = req_fuse_prepare(req);
3735 int res;
3736
3737 if (size) {
3738 char *list = (char *) malloc(size);
3739 if (list == NULL) {
3740 reply_err(req, -ENOMEM);
3741 return;
3742 }
3743 res = common_listxattr(f, req, ino, list, size);
3744 if (res > 0)
3745 fuse_reply_buf(req, list, res);
3746 else
3747 reply_err(req, res);
3748 free(list);
3749 } else {
3750 res = common_listxattr(f, req, ino, NULL, 0);
3751 if (res >= 0)
3752 fuse_reply_xattr(req, res);
3753 else
3754 reply_err(req, res);
3755 }
3756 }
3757
fuse_lib_removexattr(fuse_req_t req,fuse_ino_t ino,const char * name)3758 static void fuse_lib_removexattr(fuse_req_t req, fuse_ino_t ino,
3759 const char *name)
3760 {
3761 struct fuse *f = req_fuse_prepare(req);
3762 char *path;
3763 int err;
3764
3765 err = get_path(f, ino, &path);
3766 if (!err) {
3767 struct fuse_intr_data d;
3768 fuse_prepare_interrupt(f, req, &d);
3769 err = fuse_fs_removexattr(f->fs, path, name);
3770 fuse_finish_interrupt(f, req, &d);
3771 free_path(f, ino, path);
3772 }
3773 reply_err(req, err);
3774 }
3775
locks_conflict(struct node * node,const struct lock * lock)3776 static struct lock *locks_conflict(struct node *node, const struct lock *lock)
3777 {
3778 struct lock *l;
3779
3780 for (l = node->locks; l; l = l->next)
3781 if (l->owner != lock->owner &&
3782 lock->start <= l->end && l->start <= lock->end &&
3783 (l->type == F_WRLCK || lock->type == F_WRLCK))
3784 break;
3785
3786 return l;
3787 }
3788
delete_lock(struct lock ** lockp)3789 static void delete_lock(struct lock **lockp)
3790 {
3791 struct lock *l = *lockp;
3792 *lockp = l->next;
3793 free(l);
3794 }
3795
insert_lock(struct lock ** pos,struct lock * lock)3796 static void insert_lock(struct lock **pos, struct lock *lock)
3797 {
3798 lock->next = *pos;
3799 *pos = lock;
3800 }
3801
locks_insert(struct node * node,struct lock * lock)3802 static int locks_insert(struct node *node, struct lock *lock)
3803 {
3804 struct lock **lp;
3805 struct lock *newl1 = NULL;
3806 struct lock *newl2 = NULL;
3807
3808 if (lock->type != F_UNLCK || lock->start != 0 ||
3809 lock->end != OFFSET_MAX) {
3810 newl1 = malloc(sizeof(struct lock));
3811 newl2 = malloc(sizeof(struct lock));
3812
3813 if (!newl1 || !newl2) {
3814 free(newl1);
3815 free(newl2);
3816 return -ENOLCK;
3817 }
3818 }
3819
3820 for (lp = &node->locks; *lp;) {
3821 struct lock *l = *lp;
3822 if (l->owner != lock->owner)
3823 goto skip;
3824
3825 if (lock->type == l->type) {
3826 if (l->end < lock->start - 1)
3827 goto skip;
3828 if (lock->end < l->start - 1)
3829 break;
3830 if (l->start <= lock->start && lock->end <= l->end)
3831 goto out;
3832 if (l->start < lock->start)
3833 lock->start = l->start;
3834 if (lock->end < l->end)
3835 lock->end = l->end;
3836 goto delete;
3837 } else {
3838 if (l->end < lock->start)
3839 goto skip;
3840 if (lock->end < l->start)
3841 break;
3842 if (lock->start <= l->start && l->end <= lock->end)
3843 goto delete;
3844 if (l->end <= lock->end) {
3845 l->end = lock->start - 1;
3846 goto skip;
3847 }
3848 if (lock->start <= l->start) {
3849 l->start = lock->end + 1;
3850 break;
3851 }
3852 *newl2 = *l;
3853 newl2->start = lock->end + 1;
3854 l->end = lock->start - 1;
3855 insert_lock(&l->next, newl2);
3856 newl2 = NULL;
3857 }
3858 skip:
3859 lp = &l->next;
3860 continue;
3861
3862 delete:
3863 delete_lock(lp);
3864 }
3865 if (lock->type != F_UNLCK) {
3866 *newl1 = *lock;
3867 insert_lock(lp, newl1);
3868 newl1 = NULL;
3869 }
3870 out:
3871 free(newl1);
3872 free(newl2);
3873 return 0;
3874 }
3875
flock_to_lock(struct flock * flock,struct lock * lock)3876 static void flock_to_lock(struct flock *flock, struct lock *lock)
3877 {
3878 memset(lock, 0, sizeof(struct lock));
3879 lock->type = flock->l_type;
3880 lock->start = flock->l_start;
3881 lock->end =
3882 flock->l_len ? flock->l_start + flock->l_len - 1 : OFFSET_MAX;
3883 lock->pid = flock->l_pid;
3884 }
3885
lock_to_flock(struct lock * lock,struct flock * flock)3886 static void lock_to_flock(struct lock *lock, struct flock *flock)
3887 {
3888 flock->l_type = lock->type;
3889 flock->l_start = lock->start;
3890 flock->l_len =
3891 (lock->end == OFFSET_MAX) ? 0 : lock->end - lock->start + 1;
3892 flock->l_pid = lock->pid;
3893 }
3894
fuse_flush_common(struct fuse * f,fuse_req_t req,fuse_ino_t ino,const char * path,struct fuse_file_info * fi)3895 static int fuse_flush_common(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
3896 const char *path, struct fuse_file_info *fi)
3897 {
3898 struct fuse_intr_data d;
3899 struct flock lock;
3900 struct lock l;
3901 int err;
3902 int errlock;
3903
3904 fuse_prepare_interrupt(f, req, &d);
3905 memset(&lock, 0, sizeof(lock));
3906 lock.l_type = F_UNLCK;
3907 lock.l_whence = SEEK_SET;
3908 err = fuse_fs_flush(f->fs, path, fi);
3909 errlock = fuse_fs_lock(f->fs, path, fi, F_SETLK, &lock);
3910 fuse_finish_interrupt(f, req, &d);
3911
3912 if (errlock != -ENOSYS) {
3913 flock_to_lock(&lock, &l);
3914 l.owner = fi->lock_owner;
3915 pthread_mutex_lock(&f->lock);
3916 locks_insert(get_node(f, ino), &l);
3917 pthread_mutex_unlock(&f->lock);
3918
3919 /* if op.lock() is defined FLUSH is needed regardless
3920 of op.flush() */
3921 if (err == -ENOSYS)
3922 err = 0;
3923 }
3924 return err;
3925 }
3926
fuse_lib_release(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * fi)3927 static void fuse_lib_release(fuse_req_t req, fuse_ino_t ino,
3928 struct fuse_file_info *fi)
3929 {
3930 struct fuse *f = req_fuse_prepare(req);
3931 struct fuse_intr_data d;
3932 char *path;
3933 int err = 0;
3934
3935 get_path_nullok(f, ino, &path);
3936 if (fi->flush) {
3937 err = fuse_flush_common(f, req, ino, path, fi);
3938 if (err == -ENOSYS)
3939 err = 0;
3940 }
3941
3942 fuse_prepare_interrupt(f, req, &d);
3943 fuse_do_release(f, ino, path, fi);
3944 fuse_finish_interrupt(f, req, &d);
3945 free_path(f, ino, path);
3946
3947 reply_err(req, err);
3948 }
3949
fuse_lib_flush(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * fi)3950 static void fuse_lib_flush(fuse_req_t req, fuse_ino_t ino,
3951 struct fuse_file_info *fi)
3952 {
3953 struct fuse *f = req_fuse_prepare(req);
3954 char *path;
3955 int err;
3956
3957 get_path_nullok(f, ino, &path);
3958 err = fuse_flush_common(f, req, ino, path, fi);
3959 free_path(f, ino, path);
3960
3961 reply_err(req, err);
3962 }
3963
fuse_lock_common(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * fi,struct flock * lock,int cmd)3964 static int fuse_lock_common(fuse_req_t req, fuse_ino_t ino,
3965 struct fuse_file_info *fi, struct flock *lock,
3966 int cmd)
3967 {
3968 struct fuse *f = req_fuse_prepare(req);
3969 char *path;
3970 int err;
3971
3972 err = get_path_nullok(f, ino, &path);
3973 if (!err) {
3974 struct fuse_intr_data d;
3975 fuse_prepare_interrupt(f, req, &d);
3976 err = fuse_fs_lock(f->fs, path, fi, cmd, lock);
3977 fuse_finish_interrupt(f, req, &d);
3978 free_path(f, ino, path);
3979 }
3980 return err;
3981 }
3982
fuse_lib_getlk(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * fi,struct flock * lock)3983 static void fuse_lib_getlk(fuse_req_t req, fuse_ino_t ino,
3984 struct fuse_file_info *fi, struct flock *lock)
3985 {
3986 int err;
3987 struct lock l;
3988 struct lock *conflict;
3989 struct fuse *f = req_fuse(req);
3990
3991 flock_to_lock(lock, &l);
3992 l.owner = fi->lock_owner;
3993 pthread_mutex_lock(&f->lock);
3994 conflict = locks_conflict(get_node(f, ino), &l);
3995 if (conflict)
3996 lock_to_flock(conflict, lock);
3997 pthread_mutex_unlock(&f->lock);
3998 if (!conflict)
3999 err = fuse_lock_common(req, ino, fi, lock, F_GETLK);
4000 else
4001 err = 0;
4002
4003 if (!err)
4004 fuse_reply_lock(req, lock);
4005 else
4006 reply_err(req, err);
4007 }
4008
fuse_lib_setlk(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * fi,struct flock * lock,int sleep)4009 static void fuse_lib_setlk(fuse_req_t req, fuse_ino_t ino,
4010 struct fuse_file_info *fi, struct flock *lock,
4011 int sleep)
4012 {
4013 int err = fuse_lock_common(req, ino, fi, lock,
4014 sleep ? F_SETLKW : F_SETLK);
4015 if (!err) {
4016 struct fuse *f = req_fuse(req);
4017 struct lock l;
4018 flock_to_lock(lock, &l);
4019 l.owner = fi->lock_owner;
4020 pthread_mutex_lock(&f->lock);
4021 locks_insert(get_node(f, ino), &l);
4022 pthread_mutex_unlock(&f->lock);
4023 }
4024 reply_err(req, err);
4025 }
4026
fuse_lib_flock(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * fi,int op)4027 static void fuse_lib_flock(fuse_req_t req, fuse_ino_t ino,
4028 struct fuse_file_info *fi, int op)
4029 {
4030 struct fuse *f = req_fuse_prepare(req);
4031 char *path;
4032 int err;
4033
4034 err = get_path_nullok(f, ino, &path);
4035 if (err == 0) {
4036 struct fuse_intr_data d;
4037 fuse_prepare_interrupt(f, req, &d);
4038 err = fuse_fs_flock(f->fs, path, fi, op);
4039 fuse_finish_interrupt(f, req, &d);
4040 free_path(f, ino, path);
4041 }
4042 reply_err(req, err);
4043 }
4044
fuse_lib_bmap(fuse_req_t req,fuse_ino_t ino,size_t blocksize,uint64_t idx)4045 static void fuse_lib_bmap(fuse_req_t req, fuse_ino_t ino, size_t blocksize,
4046 uint64_t idx)
4047 {
4048 struct fuse *f = req_fuse_prepare(req);
4049 struct fuse_intr_data d;
4050 char *path;
4051 int err;
4052
4053 err = get_path(f, ino, &path);
4054 if (!err) {
4055 fuse_prepare_interrupt(f, req, &d);
4056 err = fuse_fs_bmap(f->fs, path, blocksize, &idx);
4057 fuse_finish_interrupt(f, req, &d);
4058 free_path(f, ino, path);
4059 }
4060 if (!err)
4061 fuse_reply_bmap(req, idx);
4062 else
4063 reply_err(req, err);
4064 }
4065
fuse_lib_ioctl(fuse_req_t req,fuse_ino_t ino,int cmd,void * arg,struct fuse_file_info * llfi,unsigned int flags,const void * in_buf,size_t in_bufsz,size_t out_bufsz)4066 static void fuse_lib_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg,
4067 struct fuse_file_info *llfi, unsigned int flags,
4068 const void *in_buf, size_t in_bufsz,
4069 size_t out_bufsz)
4070 {
4071 struct fuse *f = req_fuse_prepare(req);
4072 struct fuse_intr_data d;
4073 struct fuse_file_info fi;
4074 char *path, *out_buf = NULL;
4075 int err;
4076
4077 err = -EPERM;
4078 if (flags & FUSE_IOCTL_UNRESTRICTED)
4079 goto err;
4080
4081 if (flags & FUSE_IOCTL_DIR)
4082 get_dirhandle(llfi, &fi);
4083 else
4084 fi = *llfi;
4085
4086 if (out_bufsz) {
4087 err = -ENOMEM;
4088 out_buf = malloc(out_bufsz);
4089 if (!out_buf)
4090 goto err;
4091 }
4092
4093 assert(!in_bufsz || !out_bufsz || in_bufsz == out_bufsz);
4094 if (out_buf)
4095 memcpy(out_buf, in_buf, in_bufsz);
4096
4097 err = get_path_nullok(f, ino, &path);
4098 if (err)
4099 goto err;
4100
4101 fuse_prepare_interrupt(f, req, &d);
4102
4103 err = fuse_fs_ioctl(f->fs, path, cmd, arg, &fi, flags,
4104 out_buf ?: (void *)in_buf);
4105
4106 fuse_finish_interrupt(f, req, &d);
4107 free_path(f, ino, path);
4108
4109 fuse_reply_ioctl(req, err, out_buf, out_bufsz);
4110 goto out;
4111 err:
4112 reply_err(req, err);
4113 out:
4114 free(out_buf);
4115 }
4116
fuse_lib_poll(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * fi,struct fuse_pollhandle * ph)4117 static void fuse_lib_poll(fuse_req_t req, fuse_ino_t ino,
4118 struct fuse_file_info *fi, struct fuse_pollhandle *ph)
4119 {
4120 struct fuse *f = req_fuse_prepare(req);
4121 struct fuse_intr_data d;
4122 char *path;
4123 int err;
4124 unsigned revents = 0;
4125
4126 err = get_path_nullok(f, ino, &path);
4127 if (!err) {
4128 fuse_prepare_interrupt(f, req, &d);
4129 err = fuse_fs_poll(f->fs, path, fi, ph, &revents);
4130 fuse_finish_interrupt(f, req, &d);
4131 free_path(f, ino, path);
4132 }
4133 if (!err)
4134 fuse_reply_poll(req, revents);
4135 else
4136 reply_err(req, err);
4137 }
4138
fuse_lib_fallocate(fuse_req_t req,fuse_ino_t ino,int mode,off_t offset,off_t length,struct fuse_file_info * fi)4139 static void fuse_lib_fallocate(fuse_req_t req, fuse_ino_t ino, int mode,
4140 off_t offset, off_t length, struct fuse_file_info *fi)
4141 {
4142 struct fuse *f = req_fuse_prepare(req);
4143 struct fuse_intr_data d;
4144 char *path;
4145 int err;
4146
4147 err = get_path_nullok(f, ino, &path);
4148 if (!err) {
4149 fuse_prepare_interrupt(f, req, &d);
4150 err = fuse_fs_fallocate(f->fs, path, mode, offset, length, fi);
4151 fuse_finish_interrupt(f, req, &d);
4152 free_path(f, ino, path);
4153 }
4154 reply_err(req, err);
4155 }
4156
clean_delay(struct fuse * f)4157 static int clean_delay(struct fuse *f)
4158 {
4159 /*
4160 * This is calculating the delay between clean runs. To
4161 * reduce the number of cleans we are doing them 10 times
4162 * within the remember window.
4163 */
4164 int min_sleep = 60;
4165 int max_sleep = 3600;
4166 int sleep_time = f->conf.remember / 10;
4167
4168 if (sleep_time > max_sleep)
4169 return max_sleep;
4170 if (sleep_time < min_sleep)
4171 return min_sleep;
4172 return sleep_time;
4173 }
4174
fuse_clean_cache(struct fuse * f)4175 int fuse_clean_cache(struct fuse *f)
4176 {
4177 struct node_lru *lnode;
4178 struct list_head *curr, *next;
4179 struct node *node;
4180 struct timespec now;
4181
4182 pthread_mutex_lock(&f->lock);
4183
4184 curr_time(&now);
4185
4186 for (curr = f->lru_table.next; curr != &f->lru_table; curr = next) {
4187 double age;
4188
4189 next = curr->next;
4190 lnode = list_entry(curr, struct node_lru, lru);
4191 node = &lnode->node;
4192
4193 age = diff_timespec(&now, &lnode->forget_time);
4194 if (age <= f->conf.remember)
4195 break;
4196
4197 assert(node->nlookup == 1);
4198
4199 /* Don't forget active directories */
4200 if (node->refctr > 1)
4201 continue;
4202
4203 node->nlookup = 0;
4204 unhash_name(f, node);
4205 unref_node(f, node);
4206 }
4207 pthread_mutex_unlock(&f->lock);
4208
4209 return clean_delay(f);
4210 }
4211
4212 static struct fuse_lowlevel_ops fuse_path_ops = {
4213 .init = fuse_lib_init,
4214 .destroy = fuse_lib_destroy,
4215 .lookup = fuse_lib_lookup,
4216 .forget = fuse_lib_forget,
4217 .forget_multi = fuse_lib_forget_multi,
4218 .getattr = fuse_lib_getattr,
4219 .setattr = fuse_lib_setattr,
4220 .access = fuse_lib_access,
4221 .readlink = fuse_lib_readlink,
4222 .mknod = fuse_lib_mknod,
4223 .mkdir = fuse_lib_mkdir,
4224 .unlink = fuse_lib_unlink,
4225 .rmdir = fuse_lib_rmdir,
4226 .symlink = fuse_lib_symlink,
4227 .rename = fuse_lib_rename,
4228 .link = fuse_lib_link,
4229 .create = fuse_lib_create,
4230 .open = fuse_lib_open,
4231 .read = fuse_lib_read,
4232 .write_buf = fuse_lib_write_buf,
4233 .flush = fuse_lib_flush,
4234 .release = fuse_lib_release,
4235 .fsync = fuse_lib_fsync,
4236 .opendir = fuse_lib_opendir,
4237 .readdir = fuse_lib_readdir,
4238 .releasedir = fuse_lib_releasedir,
4239 .fsyncdir = fuse_lib_fsyncdir,
4240 .statfs = fuse_lib_statfs,
4241 .setxattr = fuse_lib_setxattr,
4242 .getxattr = fuse_lib_getxattr,
4243 .listxattr = fuse_lib_listxattr,
4244 .removexattr = fuse_lib_removexattr,
4245 .getlk = fuse_lib_getlk,
4246 .setlk = fuse_lib_setlk,
4247 .flock = fuse_lib_flock,
4248 .bmap = fuse_lib_bmap,
4249 .ioctl = fuse_lib_ioctl,
4250 .poll = fuse_lib_poll,
4251 .fallocate = fuse_lib_fallocate,
4252 };
4253
fuse_notify_poll(struct fuse_pollhandle * ph)4254 int fuse_notify_poll(struct fuse_pollhandle *ph)
4255 {
4256 return fuse_lowlevel_notify_poll(ph);
4257 }
4258
free_cmd(struct fuse_cmd * cmd)4259 static void free_cmd(struct fuse_cmd *cmd)
4260 {
4261 free(cmd->buf);
4262 free(cmd);
4263 }
4264
fuse_process_cmd(struct fuse * f,struct fuse_cmd * cmd)4265 void fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd)
4266 {
4267 fuse_session_process(f->se, cmd->buf, cmd->buflen, cmd->ch);
4268 free_cmd(cmd);
4269 }
4270
fuse_exited(struct fuse * f)4271 int fuse_exited(struct fuse *f)
4272 {
4273 return fuse_session_exited(f->se);
4274 }
4275
fuse_get_session(struct fuse * f)4276 struct fuse_session *fuse_get_session(struct fuse *f)
4277 {
4278 return f->se;
4279 }
4280
fuse_alloc_cmd(size_t bufsize)4281 static struct fuse_cmd *fuse_alloc_cmd(size_t bufsize)
4282 {
4283 struct fuse_cmd *cmd = (struct fuse_cmd *) malloc(sizeof(*cmd));
4284 if (cmd == NULL) {
4285 fprintf(stderr, "fuse: failed to allocate cmd\n");
4286 return NULL;
4287 }
4288 cmd->buf = (char *) malloc(bufsize);
4289 if (cmd->buf == NULL) {
4290 fprintf(stderr, "fuse: failed to allocate read buffer\n");
4291 free(cmd);
4292 return NULL;
4293 }
4294 return cmd;
4295 }
4296
fuse_read_cmd(struct fuse * f)4297 struct fuse_cmd *fuse_read_cmd(struct fuse *f)
4298 {
4299 struct fuse_chan *ch = fuse_session_next_chan(f->se, NULL);
4300 size_t bufsize = fuse_chan_bufsize(ch);
4301 struct fuse_cmd *cmd = fuse_alloc_cmd(bufsize);
4302 if (cmd != NULL) {
4303 int res = fuse_chan_recv(&ch, cmd->buf, bufsize);
4304 if (res <= 0) {
4305 free_cmd(cmd);
4306 if (res < 0 && res != -EINTR && res != -EAGAIN)
4307 fuse_exit(f);
4308 return NULL;
4309 }
4310 cmd->buflen = res;
4311 cmd->ch = ch;
4312 }
4313 return cmd;
4314 }
4315
fuse_session_loop_remember(struct fuse * f)4316 static int fuse_session_loop_remember(struct fuse *f)
4317 {
4318 struct fuse_session *se = f->se;
4319 int res = 0;
4320 struct timespec now;
4321 time_t next_clean;
4322 struct fuse_chan *ch = fuse_session_next_chan(se, NULL);
4323 size_t bufsize = fuse_chan_bufsize(ch);
4324 char *buf = (char *) malloc(bufsize);
4325 struct pollfd fds = {
4326 .fd = fuse_chan_fd(ch),
4327 .events = POLLIN
4328 };
4329
4330 if (!buf) {
4331 fprintf(stderr, "fuse: failed to allocate read buffer\n");
4332 return -1;
4333 }
4334
4335 curr_time(&now);
4336 next_clean = now.tv_sec;
4337 while (!fuse_session_exited(se)) {
4338 struct fuse_chan *tmpch = ch;
4339 struct fuse_buf fbuf = {
4340 .mem = buf,
4341 .size = bufsize,
4342 };
4343 unsigned timeout;
4344
4345 curr_time(&now);
4346 if (now.tv_sec < next_clean)
4347 timeout = next_clean - now.tv_sec;
4348 else
4349 timeout = 0;
4350
4351 res = poll(&fds, 1, timeout * 1000);
4352 if (res == -1) {
4353 if (errno == -EINTR)
4354 continue;
4355 else
4356 break;
4357 } else if (res > 0) {
4358 res = fuse_session_receive_buf(se, &fbuf, &tmpch);
4359
4360 if (res == -EINTR)
4361 continue;
4362 if (res <= 0)
4363 break;
4364
4365 fuse_session_process_buf(se, &fbuf, tmpch);
4366 } else {
4367 timeout = fuse_clean_cache(f);
4368 curr_time(&now);
4369 next_clean = now.tv_sec + timeout;
4370 }
4371 }
4372
4373 free(buf);
4374 fuse_session_reset(se);
4375 return res < 0 ? -1 : 0;
4376 }
4377
fuse_loop(struct fuse * f)4378 int fuse_loop(struct fuse *f)
4379 {
4380 if (!f)
4381 return -1;
4382
4383 if (lru_enabled(f))
4384 return fuse_session_loop_remember(f);
4385
4386 return fuse_session_loop(f->se);
4387 }
4388
fuse_invalidate(struct fuse * f,const char * path)4389 int fuse_invalidate(struct fuse *f, const char *path)
4390 {
4391 (void) f;
4392 (void) path;
4393 return -EINVAL;
4394 }
4395
fuse_exit(struct fuse * f)4396 void fuse_exit(struct fuse *f)
4397 {
4398 fuse_session_exit(f->se);
4399 }
4400
fuse_get_context(void)4401 struct fuse_context *fuse_get_context(void)
4402 {
4403 return &fuse_get_context_internal()->ctx;
4404 }
4405
4406 /*
4407 * The size of fuse_context got extended, so need to be careful about
4408 * incompatibility (i.e. a new binary cannot work with an old
4409 * library).
4410 */
4411 struct fuse_context *fuse_get_context_compat22(void);
fuse_get_context_compat22(void)4412 struct fuse_context *fuse_get_context_compat22(void)
4413 {
4414 return &fuse_get_context_internal()->ctx;
4415 }
4416 FUSE_SYMVER(".symver fuse_get_context_compat22,fuse_get_context@FUSE_2.2");
4417
fuse_getgroups(int size,gid_t list[])4418 int fuse_getgroups(int size, gid_t list[])
4419 {
4420 fuse_req_t req = fuse_get_context_internal()->req;
4421 return fuse_req_getgroups(req, size, list);
4422 }
4423
fuse_interrupted(void)4424 int fuse_interrupted(void)
4425 {
4426 struct fuse_context_i *c = fuse_get_context_internal();
4427
4428 return c->req ? fuse_req_interrupted(c->req) : 0;
4429 }
4430
fuse_set_getcontext_func(struct fuse_context * (* func)(void))4431 void fuse_set_getcontext_func(struct fuse_context *(*func)(void))
4432 {
4433 (void) func;
4434 /* no-op */
4435 }
4436
4437 enum {
4438 KEY_HELP,
4439 };
4440
4441 #define FUSE_LIB_OPT(t, p, v) { t, offsetof(struct fuse_config, p), v }
4442
4443 static const struct fuse_opt fuse_lib_opts[] = {
4444 FUSE_OPT_KEY("-h", KEY_HELP),
4445 FUSE_OPT_KEY("--help", KEY_HELP),
4446 FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP),
4447 FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP),
4448 FUSE_LIB_OPT("debug", debug, 1),
4449 FUSE_LIB_OPT("-d", debug, 1),
4450 FUSE_LIB_OPT("hard_remove", hard_remove, 1),
4451 FUSE_LIB_OPT("use_ino", use_ino, 1),
4452 FUSE_LIB_OPT("readdir_ino", readdir_ino, 1),
4453 FUSE_LIB_OPT("direct_io", direct_io, 1),
4454 FUSE_LIB_OPT("kernel_cache", kernel_cache, 1),
4455 FUSE_LIB_OPT("auto_cache", auto_cache, 1),
4456 FUSE_LIB_OPT("noauto_cache", auto_cache, 0),
4457 FUSE_LIB_OPT("umask=", set_mode, 1),
4458 FUSE_LIB_OPT("umask=%o", umask, 0),
4459 FUSE_LIB_OPT("uid=", set_uid, 1),
4460 FUSE_LIB_OPT("uid=%d", uid, 0),
4461 FUSE_LIB_OPT("gid=", set_gid, 1),
4462 FUSE_LIB_OPT("gid=%d", gid, 0),
4463 FUSE_LIB_OPT("entry_timeout=%lf", entry_timeout, 0),
4464 FUSE_LIB_OPT("attr_timeout=%lf", attr_timeout, 0),
4465 FUSE_LIB_OPT("ac_attr_timeout=%lf", ac_attr_timeout, 0),
4466 FUSE_LIB_OPT("ac_attr_timeout=", ac_attr_timeout_set, 1),
4467 FUSE_LIB_OPT("negative_timeout=%lf", negative_timeout, 0),
4468 FUSE_LIB_OPT("noforget", remember, -1),
4469 FUSE_LIB_OPT("remember=%u", remember, 0),
4470 FUSE_LIB_OPT("nopath", nopath, 1),
4471 FUSE_LIB_OPT("intr", intr, 1),
4472 FUSE_LIB_OPT("intr_signal=%d", intr_signal, 0),
4473 FUSE_LIB_OPT("modules=%s", modules, 0),
4474 FUSE_OPT_END
4475 };
4476
fuse_lib_help(void)4477 static void fuse_lib_help(void)
4478 {
4479 fprintf(stderr,
4480 " -o hard_remove immediate removal (don't hide files)\n"
4481 " -o use_ino let filesystem set inode numbers\n"
4482 " -o readdir_ino try to fill in d_ino in readdir\n"
4483 " -o direct_io use direct I/O\n"
4484 " -o kernel_cache cache files in kernel\n"
4485 " -o [no]auto_cache enable caching based on modification times (off)\n"
4486 " -o umask=M set file permissions (octal)\n"
4487 " -o uid=N set file owner\n"
4488 " -o gid=N set file group\n"
4489 " -o entry_timeout=T cache timeout for names (1.0s)\n"
4490 " -o negative_timeout=T cache timeout for deleted names (0.0s)\n"
4491 " -o attr_timeout=T cache timeout for attributes (1.0s)\n"
4492 " -o ac_attr_timeout=T auto cache timeout for attributes (attr_timeout)\n"
4493 " -o noforget never forget cached inodes\n"
4494 " -o remember=T remember cached inodes for T seconds (0s)\n"
4495 " -o nopath don't supply path if not necessary\n"
4496 " -o intr allow requests to be interrupted\n"
4497 " -o intr_signal=NUM signal to send on interrupt (%i)\n"
4498 " -o modules=M1[:M2...] names of modules to push onto filesystem stack\n"
4499 "\n", FUSE_DEFAULT_INTR_SIGNAL);
4500 }
4501
fuse_lib_help_modules(void)4502 static void fuse_lib_help_modules(void)
4503 {
4504 struct fuse_module *m;
4505 fprintf(stderr, "\nModule options:\n");
4506 pthread_mutex_lock(&fuse_context_lock);
4507 for (m = fuse_modules; m; m = m->next) {
4508 struct fuse_fs *fs = NULL;
4509 struct fuse_fs *newfs;
4510 struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
4511 if (fuse_opt_add_arg(&args, "") != -1 &&
4512 fuse_opt_add_arg(&args, "-h") != -1) {
4513 fprintf(stderr, "\n[%s]\n", m->name);
4514 newfs = m->factory(&args, &fs);
4515 assert(newfs == NULL);
4516 }
4517 fuse_opt_free_args(&args);
4518 }
4519 pthread_mutex_unlock(&fuse_context_lock);
4520 }
4521
fuse_lib_opt_proc(void * data,const char * arg,int key,struct fuse_args * outargs)4522 static int fuse_lib_opt_proc(void *data, const char *arg, int key,
4523 struct fuse_args *outargs)
4524 {
4525 (void) arg; (void) outargs;
4526
4527 if (key == KEY_HELP) {
4528 struct fuse_config *conf = (struct fuse_config *) data;
4529 fuse_lib_help();
4530 conf->help = 1;
4531 }
4532
4533 return 1;
4534 }
4535
fuse_is_lib_option(const char * opt)4536 int fuse_is_lib_option(const char *opt)
4537 {
4538 return fuse_lowlevel_is_lib_option(opt) ||
4539 fuse_opt_match(fuse_lib_opts, opt);
4540 }
4541
fuse_init_intr_signal(int signum,int * installed)4542 static int fuse_init_intr_signal(int signum, int *installed)
4543 {
4544 struct sigaction old_sa;
4545
4546 if (sigaction(signum, NULL, &old_sa) == -1) {
4547 perror("fuse: cannot get old signal handler");
4548 return -1;
4549 }
4550
4551 if (old_sa.sa_handler == SIG_DFL) {
4552 struct sigaction sa;
4553
4554 memset(&sa, 0, sizeof(struct sigaction));
4555 sa.sa_handler = fuse_intr_sighandler;
4556 sigemptyset(&sa.sa_mask);
4557
4558 if (sigaction(signum, &sa, NULL) == -1) {
4559 perror("fuse: cannot set interrupt signal handler");
4560 return -1;
4561 }
4562 *installed = 1;
4563 }
4564 return 0;
4565 }
4566
fuse_restore_intr_signal(int signum)4567 static void fuse_restore_intr_signal(int signum)
4568 {
4569 struct sigaction sa;
4570
4571 memset(&sa, 0, sizeof(struct sigaction));
4572 sa.sa_handler = SIG_DFL;
4573 sigaction(signum, &sa, NULL);
4574 }
4575
4576
fuse_push_module(struct fuse * f,const char * module,struct fuse_args * args)4577 static int fuse_push_module(struct fuse *f, const char *module,
4578 struct fuse_args *args)
4579 {
4580 struct fuse_fs *fs[2] = { f->fs, NULL };
4581 struct fuse_fs *newfs;
4582 struct fuse_module *m = fuse_get_module(module);
4583
4584 if (!m)
4585 return -1;
4586
4587 newfs = m->factory(args, fs);
4588 if (!newfs) {
4589 fuse_put_module(m);
4590 return -1;
4591 }
4592 newfs->m = m;
4593 f->fs = newfs;
4594 f->nullpath_ok = newfs->op.flag_nullpath_ok && f->nullpath_ok;
4595 f->conf.nopath = newfs->op.flag_nopath && f->conf.nopath;
4596 f->utime_omit_ok = newfs->op.flag_utime_omit_ok && f->utime_omit_ok;
4597 return 0;
4598 }
4599
fuse_fs_new(const struct fuse_operations * op,size_t op_size,void * user_data)4600 struct fuse_fs *fuse_fs_new(const struct fuse_operations *op, size_t op_size,
4601 void *user_data)
4602 {
4603 struct fuse_fs *fs;
4604
4605 if (sizeof(struct fuse_operations) < op_size) {
4606 fprintf(stderr, "fuse: warning: library too old, some operations may not not work\n");
4607 op_size = sizeof(struct fuse_operations);
4608 }
4609
4610 fs = (struct fuse_fs *) calloc(1, sizeof(struct fuse_fs));
4611 if (!fs) {
4612 fprintf(stderr, "fuse: failed to allocate fuse_fs object\n");
4613 return NULL;
4614 }
4615
4616 fs->user_data = user_data;
4617 if (op)
4618 memcpy(&fs->op, op, op_size);
4619 return fs;
4620 }
4621
node_table_init(struct node_table * t)4622 static int node_table_init(struct node_table *t)
4623 {
4624 t->size = NODE_TABLE_MIN_SIZE;
4625 t->array = (struct node **) calloc(1, sizeof(struct node *) * t->size);
4626 if (t->array == NULL) {
4627 fprintf(stderr, "fuse: memory allocation failed\n");
4628 return -1;
4629 }
4630 t->use = 0;
4631 t->split = 0;
4632
4633 return 0;
4634 }
4635
fuse_prune_nodes(void * fuse)4636 static void *fuse_prune_nodes(void *fuse)
4637 {
4638 struct fuse *f = fuse;
4639 int sleep_time;
4640
4641 while(1) {
4642 sleep_time = fuse_clean_cache(f);
4643 sleep(sleep_time);
4644 }
4645 return NULL;
4646 }
4647
fuse_start_cleanup_thread(struct fuse * f)4648 int fuse_start_cleanup_thread(struct fuse *f)
4649 {
4650 if (lru_enabled(f))
4651 return fuse_start_thread(&f->prune_thread, fuse_prune_nodes, f);
4652
4653 return 0;
4654 }
4655
fuse_stop_cleanup_thread(struct fuse * f)4656 void fuse_stop_cleanup_thread(struct fuse *f)
4657 {
4658 if (lru_enabled(f)) {
4659 pthread_mutex_lock(&f->lock);
4660 pthread_cancel(f->prune_thread);
4661 pthread_mutex_unlock(&f->lock);
4662 pthread_join(f->prune_thread, NULL);
4663 }
4664 }
4665
fuse_new_common(struct fuse_chan * ch,struct fuse_args * args,const struct fuse_operations * op,size_t op_size,void * user_data,int compat)4666 struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args,
4667 const struct fuse_operations *op,
4668 size_t op_size, void *user_data, int compat)
4669 {
4670 struct fuse *f;
4671 struct node *root;
4672 struct fuse_fs *fs;
4673 struct fuse_lowlevel_ops llop = fuse_path_ops;
4674
4675 if (fuse_create_context_key() == -1)
4676 goto out;
4677
4678 f = (struct fuse *) calloc(1, sizeof(struct fuse));
4679 if (f == NULL) {
4680 fprintf(stderr, "fuse: failed to allocate fuse object\n");
4681 goto out_delete_context_key;
4682 }
4683
4684 fs = fuse_fs_new(op, op_size, user_data);
4685 if (!fs)
4686 goto out_free;
4687
4688 fs->compat = compat;
4689 f->fs = fs;
4690 f->nullpath_ok = fs->op.flag_nullpath_ok;
4691 f->conf.nopath = fs->op.flag_nopath;
4692 f->utime_omit_ok = fs->op.flag_utime_omit_ok;
4693
4694 /* Oh f**k, this is ugly! */
4695 if (!fs->op.lock) {
4696 llop.getlk = NULL;
4697 llop.setlk = NULL;
4698 }
4699
4700 f->conf.entry_timeout = 1.0;
4701 f->conf.attr_timeout = 1.0;
4702 f->conf.negative_timeout = 0.0;
4703 f->conf.intr_signal = FUSE_DEFAULT_INTR_SIGNAL;
4704
4705 f->pagesize = getpagesize();
4706 init_list_head(&f->partial_slabs);
4707 init_list_head(&f->full_slabs);
4708 init_list_head(&f->lru_table);
4709
4710 if (fuse_opt_parse(args, &f->conf, fuse_lib_opts,
4711 fuse_lib_opt_proc) == -1)
4712 goto out_free_fs;
4713
4714 if (f->conf.modules) {
4715 char *module;
4716 char *next;
4717
4718 for (module = f->conf.modules; module; module = next) {
4719 char *p;
4720 for (p = module; *p && *p != ':'; p++);
4721 next = *p ? p + 1 : NULL;
4722 *p = '\0';
4723 if (module[0] &&
4724 fuse_push_module(f, module, args) == -1)
4725 goto out_free_fs;
4726 }
4727 }
4728
4729 if (!f->conf.ac_attr_timeout_set)
4730 f->conf.ac_attr_timeout = f->conf.attr_timeout;
4731
4732 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
4733 /*
4734 * In FreeBSD, we always use these settings as inode numbers
4735 * are needed to make getcwd(3) work.
4736 */
4737 f->conf.readdir_ino = 1;
4738 #endif
4739
4740 if (compat && compat <= 25) {
4741 if (fuse_sync_compat_args(args) == -1)
4742 goto out_free_fs;
4743 }
4744
4745 f->se = fuse_lowlevel_new_common(args, &llop, sizeof(llop), f);
4746 if (f->se == NULL) {
4747 if (f->conf.help)
4748 fuse_lib_help_modules();
4749 goto out_free_fs;
4750 }
4751
4752 fuse_session_add_chan(f->se, ch);
4753
4754 if (f->conf.debug) {
4755 fprintf(stderr, "nullpath_ok: %i\n", f->nullpath_ok);
4756 fprintf(stderr, "nopath: %i\n", f->conf.nopath);
4757 fprintf(stderr, "utime_omit_ok: %i\n", f->utime_omit_ok);
4758 }
4759
4760 /* Trace topmost layer by default */
4761 f->fs->debug = f->conf.debug;
4762 f->ctr = 0;
4763 f->generation = 0;
4764 if (node_table_init(&f->name_table) == -1)
4765 goto out_free_session;
4766
4767 if (node_table_init(&f->id_table) == -1)
4768 goto out_free_name_table;
4769
4770 fuse_mutex_init(&f->lock);
4771
4772 root = alloc_node(f);
4773 if (root == NULL) {
4774 fprintf(stderr, "fuse: memory allocation failed\n");
4775 goto out_free_id_table;
4776 }
4777 if (lru_enabled(f)) {
4778 struct node_lru *lnode = node_lru(root);
4779 init_list_head(&lnode->lru);
4780 }
4781
4782 strcpy(root->inline_name, "/");
4783 root->name = root->inline_name;
4784
4785 if (f->conf.intr &&
4786 fuse_init_intr_signal(f->conf.intr_signal,
4787 &f->intr_installed) == -1)
4788 goto out_free_root;
4789
4790 root->parent = NULL;
4791 root->nodeid = FUSE_ROOT_ID;
4792 inc_nlookup(root);
4793 hash_id(f, root);
4794
4795 return f;
4796
4797 out_free_root:
4798 free(root);
4799 out_free_id_table:
4800 free(f->id_table.array);
4801 out_free_name_table:
4802 free(f->name_table.array);
4803 out_free_session:
4804 fuse_session_destroy(f->se);
4805 out_free_fs:
4806 /* Horrible compatibility hack to stop the destructor from being
4807 called on the filesystem without init being called first */
4808 fs->op.destroy = NULL;
4809 fuse_fs_destroy(f->fs);
4810 free(f->conf.modules);
4811 out_free:
4812 free(f);
4813 out_delete_context_key:
4814 fuse_delete_context_key();
4815 out:
4816 return NULL;
4817 }
4818
fuse_new(struct fuse_chan * ch,struct fuse_args * args,const struct fuse_operations * op,size_t op_size,void * user_data)4819 struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args,
4820 const struct fuse_operations *op, size_t op_size,
4821 void *user_data)
4822 {
4823 return fuse_new_common(ch, args, op, op_size, user_data, 0);
4824 }
4825
fuse_destroy(struct fuse * f)4826 void fuse_destroy(struct fuse *f)
4827 {
4828 size_t i;
4829
4830 if (f->conf.intr && f->intr_installed)
4831 fuse_restore_intr_signal(f->conf.intr_signal);
4832
4833 if (f->fs) {
4834 struct fuse_context_i *c = fuse_get_context_internal();
4835
4836 memset(c, 0, sizeof(*c));
4837 c->ctx.fuse = f;
4838
4839 for (i = 0; i < f->id_table.size; i++) {
4840 struct node *node;
4841
4842 for (node = f->id_table.array[i]; node != NULL;
4843 node = node->id_next) {
4844 if (node->is_hidden) {
4845 char *path;
4846 if (try_get_path(f, node->nodeid, NULL, &path, NULL, false) == 0) {
4847 fuse_fs_unlink(f->fs, path);
4848 free(path);
4849 }
4850 }
4851 }
4852 }
4853 }
4854 for (i = 0; i < f->id_table.size; i++) {
4855 struct node *node;
4856 struct node *next;
4857
4858 for (node = f->id_table.array[i]; node != NULL; node = next) {
4859 next = node->id_next;
4860 free_node(f, node);
4861 f->id_table.use--;
4862 }
4863 }
4864 assert(list_empty(&f->partial_slabs));
4865 assert(list_empty(&f->full_slabs));
4866
4867 free(f->id_table.array);
4868 free(f->name_table.array);
4869 pthread_mutex_destroy(&f->lock);
4870 fuse_session_destroy(f->se);
4871 free(f->conf.modules);
4872 free(f);
4873 fuse_delete_context_key();
4874 }
4875
fuse_new_common_compat25(int fd,struct fuse_args * args,const struct fuse_operations * op,size_t op_size,int compat)4876 static struct fuse *fuse_new_common_compat25(int fd, struct fuse_args *args,
4877 const struct fuse_operations *op,
4878 size_t op_size, int compat)
4879 {
4880 struct fuse *f = NULL;
4881 struct fuse_chan *ch = fuse_kern_chan_new(fd);
4882
4883 if (ch)
4884 f = fuse_new_common(ch, args, op, op_size, NULL, compat);
4885
4886 return f;
4887 }
4888
4889 /* called with fuse_context_lock held or during initialization (before
4890 main() has been called) */
fuse_register_module(struct fuse_module * mod)4891 void fuse_register_module(struct fuse_module *mod)
4892 {
4893 mod->ctr = 0;
4894 mod->so = fuse_current_so;
4895 if (mod->so)
4896 mod->so->ctr++;
4897 mod->next = fuse_modules;
4898 fuse_modules = mod;
4899 }
4900
4901 #if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__)
4902
fuse_new_common_compat(int fd,const char * opts,const struct fuse_operations * op,size_t op_size,int compat)4903 static struct fuse *fuse_new_common_compat(int fd, const char *opts,
4904 const struct fuse_operations *op,
4905 size_t op_size, int compat)
4906 {
4907 struct fuse *f;
4908 struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
4909
4910 if (fuse_opt_add_arg(&args, "") == -1)
4911 return NULL;
4912 if (opts &&
4913 (fuse_opt_add_arg(&args, "-o") == -1 ||
4914 fuse_opt_add_arg(&args, opts) == -1)) {
4915 fuse_opt_free_args(&args);
4916 return NULL;
4917 }
4918 f = fuse_new_common_compat25(fd, &args, op, op_size, compat);
4919 fuse_opt_free_args(&args);
4920
4921 return f;
4922 }
4923
fuse_new_compat22(int fd,const char * opts,const struct fuse_operations_compat22 * op,size_t op_size)4924 struct fuse *fuse_new_compat22(int fd, const char *opts,
4925 const struct fuse_operations_compat22 *op,
4926 size_t op_size)
4927 {
4928 return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op,
4929 op_size, 22);
4930 }
4931
fuse_new_compat2(int fd,const char * opts,const struct fuse_operations_compat2 * op)4932 struct fuse *fuse_new_compat2(int fd, const char *opts,
4933 const struct fuse_operations_compat2 *op)
4934 {
4935 return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op,
4936 sizeof(struct fuse_operations_compat2),
4937 21);
4938 }
4939
fuse_new_compat1(int fd,int flags,const struct fuse_operations_compat1 * op)4940 struct fuse *fuse_new_compat1(int fd, int flags,
4941 const struct fuse_operations_compat1 *op)
4942 {
4943 const char *opts = NULL;
4944 if (flags & FUSE_DEBUG_COMPAT1)
4945 opts = "debug";
4946 return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op,
4947 sizeof(struct fuse_operations_compat1),
4948 11);
4949 }
4950
4951 FUSE_SYMVER(".symver fuse_exited,__fuse_exited@");
4952 FUSE_SYMVER(".symver fuse_process_cmd,__fuse_process_cmd@");
4953 FUSE_SYMVER(".symver fuse_read_cmd,__fuse_read_cmd@");
4954 FUSE_SYMVER(".symver fuse_set_getcontext_func,__fuse_set_getcontext_func@");
4955 FUSE_SYMVER(".symver fuse_new_compat2,fuse_new@");
4956 FUSE_SYMVER(".symver fuse_new_compat22,fuse_new@FUSE_2.2");
4957
4958 #endif /* __FreeBSD__ || __NetBSD__ */
4959
fuse_new_compat25(int fd,struct fuse_args * args,const struct fuse_operations_compat25 * op,size_t op_size)4960 struct fuse *fuse_new_compat25(int fd, struct fuse_args *args,
4961 const struct fuse_operations_compat25 *op,
4962 size_t op_size)
4963 {
4964 return fuse_new_common_compat25(fd, args, (struct fuse_operations *) op,
4965 op_size, 25);
4966 }
4967
4968 FUSE_SYMVER(".symver fuse_new_compat25,fuse_new@FUSE_2.5");
4969