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