libfuse: fuse-3.2.3/lib/fuse.c Source File

libfuse

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